diff -u --recursive --new-file v2.5.0/linux/CREDITS linux/CREDITS
--- v2.5.0/linux/CREDITS	Sun Nov 11 10:09:32 2001
+++ linux/CREDITS	Wed Dec  5 13:02:14 2001
@@ -140,9 +140,11 @@
 D: VIA MVP-3/TX Pro III chipset IDE
 
 N: Jens Axboe
-E: axboe@image.dk
-D: Linux CD-ROM maintainer
-D: jiffies wrap fixes + schedule timeouts depending on HZ == 100
+E: axboe@suse.de
+D: Linux CD-ROM maintainer, DVD support
+D: elevator + block layer rewrites
+D: highmem I/O support
+D: misc hacking on IDE, SCSI, block drivers, etc
 S: Peter Bangs Vej 258, 2TH
 S: 2500 Valby
 S: Denmark
@@ -1147,6 +1149,16 @@
 S: London SE16 1GD
 S: United Kingdom
 
+N: Jan Harkes
+E: jaharkes@cs.cmu.edu
+W: http://www.coda.cs.cmu.edu/
+D: Coda file system
+S: Computer Science Department
+S: Carnegie Mellon University
+S: 5000 Forbes Avenue
+S: Pittsburgh, Pennsylvania 15213
+S: USA
+
 N: Kai Harrekilde-Petersen
 E: kai.harrekilde@get2net.dk
 D: Original author of the ftape-HOWTO, i82078 fdc detection code.
@@ -2063,7 +2075,7 @@
 S: USA
 
 N: Patrick Mochel
-E: pat@osdl.org
+E: mochel@osdl.org
 E: mochelp@infinity.powertie.org
 D: PCI Power Management, ACPI work
 S: 15275 SW Koll Parkway, Suite H
diff -u --recursive --new-file v2.5.0/linux/Documentation/Changes linux/Documentation/Changes
--- v2.5.0/linux/Documentation/Changes	Mon Sep 17 23:10:44 2001
+++ linux/Documentation/Changes	Fri Nov 30 08:53:20 2001
@@ -2,13 +2,13 @@
 =====
 
 This document is designed to provide a list of the minimum levels of
-software necessary to run the 2.4 kernels, as well as provide brief
+software necessary to run the 2.5 kernels, as well as provide brief
 instructions regarding any other "Gotchas" users may encounter when
-trying life on the Bleeding Edge.  If upgrading from a pre-2.2.x
-kernel, please consult the Changes file included with 2.2.x kernels for
+trying life on the Bleeding Edge.  If upgrading from a pre-2.4.x
+kernel, please consult the Changes file included with 2.4.x kernels for
 additional information; most of that information will not be repeated
 here.  Basically, this document assumes that your system is already
-functional and running at least 2.2.x kernels.
+functional and running at least 2.4.x kernels.
 
 This document is originally based on my "Changes" file for 2.0.x kernels
 and therefore owes credit to the same people as that file (Jared Mauch,
@@ -31,7 +31,7 @@
 Eine deutsche Version dieser Datei finden Sie unter
 <http://www.stefan-winter.de/Changes-2.4.0.txt>.
 
-Last updated: May 9, 2001
+Last updated: November 29, 2001
 
 Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
 
@@ -43,14 +43,14 @@
 running, the suggested command should tell you.
 
 Again, keep in mind that this list assumes you are already
-functionally running a Linux 2.2 kernel.  Also, not all tools are
+functionally running a Linux 2.4 kernel.  Also, not all tools are
 necessary on all systems; obviously, if you don't have any PCMCIA (PC
 Card) hardware, for example, you probably needn't concern yourself
 with pcmcia-cs.
 
 o  Gnu C                  2.95.3                  # gcc --version
 o  Gnu make               3.77                    # make --version
-o  binutils               2.9.1.0.25              # ld -v
+o  binutils               2.9.5.0.24              # ld -v
 o  util-linux             2.10o                   # fdformat --version
 o  modutils               2.4.2                   # insmod -V
 o  e2fsprogs              1.19                    # tune2fs
@@ -70,9 +70,9 @@
 necessarily to users of other CPUs. Users of other CPUs should obtain
 information about their gcc version requirements from another source.
 
-The recommended compiler for the kernel is gcc 2.95.3 or .4, and it
+The recommended compiler for the kernel is gcc 2.95.x (x >= 3), and it
 should be used when you need absolute stability. You may use gcc 3.0.x
-instead if you wish, although it may cause problems. Later  versions of gcc 
+instead if you wish, although it may cause problems. Later versions of gcc 
 have not received much testing for Linux kernel compilation, and there are 
 almost certainly bugs (mainly, but not exclusively, in the kernel) that
 will need to be fixed in order to use these compilers. In any case, using
@@ -106,12 +106,6 @@
 your kernel.  This change does, however, mean that you need a recent
 release of binutils.
 
-If you can, upgrade to the latest 2.9.5 or 2.10 binutils release.  Older
-releases such as 2.8, 2.8.xx, and the FSF's 2.9.1 should be avoided if
-at all possible.  The later releases of 2.9.1.0.x (anything where x >= 22)
-can and do compile the kernel properly, but there are many benefits in
-upgrading to 2.9.5 or 2.10 if you're up to it.
-
 System utils
 ============
 
@@ -276,7 +270,7 @@
 
 gcc 2.95.3
 ----------
-o  <ftp://ftp.gnu.org/pub/gnu/gcc/gcc-2.95.3.tar.gz>
+o  <ftp://ftp.gnu.org/gnu/gcc/gcc-2.95.3.tar.gz>
 
 Gnu Make
 ********
@@ -287,21 +281,14 @@
 
 Binutils
 ********
-
-2.9.1 series
-------------
-o  <ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz>
-
-2.9.5 and 2.10 series
----------------------
-o  <ftp://ftp.valinux.com/pub/support/hjl/binutils/>
+o  <ftp://ftp.kernel.org/pub/linux/devel/binutils/>
 
 System utilities
 ****************
 
 Util-linux
 ----------
-o  <ftp://ftp.kernel.org/pub/linux/utils/util-linux/util-linux-2.10o.tar.gz>
+o  <ftp://ftp.kernel.org/pub/linux/utils/util-linux/>
 
 Ksymoops
 --------
diff -u --recursive --new-file v2.5.0/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.5.0/linux/Documentation/Configure.help	Thu Nov 22 10:52:44 2001
+++ linux/Documentation/Configure.help	Fri Nov 30 13:25:10 2001
@@ -2,10 +2,10 @@
 #	Eric S. Raymond <mailto:esr@thyrsus.com>
 #	Steven Cole <mailto:elenstev@mesatop.com>
 #
-# Merged version 2.49: Current with 2.4.15-pre1 and 2.4.13-ac8.
+# Merged version 2.61: current with 2.4.16/2.5.1-pre1.
 #
 # This version of the Linux kernel configuration help texts
-# corresponds to the kernel versions 2.4.x.
+# corresponds to kernel versions 2.4.x and 2.5.x.
 #
 # Translations of this file available on the WWW:
 #
@@ -14,11 +14,13 @@
 #   - Russian, by <mailto:kaf@linux.nevod.perm.su>, at
 #     <http://nevod.perm.su/service/linux/doc/kernel/Configure.help>
 #   - French, by Pierre Tane <mailto:tanep@bigfoot.com>, at
-#     <http://www.traduc.org/kernelfr>
+#     <http://www.traduc.org/kernelfr/>
 #   - Polish, by Dominik Mierzejewski <mailto:dmierzej@elka.pw.edu.pl>, at
 #     <http://home.elka.pw.edu.pl/~dmierzej/linux/kernel/>
-#   - German, by SuSE, at <http://www.suse.de/~ke/kernel>. This patch
+#   - German, by SuSE, at <http://www.suse.de/~ke/kernel/>. This patch
 #     also includes infrastructure to support different languages.
+#   - Catalan, by Antoni Bella <mailto:bella5@teleline.es>, at
+#     <http://www.terra.es/personal7/bella5/traduccions.htm>
 #
 # To access a document on the WWW, you need to have a direct Internet
 # connection and a browser program such as netscape or lynx. If you
@@ -133,8 +135,8 @@
 
   See also the <file:Documentation/smp.tex>,
   <file:Documentation/smp.txt>, <file:Documentation/i386/IO-APIC.txt>,
-  <file:Documentation/nmi_watchdog.txt> and the SMP-FAQ on the WWW at
-  <http://www.irisa.fr/prive/mentre/smp-faq/>.
+  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+  <http://www.linuxdoc.org/docs.html#howto>.
 
   If you don't know what to do here, say N.
 
@@ -577,7 +579,7 @@
 
   To fine-tune ATA/IDE drive/interface parameters for improved
   performance, look for the hdparm package at
-  <http://www.ibiblio.org/pub/Linux/system/hardware>.
+  <ftp://ibiblio.org/pub/Linux/system/hardware/>.
 
   If you want to compile this driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -666,12 +668,9 @@
   CD-ROM drive, you can say N to all other CD-ROM options, but be sure
   to say Y or M to "ISO 9660 CD-ROM file system support".
 
-  Read the CD-ROM-HOWTO, available from
-  <http://www.linuxdoc.org/docs.html#howto> and
-  <file:Documentation/cdrom/ide-cd>. Note that older versions of lilo
-  (the Linux boot loader) cannot properly deal with IDE/ATAPI CD-ROMs,
-  so install lilo-16 or higher, available from
-  <ftp://metalab.unc.edu/pub/Linux/system/boot/lilo>.
+  Note that older versions of LILO (LInux LOader) cannot properly deal
+  with IDE/ATAPI CD-ROMs, so install LILO 16 or higher, available from
+  <ftp://brun.dyndns.org/pub/linux/lilo/>.
 
   If you want to compile the driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -820,7 +819,7 @@
   for these drives, but you can change that by saying Y to the
   following question "Use DMA by default when available". You can get
   the latest version of the hdparm utility from
-  <ftp://metalab.unc.edu/pub/Linux/system/hardware/>.
+  <ftp://ibiblio.org/pub/Linux/system/hardware/>.
 
   Read the comments at the beginning of <file:drivers/ide/ide-dma.c>
   and the file <file:Documentation/ide.txt> for more information.
@@ -899,7 +898,7 @@
 
   It is normally safe to answer Y; however, the default is N.
 
-ATA Work(s) In Progress (EXPERIMENTAL)‹
+ATA Work(s) In Progress (EXPERIMENTAL)
 CONFIG_IDEDMA_PCI_WIP
   If you enable this you will be able to use and test highly
   developmental projects. If you say N, the configurator will
@@ -914,7 +913,7 @@
 
 Pacific Digital A-DMA support (EXPERIMENTAL)
 CONFIG_BLK_DEV_PDC_ADMA
-  Please read the comments at the top of <file:drivers/ide/pdcadma.c>.
+  Please read the comments at the top of <file:drivers/ide/ide-pci.c>.
 
 3ware Hardware ATA-RAID support
 CONFIG_BLK_DEV_3W_XXXX_RAID
@@ -1118,11 +1117,13 @@
 
 Special UDMA Feature
 CONFIG_PDC202XX_BURST
-  For PDC20246, PDC20262, PDC20265 and PDC20267 Ultra DMA chipsets.
-  Designed originally for PDC20246/Ultra33 that has BIOS setup
-  failures when using 3 or more cards.
+  This option causes the pdc202xx driver to enable UDMA modes on the
+  PDC202xx even when the PDC202xx BIOS has not done so.
 
-  Unknown for PDC20265/PDC20267 Ultra DMA 100.
+  It was originally designed for the PDC20246/Ultra33, whose BIOS will
+  only setup UDMA on the first two PDC20246 cards.  It has also been
+  used succesfully on a PDC20265/Ultra100, allowing use of UDMA modes
+  when the PDC20265 BIOS has been disabled (for faster boot up).
 
   Please read the comments at the top of
   <file:drivers/ide/pdc202xx.c>.
@@ -1251,15 +1252,6 @@
   <file:Documentation/ide.txt> and <file:drivers/ide/pdc4030.c> files
   for more info.
 
-# This is for Linus's tree.
-QDI QD6580 support
-CONFIG_BLK_DEV_QD6580
-  This driver is enabled at runtime using the "ide0=qd6580" kernel
-  boot parameter.  It permits faster I/O speeds to be set.  See the
-  <file:Documentation/ide.txt> and <file:drivers/ide/qd6580.c> for
-  more info.
-
-# This is for Alan's tree.  Note the name difference.
 QDI QD65XX support
 CONFIG_BLK_DEV_QD65XX
   This driver is enabled at runtime using the "ide0=qd65xx" kernel
@@ -1488,7 +1480,7 @@
 CONFIG_PARIDE_PG
   This option enables a special high-level driver for generic ATAPI
   devices connected through a parallel port. The driver allows user
-  programs, such as cdrecord, to send ATAPI commands directly to a
+  programs, such as cdrtools, to send ATAPI commands directly to a
   device.
 
   If you chose to build PARIDE support into your kernel, you may
@@ -1502,7 +1494,7 @@
   This driver implements an API loosely related to the generic SCSI
   driver. See <file:include/linux/pg.h>. for details.
 
-  You can obtain the most recent version of cdrecord from
+  You can obtain the most recent version of cdrtools from
   <ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/>. Versions 1.6.1a3 and
   later fully support this driver.
 
@@ -1716,9 +1708,9 @@
   controller, you do not need to say Y here.
 
   More information about Software RAID on Linux is contained in the
-  Software-RAID mini-HOWTO, available from
-  <http://www.linuxdoc.org/docs.html#howto>. There you will also
-  learn where to get the supporting user space utilities raidtools.
+  Software RAID mini-HOWTO, available from
+  <http://www.linuxdoc.org/docs.html#howto>. There you will also learn
+  where to get the supporting user space utilities raidtools.
 
   If unsure, say N.
 
@@ -1811,7 +1803,6 @@
 
   If unsure, say N.
 
-# AC tree only
 Support for IDE Raid controllers
 CONFIG_BLK_DEV_ATARAID
   Say Y or M if you have an IDE Raid controller and want linux
@@ -1824,7 +1815,6 @@
   has its own Raid drivers, which you should use if you need better
   performance.
 
-# AC tree only
 Support Promise software RAID (Fasttrak(tm))
 CONFIG_BLK_DEV_ATARAID_PDC
   Say Y or M if you have a Promise Fasttrak (tm) Raid controller
@@ -1835,7 +1825,6 @@
   If you choose to compile this as a module, the module will be called
   pdcraid.o.
 
-# AC tree only
 Highpoint 370 software RAID
 CONFIG_BLK_DEV_ATARAID_HPT
   Say Y or M if you have a Highpoint HPT 370 Raid controller
@@ -1851,19 +1840,19 @@
   This is a machine with a R4400 133/150 MHz CPU. To compile a Linux
   kernel that runs on these, say Y here. For details about Linux on
   the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-  <http://oss.sgi.com/mips>.
+  <http://oss.sgi.com/mips/>.
 
 Support for Algorithmics P4032 (EXPERIMENTAL)
 CONFIG_ALGOR_P4032
   This is an evaluation board of the British company Algorithmics.
   The board uses the R4300 and a R5230 CPUs.  For more information
-  about this board see <http://www.algor.co.uk>.
+  about this board see <http://www.algor.co.uk/>.
 
 Support for BAGET MIPS series
 CONFIG_BAGET_MIPS
   This enables support for the Baget, a Russian embedded system.  For
   more details about the Baget see the Linux/MIPS FAQ on
-  <http://oss.sgi.com/mips>.
+  <http://oss.sgi.com/mips/>.
 
 Baget AMD LANCE support
 CONFIG_BAGETLANCE
@@ -1874,8 +1863,8 @@
 Support for DECstations
 CONFIG_DECSTATION
   This enables support for DEC's MIPS based workstations.  For details
-  see the Linux/MIPS FAQ on <http://oss.sgi.com/mips> and the
-  DECstation porting pages on <http://decstation.unix-ag.org>.
+  see the Linux/MIPS FAQ on <http://oss.sgi.com/mips/> and the
+  DECstation porting pages on <http://decstation.unix-ag.org/>.
 
   If you have one of the following DECstation Models you definitely
   want to choose R4xx0 for the CPU Type:
@@ -1904,7 +1893,7 @@
 Support for the Momentum Computer Ocelot SBC
 CONFIG_MOMENCO_OCELOT
   The Ocelot is a MIPS-based Single Board Computer (SBC) made by
-  Momentum Computer <http://www.momenco.com>.
+  Momentum Computer <http://www.momenco.com/>.
 
 Support for NEC DDB Vrc-5074
 CONFIG_DDB5074
@@ -1917,7 +1906,7 @@
   evaluation board.
 
   Features : kernel debugging, serial terminal, NFS root fs, on-board
-  ether port (Need an additional patch at <http://linux.junsun.net>),
+  ether port (Need an additional patch at <http://linux.junsun.net/>),
   USB, AC97, PCI, PCI VGA card & framebuffer console, IDE controller,
   PS2 keyboard, PS2 mouse, etc.
 
@@ -1927,7 +1916,7 @@
   evaluation board.
 
   Features : kernel debugging, serial terminal, NFS root fs, on-board
-  ether port (Need an additional patch at <http://linux.junsun.net>),
+  ether port (Need an additional patch at <http://linux.junsun.net/>),
   USB, AC97, PCI, etc.
 
 Support for MIPS Atlas board
@@ -1953,7 +1942,7 @@
   This is a machine with a R4000 100 MHz CPU. To compile a Linux
   kernel that runs on these, say Y here. For details about Linux on
   the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-  <http://oss.sgi.com/mips>.
+  <http://oss.sgi.com/mips/>.
 
 Enable Qtronix 990P Keyboard Support
 CONFIG_QTRONIX_KEYBOARD
@@ -1965,7 +1954,7 @@
   This is a machine with a R4000 100 MHz CPU. To compile a Linux
   kernel that runs on these, say Y here. For details about Linux on
   the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at
-  <http://oss.sgi.com/mips>.
+  <http://oss.sgi.com/mips/>.
 
 Support for SNI RM200 PCI
 CONFIG_SNI_RM200_PCI
@@ -2072,7 +2061,7 @@
 CONFIG_PCMCIA_NINJA_SCSI
   If you intend to attach this type of PCMCIA SCSI host adapter to
   your computer, say Y here and read
-  <file:Documentation/README.nsp_cs>.
+  <file:Documentation/README.nsp_cs.eng>.
 
   This driver is also available as a module called nsp_cs.o ( =
   code which can be inserted in and removed from the running kernel
@@ -2263,7 +2252,7 @@
   of which are given in <file:Documentation/Changes>.
 
   For a general introduction to Linux networking, it is highly
-  recommended to read the NET-3-HOWTO, available from
+  recommended to read the NET-HOWTO, available from
   <http://www.linuxdoc.org/docs.html#howto>.
 
 Socket filtering
@@ -2658,6 +2647,23 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+Multiple port match support
+CONFIG_IP6_NF_MATCH_MULTIPORT
+  Multiport matching allows you to match TCP or UDP packets based on
+  a series of source or destination ports: normally a rule can only
+  match a single range of ports.
+
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
+Owner match support
+CONFIG_IP6_NF_MATCH_OWNER
+  Packet owner matching allows you to match locally-generated packets
+  based on who created them: the user, group, process or session.
+
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 Packet filtering
 CONFIG_IP6_NF_FILTER
   Packet filtering defines a table `filter', which has a series of
@@ -2724,6 +2730,14 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+LOG target support
+CONFIG_IP6_NF_TARGET_LOG
+  This option adds a `LOG' target, which allows you to create rules in
+  any iptables table which records the packet header to the syslog.
+
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  If unsure, say `N'.
+
 SYN flood protection
 CONFIG_SYN_COOKIES
   Normal TCP/IP networking is open to an attack known as "SYN
@@ -2776,7 +2790,7 @@
 
   To find out what type of Alpha system you have, you may want to
   check out the Linux/Alpha FAQ, accessible on the WWW from
-  <http://www.alphalinux.org>. In summary:
+  <http://www.alphalinux.org/>. In summary:
 
   Alcor/Alpha-XLT     AS 600
   Alpha-XL            XL-233, XL-266
@@ -2961,7 +2975,7 @@
   which is command line driven, and ARC, which uses menus and arrow
   keys. Details about the Linux/Alpha booting process are contained in
   the Linux/Alpha FAQ, accessible on the WWW from
-  <http://www.alphalinux.org>.
+  <http://www.alphalinux.org/>.
 
   The usual way to load Linux on an Alpha machine is to use MILO
   (a bootloader that lets you pass command line parameters to the
@@ -3130,7 +3144,7 @@
 
   The user level application needed to use this driver can be found at
   the IBM Linux Technology Center (LTC) web site:
-  http://www.ibm.com/linux/ltc/
+  <http://www.ibm.com/linux/ltc/>.
 
   If you own one of the above IBM Thinkpads which has the Mwave chipset
   in it, say Y.
@@ -3505,7 +3519,7 @@
   example, used on modern desktops as well as laptops, is USB.
 
   Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
-  software (at <http://linux-hotplug.sourceforge.net>) and install it.
+  software (at <http://linux-hotplug.sourceforge.net/>) and install it.
   Then your kernel will automatically call out to a user mode "policy
   agent" (/sbin/hotplug) to load modules and set up software needed
   to use devices as you hotplug them.
@@ -3547,6 +3561,12 @@
 
   If unsure, say Y.
 
+i82092 compatible bridge support
+CONFIG_I82092
+  This provides support for the Intel I82092AA PCI-to-PCMCIA bridge device,
+  found in some older laptops and more commonly in evaluation boards for the
+  chip.
+
 i82365 compatible host bridge support
 CONFIG_I82365
   Say Y here to include support for ISA-bus PCMCIA host bridges that
@@ -3821,7 +3841,7 @@
 
   The program SVGATextMode can be used to utilize SVGA video cards to
   their full potential in text mode. Download it from
-  <ftp://metalab.unc.edu/pub/Linux/utils/console>.
+  <ftp://ibiblio.org/pub/Linux/utils/console/>.
 
   Say Y.
 
@@ -4053,21 +4073,18 @@
   module will be called aty128fb.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
-# AC tree only
 Maxine (Personal DECstation) onboard framebuffer support
 CONFIG_FB_MAXINE
   Say Y here to directly support the on-board framebuffer in the
   Maxine (5000/20, /25, /33) version of the DECstation.  There is a
   page dedicated to Linux on DECstations at <http://decstation.unix-ag.org/>.
 
-# AC tree only
 PMAG-BA TURBOchannel framebuffer support
 CONFIG_FB_PMAG_BA
   Say Y here to directly support the on-board PMAG-BA framebuffer in
   the 5000/1xx versions of the DECstation.  There is a page dedicated
   to Linux on DECstations at <http://decstation.unix-ag.org/>.
 
-# AC tree only
 PMAGB-B TURBOchannel framebuffer support
 CONFIG_FB_PMAGB_B
   Say Y here to directly support the on-board PMAGB-B framebuffer in
@@ -4079,10 +4096,32 @@
   Say Y here if you intend to run this kernel on a FutureTV (nee Nexus
   Electronics) StrongARM PCI card.
 
-P720T
-CONFIG_ARCH_P720T
-  Say Y here if you intend to run this kernel on the ARM Prospector
-  720T.
+ANAKIN Vehicle Telematics Platform
+CONFIG_ARCH_ANAKIN
+  The Anakin is a StrongArm based SA110 - 2 DIN Vehicle Telematics Platform.
+  64MB SDRAM - 4 Mb Flash - Compact Flash Interface - 1 MB VRAM
+
+  On board peripherals:
+        * Front display: 400x234 16 bit TFT touchscreen
+        * External independent second screen interface
+        * CAN controller SJA1000
+        * USB host controller
+        * 6 channel video codec with hardware overlay
+        * Smartcard reader
+        * IrDa
+
+  Modules interfaced over the Multi Media Extension slots:
+        * A communication card
+                Wavecom GPRS modem
+                uBlock GPS
+                Bosch DAB module
+        * An audio card ( 4 * 40W, AC97 Codec, I2S)
+
+Altera Excalibur XA10 Dev Board
+ARCH_CAMELOT
+  This enables support for Altera's Excalibur XA10 development board.
+  If you would like to build your kernel to run on one of these boards
+  then you must say 'Y' here. Otherwise say 'N'
 
 Link-Up Systems LCD support
 CONFIG_FB_L7200
@@ -4306,10 +4345,8 @@
   a module, say M here and read <file:Documentation/modules.txt>.
 
   You can pass several parameters to the driver at boot time or at
-  module load time. The parameters look like "video=matrox:XXX", where
-  the meaning of XXX can be found at the end of the main source file
-  (<file:drivers/video/matroxfb.c>). Please see
-  <file:Documentation/fb/matroxfb.txt>.
+  module load time. The parameters look like "video=matrox:XXX", and
+  are described in <file:Documentation/fb/matroxfb.txt>.
 
 Matrox Millennium I/II support
 CONFIG_FB_MATROX_MILLENIUM
@@ -4372,7 +4409,7 @@
 
   The driver starts in monitor mode and you must use the matroxset
   tool (available at
-  <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest>) to switch it to
+  <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to switch it to
   PAL or NTSC or to swap primary and secondary head outputs.
   Secondary head driver also always start in 640x480 resolution, you
   must use fbset to change it.
@@ -4394,7 +4431,7 @@
 
   The driver starts in monitor mode and currently does not support
   output in TV modes.  You must use the matroxset tool (available
-  at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest>) to swap
+  at <ftp://platan.vc.cvut.cz/pub/linux/matrox-latest/>) to swap
   primary and secondary head outputs.  Secondary head driver always
   start in 640x480 resolution and you must use fbset to change it.
 
@@ -4509,14 +4546,12 @@
   This is the frame buffer device driver for the SiS 630 and 640 Super
   Socket 7 UMA cards.  Specs available at <http://www.sis.com.tw/>.
 
-# AC tree only
 SIS 630/540/730 support
 CONFIG_FB_SIS_300
   This is the frame buffer device driver for the SiS 630 and related
   Super Socket 7 UMA cards.  Specs available at
   <http://www.sis.com.tw/>.
 
-# AC tree only
 SIS 315H/315 support
 CONFIG_FB_SIS_315
   This is the frame buffer device driver for the SiS 315 graphics
@@ -4570,7 +4605,6 @@
   is at
   <http://support.ati.com/products/pc/mach64/graphics_xpression.html>.
 
-# AC tree only
 ATI Radeon display support
 CONFIG_FB_RADEON
   Choose this option if you want to use an ATI Radeon graphics card as
@@ -4697,7 +4731,8 @@
   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
-  <file:Documentation/parport.txt> and drivers/parport/BUGS-parport.
+  <file:Documentation/parport.txt> and
+  <file: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
@@ -5186,7 +5221,7 @@
   used for local networks of Windows machines.  You need it if you
   want to access Novell NetWare file or print servers using the Linux
   Novell client ncpfs (available from
-  <ftp://metalab.unc.edu/pub/Linux/system/filesystems/>) or from
+  <ftp://platan.vc.cvut.cz/pub/linux/ncpfs/>) or from
   within the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO,
   available from <http://www.linuxdoc.org/docs.html#howto>).  In order
   to do the former, you'll also have to say Y to "NCP file system
@@ -5198,8 +5233,8 @@
 
   To turn your Linux box into a fully featured NetWare file server and
   IPX router, say Y here and fetch either lwared from
-  <ftp://metalab.unc.edu/pub/Linux/system/network/daemons/> or
-  mars_nwe from <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs>. For more
+  <ftp://ibiblio.org/pub/Linux/system/network/daemons/> or
+  mars_nwe from <ftp://www.compu-art.de/mars_nwe/>. For more
   information, read the IPX-HOWTO available from
   <http://www.linuxdoc.org/docs.html#howto>.
 
@@ -5235,7 +5270,7 @@
   'special' sockets to sockets listening on the primary network is
   disabled. This might break existing applications, especially RIP/SAP
   daemons. A RIP/SAP daemon that works well with the full internal net
-  can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs>.
+  can be found on <ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/>.
 
   If you don't know what you are doing, say N.
 
@@ -5303,7 +5338,7 @@
   network link driver", "Routing messages" and "Network packet
   filtering".  The first two are required to allow configuration via
   rtnetlink (currently you need Alexey Kuznetsov's iproute2 package
-  from <ftp://ftp.inr.ac.ru>). The "Network packet filtering" option
+  from <ftp://ftp.inr.ac.ru/>). The "Network packet filtering" option
   will be required for the forthcoming routing daemon to work.
 
   See <file:Documentation/networking/decnet.txt> for more information.
@@ -5424,9 +5459,8 @@
 Amateur Radio support
 CONFIG_HAMRADIO
   If you want to connect your Linux box to an amateur radio, answer Y
-  here. You want to read <http://www.tapr.org/tapr/html/pkthome.html>
-  and the HAM-HOWTO and the AX25-HOWTO, both available from
-  <http://www.linuxdoc.org/docs.html#howto>.
+  here. You want to read <http://www.tapr.org/tapr/html/pkthome.html> and
+  the AX25-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>.
 
   Note that the answer to this question won't directly affect the
   kernel: saying N will just cause the configurator to skip all
@@ -5633,7 +5667,7 @@
   connect to a parallel interface. The driver supports the picpar and
   par96 designs. To configure the driver, use the sethdlc utility
   available in the standard ax25 utilities package. For information on
-  the modems, see <http://www.baycom.de> and the file
+  the modems, see <http://www.baycom.de/> and the file
   <file:Documentation/networking/baycom.txt>.
 
   If you want to compile this driver as a module ( = code which can be
@@ -5647,7 +5681,7 @@
   connect to a parallel interface. The driver supports the EPP
   designs. To configure the driver, use the sethdlc utility available
   in the standard ax25 utilities package. For information on the
-  modems, see <http://www.baycom.de> and the file
+  modems, see <http://www.baycom.de/> and the file
   <file:Documentation/networking/baycom.txt>.
 
   If you want to compile this driver as a module ( = code which can be
@@ -5666,7 +5700,7 @@
   driver and still provided in case this driver does not work with
   your serial interface chip. To configure the driver, use the sethdlc
   utility available in the standard ax25 utilities package. For
-  information on the modems, see <http://www.baycom.de> and
+  information on the modems, see <http://www.baycom.de/> and
   <file:Documentation/networking/baycom.txt>.
 
   If you want to compile this driver as a module ( = code which can be
@@ -5683,7 +5717,7 @@
   the full-duplex driver. This driver is depreciated.  To configure
   the driver, use the sethdlc utility available in the standard ax25
   utilities package. For information on the modems, see
-  <http://www.baycom.de> and
+  <http://www.baycom.de/> and
   <file:Documentation/networking/baycom.txt>.
 
   If you want to compile this driver as a module ( = code which can be
@@ -5860,7 +5894,7 @@
    - etc...
 
   For more informations, please refer to:
-    <http://www.freshmeat.net/projects/etherdivert>
+    <http://diverter.sourceforge.net/>
     <http://perso.wanadoo.fr/magpie/EtherDivert.html>
 
   If unsure, say N.
@@ -5921,8 +5955,7 @@
   user processes.  It does so by creating a new socket family,
   PF_NETLINK.  Over this socket, the kernel can send and receive
   datagrams carrying information.  It is documented on many systems in
-  netlink(7), a HOWTO is provided as well, for example on
-  <http://snafu.freedom.org/linux2.2/docs/netlink-HOWTO.html>.
+  netlink(7).
 
   So far, the kernel uses this feature to publish some network related
   information if you say Y to "Routing messages", below. You also need
@@ -5938,7 +5971,7 @@
 CONFIG_RTNETLINK
   If you say Y here, user space programs can receive some network
   related routing information over the netlink. 'rtmon', supplied
-  with the iproute2 package (<ftp://ftp.inr.ac.ru>), can read and
+  with the iproute2 package (<ftp://ftp.inr.ac.ru/>), can read and
   interpret this data.  Information sent to the kernel over this link
   is ignored.
 
@@ -6225,7 +6258,7 @@
   control memory (128K-1KVC, 512K-4KVC), the size of the packet
   memory (128K, 512K, 1M), and the PHY type (Single/Multi mode OC3,
   UTP155, UTP25, DS3 and E3). Go to:
-  	www.iphase.com/products/ClassSheet.cfm?ClassID=ATM
+  	<http://www.iphase.com/products/ClassSheet.cfm?ClassID=ATM>
   for more info about the cards. Say Y (or M to compile as a module
   named iphase.o) here if you have one of these cards.
 
@@ -6238,7 +6271,7 @@
   messages is controlled by a bitmap. This may be specified as a
   module argument (kernel command line argument as well?), changed
   dynamically using an ioctl (Get the debug utility, iadbg, from
-  <ftp://ftp.iphase.com/pub/atm/pci>).
+  <ftp://ftp.iphase.com/pub/atm/pci/>).
 
   See the file <file:drivers/atm/iphase.h> for the meanings of the
   bits in the mask.
@@ -6490,12 +6523,6 @@
   You also need to say Y here if you want support for the parallel
   port version of the 100 MB IOMEGA ZIP drive.
 
-  Please read the SCSI-HOWTO, available from
-  <http://www.linuxdoc.org/docs.html#howto>. The
-  SCSI-Programming-HOWTO contains information about how to add or
-  remove an SCSI device from a running Linux machine without
-  rebooting.
-
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module will be called scsi_mod.o.  If you want to compile it as
@@ -6573,7 +6600,7 @@
   tape drives (ADR-x0) that supports the standard SCSI-2 commands for
   tapes (QIC-157) and can be driven by the standard driver st.
   For more information, you may have a look at the SCSI-HOWTO
-  <ftp://metalab.unc.edu/pub/Linux/docs/HOWTO>  and
+  <http://www.linuxdoc.org/docs.html#howto>  and
   <file:drivers/scsi/README.osst>  in the kernel source.
   More info on the OnStream driver may be found on
   <http://linux1.onstream.nl/test/>
@@ -6628,12 +6655,12 @@
   directly, so you need some additional software which knows how to
   talk to these devices using the SCSI protocol:
 
-  For scanners, look at SANE (<http://www.mostang.com/sane>). For CD
-  writer software look at cdrecord
+  For scanners, look at SANE (<http://www.mostang.com/sane/>). For CD
+  writer software look at Cdrtools
   (<http://www.fokus.gmd.de/research/cc/glone/employees/joerg.schilling/private/cdrecord.html>)
-  and for burning a "disk at once": cdrdao
-  (<http://www.ping.de/sites/daneb/cdrdao.html>). Cdparanoia is a high
-  quality digital reader of audio CDs (<http://www.xiph.org/paranoia>).
+  and for burning a "disk at once": CDRDAO
+  (<http://cdrdao.sourceforge.net/>). Cdparanoia is a high
+  quality digital reader of audio CDs (<http://www.xiph.org/paranoia/>).
   For other devices, it's possible that you'll have to write the
   driver software yourself. Please read the file
   <file:Documentation/scsi-generic.txt> for more information.
@@ -6644,17 +6671,6 @@
   <file:Documentation/scsi.txt>. The module will be called sg.o. If unsure,
   say N.
 
-Enable extra checks in SCSI queueing code
-CONFIG_SCSI_DEBUG_QUEUES
-  This option turns on a lot of additional consistency checking for
-  the new queueing code. This will adversely affect performance, but
-  it is likely that bugs will be caught sooner if this is turned on.
-  This will typically cause the kernel to panic if an error is
-  detected, but it would have probably crashed if the panic weren't
-  there. Comments/questions/problems to linux-scsi mailing list
-  please. See <http://www.andante.org/scsi_queue.html> for more
-  up-to-date information.
-
 Probe all LUNs on each SCSI device
 CONFIG_SCSI_MULTI_LUN
   If you have a SCSI device that supports more than one LUN (Logical
@@ -6941,10 +6957,10 @@
   This is support for BusLogic MultiMaster and FlashPoint SCSI Host
   Adapters. Consult the SCSI-HOWTO, available from
   <http://www.linuxdoc.org/docs.html#howto>, and the files
-  README.BusLogic and README.FlashPoint in drivers/scsi for more
-  information. If this driver does not work correctly without
-  modification, please contact the author, Leonard N. Zubkoff, by
-  email to lnz@dandelion.com.
+  <file:drivers/scsi/README.BusLogic> and
+  <file:drivers/scsi/README.FlashPoint> for more information. If this
+  driver does not work correctly without modification, please contact
+  the author, Leonard N. Zubkoff, by email to lnz@dandelion.com.
 
   You can also build this driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -7186,7 +7202,7 @@
   If your system has problems using this new major version of the
   SYM53C8XX driver, you may switch back to driver version 1.
 
-  Please read drivers/scsi/sym53c8xx_2/Documentation.txt for more
+  Please read <file:drivers/scsi/sym53c8xx_2/Documentation.txt> for more
   information.
 
 PCI DMA addressing mode
@@ -7727,7 +7743,7 @@
 NCR53c406a SCSI support
 CONFIG_SCSI_NCR53C406A
   This is support for the NCR53c406a SCSI host adapter.  For user
-  configurable parameters, check out <file:drivers/scsi/NCR53c406.c>
+  configurable parameters, check out <file:drivers/scsi/NCR53c406a.c>
   in the kernel source.  Also read the SCSI-HOWTO, available from
   <http://www.linuxdoc.org/docs.html#howto>.
 
@@ -7839,7 +7855,8 @@
  
   This is a driver for RAID/SCSI Disk Array Controllers (EISA/ISA/PCI) 
   manufactured by Intel/ICP vortex (an Intel Company). It is documented
-  in the kernel source in drivers/scsi/gdth.c and drivers/scsi/gdth.h. 
+  in the kernel source in <file:drivers/scsi/gdth.c> and
+  <file:drivers/scsi/gdth.h.>
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -8252,8 +8269,8 @@
 
   Normally, your access provider has to support SLIP in order for you
   to be able to use it, but there is now a SLIP emulator called SLiRP
-  around (available via FTP (user: anonymous) from
-  <ftp://metalab.unc.edu/pub/Linux/system/network/serial/>) which
+  around (available from
+  <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
   allows you to use SLIP over a regular dial up shell connection. If
   you plan to use SLiRP, make sure to say Y to CSLIP, below. The
   NET-3-HOWTO, available from
@@ -8278,7 +8295,7 @@
   on both ends. Ask your access provider if you are not sure and
   answer Y, just in case. You will still be able to use plain SLIP. If
   you plan to use SLiRP, the SLIP emulator (available from
-  <ftp://metalab.unc.edu/pub/Linux/system/network/serial/>) which
+  <ftp://ibiblio.org/pub/Linux/system/network/serial/>) which
   allows you to use SLIP over a regular dial up shell connection, you
   definitely want to say Y here. The NET-3-HOWTO, available from
   <http://www.linuxdoc.org/docs.html#howto>, explains how to configure
@@ -8415,7 +8432,7 @@
 
   This driver requires a specially patched pppd daemon.  The patch to
   pppd, along with binaries of a patched pppd package can be found at:
-  <http://www.shoshin.uwaterloo.ca/~mostrows>.
+  <http://www.shoshin.uwaterloo.ca/~mostrows/>.
 
 Wireless LAN (non-hamradio)
 CONFIG_NET_RADIO
@@ -8437,7 +8454,7 @@
 
   Some user-level drivers for scarab devices which don't require
   special kernel support are available from
-  <ftp://shadow.cabi.net/pub/Linux>.
+  <ftp://shadow.cabi.net/pub/Linux/>.
 
 STRIP (Metricom Starmode radio IP)
 CONFIG_STRIP
@@ -8783,12 +8800,6 @@
   configure your card and that /etc/pcmcia/wireless.opts works :
   <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
 
-Apple Airport support (built-in)
-CONFIG_APPLE_AIRPORT
-  Enable support for the Apple Airport card (which is essentially a
-  Lucent Orinoco card with a non-standard interface) built into some
-  newer Apple Macintosh machines.
-
 Hermes 802.11b in PLX9052 based PCI adaptor support
 CONFIG_PLX_HERMES
   Enable support for PCMCIA cards supported by the "Hermes" (aka
@@ -8870,7 +8881,8 @@
 CONFIG_APPLE_AIRPORT
   Say Y here to support the Airport 802.11b wireless Ethernet hardware
   built into the Macintosh iBook and other recent PowerPC-based
-  Macintosh machines.
+  Macintosh machines. This is essentially a Lucent Orinoco card with 
+  a non-standard interface
 
 Xircom Netwave AirSurfer wireless support
 CONFIG_PCMCIA_NETWAVE
@@ -9118,7 +9130,7 @@
   the price of an external router.  If you have one of those cards and
   wish to use your Linux box as a WAN router, say Y here and also to
   the WAN driver for your card, below.  You will then need the
-  wan-tools package which is available from <ftp://ftp.sangoma.com>.
+  wan-tools package which is available from <ftp://ftp.sangoma.com/>.
   Read <file:Documentation/networking/wan-router.txt> for more
   information.
 
@@ -9500,7 +9512,7 @@
   up. Look at the <http://www.fi.muni.cz/~kas/cosa/> for more
   information about the cards (including the pointer to the user-space
   utilities). You can also read the comment at the top of the
-  <file:drivers/net/cosa.c> for details about the cards and the driver
+  <file:drivers/net/wan/cosa.c> for details about the cards and the driver
   itself.
 
   The driver will be compiled as a module ( = code which can be
@@ -9512,7 +9524,7 @@
 CONFIG_DSCC4
   This is a driver for Etinc PCISYNC boards based on the Infineon
   (ex. Siemens) DSCC4 chipset. It is supposed to work with the four
-  ports card. Take a look at <http://www.cogenit.fr/dscc4>
+  ports card. Take a look at <http://www.cogenit.fr/dscc4/>
   for further informations about the driver and his configuration.
 
   The driver will be compiled as a module ( = code which can be
@@ -9539,7 +9551,7 @@
   additional external hardware.
 
   To change setting such as syncPPP vs cisco HDLC or clock source you
-  will need lmcctl.  It is available at <ftp://ftp.lanmedia.com>.
+  will need lmcctl.  It is available at <ftp://ftp.lanmedia.com/>.
 
   This code is also available as a module called lmc.o ( = code
   which can be inserted in and removed from the running kernel
@@ -9584,7 +9596,7 @@
   module will be called sbni.o).
 
   You can find more information and last versions of drivers and
-  utilities at <http://www.granch.ru>. If you have any question you
+  utilities at <http://www.granch.ru/>. If you have any question you
   can send email to sbni@granch.ru.
 
   Say N if unsure.
@@ -9607,7 +9619,7 @@
   Router".
 
   You will need the wan-tools package which is available from
-  <ftp://ftp.sangoma.com>. Read
+  <ftp://ftp.sangoma.com/>. Read
   <file:Documentation/networking/wan-router.txt> for more information.
 
   Note that the answer to this question won't directly affect the
@@ -9616,7 +9628,7 @@
 
 Sangoma WANPIPE(tm) multiprotocol cards
 CONFIG_VENDOR_SANGOMA
-  WANPIPE from Sangoma Technologies Inc. (<http://www.sangoma.com>)
+  WANPIPE from Sangoma Technologies Inc. (<http://www.sangoma.com/>)
   is a family of intelligent multiprotocol WAN adapters with data
   transfer rates up to 4Mbps. They are also known as Synchronous
   Data Link Adapters (SDLA) and are designated as S514-PCI or
@@ -9704,7 +9716,7 @@
 
   Read <file:Documentation/networking/comx.txt> for help on
   configuring and using COMX interfaces.  Further info on these cards
-  can be found at <http://www.itc.hu> or <info@itc.hu>.
+  can be found at <http://www.itc.hu/> or <info@itc.hu>.
 
   You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
   use this driver.
@@ -9798,8 +9810,8 @@
 
 Cyclom 2X(tm) multiprotocol cards
 CONFIG_CYCLADES_SYNC
-  Cyclom 2X from Cyclades Corporation (<http://www.cyclades.com> and
-  <http://www.cyclades.com.br)> is an intelligent multiprotocol WAN
+  Cyclom 2X from Cyclades Corporation (<http://www.cyclades.com/> and
+  <http://www.cyclades.com.br/>) is an intelligent multiprotocol WAN
   adapter with data transfer rates up to 512 Kbps. These cards support
   the X.25 and SNA related protocols. If you have one or more of these
   cards, say Y to this option. The next questions will ask you about
@@ -9808,10 +9820,10 @@
 
   While no documentation is available at this time please grab the
   wanconfig tarball in
-  <http://www.conectiva.com.br/~acme/cycsyn-devel> (with minor changes
+  <http://www.conectiva.com.br/~acme/cycsyn-devel/> (with minor changes
   to make it compile with the current wanrouter include files; efforts
   are being made to use the original package available at
-  <ftp://ftp.sangoma.com>).
+  <ftp://ftp.sangoma.com/>).
 
   Feel free to contact me or the cycsyn-devel mailing list at
   acme@conectiva.com.br and cycsyn-devel@bazar.conectiva.com.br for
@@ -10288,15 +10300,7 @@
   is a 10Mbit/sec Ethernet controller.  Product overview and specs at
   <http://www.national.com/pf/DP/DP83902A.html>.
 
-CompactFlash Connection Area
-CONFIG_CF_AREA5
-  If your board has "Directly Connected" CompactFlash, You should
-  select the area where your CF is connected to.
-
-  - "Area5" if CompactFlash is connected to Area 5 (0x14000000)
-  - "Area6" if it is connected to Area 6 (0x18000000)
-
-  "Area6" will work for most boards. For ADX, select "Area5".
+  If unsure, say N.
 
 3COM cards
 CONFIG_NET_VENDOR_3COM
@@ -10643,7 +10647,7 @@
   module, say M here and read <file:Documentation/modules.txt> as well
   as <file:Documentation/networking/net-modules.txt>.
 
-EtherExpressPro support/EtherExpress 10 (i82595) support
+EtherExpressPro and EtherExpress 10 (i82595) support
 CONFIG_EEXPRESS_PRO
   If you have a network (Ethernet) card of this type, say Y. This
   driver supports intel i82595{FX,TX} based boards. Note however
@@ -10787,10 +10791,7 @@
   driver and as a module ( = code which can be inserted in and removed
   from the running kernel whenever you want).  If you want to compile
   it as a module, say M here and read <file:Documentation/modules.txt>
-  as well as <file:Documentation/networking/net-modules.txt>.
-  If you plan to use more than one network card under linux, read the
-  Multiple-Ethernet-mini-HOWTO, available from
-  <ftp://sunsite.unc.edu:/pub/Linux/docs/HOWTO/mini>.  The only
+  as well as <file:Documentation/networking/net-modules.txt>. The only
   currently supported card is the IBM LAN Adapter/A for Ethernet.  It
   will both support 16K and 32K memory windows, however a 32K window
   gives a better security against packet losses.  Usage of multiple
@@ -10957,7 +10958,7 @@
 CONFIG_FEALNX
   Say Y here to support the Mysom MTD-800 family of PCI-based Ethernet
   cards. Specifications and data at
-  <http:www.myson.com.hk/mtd/datasheet>.
+  <http://www.myson.com.hk/mtd/datasheet/>.
 
 ICL EtherTeam 16i/32 support
 CONFIG_ETH16I
@@ -11004,7 +11005,7 @@
 Davicom DM910x/DM980x support
 CONFIG_DM9102
   This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
-  Davicom (<http://www.davicom.com.tw>).  If you have such a network
+  Davicom (<http://www.davicom.com.tw/>).  If you have such a network
   (Ethernet) card, say Y.  Some information is contained in the file
   <file:Documentation/networking/dmfe.txt>.
 
@@ -11189,8 +11190,7 @@
   Wake On Lan, and PCI 100/16/4 adapters.
 
   If you have such an adapter, say Y and read the Token-Ring
-  mini-HOWTO, available from
-  <http://www.linuxdoc.org/docs.html#howto>.
+  mini-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -11199,15 +11199,14 @@
 
   Also read <file:Documentation/networking/olympic.txt> or check the
   Linux Token Ring Project site for the latest information at
-  <http://www.linuxtr.net>.
+  <http://www.linuxtr.net/>.
 
 IBM Lanstreamer chipset PCI adapter support
 CONFIG_IBMLS
   This is support for IBM Lanstreamer PCI Token Ring Cards.
 
   If you have such an adapter, say Y and read the Token-Ring
-  mini-HOWTO available via FTP (user:anonymous) from
-  <ftp://metalab.unc/edu/pub/Linux/docs/HOWTO>.
+  mini-HOWTO, available from <http://www.linuxdoc.org/docs.html#howto>.
 
   This driver is also available as a modules ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -11358,7 +11357,7 @@
   say Y to "QoS and/or fair queueing" above.
 
   To set up and configure shaper devices, you need the shapecfg
-  program, available from <ftp://shadow.cabi.net/pub/Linux> in the
+  program, available from <ftp://shadow.cabi.net/pub/Linux/> in the
   shaper package.
 
   This driver is also available as a module ( = code which can be
@@ -11619,7 +11618,7 @@
   Say Y here only if you have two CD-ROM controller cards of this type
   (usually only if you have more than four drives).  You should enter
   the parameters for the second, third and fourth interface card into
-  <file:include/linux/sbpcd.h> before compiling the new kernel.  Read
+  <file:drivers/cdrom/sbpcd.h> before compiling the new kernel.  Read
   the file <file:Documentation/cdrom/sbpcd>.
 
 Matsushita/Panasonic, ... third CD-ROM controller support
@@ -12394,6 +12393,100 @@
   NVRAM on the Momenco Ocelot board.  If you have one of these boards
   and would like access to either of these, say 'Y'.
 
+Support for absent chips in bus mapping
+CONFIG_MTD_ABSENT
+  This option enables support for a dummy probing driver used to
+  allocated placeholder MTD devices on systems that have socketed
+  or removable media.  Use of this driver as a fallback chip probe
+  preserves the expected registration order of MTD device nodes on
+  the system regardless of media presence.  Device nodes created
+  with this driver will return -ENODEV upon access.
+
+MTD Emulation using block device
+CONFIG_MTD_BLKMTD
+  This driver allows a block device to appear as an MTD. It would
+  generally be used in the following cases:
+
+    Using Compact Flash as an MTD, these usually present themselves to
+    the system as an ATA drive.
+    Testing MTD users (eg JFFS2) on large media and media that might
+    be removed during a write (using the floppy drive).
+
+Cirrus CDB89712 evaluation board mappings
+CONFIG_MTD_CDB89712
+  This enables access to the flash or ROM chips on the CDB89712 board.
+  If you have such a board, say 'Y'.
+
+Detect non-CFI AMD/JEDEC-compatible flash chips
+CONFIG_MTD_JEDECPROBE
+  This option enables JEDEC-style probing of flash chips which are not
+  compatible with the Common Flash Interface, but will use the common
+  CFI-targetted flash drivers for any chips which are identified which
+  are in fact compatible in all but the probe method. This actually
+  covers most AMD/Fujitsu-compatible chips, and will shortly cover also
+  non-CFI Intel chips (that code is in MTD CVS and should shortly be sent
+  for inclusion in Linus' tree)
+
+BIOS flash chip on Intel L440GX boards
+CONFIG_MTD_L440GX
+  Support for treating the BIOS flash chip on Intel L440GX motherboards
+  as an MTD device - with this you can reprogram your BIOS.
+
+  BE VERY CAREFUL.
+
+28F160xx flash driver for LART
+CONFIG_MTD_LART
+  This enables the flash driver for LART. Please note that you do
+  not need any mapping/chip driver for LART. This one does it all
+  for you, so go disable all of those if you enabled some of them (:
+
+Older (theoretically obsoleted now) drivers for non-CFI chips
+CONFIG_MTD_OBSOLETE_CHIPS
+  This option does not enable any code directly, but will allow you to
+  select some other chip drivers which are now considered obsolete,
+  because the generic CONFIG_JEDEC_PROBE code above should now detect
+  the chips which are supported by these drivers, and allow the generic
+  CFI-compatible drivers to drive the chips. Say 'N' here unless you have
+  already tried the CONFIG_JEDEC_PROBE method and reported its failure
+  to the MTD mailing list at <linux-mtd@lists.infradead.org>
+
+CFI Flash device mapped on Hitachi SolutionEngine
+CONFIG_MTD_SOLUTIONENGINE
+  This enables access to the flash chips on the Hitachi SolutionEngine and
+  similar boards. Say 'Y' if you are building a kernel for such a board.
+
+Flash chip mapping on TQM8xxL PPC board
+CONFIG_MTD_TQM8XXL
+  The TQM8xxL PowerPC board has up to two banks of CFI-compliant
+  chips, currently uses AMD one. This 'mapping' driver supports
+  that arrangement, allowing the CFI probe and command set driver
+  code to communicate with the chips on the TQM8xxL board. More at
+  <http://www.denx.de/embedded-ppc-en.html>.
+
+Darkness
+CONFIG_MEMORY_SET
+  This is an option about which you will never be asked a question.
+  Therefore, I conclude that you do not exist - go away.
+
+  There is a grue here.
+
+Physical memory size
+CONFIG_MEMORY_SIZE
+  This sets the default memory size assumed by your SH kernel. It can
+  be overridden as normal by the 'mem=' argument on the kernel command
+  line. If unsure, consult your board specifications or just leave it
+  as 0x00400000 which was the default value before this became
+  configurable.
+
+Cache and PCI noncoherent
+CONFIG_SH_PCIDMA_NONCOHERENT
+  Enable this option if your platform does not have a CPU cache which
+  remains coherent with PCI DMA. It is safest to say 'Y', although you
+  will see better performance if you can say 'N', because the PCI DMA
+  code will not have to flush the CPU's caches. If you have a PCI host
+  bridge integrated with your SH CPU, refer carefully to the chip specs
+  to see if you can say 'N' here. Otherwise, leave it as 'Y'.
+
 USB (Universal Serial Bus) support
 CONFIG_USB
   Universal Serial Bus (USB) is a specification for a serial bus
@@ -12579,7 +12672,7 @@
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
   The module will be called aiptek.o. If you want to compile it as a
-  module, say M here and read Documentation/modules.txt.
+  module, say M here and read <file:Documentation/modules.txt>.
 
 Use input layer for ADB devices
 CONFIG_INPUT_ADBHID
@@ -12740,7 +12833,7 @@
 CONFIG_USB_SERIAL_VISOR
   Say Y here if you want to connect to your HandSpring Visor, Palm
   m500 or m505 through its USB docking station. See
-  <http://usbvisor.sourceforge.net> for more information on using this
+  <http://usbvisor.sourceforge.net/> for more information on using this
   driver.
 
   This code is also available as a module ( = code which can be
@@ -12759,6 +12852,17 @@
   The module will be called ir-usb.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
+USB IR Dongle Serial Driver
+CONFIG_USB_SERIAL_IR
+  Say Y here if you want to enable simple serial support for USB IrDA
+  devices.  This is useful if you do not want to use the full IrDA
+  stack.
+  
+  This code is also available as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want).
+  The module will be called ir-usb.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
 USB Belkin and Paracom Single Port Serial Driver
 CONFIG_USB_SERIAL_BELKIN
   Say Y here if you want to use a Belkin USB Serial single port
@@ -12776,7 +12880,7 @@
   converter device. The implementation I have is called the USC-1000.
   This driver has also be tested with the 245 and 232 devices.
 
-  See  http://ftdi-usb-sio.sourceforge.net for more
+  See <http://ftdi-usb-sio.sourceforge.net/> for more
   information on this driver and the device.
 
   This code is also available as a module ( = code which can be
@@ -13013,7 +13117,7 @@
   This driver supports devices conforming to the Communication Device
   Class Ethernet Control Model.  This is used in some cable modems.
   For more details on the specification, get the Communication Device
-  Class specification from <http://www.usb.org>.
+  Class specification from <http://www.usb.org/>.
 
   This driver should work with the following devices:
         * Ericsson PipeRider (all variants)
@@ -13140,7 +13244,7 @@
   Say Y here if you want to connect this type of still camera to your
   computer's USB port.  See <file:Documentation/usb/dc2xx.txt> for
   more information; some non-Kodak cameras may also work with this
-  driver, given application support (such as <http://www.gPhoto.org>).
+  driver, given application support (such as <http://www.gphoto.org/>).
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -13151,7 +13255,7 @@
 CONFIG_USB_MDC800
   Say Y here if you want to connect this type of still camera to
   your computer's USB port. This driver can be used with gphoto 0.4.3
-  and higher (look at <http://www.gphoto.org>).
+  and higher (look at <http://www.gphoto.org/>).
   To use it create a device node with "mknod /dev/mustek c 180 32" and
   configure it in your software.
 
@@ -13255,7 +13359,7 @@
 DABUSB driver
 CONFIG_USB_DABUSB
   A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
-  brought to you by the DAB-Team (<http://dab.in.tum.de>).  This
+  brought to you by the DAB-Team (<http://dab.in.tum.de/>).  This
   driver can be taken as an example for URB-based bulk, control, and
   isochronous transactions. URB's are explained in
   <file:Documentation/usb/URB.txt>.
@@ -13493,7 +13597,7 @@
   running UML to exchange packets with its host over one of the
   host's Ethertap devices, such as /dev/tap0.  Additional running
   UMLs can use additional Ethertap devices, one per running UML.
-  While the UML believes its on a (multi-device, broadcast) virtual
+  While the UML believes it's on a (multi-device, broadcast) virtual
   Ethernet network, it's in fact communicating over a point-to-point
   link with the host.
 
@@ -13588,7 +13692,7 @@
 CONFIG_USB_BLUETOOTH
   Say Y here if you want to connect a USB Bluetooth device to your
   computer's USB port. You will need the Bluetooth stack (available
-  at <http://developer.axis.com/software/index.shtml)> to fully use
+  at <http://developer.axis.com/software/index.shtml>) to fully use
   the device.
 
   This code is also available as a module ( = code which can be
@@ -13624,7 +13728,7 @@
 
   In general, ReiserFS is as fast as ext2, but is very efficient with
   large directories and small files.  Additional patches are needed
-  for NFS and quotas, please see <http://www.reiserfs.org> for links.
+  for NFS and quotas, please see <http://www.reiserfs.org/> for links.
 
   It is more easily extended to have features currently found in
   database and keyword search systems than block allocation based file
@@ -13632,7 +13736,7 @@
   plugins consistent with our motto ``It takes more than a license to
   make source code open.''
 
-  Read <http://www.reiserfs.org> to learn more about reiserfs.
+  Read <http://www.reiserfs.org/> to learn more about reiserfs.
 
   Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com.
 
@@ -13660,15 +13764,6 @@
   everyone but ReiserFS developers and people fine-tuning reiserfs or
   tracing problems should say N.
 
-Publish some reiserfs-specific info under /proc/fs/reiserfs
-CONFIG_REISERFS_PROC_INFO
-  Create under /proc/fs/reiserfs hierarchy of files, displaying
-  various ReiserFS statistics and internal data on the expense of
-  making your kernel or module slightly larger (+8K). This also increases 
-  amount of kernel memory required for each mount. Almost everyone
-  but ReiserFS developers and people fine-tuning reiserfs or tracing
-  problems should say NO.
-
 Second extended fs support
 CONFIG_EXT2_FS
   This is the de facto standard Linux file system (method to organize
@@ -13698,10 +13793,10 @@
   directories on ext2 file systems, use chattr ("man chattr").
 
   Ext2fs partitions can be read from within DOS using the ext2tool
-  command line tool package (available via FTP (user: anonymous) from
-  <ftp://metalab.unc.edu/pub/Linux/system/filesystems/ext2>) and from
+  command line tool package (available from
+  <ftp://ibiblio.org/pub/Linux/system/filesystems/ext2/>) and from
   within Windows NT using the ext2nt command line tool package from
-  <ftp://metalab.unc.edu/pub/Linux/utils/dos>.  Explore2fs is a
+  <ftp://ibiblio.org/pub/Linux/utils/dos/>.  Explore2fs is a
   graphical explorer for ext2fs partitions which runs on Windows 95
   and Windows NT and includes experimental write support; it is
   available from
@@ -13901,7 +13996,7 @@
   which allows for long filenames in unicode format (unicode is the
   new 16 bit character code, successor to ASCII, which encodes the
   characters of almost all languages of the world; see
-  <http://www.unicode.org> for more information).  Say Y here if you
+  <http://www.unicode.org/> for more information).  Say Y here if you
   want to be able to read Joliet CD-ROMs under Linux.
 
 Transparent decompression extension
@@ -13986,7 +14081,7 @@
   Linux, you can either use the DOS emulator DOSEMU, described in the
   DOSEMU-HOWTO, available from
   <http://www.linuxdoc.org/docs.html#howto>, or try dmsdosfs in
-  <ftp://metalab.unc.edu/pub/Linux/system/filesystems/dosfs>. If you
+  <ftp://ibiblio.org/pub/Linux/system/filesystems/dosfs/>. If you
   intend to use dosemu with a non-compressed MSDOS partition, say Y
   here) and MSDOS floppies. This means that file access becomes
   transparent, i.e. the MSDOS files look and behave just like all
@@ -14161,8 +14256,9 @@
   level IP autoconfiguration" above and to "Root file system on NFS"
   below. You cannot compile this driver as a module in this case.
   There are two packages designed for booting diskless machines over
-  the net: netboot and etherboot, both available via FTP from
-  <ftp://metalab.unc.edu/pub/Linux/system/boot/Ethernet/>.
+  the net: netboot, available from
+  <http://ftp1.sourceforge.net/netboot/>, and Etherboot,
+  available from <http://ftp1.sourceforge.net/etherboot/>.
 
   If you don't know what all this is about, say N.
 
@@ -14285,7 +14381,7 @@
   a set of kernel modules that lets you run SCO, Xenix, Wyse,
   UnixWare, Dell Unix and System V programs under Linux.  It is
   available via FTP (user: ftp) from
-  <ftp://ftp.openlinux.org/pub/people/hch/linux-abi>).
+  <ftp://ftp.openlinux.org/pub/people/hch/linux-abi/>).
   NOTE: that will work only for binaries from Intel-based systems;
   PDP ones will have to wait until somebody ports Linux to -11 ;-)
 
@@ -14414,7 +14510,7 @@
   automounter (amd), which is a pure user space daemon.
 
   To use the automounter you need the user-space tools from
-  <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4>; you also
+  <ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4/>; you also
   want to answer Y to "NFS file system support", below.
 
   If you want to compile this as a module ( = code which can be
@@ -14478,6 +14574,11 @@
   If reporting bugs, please try to have available a full dump of the
   messages at debug level 1 while the misbehaviour was occurring.
 
+JFFS stats available in /proc filesystem
+CONFIG_JFFS_PROC_FS
+  Enabling this option will cause statistics from mounted JFFS file systems
+  to be made available to the user in the /proc/fs/jffs/ directory.
+
 UFS file system support (read-only)
 CONFIG_UFS_FS
   BSD and derivate versions of Unix (such as SunOS, FreeBSD, NetBSD,
@@ -14578,7 +14679,7 @@
   XP.
 
   Technical documentation to accompany this driver is available from:
-  <http://linux-ntfs.sf.net/ldm>.
+  <http://linux-ntfs.sf.net/ldm/>.
 
   If unsure, say N.
 
@@ -14706,7 +14807,6 @@
   Note that the experimental "/dev file system support"
   (CONFIG_DEVFS_FS)  is a more general facility.
 
-# This is for Linus's tree
 FreeVxFS file system support (VERITAS VxFS(TM) compatible)
 CONFIG_VXFS_FS
   FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
@@ -14725,25 +14825,6 @@
   module, say M here and read <file:Documentation/modules.txt>.  If
   unsure, say N. 
 
-# This is for Alan's tree.  Note the name difference.
-FreeVxFS file system support (VERITAS VxFS(TM) compatible)
-CONFIG_FREEVXFS_FS
-  FreeVxFS is a file system driver that support the VERITAS VxFS(TM)
-  file system format.  VERITAS VxFS(TM) is the standard file system
-  of SCO UnixWare (and possibly others) and optionally available
-  for Sunsoft Solaris, HP-UX and many other operating systems.
-  Currently only readonly access is supported.
-
-  NOTE: the file system type as used by mount(1), mount(2) and
-        fstab(5) is 'vxfs' as it describes the filesystem format, not
-        the actual driver.
-
-  This file system is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module is called freevxfs.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.  If
-  unsure, say N.
-
 UnixWare slices support
 CONFIG_UNIXWARE_DISKLABEL
   Like some systems, UnixWare uses its own slice table inside a
@@ -14777,8 +14858,8 @@
   Note: if you just want your box to act as an SMB *server* and make
   files and printing services available to Windows clients (which need
   to have a TCP/IP stack), you don't need to say Y here; you can use
-  the program samba (available via FTP (user: anonymous) in
-  <ftp://metalab.unc.edu/pub/Linux/system/network/samba>) for that.
+  the program SAMBA (available from <ftp://ftp.samba.org/pub/samba/>)
+  for that.
 
   General information about how to connect Linux, Windows machines and
   Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
@@ -14827,7 +14908,7 @@
   client and server.  Servers are currently user level, i.e. they need
   no kernel support.  Please read
   <file:Documentation/filesystems/coda.txt> and check out the Coda
-  home page <http://www.coda.cs.cmu.edu>.
+  home page <http://www.coda.cs.cmu.edu/>.
 
   If you want to compile the coda client support as a module ( = code
   which can be inserted in and removed from the running kernel
@@ -14843,7 +14924,7 @@
 
   If you say Y or M your kernel or module will provide InterMezzo
   support.  You will also need a file server daemon, which you can get
-  from <http://www.inter-mezzo.org>.
+  from <http://www.inter-mezzo.org/>.
 
 NCP file system support (to mount NetWare volumes)
 CONFIG_NCP_FS
@@ -15495,7 +15576,7 @@
 CONFIG_ADB_IOP
   The I/O Processor (IOP) is an Apple custom IC designed to provide
   intelligent support for I/O controllers.  It is described at
-  <http://www.angelfire.com/ca2/dev68k/iopdesc.html;> to enable direct
+  <http://www.angelfire.com/ca2/dev68k/iopdesc.html> to enable direct
   support for it, say 'Y' here.
 
 Mac II style Apple Desktop Bus support
@@ -16204,9 +16285,7 @@
   Say Y here if your machine has a bus mouse as opposed to a serial
   mouse. Most people have a regular serial MouseSystem or
   Microsoft mouse (made by Logitech) that plugs into a COM port
-  (rectangular with 9 or 25 pins). These people say N here. If you
-  have something else, read the Busmouse-HOWTO, available from
-  <http://www.linuxdoc.org/docs.html#howto>, and say Y here.
+  (rectangular with 9 or 25 pins). These people say N here. 
 
   If you have a laptop, you either have to check the documentation or
   experiment a bit to find out whether the trackball is a serial mouse
@@ -16271,8 +16350,8 @@
   When using a PS/2 mouse, you can get problems if you want to use the
   mouse both on the Linux console and under X. Using the "-R" option
   of the Linux mouse managing program gpm (available from
-  <ftp://metalab.unc.edu/pub/Linux/system/mouse>) solves this
-  problem, or you can get the "mconv2" utility from the same location.
+  <ftp://gnu.systemy.it/pub/gpm/>) solves this problem, or you can get
+  the "mconv2" utility from <ftp://ibiblio.org/pub/Linux/system/mouse/>.
 
 C&T 82C710 mouse port support (as on TI Travelmate)
 CONFIG_82C710_MOUSE
@@ -16391,7 +16470,7 @@
   Note that the Ftape-HOWTO is out of date (sorry) and documents the
   older version 2.08 of this software but still contains useful
   information.  There is a web page with more recent documentation at
-  <http://www.math1.rwth-aachen.de/~heine/ftape/>.  This page
+  <http://www.instmath.rwth-aachen.de/~heine/ftape/>.  This page
   always contains the latest release of the ftape driver and useful
   information (backup software, ftape related patches and
   documentation, FAQ).  Note that the file system interface has
@@ -16427,7 +16506,7 @@
   file <file:Documentation/ftape.txt> contains a short description of
   the most important changes in the file system interface compared to
   previous versions of ftape.  The ftape home page
-  <http://www-math.math.rwth-aachen.de/~LBFM/claus/ftape/> contains
+  <http://www.instmath.rwth-aachen.de/~heine/ftape/> contains
   further information.
 
   IMPORTANT NOTE: zftape can read archives created by previous
@@ -16670,7 +16749,7 @@
   introduced in XFree86 4.0. If you say Y here, you need to select
   the module that's right for your graphics card from the list below.
   These modules provide support for synchronization, security, and
-  DMA transfers. Please see <http://dri.sourceforge.net> for more
+  DMA transfers. Please see <http://dri.sourceforge.net/> for more
   details.  You should also select and configure AGP
   (/dev/agpgart) support.
 
@@ -16925,8 +17004,8 @@
   can be downloaded from:
   <http://developer.intel.com/technology/iapc/acpi/downloads.htm>.
 
-  The ACPI mailing list may also be of interest:
-  <http://phobos.fs.tum.de/acpi/index.html>.
+  The ACPI Sourceforge project may also be of interest:
+  <http://sf.net/projects/acpi/>
 
 Enable ACPI 2.0 with errata 1.3
 CONFIG_ACPI20
@@ -17136,9 +17215,9 @@
   in the kernel source.
 
   The watchdog is usually used together with the watchdog daemon
-  which is available via FTP (user: anonymous) from
-  <ftp://tsx-11.mit.edu/pub/linux/sources/sbin/>. This daemon can also
-  monitor NFS connections and can reboot the machine when the process
+  which is available from
+  <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
+  also monitor NFS connections and can reboot the machine when the process
   table is full.
 
   If unsure, say N.
@@ -17212,7 +17291,7 @@
   and if it does, it reboots your computer after a certain amount of
   time. This driver is like the WDT501 driver but for different
   hardware. Please read <file:Documentation/pcwd-watchdog.txt>. The PC
-  watchdog cards can be ordered from <http://www.berkprod.com>.
+  watchdog cards can be ordered from <http://www.berkprod.com/>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17446,7 +17525,6 @@
   The module will be called nvram.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
-# Linus tree only
 Joystick support
 CONFIG_JOYSTICK
   If you have a joystick, 6dof controller, gamepad, steering wheel,
@@ -17454,18 +17532,17 @@
   enable generic support for these controllers. You will also need to
   say Y or M to at least one of the hardware specific drivers. This
   will make the controllers available as /dev/input/jsX devices.
-  Please read the file <file:Documentation/joystick.txt> which
+  Please read the file <file:Documentation/input/joystick.txt> which
   contains more information and the location of the joystick package
   that you'll need.
 
-# AC tree only
 Game port support
 CONFIG_INPUT_GAMEPORT
   Gameport support is for the standard 15-pin PC gameport.  If you
   have a joystick, gamepad, gameport card, a soundcard with a gameport
   or anything else that uses the gameport, say Y or M here and also to
   at least one of the hardware specific drivers.
-  Please read the file <file:Documentation/joystick.txt> which
+  Please read the file <file:Documentation/input/joystick.txt> which
   contains more information and the location of the joystick package
   that you'll need if you use the gameport with a joystick.
 
@@ -17478,7 +17555,7 @@
 CONFIG_INPUT_NS558
   Say Y here if you have an ISA or PnP gameport.
   For more information on how to use the driver please read
-  <file:Documentation/joystick.txt>.
+  <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17489,7 +17566,7 @@
 CONFIG_INPUT_LIGHTNING
   Say Y here if you have a PDPI Lightning 4 gamecard. For more
   information on how to use the driver please read
-  <file:Documentation/joystick.txt>.
+  <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17511,7 +17588,7 @@
 CONFIG_INPUT_PCIGAME
   Say Y here if you have a Trident 4DWave DX/NX or Aureal Vortex 1/2
   card. For more information on how to use the driver please read
-  <file:Documentation/joystick.txt>.
+  <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17522,7 +17599,7 @@
 CONFIG_INPUT_EMU10K1
   Say Y here if you have a SoundBlaster Live! card and want to use
   its gameport.  For more information on how to use the driver
-  please read <file:Documentation/joystick.txt>.
+  please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17537,7 +17614,7 @@
   additional hats and buttons compatible with CH Flightstick Pro,
   ThrustMaster FCS, 6 and 8 button gamepads, or Saitek Cyborg
   joysticks.  For more information on how to use the driver please
-  read <file:Documentation/joystick.txt>.
+  read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17548,7 +17625,7 @@
 CONFIG_INPUT_A3D
   Say Y here if you have an FPGaming or MadCatz controller using the
   A3D protocol over the PC gameport.  For more information on how to
-  use the driver please read <file:Documentation/joystick.txt>.
+  use the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17559,7 +17636,7 @@
 CONFIG_INPUT_ADI
   Say Y here if you have a Logitech controller using the ADI
   protocol over the PC gameport. For more information on how to use
-  the driver please read <file:Documentation/joystick.txt>.
+  the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17570,7 +17647,7 @@
 CONFIG_INPUT_COBRA
   Say Y here if you have a Creative Labs Blaster Cobra gamepad.
   For more information on how to use the driver please read
-  <file:Documentation/joystick.txt>.
+  <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17581,7 +17658,7 @@
 CONFIG_INPUT_GF2K
   Say Y here if you have a Genius Flight2000 or MaxFighter digitally
   communicating joystick or gamepad.  For more information on how to
-  use the driver please read <file:Documentation/joystick.txt>.
+  use the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17592,7 +17669,7 @@
 CONFIG_INPUT_GRIP
   Say Y here if you have a Gravis controller using the GrIP protocol
   over the PC gameport.  For more information on how to use the driver
-  please read <file:Documentation/joystick.txt>.
+  please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17603,7 +17680,7 @@
 CONFIG_INPUT_INTERACT
   Say Y hereif you have an InterAct gameport or joystick
   communicating digitally over the gameport.  For more information on
-  how to use the driver please read <file:Documentation/joystick.txt>.
+  how to use the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17615,7 +17692,7 @@
   Say Y here if you have a ThrustMaster controller using the
   DirectConnect (BSP) protocol over the PC gameport.  For more
   information on how to use the driver please read
-  <file:Documentation/joystick.txt>.
+  <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17626,7 +17703,7 @@
 CONFIG_INPUT_SIDEWINDER
   Say Y here if you have a Microsoft controller using the Digital
   Overdrive protocol over PC gameport.  For more information on how to
-  use the driver please read <file:Documentation/joystick.txt>.
+  use the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17638,7 +17715,7 @@
   Say Y here and to the Serial port input line discipline option if
   you plan to use a joystick that communicates over the serial (COM)
   port.  For more information on how to use the driver please read
-  <file:Documentation/joystick.txt>.
+  <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17649,7 +17726,7 @@
 CONFIG_INPUT_SERPORT
   Say Y here if you plan to use a joystick that communicates over the
   serial (COM) port.  For more information on how to use the driver
-  please read <file:Documentation/joystick.txt>.
+  please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17660,7 +17737,7 @@
 CONFIG_INPUT_WARRIOR
   Say Y here if you have a Logitech WingMan Warrior joystick connected
   to your computer's serial port.  For more information on how to use
-  the driver please read <file:Documentation/joystick.txt>.
+  the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17671,7 +17748,7 @@
 CONFIG_INPUT_MAGELLAN
   Say Y here if you have a Magellan or Space Mouse 6DOF controller
   connected to your computer's serial port.  For more information on
-  how to use the driver please read <file:Documentation/joystick.txt>.
+  how to use the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17683,7 +17760,7 @@
   Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
   controller connected to your computer's serial port.  For more
   information on how to use the driver please read
-  <file:Documentation/joystick.txt>.
+  <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17694,7 +17771,7 @@
 CONFIG_INPUT_SPACEBALL
   Say Y here if you have a SpaceTec SpaceBall 4000 FLX controller
   connected to your computer's serial port.  For more information on
-  how to use the driver please read <file:Documentation/joystick.txt>.
+  how to use the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17705,7 +17782,7 @@
 CONFIG_INPUT_STINGER
   Say Y here if you have a Gravis Stinger connected to one of your
   serial ports.  For more information on how to use the driver please
-  read <file:Documentation/joystick.txt>.
+  read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17716,7 +17793,7 @@
 CONFIG_INPUT_IFORCE_232
   Say Y here if you have an I-Force joystick or steering wheel
   connected to your serial (COM) port.  For more information on how
-  to use the driver please read <file:Documentation/joystick.txt>.
+  to use the driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17727,7 +17804,7 @@
 CONFIG_INPUT_IFORCE_USB
   Say Y here if you have an I-Force joystick or steering wheel
   connected to your USB port.  For more information on how to use the
-  driver please read <file:Documentation/joystick.txt>.
+  driver please read <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17740,8 +17817,8 @@
   gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
   Commodore, Amstrad CPC joystick connected to your parallel port.
   For more information on how to use the driver please read
-  <file:Documentation/joystick.txt> and
-  <file:Documentation/joystick-parport.txt>.
+  <file:Documentation/input/joystick.txt> and
+  <file:Documentation/input/joystick-parport.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17755,8 +17832,8 @@
   Sony PlayStation gamepad or a Multisystem -- Atari, Amiga,
   Commodore, Amstrad CPC joystick connected to your parallel port.
   For more information on how to use the driver please read
-  <file:Documentation/joystick.txt> and
-  <file:Documentation/joystick-parport.txt>.
+  <file:Documentation/input/joystick.txt> and
+  <file:Documentation/input/joystick-parport.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17768,8 +17845,8 @@
   Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
   and want to use it with Multisystem -- Atari, Amiga, Commodore,
   Amstrad CPC joystick.  For more information on how to use the driver
-  please read <file:Documentation/joystick.txt> and
-  <file:Documentation/joystick-parport.txt>.
+  please read <file:Documentation/input/joystick.txt> and
+  <file:Documentation/input/joystick-parport.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -17780,7 +17857,7 @@
 CONFIG_INPUT_AMIJOY
   Say Y here if you have an Amiga with a digital joystick connected
   to it.  For more information on how to use the driver please read
-  <file:Documentation/joystick.txt>.
+  <file:Documentation/input/joystick.txt>.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -18353,7 +18430,7 @@
   questions.
 
   Read the <file:Documentation/sound/README.OSS> file and the head of
-  <file:drivers/sound/lowlevel/aedsp16.c> as well as
+  <file:drivers/sound/aedsp16.c> as well as
   <file:Documentation/sound/AudioExcelDSP16> to get more information
   about this driver and its configuration.
 
@@ -18412,12 +18489,20 @@
   or the CMI8378 chipset.  Data on these chips are available at
   <http://www.cmedia.com.tw/>.
 
+  A userspace utility to control some internal registers of these
+  chips is available at
+  <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
+
 Support CMI8738 based audio cards
 CONFIG_SOUND_CMPCI_CM8738
   Say Y or M if you have a PCI sound card using the CMI8338
   or the CMI8378 chipset.  Data on this chip is available at
   <http://www.cmedia.com.tw/doc8738.htm>.
 
+  A userspace utility to control some internal registers of these
+  chips is available at
+  <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
+
 Enable joystick
 CONFIG_SOUND_CMPCI_JOYSTICK
   Say here in order to enable the joystick port on a sound crd using
@@ -18435,13 +18520,19 @@
   "The 8738 Audio SPDIF In/Out Technical Data" on the technical
   support page at <http://www.cmedia.com.tw/>.
 
+  A userspace utility to control even more internal registers of these
+  chips is available at
+  <http://member.nifty.ne.jp/Breeze/softwares/unix/cmictl-e.html>.
+  This package will among other things help you enable SPDIF 
+  out/in/loop/monitor.
+
 Creative SBLive! (EMU10K1) based PCI sound cards
 CONFIG_SOUND_EMU10K1
   Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
   such as the Creative SBLive!, SB PCI512 or Emu-APS.
 
   For more information on this driver and the degree of support for the
-  different card models please check <http://opensource.creative.com>.
+  different card models please check <http://opensource.creative.com/>.
 
   It is now possible to load dsp microcode patches into the EMU10K1
   chip.  These patches are used to implement real time sound
@@ -18674,7 +18765,7 @@
 
 Support for ITE 8172G board
 CONFIG_MIPS_ITE8172
-  Ths is an evaluation board made by ITE (http://www.ite.com.tw/)
+  Ths is an evaluation board made by ITE <http://www.ite.com.tw/>
   with ATX form factor that utilizes a MIPS R5000 to work with its
   ITE8172G companion internet appliance chip. The MIPS core can be
   either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build
@@ -19188,7 +19279,7 @@
   can be inserted in and removed from the running kernel whenever you
   want, details in <file:Documentation/modules.txt>); the module will
   be called sc.o.  See <file:Documentation/isdn/README.sc> and
-  <http://www.spellcast.com> for more information.
+  <http://www.spellcast.com/> for more information.
 
 Eicon active card support
 CONFIG_ISDN_DRV_EICON
@@ -19330,7 +19421,7 @@
   This enables support for the Auvertech TurboPAM ISDN-card.
   For running this card, additional firmware is necessary, which has
   to be downloaded into the card using a utility which is distributed
-  separately from the Auvertech's web site: <http://www.auvertech.fr>.
+  separately from the Auvertech's web site: <http://www.auvertech.fr/>.
 
   Please redirect all support questions to support@auvertech.fr.
 
@@ -19525,7 +19616,7 @@
   It was designed as a replacement for cables and other short-range
   technologies like IrDA.  Bluetooth operates in personal area range
   that typically extends up to 10 meters.  More information about
-  Bluetooth can be found at <http://www.bluetooth.com>.
+  Bluetooth can be found at <http://www.bluetooth.com/>.
 
   Linux Bluetooth subsystem consist of several layers:
                HCI Core (device and connection manager, scheduler)
@@ -19538,7 +19629,7 @@
   To use Linux Bluetooth subsystem, you will need several user-space
   utilities like hciconfig and hcid.  These utilities and updates to
   Bluetooth kernel modules are provided in the BlueZ package.
-  For more information, see <http://bluez.sf.net>.
+  For more information, see <http://bluez.sourceforge.net/>.
 
   If you want to compile HCI Core as module (hci.o) say M here.
 
@@ -19580,62 +19671,6 @@
 # The following options are for Linux when running on the Hitachi
 # SuperH family of RISC microprocessors.
 
-CPU Selection
-CONFIG_CPU_SUBTYPE_SH7707
-  This is the type of your Hitachi SuperH processor. This information is
-  used for optimizing and configuration purposes.
-
-  - "SH7707" for SH7707
-  - "SH7708" for SH7708, SH7708S, SH7708R
-  - "SH7709" for SH7707, SH7709, SH7709A, and SH7729.
-  - "SH7750" for SH7750, SH7750S
-  - "SH7751" for SH7751
-  - "ST40STB1" for ST40STB1
-
-Target machine selection
-CONFIG_SH_GENERIC
-  This is machine type of your target.
-
-  - "Generic" for Generic kernel which might support all of them
-  - "SolutionEngine" for Hitachi SolutionEngine (7709A, 7750, 7750S)
-  - "SolutionEngine7751" for Hitachi SolutionEngine (7751)
-  - "STB1_Harp" for STMicroelectronics HARP
-  - "STB1_Overdrive" for STMicroelectronics Overdrive
-  - "HP620" for HP 'Jornada' 620
-  - "HP680" for HP 'Jornada' 680
-  - "HP690" for HP 'Jornada' 690
-  - "CqREEK" for CQ Publishing CqREEK SH-4
-  - "DMIDA" for DMIDA, industrial data assistant
-  - "EC3104" for Compaq Aero 8000
-  - "Dreamcast" for SEGA Dreamcast
-  - "CAT68701" for CAT 68701 Evaluation Board (SH7708)
-  - "BigSur" for Big Sur Evaluation Board
-  - "SH2000" for SH2000 Evaluation Board (SH7709A)
-  - "ADX" for A&D ADX
-  - "BareCPU" for Bare CPU board such as CqREEK SH-3
-
-  If unsure, select "BareCPU".
-
-Physical memory start address
-CONFIG_MEMORY_START
-  Computers built with Hitachi SuperH processors always
-  map the ROM starting at address zero.  But the processor
-  does not specify the range that RAM takes.  RAM is usually
-  mapped starting at 0c000000, but it may be elsewhere.
-
-  You should set this value to the address of the lowest
-  RAM location.
-
-  A value of 0c000000 will work for most boards.
-
-Directly Connected Compact Flash support
-CONFIG_CF_ENABLER
-  If your board has "Directly Connected" CompactFlash at area 5 or 6, 
-  you may want to enable this option.  Then, you can use CF as
-  primary IDE drive (only tested for SanDisk).
-
-  If in doubt, press "n".
-
 SuperH RTC support
 CONFIG_SH_RTC
   Selecting this option will allow the Linux kernel to emulate
@@ -19650,38 +19685,7 @@
 
   If unsure, say N.
 
-SuperH SCI (serial) support
-CONFIG_SH_SCI
-  Selecting this option will allow the Linux kernel to transfer
-  data over SCI (Serial Communication Interface) and/or SCIF
-  which are built into the Hitachi SuperH processor.
-
-  If unsure, say N.
-
-Use LinuxSH standard BIOS
-CONFIG_SH_STANDARD_BIOS
-  Say Y here if your target has the gdb-sh-stub package from
-  www.m17n.org (or any conforming standard LinuxSH BIOS) in FLASH
-  or EPROM.  The kernel will use standard BIOS calls during boot
-  for various housekeeping tasks.  Note this does not work with
-  WindowsCE machines.  If unsure, say N.
-
-Early printk support
-CONFIG_SH_EARLY_PRINTK
-  If you say Y here, the kernel printk routine will begin output to
-  the console much earlier in the boot process, before the serial
-  console is initialised, instead of buffering output.  Standard
-  LinuxSH BIOS calls are used for the output.  This helps when
-  debugging fatal problems early in the boot sequence.  This is only
-  useful for kernel hackers.  If unsure, say N.
-  
-National Semiconductor DP83902AV 'ST-NIC' support
-CONFIG_STNIC
-  If you have a network adaptor with National Semiconductor DP83902AV, 
-  say Y or M (for module).
-
-  If unsure, say N.
-
+# Choice: cf_area
 CompactFlash Connection Area
 CONFIG_CF_AREA5
   If your board has "Directly Connected" CompactFlash, You should
@@ -20483,7 +20487,7 @@
   <http://www.synergymicro.com/PressRel/97_10_15.html>.
 
   Select APUS if configuring for a PowerUP Amiga.  More information is
-  available at: <http://linux-apus.sourceforge.net>.
+  available at: <http://linux-apus.sourceforge.net/>.
 
 Synergy-Gemini
 CONFIG_GEMINI
@@ -20495,122 +20499,7 @@
 CONFIG_APUS
   Select APUS if configuring for a PowerUP Amiga.
   More information is available at:
-  <http://linux-apus.sourceforge.net>.
-
-Embedded 8xx Board Type
-CONFIG_RPXLITE
-  RPX-Lite:
-    Embedded Planet RPX Lite
-
-  RPX-Classic:
-    Embedded Planet RPX Classic Low-fat.
-
-  BSE-IP: 
-    Bright Star Engineering ip-Engine.
-
-  TQM823L:
-  TQM850L:
-  TQM855L:
-  TQM860L:
-    MPC8xx based family of mini modules, half credit card size,
-    up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
-    2 x CAN bus interface, ...
-      Manufacturer: TQ Components, www.tq-group.de
-      Date of Release: October (?) 1999
-      End of Life: not yet :-)
-      URL:
-      - module: http://www.denx.de/PDF/TQM8xxLHWM201.pdf
-      - starter kit: http://www.denx.de/PDF/STK8xxLHWM201.pdf
-      - images: http://www.denx.de/embedded-ppc-en.html
-
-  FPS850L:
-    FingerPrint Sensor System (based on TQM850L)
-      Manufacturer: IKENDI AG, http://www.ikendi.com/
-      Date of Release: November 1999
-      End of life: end 2000 ?
-      URL: see TQM850L
-
-  SPD823TS:
-    MPC823 based board used in the "Tele Server" product
-    Manufacturer: Speech Design, http://www.speech-design.de/
-    Date of Release: Mid 2000 (?)
-    End of life: -
-    URL: http://www.speech-design.de/
-         select "English", then "Teleteam Solutions", then "TeleServer"
-
-  IVMS8:
-    MPC860 based board used in the "Integrated Voice Mail System",
-    Small Version (8 voice channels)
-    Manufacturer: Speech Design, http://www.speech-design.de/
-    Date of Release: December 2000 (?)
-    End of life: -
-    URL: http://www.speech-design.de/
-
-  IVML24:
-    MPC860 based board used in the "Integrated Voice Mail System", 
-    Large Version (24 voice channels)
-    Manufacturer: Speech Design, http://www.speech-design.de/
-    Date of Release: March 2001  (?)
-    End of life: -
-    URL: http://www.speech-design.de/
-
-  SM850:
-    Service Module (based on TQM850L)
-    Manufacturer: Dependable Computer Systems, http://www.decomsys.com/
-    Date of Release: end 2000 (?)
-    End of life: mid 2001 (?)
-    URL: http://www.tz-mikroelektronik.de/ServiceModule/index.html
-
-  HERMES:
-    Hermes-Pro ISDN/LAN router with integrated 8 x hub
-    Manufacturer: Multidata Gesellschaft für Datentechnik und Informatik
-      http://www.multidata.de/
-    Date of Release: 2000 (?)
-    End of life: -
-    URL: http://www.multidata.de/english/products/hpro.htm
-
-  IP860:	
-    VMEBus IP (Industry Pack) carrier board with MPC860
-    Manufacturer: MicroSys GmbH, http://www.microsys.de/
-    Date of Release: ?
-    End of life: -
-    URL: http://www.microsys.de/html/ip860.html
-
-  PCU_E:
-    PCU = Peripheral Controller Unit, Extended
-    Manufacturer: Siemens AG, ICN (Information and Communication Networks)
-    	http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html
-    Date of Release: April 2001
-    End of life: August 2001
-    URL: n. a.
-
-Embedded 82xx Board Type
-CONFIG_EST8260
-  EST8260: Wind River System, Inc. EST SBC8260
-
-  TQM8260:
-    MPC8260 based module, little larger than credit card,
-    up to 128 MB global + 64 MB local RAM, 32 MB Flash,
-    32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet,
-    2 x serial ports, ...
-      Manufacturer: TQ Components, www.tq-group.de
-      Date of Release: June 2001
-      End of Life: not yet :-)
-      URL: http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf
-
-  PM826:
-    Modular system with MPC8260 CPU
-    Manufacturer: MicroSys GmbH, http://www.microsys.de/
-    Date of Release: mid 2001
-    End of life: -
-    URL: http://www.microsys.de/html/pm826.html
-
-  CU824:
-    VMEBus Board with PCI extension with MPC8240 CPU
-    Manufacturer: MicroSys GmbH, http://www.microsys.de/
-    Date of Release: early 2001 (?)
-    End of life: -
-    URL: http://www.microsys.de/html/cu824.html
+  <http://linux-apus.sourceforge.net/>.
 
 AltiVec Kernel Support
 CONFIG_ALTIVEC
@@ -20684,26 +20573,97 @@
   change the screen brightness.
 
 # Choice: ppc8xxtype
-RPX-Lite
+Embedded 8xx Board Type
 CONFIG_RPXLITE
   Single-board computers based around the PowerPC MPC8xx chips and
   intended for embedded applications.  The following types are
   supported:
 
-    RPX-Lite    -- PC104 form-factor SBC based on the MPC823
-    RPX-Classic -- Credit-card-size SBC based on the MPC 860
-    BSE-IP      -- Bright Star Engineering BSE-IP SBC
-    TQM823L     -- TQM823L SBC from TQ Components
-    TQM850L     -- TQM850L SBC from TQ Components
-    TQM855L     -- TQM855L SBC from TQ Components
-    TQM860L     -- TQM860L SBC from TQ Components
-    FPS850L	-- FingerPrint Sensor from TQ Components
-    TQM860      -- TQM860 SBC from IKENDI AG
-    SPD823TS	-- Speech Design TeleServer from Speech Design
-    IVMS8	-- Integrated VoiceMail SBC from Speech Design
-    SM850       -- Service Module 850 from Dependable Computer Systems
-    MBX         -- MBX821 and MBX860 SBCs
-    Wincept     -- Wincept SBCs for thin-client machines
+  RPX-Lite:
+    Embedded Planet RPX Lite. PC104 form-factor SBC based on the MPC823.
+
+  RPX-Classic:
+    Embedded Planet RPX Classic Low-fat. Credit-card-size SBC based on 
+    the MPC 860
+
+  BSE-IP: 
+    Bright Star Engineering ip-Engine.
+
+  TQM823L:
+  TQM850L:
+  TQM855L:
+  TQM860L:
+    MPC8xx based family of mini modules, half credit card size,
+    up to 64 MB of RAM, 8 MB Flash, (Fast) Ethernet, 2 x serial ports,
+    2 x CAN bus interface, ...
+      Manufacturer: TQ Components, www.tq-group.de
+      Date of Release: October (?) 1999
+      End of Life: not yet :-)
+      URL:
+      - module: <http://www.denx.de/PDF/TQM8xxLHWM201.pdf>
+      - starter kit: <http://www.denx.de/PDF/STK8xxLHWM201.pdf>
+      - images: <http://www.denx.de/embedded-ppc-en.html>
+
+  FPS850L:
+    FingerPrint Sensor System (based on TQM850L)
+      Manufacturer: IKENDI AG, <http://www.ikendi.com/>
+      Date of Release: November 1999
+      End of life: end 2000 ?
+      URL: see TQM850L
+
+  SPD823TS:
+    MPC823 based board used in the "Tele Server" product
+    Manufacturer: Speech Design, <http://www.speech-design.de/>
+    Date of Release: Mid 2000 (?)
+    End of life: -
+    URL: <http://www.speech-design.de/>
+         select "English", then "Teleteam Solutions", then "TeleServer"
+
+  IVMS8:
+    MPC860 based board used in the "Integrated Voice Mail System",
+    Small Version (8 voice channels)
+    Manufacturer: Speech Design, <http://www.speech-design.de/>
+    Date of Release: December 2000 (?)
+    End of life: -
+    URL: <http://www.speech-design.de/>
+
+  IVML24:
+    MPC860 based board used in the "Integrated Voice Mail System", 
+    Large Version (24 voice channels)
+    Manufacturer: Speech Design, <http://www.speech-design.de/>
+    Date of Release: March 2001  (?)
+    End of life: -
+    URL: <http://www.speech-design.de/>
+
+  SM850:
+    Service Module (based on TQM850L)
+    Manufacturer: Dependable Computer Systems, <http://www.decomsys.com/>
+    Date of Release: end 2000 (?)
+    End of life: mid 2001 (?)
+    URL: <http://www.tz-mikroelektronik.de/ServiceModule/index.html>
+
+  HERMES:
+    Hermes-Pro ISDN/LAN router with integrated 8 x hub
+    Manufacturer: Multidata Gesellschaft für Datentechnik und Informatik
+      <http://www.multidata.de/>
+    Date of Release: 2000 (?)
+    End of life: -
+    URL: <http://www.multidata.de/english/products/hpro.htm>
+
+  IP860:	
+    VMEBus IP (Industry Pack) carrier board with MPC860
+    Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+    Date of Release: ?
+    End of life: -
+    URL: <http://www.microsys.de/html/ip860.html>
+
+  PCU_E:
+    PCU = Peripheral Controller Unit, Extended
+    Manufacturer: Siemens AG, ICN (Information and Communication Networks)
+    	<http://www.siemens.de/page/1,3771,224315-1-999_2_226207-0,00.html>
+    Date of Release: April 2001
+    End of life: August 2001
+    URL: n. a.
 
 RPX-Classic
 CONFIG_RPXCLASSIC
@@ -20831,7 +20791,7 @@
 #         Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
 #         Date of Release: early 2001 (?)
 #         End of life: -
-#         URL: <http://www.microsys.de/html/cu824.html
+#         URL: <http://www.microsys.de/html/cu824.html>
 #
 # PM826:
 #         Modular system with MPC8260 CPU
@@ -20850,13 +20810,39 @@
 #         End of life: -
 #         URL: n. a.o
 
-Support for EST8260
+# Choice: ppc82xxtype
+Embedded 82xx Board Type
 CONFIG_EST8260
-  The EST8260 is a single-board computer manufactured by Wind River
-  Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
-  the MPC8260.  Wind River Systems has a website at
-  <http://www.windriver.com/>, but the EST8260 cannot be found on it
-  and has probably been discontinued or rebadged.
+  EST8260:
+    The EST8260 is a single-board computer manufactured by Wind River
+    Systems, Inc. (formerly Embedded Support Tools Corp.) and based on
+    the MPC8260.  Wind River Systems has a website at
+    <http://www.windriver.com/>, but the EST8260 cannot be found on it
+    and has probably been discontinued or rebadged.
+
+  TQM8260:
+    MPC8260 based module, little larger than credit card,
+    up to 128 MB global + 64 MB local RAM, 32 MB Flash,
+    32 kB EEPROM, 256 kB L@ Cache, 10baseT + 100baseT Ethernet,
+    2 x serial ports, ...
+      Manufacturer: TQ Components, www.tq-group.de
+      Date of Release: June 2001
+      End of Life: not yet :-)
+      URL: <http://www.denx.de/PDF/TQM82xx_SPEC_Rev005.pdf>
+
+  PM826:
+    Modular system with MPC8260 CPU
+    Manufacturer: MicroSys GmbH, <http://www.microsys.de/>
+    Date of Release: mid 2001
+    End of life: -
+    URL: <http://www.microsys.de/html/pm826.html>
+
+  CU824:
+    VMEBus Board with PCI extension with MPC8240 CPU
+    Manufacturer: MicroSys GmbH, http://www.microsys.de/
+    Date of Release: early 2001 (?)
+    End of life: -
+    URL: <http://www.microsys.de/html/cu824.html>
 
 ADB raw keycode support
 CONFIG_MAC_ADBKEYCODES
@@ -20870,6 +20856,13 @@
 
   If unsure, say Y here.
 
+I2C/SPI Microcode Patch
+UCODE_PATCH
+  Motorola releases microcode updates for their 8xx CPM modules.  The
+  microcode update file has updates for IIC, SMC and USB.  Currently only
+  the USB update is available by default, if the MPC8xx USB option is
+  enabled.  If in doubt, say 'N' here.
+
 Mouse button 2+3 emulation support
 CONFIG_MAC_EMUMOUSEBTN
   This provides generic support for emulating the 2nd and 3rd mouse
@@ -21013,7 +21006,7 @@
   Support for audio/video capture and overlay devices and FM radio
   cards. The exact capabilities of each device vary. User tools for
   this are available from
-  <ftp://ftp.uk.linux.org/pub/linux/video4linux>.
+  <ftp://ftp.uk.linux.org/pub/linux/video4linux/>.
 
   If you are interested in writing a driver for such an audio/video
   device or user software interacting with such a driver, please read
@@ -21399,7 +21392,7 @@
   Miro DC10 and DC30 video capture cards).
 
 Include support for Iomega Buz
-CONFIG_VIDEO_BUZ
+CONFIG_VIDEO_ZORAN_BUZ
   Say Y here to include support for the Iomega Buz video card.  There
   is a Buz/Linux homepage at <http://www.lysator.liu.se/~gz/buz/>.
 
@@ -21452,8 +21445,8 @@
   otherwise say N.
   This driver is also available as a module (w9966.o).
 
-  Check out <file:Documentation/video4linux/w9966.txt> and
-  <file:Documentation/video4linux/w9966.c> for more information.
+  Check out <file:Documentation/video4linux/w9966.txt> for more
+  information.
 
 CPiA Video For Linux
 CONFIG_VIDEO_CPIA
@@ -21577,25 +21570,23 @@
   CONFIG_IPLABE.
 
 Support for 3215 line mode terminal
-CONFIG_3215
-  Include support for IBM 3215 line-mode terminals.  Can't be used
-  if 3270 console support is chosen.
+CONFIG_TN3215
+  Include support for IBM 3215 line-mode terminals.
 
 Support for console on 3215 line mode terminal
-CONFIG_3215_CONSOLE
-  Include support for using an IBM 3215 line-mode terminal as the
-  Linux system console.  Can't be used if 3270 console support is
-  chosen.
+CONFIG_TN3215_CONSOLE
+  Include support for using an IBM 3215 line-mode terminal as a
+  Linux system console.
 
 Support for 3270 line mode terminal
-CONFIG_3270
+CONFIG_TN3270
   Include support for IBM 3270 line-mode terminals.
 
 Support for console on 3270 line mode terminal
-CONFIG_3270_CONSOLE
-  Include support for using an IBM 3270 line-mode terminal as the
-  Linux system console.  Excludes using 3215s.  Available only if 3270
-  support is compiled in statically.
+CONFIG_TN3270_CONSOLE
+  Include support for using an IBM 3270 line-mode terminal as a Linux
+  system console.  Available only if 3270 support is compiled in
+  statically.
 
 Support for HWC line mode terminal
 CONFIG_HWC
@@ -21846,7 +21837,7 @@
   There are no product plans beyond the current research
   prototypes at this time.  Information is available at:
 
-  <http://crl.research.compaq.com/projects/personalserver>
+  <http://crl.research.compaq.com/projects/personalserver/>
 
   If you have any questions or comments about the  Compaq Personal
   Server, send e-mail to skiff@crl.dec.com.
@@ -21897,6 +21888,12 @@
   Say Y if configuring for an Intrinsyc CerfBoard.
   Say N otherwise.
 
+FlexaNet
+CONFIG_SA1100_FLEXANET
+  Say Y here if you intend to run this kernel on the FlexaNet
+  handheld instruments. Information about this machine can be
+  found at: <http://www.flexanet.com/>.
+
 nanoEngine
 CONFIG_SA1100_NANOENGINE
   The nanoEngine is a StrongARM 1110-based single board computer
@@ -22284,11 +22281,6 @@
   no management frames, simple fixed header).
   Ultra is available as a special socket : socket(AF_IRDA, SOCK_DGRAM, 1);
 
-IrDA protocol options
-CONFIG_IRDA_OPTIONS
-  Say Y here if you want to configure any of the following IrDA
-  options.
-
 IrDA cache last LSAP
 CONFIG_IRDA_CACHE_LAST_LSAP
   Say Y here if you want IrLMP to cache the last LSAP used.  This
@@ -22300,47 +22292,35 @@
 IrDA Fast RRs
 CONFIG_IRDA_FAST_RR
   Say Y here is you want IrLAP to send fast RR (Receive Ready) frames
-  when acting as a primary station. This will make IrLAP send out a RR
-  frame immediately when receiving a frame if its own transmit queue
-  is currently empty. This will give a lot of speed improvement when
-  receiving much data since the secondary station will not have to
-  wait the max. turn around time before it is allowed to transmit the
-  next time. If the transmit queue of the secondary is also empty the
-  primary will back off waiting longer for sending out the RR frame
-  until the timeout reaches the normal value. Enabling this option
-  will make the IR-diode burn more power and thus reduce your battery
-  life.
+  when acting as a primary station.
+  Disabling this option will make latency over IrDA very bad. Enabling
+  this option will make the IrDA stack send more packet than strictly
+  necessary, thus reduce your battery life (but not that much).
+
+  Fast RR will make IrLAP send out a RR frame immediately when
+  receiving a frame if its own transmit queue is currently empty. This
+  will give a lot of speed improvement when receiving much data since
+  the secondary station will not have to wait the max. turn around
+  time (usually 500ms) before it is allowed to transmit the next time.
+  If the transmit queue of the secondary is also empty, the primary will
+  start backing-off before sending another RR frame, waiting longer
+  each time until the back-off reaches the max. turn around time.
+  This back-off increase in controlled via
+  /proc/sys/net/irda/fast_poll_increase
 
-  If unsure, say N.
+  If unsure, say Y.
 
 IrDA debugging information
 CONFIG_IRDA_DEBUG
   Say Y here if you want the IrDA subsystem to write debug information
   to your syslog. You can change the debug level in
   /proc/sys/net/irda/debug .
+  When this option is enabled, the IrDA also perform many extra internal
+  verifications which will usually prevent the kernel to crash in case of
+  bugs.
 
   If unsure, say Y (since it makes it easier to find the bugs).
 
-IrLAP compression support
-CONFIG_IRDA_COMPRESSION
-  Compression is _not_ part of the IrDA(tm) protocol specification,
-  but it's working great! Linux is the first to try out compression
-  support at the IrLAP layer. This means that you will only benefit
-  from compression if you are running a Linux <-> Linux configuration.
-
-  If you say Y here, you also need to say Y or M to a compression
-  protocol below.
-
-IrLAP Deflate compression
-CONFIG_IRDA_DEFLATE
-  Say Y here if you want to build support for the Deflate compression
-  protocol. The deflate compression (GZIP) is exactly
-  the same as the one used by the PPP protocol.
-
-  If you want to compile this compression support as a module, say M
-  here and read <file:Documentation/modules.txt>.  The module will be
-  called irda_deflate.o.
-
 IrLAN protocol
 CONFIG_IRLAN
   Say Y here if you want to build support for the IrLAN protocol.  If
@@ -23541,7 +23521,7 @@
   this.  If in doubt, say Y.
 
 /proc/efi/vars support
-CONFIG_IA64_EFIVARS
+CONFIG_EFI_VARS
   If you say Y here, you are able to get EFI (Extensible Firmware
   Interface) variable information in /proc/efi/vars.  You may read,
   write, create, and destroy EFI variables through this interface.
@@ -23698,7 +23678,7 @@
   each of the machines below is described by a machine vector.
 
   Select SolutionEngine if configuring for a Hitachi SH7709
-  or SH7750 evalutation board.
+  or SH7750/7750S evalutation board.
 
   Select Overdrive if configuring for a ST407750 Overdrive board.
   More information at
@@ -23706,34 +23686,43 @@
 
   Select HP620 if configuring for a HP Jornada HP620.
   More information (hardware only) at
-  <http://www.hp.com/jornada>.
+  <http://www.hp.com/jornada/>.
 
   Select HP680 if configuring for a HP Jornada HP680.
   More information (hardware only) at
-  <http://www.hp.com/jornada/products/680>.
+  <http://www.hp.com/jornada/products/680/>.
 
   Select HP690 if configuring for a HP Jornada HP690.
   More information (hardware only) at
-  <http://www.hp.com/jornada/products/680>.
+  <http://www.hp.com/jornada/products/680/>.
 
   Select CqREEK if configuring for a CqREEK SH7708 or SH7750.
   More information at
   <http://sources.redhat.com/ecos/hardware.html#SuperH>.
 
   Select DMIDA if configuring for a DataMyte 4000 Industrial
-  Digital Assistant. More information at <http://www.dmida.com>.
+  Digital Assistant. More information at <http://www.dmida.com/>.
 
   Select EC3104 if configuring for a system with an Eclipse
-  International EC3104 chip, e.g. the Harris AD2000.
+  International EC3104 chip, e.g. the Harris AD2000 or Compaq Aero 8000.
 
   Select Dreamcast if configuring for a SEGA Dreamcast.
   More information at
-  <http://www.m17n.org/linux-sh/dreamcast>.  There is a
+  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
   Dreamcast project is at <http://linuxdc.sourceforge.net/>.
 
   Select BareCPU if you know what this means, and it applies
   to your system.
 
+# These may have to be merged in when we go to CML2:
+#  - "SolutionEngine7751" for Hitachi SolutionEngine (7751)
+#  - "STB1_Harp" for STMicroelectronics HARP
+#  - "CqREEK" for CQ Publishing CqREEK SH-4
+#  - "CAT68701" for CAT 68701 Evaluation Board (SH7708)
+#  - "BigSur" for Big Sur Evaluation Board
+#  - "SH2000" for SH2000 Evaluation Board (SH7709A)
+#  - "ADX" for A&D ADX
+
 SolutionEngine
 CONFIG_SH_SOLUTION_ENGINE
   Select SolutionEngine if configuring for a Hitachi SH7709
@@ -23754,19 +23743,19 @@
 CONFIG_SH_HP620
   Select HP620 if configuring for a HP jornada HP620.
   More information (hardware only) at
-  <http://www.hp.com/jornada>.
+  <http://www.hp.com/jornada/>.
 
 HP680
 CONFIG_SH_HP680
   Select HP680 if configuring for a HP Jornada HP680.
   More information (hardware only) at
-  <http://www.hp.com/jornada/products/680>.
+  <http://www.hp.com/jornada/products/680/>.
 
 HP690
 CONFIG_SH_HP690
   Select HP690 if configuring for a HP Jornada HP690.
   More information (hardware only)
-  at <http://www.hp.com/jornada/products/680>.
+  at <http://www.hp.com/jornada/products/680/>.
 
 CqREEK
 CONFIG_SH_CQREEK
@@ -23777,7 +23766,7 @@
 DMIDA
 CONFIG_SH_DMIDA
   Select DMIDA if configuring for a DataMyte 4000 Industrial
-  Digital Assistant. More information at <http://www.dmida.com>.
+  Digital Assistant. More information at <http://www.dmida.com/>.
 
 EC3104
 CONFIG_SH_EC3104
@@ -23788,7 +23777,7 @@
 CONFIG_SH_DREAMCAST
   Select Dreamcast if configuring for a SEGA Dreamcast.
   More information at
-  <http://www.m17n.org/linux-sh/dreamcast>.  There is a
+  <http://www.m17n.org/linux-sh/dreamcast/>.  There is a
   Dreamcast project is at <http://linuxdc.sourceforge.net/>.
 
 BareCPU
@@ -23805,7 +23794,8 @@
 # Choice: superhtype
 SH7707
 CONFIG_CPU_SUBTYPE_SH7707
-  Select the type of SuperH processor you have.
+  Select the type of SuperH processor you have. This information is
+  used for optimizing and configuration purposes.
 
   Select SH7707 if you have a  60 Mhz SH-3 HD6417707 CPU.
 
@@ -23816,6 +23806,10 @@
 
   Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU.
 
+  Select SH7751 if you have a SH7751
+
+  Select ST40STB1 if you have a ST40STB1
+
 SH7708
 CONFIG_CPU_SUBTYPE_SH7708
   Select SH7708 if you have a  60 Mhz SH-3 HD6417708S or
@@ -23831,7 +23825,11 @@
 
 Physical memory start address
 CONFIG_MEMORY_START
-  The physical memory start address will be automatically
+  Computers built with Hitachi SuperH processors always
+  map the ROM starting at address zero.  But the processor
+  does not specify the range that RAM takes.  
+
+  The physical memory (RAM) start address will be automatically
   set to 08000000, unless you selected one of the following
   processor types: SolutionEngine, Overdrive, HP620, HP680, HP690,
   in which case the start address will be set to 0c000000.
@@ -23889,15 +23887,15 @@
   The default setting of the HD64465 IO base address is 0xb0000000.
 
   Do not change this unless you know what you are doing.
-
+  
 Early printk support
 CONFIG_SH_EARLY_PRINTK
-  Say Y here to redirect kernel messages to the serial port
+  Say Y here to redirect kernel printk messages to the serial port
   used by the SH-IPL bootloader, starting very early in the boot
   process and ending when the kernel's serial console is initialised.
   This option is only useful porting the kernel to a new machine,
   when the kernel may crash or hang before the serial console is
-  initialised.
+  initialised. If unsure, say N.
 
 SuperH SCI (serial) support
 CONFIG_SH_SCI
@@ -23951,7 +23949,7 @@
 #
 # This is used by Emacs' spell checker ispell.el:
 #
-# LocalWords:  CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp metalab
+# LocalWords:  CONFIG coprocessor DX Pentium SX lilo loadlin HOWTO ftp ibiblio
 # LocalWords:  unc edu docs emu README kB BLK DEV FD Thinkpad fd MFM RLL IDE gz
 # LocalWords:  cdrom diskless netboot nfs xzvf ATAPI MB ide pavia rubini pl pd
 # LocalWords:  HD CD-ROMs IDECD NEC MITSUMI filesystem XT XD PCI BIOS cezar ATEN
@@ -23997,7 +23995,7 @@
 # LocalWords:  bsd comp SPARCstation le SunOS ie Gracilis PackeTwin PT pt LU FX
 # LocalWords:  FX TEAC CR LCS mS ramdisk IDETAPE cmd fperllo encis tcfs unisa
 # LocalWords:  Vertos Genoa Funai hsfs NCP NetWare tgz APM apm ioctls UltraLite
-# LocalWords:  TravelMate CDT LCD backlight VC RPC Mips AXP barlow cdrecord pg
+# LocalWords:  TravelMate CDT LCD backlight VC RPC Mips AXP barlow cdrtools pg
 # LocalWords:  PMAX MILO Alphas Multia Tseng linuxelf endian mipsel mips drv HT
 # LocalWords:  kerneld callouts AdvanSys advansys Admin WDT DataStor EP verden
 # LocalWords:  wdt hdb hdc bugfix SiS vlb Acculogic CSA DTC dtc Holtek ht QDI
diff -u --recursive --new-file v2.5.0/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- v2.5.0/linux/Documentation/DocBook/Makefile	Fri Nov  2 17:13:53 2001
+++ linux/Documentation/DocBook/Makefile	Thu Nov 29 13:45:52 2001
@@ -108,7 +108,9 @@
 		$(TOPDIR)/drivers/video/modedb.c \
 		$(TOPDIR)/fs/devfs/base.c \
 		$(TOPDIR)/fs/locks.c \
+		$(TOPDIR)/fs/bio.c \
 		$(TOPDIR)/include/asm-i386/bitops.h \
+		$(TOPDIR)/include/linux/usb.h \
 		$(TOPDIR)/kernel/pm.c \
 		$(TOPDIR)/kernel/ksyms.c \
 		$(TOPDIR)/kernel/kmod.c \
diff -u --recursive --new-file v2.5.0/linux/Documentation/DocBook/kernel-api.tmpl linux/Documentation/DocBook/kernel-api.tmpl
--- v2.5.0/linux/Documentation/DocBook/kernel-api.tmpl	Fri Oct  5 12:06:51 2001
+++ linux/Documentation/DocBook/kernel-api.tmpl	Thu Nov 29 13:45:52 2001
@@ -204,8 +204,83 @@
   </chapter>
 
   <chapter id="usb">
-     <title>USB Devices</title>
+    <title>USB Devices</title>
+
+    <para>Drivers for USB devices talk to the "usbcore" APIs, and are
+    exposed through driver frameworks such as block, character,
+    or network devices.
+    There are two types of public "usbcore" APIs:  those intended for
+    general driver use, and those which are only public to drivers that
+    are part of the core.
+    The drivers that are part of the core are involved in managing a USB bus.
+    They include the "hub" driver, which manages trees of USB devices, and
+    several different kinds of "host controller" driver (HCD), which control
+    individual busses.
+    </para>
+
+    <para>The device model seen by USB drivers is relatively complex.
+    </para>
+     
+    <itemizedlist>
+
+	<listitem><para>USB supports four kinds of data transfer
+	(control, bulk, interrupt, and isochronous).  Two transfer
+	types use bandwidth as it's available (control and bulk),
+	while the other two types of transfer (interrupt and isochronous)
+	are scheduled to provide guaranteed bandwidth.
+	</para></listitem>
+
+	<listitem><para>The device description model includes one or more
+	"configurations" per device, only one of which is active at a time.
+	</para></listitem>
+
+	<listitem><para>Configurations have one or more "interface", each
+	of which may have "alternate settings".  Interfaces may be
+	standardized by USB "Class" specifications, or may be specific to
+	a vendor or device.</para>
+
+	<para>USB device drivers actually bind to interfaces, not devices.
+	Think of them as "interface drivers", though you
+	may not see many devices where the distinction is important.
+	Most USB devices are simple, with only one configuration,
+	one interface, and one alternate setting.
+	</para></listitem>
+
+	<listitem><para>Interfaces have one or more "endpoints", each of
+	which supports one type and direction of data transfer such as
+	"bulk out" or "interrupt in".  The entire configuration may have
+	up to sixteen endpoints in each direction, allocated as needed
+	among all the interfaces.
+	</para></listitem>
+
+	<listitem><para>Data transfer on USB is packetized; each endpoint
+	has a maximum packet size.
+	Drivers must often be aware of conventions such as flagging the end
+	of bulk transfers using "short" (including zero length) packets.
+	</para></listitem>
+
+	<listitem><para>The Linux USB API supports synchronous calls for
+	control and bulk messaging.
+	It also supports asynchnous calls for all kinds of data transfer,
+	using request structures called "URBs" (USB Request Blocks).
+	</para></listitem>
+
+    </itemizedlist>
+
+    <para>Accordingly, the USB Core API exposed to device drivers
+    covers quite a lot of territory.  You'll probably need to consult
+    the USB 2.0 specification, available online from www.usb.org at
+    no cost, as well as class or device specifications.
+    </para>
+
+    <sect1><title>Data Types and Macros</title>
+!Iinclude/linux/usb.h
+    </sect1>
+
+    <sect1><title>USB Core APIs</title>
 !Edrivers/usb/usb.c
+    </sect1>
+
   </chapter>
 
   <chapter id="uart16x50">
diff -u --recursive --new-file v2.5.0/linux/Documentation/DocBook/via-audio.tmpl linux/Documentation/DocBook/via-audio.tmpl
--- v2.5.0/linux/Documentation/DocBook/via-audio.tmpl	Fri Nov  9 13:45:35 2001
+++ linux/Documentation/DocBook/via-audio.tmpl	Mon Dec 10 10:39:20 2001
@@ -8,11 +8,6 @@
    <author>
     <firstname>Jeff</firstname>
     <surname>Garzik</surname>
-    <affiliation>
-     <address>
-      <email>jgarzik@mandrakesoft.com</email>
-     </address>
-    </affiliation>
    </author>
   </authorgroup>
 
@@ -115,7 +110,7 @@
   <sect1 id="bugrepdiag"><title>Diagnostic output</title>
   <para>
 	Obtain the via-audio-diag diagnostics program from
-	http://gtf.org/garzik/drivers/via82cxxx/ and provide a dump of the
+	http://sf.net/projects/gkernel/ and provide a dump of the
 	audio chip's registers while the problem is occurring.  Sample command line:
   </para>
   <programlisting>
diff -u --recursive --new-file v2.5.0/linux/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog
--- v2.5.0/linux/Documentation/filesystems/devfs/ChangeLog	Sat Nov  3 10:06:38 2001
+++ linux/Documentation/filesystems/devfs/ChangeLog	Sat Nov 24 13:06:43 2001
@@ -1778,3 +1778,19 @@
   Thanks to Kari Hurtta <hurtta@leija.mh.fmi.fi>
 
 - Avoid deadlock in <devfs_follow_link> by using temporary buffer
+===============================================================================
+Changes for patch v197
+
+- First release of new locking code for devfs core (v1.0)
+
+- Fixed bug in drivers/cdrom/cdrom.c
+===============================================================================
+Changes for patch v198
+
+- Discard temporary buffer, now use "%s" for dentry names
+
+- Don't generate path in <try_modload>: use fake entry instead
+
+- Use "existing" directory in <_devfs_make_parent_for_leaf>
+
+- Use slab cache rather than fixed buffer for devfsd events
diff -u --recursive --new-file v2.5.0/linux/Documentation/filesystems/devfs/README linux/Documentation/filesystems/devfs/README
--- v2.5.0/linux/Documentation/filesystems/devfs/README	Wed Oct 10 23:23:24 2001
+++ linux/Documentation/filesystems/devfs/README	Sat Nov 24 13:06:43 2001
@@ -3,7 +3,7 @@
 
 Linux Devfs (Device File System) FAQ
 Richard Gooch
-29-SEP-2001
+9-NOV-2001
 
 -----------------------------------------------------------------------------
 
@@ -11,7 +11,9 @@
 
 http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.html
 and looks much better than the text version distributed with the
-kernel sources.
+kernel sources. A mirror site is available at:
+
+http://www.ras.ucalgary.ca/~rgooch/linux/docs/devfs.html
 
 There is also an optional daemon that may be used with devfs. You can
 find out more about it at:
diff -u --recursive --new-file v2.5.0/linux/Documentation/filesystems/ntfs.txt linux/Documentation/filesystems/ntfs.txt
--- v2.5.0/linux/Documentation/filesystems/ntfs.txt	Sun Sep 30 11:42:44 2001
+++ linux/Documentation/filesystems/ntfs.txt	Mon Dec 10 19:37:38 2001
@@ -98,6 +98,16 @@
 ChangeLog
 =========
 
+NTFS 1.1.21:
+	- Fixed bug with reading $MFT where we try to read higher mft records
+	  before having read the $DATA attribute of $MFT. (Note this is only a
+	  partial solution which will only work in the case that the attribute
+	  list is resident or non-resident but $DATA is in the first 1024
+	  bytes. But this should be enough in the majority of cases. I am not
+	  going to bother fixing the general case until someone finds this to
+	  be a problem for them, which I doubt very much will ever happen...)
+	- Fixed bogus BUG() call in readdir().
+
 NTFS 1.1.20:
 	- Fixed two bugs in ntfs_readwrite_attr(). Thanks to Jan Kara for
 	  spotting the out of bounds one.
diff -u --recursive --new-file v2.5.0/linux/Documentation/networking/tulip.txt linux/Documentation/networking/tulip.txt
--- v2.5.0/linux/Documentation/networking/tulip.txt	Fri Mar  2 11:02:14 2001
+++ linux/Documentation/networking/tulip.txt	Wed Dec 31 16:00:00 1969
@@ -1,226 +0,0 @@
-                Tulip Ethernet Card Driver
-	  Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
-
-The Tulip driver was developed by Donald Becker and changed by
-Takashi Manabe and a cast of thousands.
-
-For 2.4.x and later kernels, the Linux Tulip driver is available at
-http://sourceforge.net/projects/tulip/
-
-	This driver is for the Digital "Tulip" Ethernet adapter interface.
-	It should work with most DEC 21*4*-based chips/ethercards, as well as
-	with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-
-	Additional information on Donald Becker's tulip.c
-	is available at http://www.scyld.com/network/tulip.html
-
-
-
-
-				Theory of Operation
-
-Board Compatibility
-===================
-
-This device driver is designed for the DECchip "Tulip", Digital's
-single-chip ethernet controllers for PCI.  Supported members of the family
-are the 21040, 21041, 21140, 21140A, 21142, and 21143.  Similar work-alike
-chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
-supported.
-
-These chips are used on at least 140 unique PCI board designs.  The great
-number of chips and board designs supported is the reason for the
-driver size and complexity.  Almost of the increasing complexity is in the
-board configuration and media selection code.  There is very little
-increasing in the operational critical path length.
-
-Board-specific settings
-=======================
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS preferably should assign the
-PCI INTA signal to an otherwise unused system IRQ line.
-
-Some boards have EEPROMs tables with default media entry.  The factory default
-is usually "autoselect".  This should only be overridden when using
-transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
-for forcing full-duplex when used with old link partners that do not do
-autonegotiation.
-
-Driver operation
-================
-
-Ring buffers
-------------
-
-The Tulip can use either ring buffers or lists of Tx and Rx descriptors.
-This driver uses statically allocated rings of Rx and Tx descriptors, set at
-compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
-for the Rx ring buffers at open() time and passes the skb->data field to the
-Tulip as receive data buffers.  When an incoming frame is less than
-RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
-copied to the new skbuff.  When the incoming frame is larger, the skbuff is
-passed directly up the protocol stack and replaced by a newly allocated
-skbuff.
-
-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
-using a full-sized skbuff for small frames vs. the copying costs of larger
-frames.  For small frames the copying cost is negligible (esp. considering
-that we are pre-loading the cache with immediately useful header
-information).  For large frames the copying cost is non-trivial, and the
-larger copy might flush the cache of useful data.  A subtle aspect of this
-choice is that the Tulip only receives into longword aligned buffers, thus
-the IP header at offset 14 isn't longword aligned for further processing.
-Copied frames are put into the new skbuff at an offset of "+2", thus copying
-has the beneficial effect of aligning the IP header and preloading the
-cache.
-
-Synchronization
----------------
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-
-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
-flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'tp->tx_full' flag.
-
-The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
-stats.)	 After reaping the stats, it marks the queue entry as empty by setting
-the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
-tx_full and tbusy flags.
-
-Notes
-=====
-
-Thanks to Duke Kamstra of SMC for long ago providing an EtherPower board.
-Greg LaPolla at Linksys provided PNIC and other Linksys boards.
-Znyx provided a four-port card for testing.
-
-References
-==========
-
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
-http://www.digital.com  (search for current 21*4* datasheets and "21X4 SROM")
-http://www.national.com/pf/DP/DP83840A.html
-http://www.asix.com.tw/pmac.htm
-http://www.admtek.com.tw/
-
-Errata
-======
-
-The old DEC databooks were light on details.
-The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
-register of the set CSR12-15 written.  Hmmm, now how is that possible?
-
-The DEC SROM format is very badly designed not precisely defined, leading to
-part of the media selection junkheap below.  Some boards do not have EEPROM
-media tables and need to be patched up.  Worse, other boards use the DEC
-design kit media table when it isn't correct for their board.
-
-We cannot use MII interrupts because there is no defined GPIO pin to attach
-them.  The MII transceiver status is polled using an kernel timer.
-
-
-Source tree tour
-================
-The following is a list of files comprising the Tulip ethernet driver in
-drivers/net/tulip subdirectory.
-
-21142.c		- 21142-specific h/w interaction
-eeprom.c	- EEPROM reading and parsing
-interrupt.c	- Interrupt handler
-media.c		- Media selection and MII support
-pnic.c		- PNIC-specific h/w interaction
-timer.c		- Main driver timer, and misc h/w timers
-tulip.h		- Private driver header
-tulip_core.c	- Driver core (a.k.a. where "everything else" goes)
-
-
-
-Version history
-===============
-0.9.14 (February 20, 2000):
-* Fix PNIC problems (Manfred Spraul)
-* Add new PCI id for Accton comet
-* Support Davicom tulips
-* Fix oops in eeprom parsing
-* Enable workarounds for early PCI chipsets
-* IA64, hppa csr0 support
-* Support media types 5, 6
-* Interpret a bit more of the 21142 SROM extended media type 3
-* Add missing delay in eeprom reading
-
-0.9.11 (November 3, 2000):
-* Eliminate extra bus accesses when sharing interrupts (prumpf)
-* Barrier following ownership descriptor bit flip (prumpf)
-* Endianness fixes for >14 addresses in setup frames (prumpf)
-* Report link beat to kernel/userspace via netif_carrier_*. (kuznet)
-* Better spinlocking in set_rx_mode.
-* Fix I/O resource request failure error messages (DaveM catch)
-* Handle DMA allocation failure.
-
-0.9.10 (September 6, 2000):
-* Simple interrupt mitigation (via jamal)
-* More PCI ids
-
-0.9.9 (August 11, 2000):
-* More PCI ids
-
-0.9.8 (July 13, 2000):
-* Correct signed/unsigned comparison for dummy frame index
-* Remove outdated references to struct enet_statistics
-
-0.9.7 (June 17, 2000):
-* Timer cleanups (Andrew Morton)
-* Alpha compile fix (somebody?)
-
-0.9.6 (May 31, 2000):
-* Revert 21143-related support flag patch
-* Add HPPA/media-table debugging printk
-
-0.9.5 (May 30, 2000):
-* HPPA support (willy@puffingroup)
-* CSR6 bits and tulip.h cleanup (Chris Smith)
-* Improve debugging messages a bit
-* Add delay after CSR13 write in t21142_start_nway
-* Remove unused ETHER_STATS code
-* Convert 'extern inline' to 'static inline' in tulip.h (Chris Smith)
-* Update DS21143 support flags in tulip_chip_info[]
-* Use spin_lock_irq, not _irqsave/restore, in tulip_start_xmit()
-* Add locking to set_rx_mode()
-* Fix race with chip setting DescOwned bit (Hal Murray)
-* Request 100% of PIO and MMIO resource space assigned to card
-* Remove error message from pci_enable_device failure
-
-0.9.4.3 (April 14, 2000):
-* mod_timer fix (Hal Murray)
-* PNIC2 resuscitation (Chris Smith)
-
-0.9.4.2 (March 21, 2000):
-* Fix 21041 CSR7, CSR13/14/15 handling
-* Merge some PCI ids from tulip 0.91x
-* Merge some HAS_xxx flags and flag settings from tulip 0.91x
-* asm/io.h fix (submitted by many) and cleanup
-* s/HAS_NWAY143/HAS_NWAY/
-* Cleanup 21041 mode reporting
-* Small code cleanups
-
-0.9.4.1 (March 18, 2000):
-* Finish PCI DMA conversion (davem)
-* Do not netif_start_queue() at end of tulip_tx_timeout() (kuznet)
-* PCI DMA fix (kuznet)
-* eeprom.c code cleanup
-* Remove Xircom Tulip crud
-
-
-[EOF]
-
diff -u --recursive --new-file v2.5.0/linux/Documentation/pm.txt linux/Documentation/pm.txt
--- v2.5.0/linux/Documentation/pm.txt	Fri Apr  6 10:42:55 2001
+++ linux/Documentation/pm.txt	Thu Nov 29 17:00:33 2001
@@ -34,7 +34,7 @@
 system the associated daemon will exit gracefully.
 
   apmd:   http://worldvisions.ca/~apenwarr/apmd/
-  acpid:  http://phobos.fs.tum.de/acpi/
+  acpid:  http://acpid.sf.net/
 
 Driver Interface
 ----------------
@@ -260,7 +260,7 @@
 Q: Who do I contact for additional information about
    enabling power management for my specific driver/device?
 
-ACPI4Linux mailing list: acpi@phobos.fs.tum.de
+ACPI Development mailing list: acpi-devel@lists.sourceforge.net
 
 System Interface
 ----------------
diff -u --recursive --new-file v2.5.0/linux/Documentation/sh/new-machine.txt linux/Documentation/sh/new-machine.txt
--- v2.5.0/linux/Documentation/sh/new-machine.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sh/new-machine.txt	Tue Dec 11 10:10:18 2001
@@ -0,0 +1,77 @@
+The multiple machine support relies on redirecting all functions which will
+need to be machine specific through a table of function pointers, the
+machvec. These functions fall into a number of categories:
+
+ - I/O functions to IO memory (inb etc) and PCI/main memory (readb etc).
+ - I/O remapping functions (ioremap etc)
+ - some initialisation functions
+ - a 'heartbeat' function
+ - some miscellaneous flags
+
+The tree can be built in two ways:
+ - as a fully generic build. All drivers are linked in, and all functions
+   go through the machvec
+ - as a machine specific build. In this case only the required drivers
+   will be linked in, and some macros may be redefined to not go through
+   the machvec where performance is important (in particular IO functions).
+
+There are three ways in which IO can be performed:
+ - none at all. This is really only useful for the 'unknown' machine type,
+   which us designed to run on a machine about which we know nothing, and
+   so all all IO instructions do nothing.
+ - fully custom. In this case all IO functions go to a machine specific
+   set of functions which can do what they like
+ - a generic set of functions. These will cope with most situations,
+   and rely on a single function, mv_port2addr, which is called through the
+   machine vector, and converts an IO address into a memory address, which
+   can be read from/written to directly.
+
+Thus adding a new machine involves the following steps (I will assume I am
+adding a machine called fred):
+
+ - add a new file include/asm-sh/io_fred.h which contains prototypes for
+   any machine specific IO functions prefixed with the machine name, for
+   example fred_inb. These will be needed when filling out the machine
+   vector. In addition, a section is required which defines what to do when
+   building a machine specific version. For example:
+
+     #ifdef __WANT_IO_DEF
+     #define inb  fred_inb
+     ...
+     #endif
+
+   This is the minimum that is required, however there are ample
+   opportunities to optimise this. In particular, by making the prototypes
+   inline function definitions, it is possible to inline the function when
+   building machine specific versions. Note that the machine vector
+   functions will still be needed, so that a module built for a generic
+   setup can be loaded.
+
+ - add a new file arch/sh/kernel/mach_fred.c. This contains the definition
+   of the machine vector. When building the machine specific version, this
+   will be the real machine vector (via an alias), while in the generic
+   version is used to initialise the machine vector, and then freed, by
+   making it initdata. This should be defined as:
+
+     struct sh_machine_vector mv_fred __initmv = {
+       mv_name: "Fred"
+     }
+     ALIAS_MV(se)
+
+ - finally add a file arch/sh/kernel/io_fred.c, which contains
+   definitions of the machine specific io functions.
+
+A note about initialisation functions. Three initialisation functions are
+provided in the machine vector:
+ - mv_arch_init - called very early on from setup_arch
+ - mv_init_irq - called from init_IRQ, after the generic SH interrupt
+   initialisation
+ - mv_init_pci - currently not used
+
+Any other remaining functions which need to be called at start up can be
+added to the list using the __initcalls macro (or module_init if the code
+can be built as a module). Many generic drivers probe to see if the device
+they are targeting is present, however this may not always be appropriate,
+so a flag can be added to the machine vector which will be set on those
+machines which have the hardware in question, reducing the probe to a
+single conditional.
diff -u --recursive --new-file v2.5.0/linux/Documentation/sonypi.txt linux/Documentation/sonypi.txt
--- v2.5.0/linux/Documentation/sonypi.txt	Mon Oct 15 08:38:31 2001
+++ linux/Documentation/sonypi.txt	Thu Nov 29 07:53:34 2001
@@ -58,6 +58,10 @@
 			get enabled unless you set this parameter to 1.
 			Do not use this option unless it's actually necessary,
 			some Vaio models don't deal well with this option.
+			This option is available only if the kernel is 
+			compiled without ACPI support (since it conflicts
+			with it and it shouldn't be required anyway if 
+			ACPI is already enabled).
 
 	verbose:	print unknown events from the sonypi device
 
@@ -93,7 +97,10 @@
 	- some users reported that the laptop speed is lower (dhrystone
 	  tested) when using the driver with the fnkeyinit parameter. I cannot
 	  reproduce it on my laptop and not all users have this problem.
-	  Still under investigation.
+	  This happens because the fnkeyinit parameter enables the ACPI 
+	  mode (but without additionnal ACPI control, like processor 
+	  speed handling etc). Use ACPI instead of APM if it works on your
+	  laptop.
 	
 	- since all development was done by reverse engineering, there is
 	  _absolutely no guarantee_ that this driver will not crash your
diff -u --recursive --new-file v2.5.0/linux/Documentation/usb/error-codes.txt linux/Documentation/usb/error-codes.txt
--- v2.5.0/linux/Documentation/usb/error-codes.txt	Wed Oct 17 14:34:06 2001
+++ linux/Documentation/usb/error-codes.txt	Sat Dec  8 20:28:45 2001
@@ -1,14 +1,9 @@
-Revised: 2000-Dec-05.
+Revised: 2001-Dec-06.
 
 This is the documentation of (hopefully) all possible error codes (and
 their interpretation) that can be returned from the host controller drivers 
 and from usbcore.
 
-NOTE:
-The USB_ST_* codes are deprecated and are only listed for compatibility;
-new software should use only -E* instead!
-
-
 
 **************************************************************************
 *                   Error codes returned by usb_submit_urb               *
@@ -16,7 +11,6 @@
 
 Non-USB-specific:
 
-USB_ST_NOERROR
 0		URB submission went fine
 
 -ENOMEM		no memory for allocation of internal structures	
@@ -25,12 +19,10 @@
 
 -ENODEV		specified USB-device or bus doesn't exist
 
-USB_ST_REQUEST_ERROR
 -ENXIO		a control or interrupt URB is already queued to this endpoint; or
 		  a bulk URB is already queued to this endpoint and
 		  USB_QUEUE_BULK wasn't used (UHCI HCDs only)
 
-USB_ST_URB_INVALID_ERROR
 -EINVAL		a) Invalid transfer type specified (or not supported)
 		b) Invalid interrupt interval (0<=n<256)
 		c) more than one interrupt packet requested
@@ -42,12 +34,10 @@
 
 -EFBIG		too much ISO frames requested (currently uhci>900)
 
-USB_ST_STALL
 -EPIPE		specified pipe-handle is already stalled
 
 -EMSGSIZE	endpoint message size is zero, do interface/alternate setting
 
-USB_ST_BANDWIDTH_ERROR
 -ENOSPC		The host controller's bandwidth is already consumed and
 		this request would push it past its allowed limit.
 
@@ -60,60 +50,43 @@
 *                   or in iso_frame_desc[n].status (for ISO)             *
 **************************************************************************
 
-USB_ST_NOERROR
 0			Transfer completed successfully
 
-USB_ST_URB_KILLED
 -ENOENT			URB was canceled by usb_unlink_urb
 
-USB_ST_URB_PENDING
 -EINPROGRESS		URB still pending, no results yet
 			(actually no error until now;-)
 
-USB_ST_BITSTUFF
-USB_ST_INTERNALERROR
 -EPROTO			a) bitstuff error
 			b) unknown USB error 
 
-USB_ST_CRC
 -EILSEQ			CRC mismatch
 
-USB_ST_STALL
 -EPIPE			endpoint stalled
 
-USB_ST_BUFFEROVERRUN
 -ECOMM			During an IN transfer, the host controller
 			received data from an endpoint faster than it
 			could be written to system memory
 
-USB_ST_BUFFERUNDERRUN
 -ENOSR			During an OUT transfer, the host controller
 			could not retrieve data from system memory fast
 			enough to keep up with the USB data rate
 
-USB_ST_DATAOVERRUN
 -EOVERFLOW		The amount of data returned by the endpoint was
 			greater than either the max packet size of the
 			endpoint or the remaining buffer size.  "Babble".
 
-USB_ST_DATAUNDERRUN
 -EREMOTEIO		The endpoint returned less than max packet size
 			and that amount did not fill the specified buffer
-USB_ST_NORESPONSE
-USB_ST_TIMEOUT
 -ETIMEDOUT		transfer timed out, NAK
 
-USB_ST_REMOVED	
 -ENODEV			device was removed
 
-USB_ST_SHORT_PACKET
 -EREMOTEIO		short packet detected
 
-USB_ST_PARTIAL_ERROR
 -EXDEV			ISO transfer only partially completed
 			look at individual frame status for details
 
-USB_ST_URB_INVALID_ERROR
 -EINVAL			ISO madness, if this happens: Log off and go home
 
 -ECONNRESET		the URB is being unlinked asynchronously
diff -u --recursive --new-file v2.5.0/linux/Documentation/usb/philips.txt linux/Documentation/usb/philips.txt
--- v2.5.0/linux/Documentation/usb/philips.txt	Wed Oct 17 14:34:06 2001
+++ linux/Documentation/usb/philips.txt	Mon Nov 26 17:09:10 2001
@@ -1,5 +1,5 @@
 This file contains some additional information for the Philips webcams.
-E-mail: webcam@smcc.demon.nl                        Last updated: 2001-07-27
+E-mail: webcam@smcc.demon.nl                        Last updated: 2001-09-24
 
 The main webpage for the Philips driver is http://www.smcc.demon.nl/webcam/.
 It contains a lot of extra information, a FAQ, and the binary plugin
@@ -13,11 +13,9 @@
 the latter, since it makes troubleshooting a lot easier. The built-in
 microphone is supported through the USB Audio class.
 
-(Taken from install.html)
-
 When you load the module you can set some default settings for the
-camera; some programs depend on a particular image-size or -format. The
-options are:
+camera; some programs depend on a particular image-size or -format and
+don't know how to set it properly in the driver. The options are:
 
 size
    Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
@@ -99,6 +97,57 @@
    This parameter works only with the ToUCam range of cameras (730, 740,
    750). For other cameras this command is silently ignored, and the LED
    cannot be controlled.
+
+dev_hint
+   A long standing problem with USB devices is their dynamic nature: you
+   never know what device a camera gets assigned; it depends on module load
+   order, the hub configuration, the order in which devices are plugged in,
+   and the phase of the moon (i.e. it can be random). With this option you
+   can give the driver a hint as to what video device node (/dev/videoX) it
+   should use with a specific camera. This is also handy if you have two
+   cameras of the same model.
+
+   A camera is specified by its type (the number from the camera model,
+   like PCA645, PCVC750VC, etc) and optionally the serial number (visible
+   in /proc/bus/usb/devices). A hint consists of a string with the following
+   format:
+
+      [type[.serialnumber]:]node
+      
+   The square brackets mean that both the type and the serialnumber are
+   optional, but a serialnumber cannot be specified without a type (which
+   would be rather pointless). The serialnumber is separated from the type
+   by a '.'; the node number by a ':'.
+   
+   This somewhat cryptic syntax is best explained by a few examples:
+
+     dev_hint=3,5              The first detected cam gets assigned
+                               /dev/video3, the second /dev/video5. Any
+                               other cameras will get the first free 
+                               available slot (see below).
+
+     dev_hint=645:1,680=2      The PCA645 camera will get /dev/video1,
+                               and a PCVC680 /dev/video2.
+                               
+     dev_hint=645.0123:3,645.4567:0	The PCA645 camera with serialnumber 
+                                        0123 goes to /dev/video3, the same
+                                        camera model with the 4567 serial
+                                        gets /dev/video0.
+
+     dev_hint=750:1,4,5,6       The PCVC750 camera will get /dev/video1, the 
+                                next 3 Philips cams will use /dev/video4 
+                                through /dev/video6.
+
+   Some points worth knowing:
+   - Serialnumbers are case sensitive and must be written full, including 
+     leading zeroes (it's treated as a string).
+   - If a device node is already occupied, registration will fail and 
+     the webcam is not available.
+   - You can have up to 64 video devices; be sure to make enough device
+     nodes in /dev if you want to spread the numbers (this does not apply
+     to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA).
+   - If a camera does not match any dev_hint, it will simply get assigned
+     the first available device node, just as it used to be.
 
 trace
    In order to better detect problems, it is now possible to turn on a
diff -u --recursive --new-file v2.5.0/linux/Documentation/usb/scanner.txt linux/Documentation/usb/scanner.txt
--- v2.5.0/linux/Documentation/usb/scanner.txt	Sat Oct 20 19:13:11 2001
+++ linux/Documentation/usb/scanner.txt	Sat Dec  8 20:28:44 2001
@@ -83,7 +83,7 @@
 	`mknod /dev/usbscanner1 c 180 49`
                       . 
                       .
-	`mknod /dev/usbscanner15 180 63`
+	`mknod /dev/usbscanner15 c 180 63`
 
 
 If you foresee using only one scanner it is best to:
diff -u --recursive --new-file v2.5.0/linux/MAINTAINERS linux/MAINTAINERS
--- v2.5.0/linux/MAINTAINERS	Fri Nov 16 10:03:24 2001
+++ linux/MAINTAINERS	Mon Dec 10 10:39:20 2001
@@ -148,8 +148,8 @@
 ACPI
 P:	Andy Grover
 M:	andrew.grover@intel.com
-L:	acpi@phobos.fs.tum.de
-W:	http://phobos.fs.tum.de/acpi/index.html
+L:	acpi-devel@lists.sourceforge.net
+W:	http://sf.net/projects/acpi/
 S:	Maintained
 
 AD1816 SOUND DRIVER
@@ -285,6 +285,14 @@
 M:	Nils Faerber <nils@kernelconcepts.de>
 S:	Maintained
 
+CODA FILE SYSTEM
+P:	Jan Harkes
+M:	jaharkes@cs.cmu.edu
+M:	coda@cs.cmu.edu
+L:	codalist@coda.cs.cmu.edu
+W:	http://www.coda.cs.cmu.edu/
+S:	Maintained
+
 COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
 P:      Amy Vanzant-Hodge 
 M:      Amy Vanzant-Hodge (fibrechannel@compaq.com)
@@ -1660,8 +1668,8 @@
 W:	http://misc.nu/hugh/keyspan/
 
 USB SUBSYSTEM
-P:	Johannes Erdfelt
-M:	johannes@erdfelt.com
+P:	Greg Kroah-Hartman
+M:	greg@kroah.com
 L:	linux-usb-users@lists.sourceforge.net
 L:	linux-usb-devel@lists.sourceforge.net
 W:	http://www.linux-usb.org
@@ -1684,10 +1692,8 @@
 
 VIA 82Cxxx AUDIO DRIVER
 P:	Jeff Garzik
-M:	jgarzik@mandrakesoft.com
 L:	linux-via@gtf.org
-W:	http://sourceforge.net/projects/gkernel/
-S:	Maintained
+S:	Odd fixes
 
 USB DIAMOND RIO500 DRIVER
 P:	Cesar Miquel
diff -u --recursive --new-file v2.5.0/linux/Makefile linux/Makefile
--- v2.5.0/linux/Makefile	Thu Nov 22 22:23:44 2001
+++ linux/Makefile	Tue Dec 11 10:20:37 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 0
-EXTRAVERSION =
+SUBLEVEL = 1
+EXTRAVERSION =-pre10
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -257,8 +257,8 @@
 boot: vmlinux
 	@$(MAKE) CFLAGS="$(CFLAGS) $(CFLAGS_KERNEL)" -C arch/$(ARCH)/boot
 
-vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
-	$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
+vmlinux: include/linux/version.h $(CONFIGURATION) init/main.o init/version.o init/do_mounts.o linuxsubdirs
+	$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o init/do_mounts.o \
 		--start-group \
 		$(CORE_FILES) \
 		$(DRIVERS) \
@@ -333,6 +333,9 @@
 	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) -DUTS_MACHINE='"$(ARCH)"' -c -o init/version.o init/version.c
 
 init/main.o: init/main.c include/config/MARKER
+	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<
+
+init/do_mounts.o: init/do_mounts.c include/config/MARKER
 	$(CC) $(CFLAGS) $(CFLAGS_KERNEL) $(PROFILING) -c -o $*.o $<
 
 fs lib mm ipc kernel drivers net: dummy
diff -u --recursive --new-file v2.5.0/linux/README linux/README
--- v2.5.0/linux/README	Fri Oct  5 12:10:00 2001
+++ linux/README	Fri Nov 30 08:54:18 2001
@@ -1,9 +1,12 @@
-	Linux kernel release 2.4.xx
+	Linux kernel release 2.5.xx
 
-These are the release notes for Linux version 2.4.  Read them carefully,
+These are the release notes for Linux version 2.5.  Read them carefully,
 as they tell you what this is all about, explain how to install the
 kernel, and what to do if something goes wrong. 
 
+NOTE! As with all odd-numbered releases, 2.5.x is a development kernel. 
+For stable kernels, see the 2.4.x maintained by Marcelo Tosatti.
+
 WHAT IS LINUX?
 
   Linux is a Unix clone written from scratch by Linus Torvalds with
@@ -52,7 +55,7 @@
    directory where you have permissions (eg. your home directory) and
    unpack it:
 
-		gzip -cd linux-2.4.XX.tar.gz | tar xvf -
+		gzip -cd linux-2.5.XX.tar.gz | tar xvf -
 
    Replace "XX" with the version number of the latest kernel.
 
@@ -61,7 +64,7 @@
    files.  They should match the library, and not get messed up by
    whatever the kernel-du-jour happens to be.
 
- - You can also upgrade between 2.4.xx releases by patching.  Patches are
+ - You can also upgrade between 2.5.xx releases by patching.  Patches are
    distributed in the traditional gzip and the new bzip2 format.  To
    install by patching, get all the newer patch files, enter the
    directory in which you unpacked the kernel source and execute:
@@ -96,7 +99,7 @@
 
 SOFTWARE REQUIREMENTS
 
-   Compiling and running the 2.4.xx kernels requires up-to-date
+   Compiling and running the 2.5.xx kernels requires up-to-date
    versions of various software packages.  Consult
    ./Documentation/Changes for the minimum version numbers required
    and how to get updates for these packages.  Beware that using
@@ -150,13 +153,12 @@
 
 COMPILING the kernel:
 
- - Make sure you have gcc-2.91.66 (egcs-1.1.2) available.  gcc 2.95.2 may
+ - Make sure you have gcc 2.95.3 available.  gcc 2.91.66 (egcs-1.1.2) may
    also work but is not as safe, and *gcc 2.7.2.3 is no longer supported*.
    Also remember to upgrade your binutils package (for as/ld/nm and company)
    if necessary. For more information, refer to ./Documentation/Changes.
 
-   Please note that you can still run a.out user programs with this
-   kernel.
+   Please note that you can still run a.out user programs with this kernel.
 
  - Do a "make bzImage" to create a compressed kernel image.  If you want
    to make a boot disk (without root filesystem or LILO), insert a floppy
diff -u --recursive --new-file v2.5.0/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.5.0/linux/arch/alpha/kernel/alpha_ksyms.c	Tue Nov 20 15:49:31 2001
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Sun Nov 25 09:45:10 2001
@@ -109,6 +109,7 @@
 EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(__memsetw);
diff -u --recursive --new-file v2.5.0/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.5.0/linux/arch/alpha/kernel/irq.c	Mon Sep 17 13:16:30 2001
+++ linux/arch/alpha/kernel/irq.c	Wed Nov 28 13:22:25 2001
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -514,64 +515,63 @@
 }
 
 int
-get_irq_list(char *buf)
+show_interrupts(struct seq_file *p, void *v)
 {
 #ifdef CONFIG_SMP
 	int j;
 #endif
 	int i;
 	struct irqaction * action;
-	char *p = buf;
 
 #ifdef CONFIG_SMP
-	p += sprintf(p, "           ");
+	seq_puts(p, "           ");
 	for (i = 0; i < smp_num_cpus; i++)
-		p += sprintf(p, "CPU%d       ", i);
+		seq_printf(p, "CPU%d       ", i);
 #ifdef DO_BROADCAST_INTS
 	for (i = 0; i < smp_num_cpus; i++)
-		p += sprintf(p, "TRY%d       ", i);
+		seq_printf(p, "TRY%d       ", i);
 #endif
-	*p++ = '\n';
+	seq_putc(p, '\n');
 #endif
 
 	for (i = 0; i < NR_IRQS; i++) {
 		action = irq_desc[i].action;
 		if (!action) 
 			continue;
-		p += sprintf(p, "%3d: ",i);
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < smp_num_cpus; j++)
-			p += sprintf(p, "%10u ",
+			seq_printf(p, "%10u ",
 				     kstat.irqs[cpu_logical_map(j)][i]);
 #ifdef DO_BROADCAST_INTS
 		for (j = 0; j < smp_num_cpus; j++)
-			p += sprintf(p, "%10lu ",
+			seq_printf(p, "%10lu ",
 				     irq_attempt(cpu_logical_map(j), i));
 #endif
 #endif
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %c%s",
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %c%s",
 			     (action->flags & SA_INTERRUPT)?'+':' ',
 			     action->name);
 
 		for (action=action->next; action; action = action->next) {
-			p += sprintf(p, ", %c%s",
+			seq_printf(p, ", %c%s",
 				     (action->flags & SA_INTERRUPT)?'+':' ',
 				     action->name);
 		}
-		*p++ = '\n';
+		seq_putc(p, '\n');
 	}
 #if CONFIG_SMP
-	p += sprintf(p, "IPI: ");
+	seq_puts(p, "IPI: ");
 	for (j = 0; j < smp_num_cpus; j++)
-		p += sprintf(p, "%10lu ",
+		seq_printf(p, "%10lu ",
 			     cpu_data[cpu_logical_map(j)].ipi_count);
-	p += sprintf(p, "\n");
+	seq_putc(p, '\n');
 #endif
-	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
-	return p - buf;
+	seq_printf(p, "ERR: %10lu\n", irq_err_count);
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/alpha/kernel/irq_i8259.c linux/arch/alpha/kernel/irq_i8259.c
--- v2.5.0/linux/arch/alpha/kernel/irq_i8259.c	Mon Jun 19 17:59:32 2000
+++ linux/arch/alpha/kernel/irq_i8259.c	Mon Dec 10 13:52:53 2001
@@ -22,7 +22,7 @@
 
 /* Note mask bit is true for DISABLED irqs.  */
 static unsigned int cached_irq_mask = 0xffff;
-spinlock_t i8259_irq_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t i8259_irq_lock = SPIN_LOCK_UNLOCKED;
 
 static inline void
 i8259_update_irq_hw(unsigned int irq, unsigned long mask)
diff -u --recursive --new-file v2.5.0/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c
--- v2.5.0/linux/arch/arm/kernel/fiq.c	Wed Jun 27 14:12:04 2001
+++ linux/arch/arm/kernel/fiq.c	Wed Nov 28 13:22:25 2001
@@ -40,6 +40,7 @@
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/fiq.h>
 #include <asm/io.h>
@@ -92,15 +93,12 @@
 
 static struct fiq_handler *current_fiq = &default_owner;
 
-int get_fiq_list(char *buf)
+int show_fiq_list(struct seq_file *p, void *v)
 {
-	char *p = buf;
-
 	if (current_fiq != &default_owner)
-		p += sprintf(p, "FIQ:              %s\n",
-			     current_fiq->name);
+		seq_printf(p, "FIQ:              %s\n", current_fiq->name);
 
-	return p - buf;
+	return 0;
 }
 
 void set_fiq_handler(void *start, unsigned int length)
diff -u --recursive --new-file v2.5.0/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c
--- v2.5.0/linux/arch/arm/kernel/irq.c	Wed Jul  4 14:56:44 2001
+++ linux/arch/arm/kernel/irq.c	Wed Nov 28 13:22:25 2001
@@ -28,6 +28,7 @@
 #include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -95,29 +96,28 @@
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 	int i;
 	struct irqaction * action;
-	char *p = buf;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 	    	action = irq_desc[i].action;
 		if (!action)
 			continue;
-		p += sprintf(p, "%3d: %10u ", i, kstat_irqs(i));
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, "%3d: %10u ", i, kstat_irqs(i));
+		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next) {
-			p += sprintf(p, ", %s", action->name);
+			seq_printf(p, ", %s", action->name);
 		}
-		*p++ = '\n';
+		seq_putc(p, '\n');
 	}
 
 #ifdef CONFIG_ARCH_ACORN
-	p += get_fiq_list(p);
+	show_fiq_list(p);
 #endif
-	p += sprintf(p, "Err: %10lu\n", irq_err_count);
-	return p - buf;
+	seq_printf(p, "Err: %10lu\n", irq_err_count);
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/arch/cris/kernel/irq.c linux/arch/cris/kernel/irq.c
--- v2.5.0/linux/arch/cris/kernel/irq.c	Thu Jul 26 15:10:06 2001
+++ linux/arch/cris/kernel/irq.c	Wed Nov 28 13:22:25 2001
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -223,27 +224,27 @@
 	NULL, NULL, NULL, NULL
 };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	struct irqaction * action;
 
 	for (i = 0; i < NR_IRQS; i++) {
 		action = irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %10u %c %s",
+		seq_printf(p, "%2d: %10u %c %s",
 			i, kstat.irqs[0][i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action = action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, "\n");
+		seq_putc(p, '\n');
 	}
-	return len;
+	return 0;
 }
 
 /* called by the assembler IRQ entry functions defined in irq.h
diff -u --recursive --new-file v2.5.0/linux/arch/i386/boot/bootsect.S linux/arch/i386/boot/bootsect.S
--- v2.5.0/linux/arch/i386/boot/bootsect.S	Fri Nov  9 13:58:02 2001
+++ linux/arch/i386/boot/bootsect.S	Wed Nov 28 14:07:46 2001
@@ -236,7 +236,7 @@
 rp_read:
 #ifdef __BIG_KERNEL__			# look in setup.S for bootsect_kludge
 	bootsect_kludge = 0x220		# 0x200 + 0x20 which is the size of the
-	lcall	bootsect_kludge		# bootsector + bootsect_kludge offset
+	lcall	*bootsect_kludge	# bootsector + bootsect_kludge offset
 #else
 	movw	%es, %ax
 	subw	$SYSSEG, %ax
diff -u --recursive --new-file v2.5.0/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S
--- v2.5.0/linux/arch/i386/boot/setup.S	Fri Nov  9 13:58:02 2001
+++ linux/arch/i386/boot/setup.S	Wed Nov 28 10:24:33 2001
@@ -539,7 +539,7 @@
 	cmpw	$0, %cs:realmode_swtch
 	jz	rmodeswtch_normal
 
-	lcall	%cs:realmode_swtch
+	lcall	*%cs:realmode_swtch
 
 	jmp	rmodeswtch_end
 
diff -u --recursive --new-file v2.5.0/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.5.0/linux/arch/i386/defconfig	Mon Nov 12 11:59:03 2001
+++ linux/arch/i386/defconfig	Sat Dec  8 20:30:25 2001
@@ -286,7 +286,6 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
-CONFIG_SCSI_DEBUG_QUEUES=y
 CONFIG_SCSI_MULTI_LUN=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -431,6 +430,7 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_NET_POCKET is not set
 
diff -u --recursive --new-file v2.5.0/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.5.0/linux/arch/i386/kernel/apm.c	Fri Nov  9 13:58:02 2001
+++ linux/arch/i386/kernel/apm.c	Fri Nov 30 08:38:44 2001
@@ -387,6 +387,7 @@
 static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue);
 static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue);
 static struct apm_user *	user_list;
+static spinlock_t		user_list_lock = SPIN_LOCK_UNLOCKED;
 
 static char			driver_version[] = "1.15";	/* no spaces */
 
@@ -526,7 +527,7 @@
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
-		"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
+		"lcall *%%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
 		"setc %%al\n\t"
 		"popl %%ebp\n\t"
 		"popl %%edi\n\t"
@@ -573,7 +574,7 @@
 		__asm__ __volatile__(APM_DO_ZERO_SEGS
 			"pushl %%edi\n\t"
 			"pushl %%ebp\n\t"
-			"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
+			"lcall *%%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
 			"setc %%bl\n\t"
 			"popl %%ebp\n\t"
 			"popl %%edi\n\t"
@@ -1053,8 +1054,9 @@
 {
 	struct apm_user *	as;
 
+	spin_lock(&user_list_lock);
 	if (user_list == NULL)
-		return;
+		goto out;
 	for (as = user_list; as != NULL; as = as->next) {
 		if ((as == sender) || (!as->reader))
 			continue;
@@ -1084,6 +1086,8 @@
 		}
 	}
 	wake_up_interruptible(&apm_waitqueue);
+out:
+	spin_unlock(&user_list_lock);
 }
 
 static void set_time(void)
@@ -1179,10 +1183,12 @@
 	send_event(APM_NORMAL_RESUME);
 	sti();
 	queue_event(APM_NORMAL_RESUME, NULL);
+	spin_lock(&user_list_lock);
 	for (as = user_list; as != NULL; as = as->next) {
 		as->suspend_wait = 0;
 		as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
 	}
+	spin_unlock(&user_list_lock);
 	ignore_normal_resume = 1;
 	wake_up_interruptible(&apm_suspend_waitqueue);
 	return err;
@@ -1519,7 +1525,6 @@
 	if (check_apm_user(as, "release"))
 		return 0;
 	filp->private_data = NULL;
-	lock_kernel();
 	if (as->standbys_pending > 0) {
 		standbys_pending -= as->standbys_pending;
 		if (standbys_pending <= 0)
@@ -1530,6 +1535,7 @@
 		if (suspends_pending <= 0)
 			(void) suspend();
 	}
+  	spin_lock(&user_list_lock);
 	if (user_list == as)
 		user_list = as->next;
 	else {
@@ -1544,7 +1550,7 @@
 		else
 			as1->next = as->next;
 	}
-	unlock_kernel();
+	spin_unlock(&user_list_lock);
 	kfree(as);
 	return 0;
 }
@@ -1573,8 +1579,10 @@
 	as->suser = capable(CAP_SYS_ADMIN);
 	as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE;
 	as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ;
+	spin_lock(&user_list_lock);
 	as->next = user_list;
 	user_list = as;
+	spin_unlock(&user_list_lock);
 	filp->private_data = as;
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
--- v2.5.0/linux/arch/i386/kernel/dmi_scan.c	Sun Nov 11 10:38:46 2001
+++ linux/arch/i386/kernel/dmi_scan.c	Thu Dec  6 14:01:17 2001
@@ -191,6 +191,7 @@
  *	corruption problems
  */ 
  
+#if 0
 static __init int disable_ide_dma(struct dmi_blacklist *d)
 {
 #ifdef CONFIG_BLK_DEV_IDE
@@ -203,6 +204,7 @@
 #endif	
 	return 0;
 }
+#endif
 
 /* 
  * Reboot options and system auto-detection code provided by
@@ -521,6 +523,12 @@
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "R0121Z1"),
 			MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
+			} },
+
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z600NE */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "WME01Z1"),
+			MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
 			} },
 
 	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
diff -u --recursive --new-file v2.5.0/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.5.0/linux/arch/i386/kernel/irq.c	Thu Oct 25 13:53:46 2001
+++ linux/arch/i386/kernel/irq.c	Wed Nov 28 13:22:25 2001
@@ -32,6 +32,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -131,57 +132,53 @@
  * Generic, controller-independent functions:
  */
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 	int i, j;
 	struct irqaction * action;
-	char *p = buf;
 
-	p += sprintf(p, "           ");
+	seq_printf(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
-		p += sprintf(p, "CPU%d       ",j);
-	*p++ = '\n';
+		seq_printf(p, "CPU%d       ",j);
+	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		action = irq_desc[i].action;
 		if (!action) 
 			continue;
-		p += sprintf(p, "%3d: ",i);
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < smp_num_cpus; j++)
-			p += sprintf(p, "%10u ",
+			seq_printf(p, "%10u ",
 				kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-			p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
+			seq_printf(p, ", %s", action->name);
+		seq_putc(p, '\n');
 	}
-	p += sprintf(p, "NMI: ");
+	seq_printf(p, "NMI: ");
 	for (j = 0; j < smp_num_cpus; j++)
-		p += sprintf(p, "%10u ",
-			nmi_count(cpu_logical_map(j)));
-	p += sprintf(p, "\n");
+		seq_printf(p, "%10u ", nmi_count(cpu_logical_map(j)));
+	seq_putc(p, '\n');
 #if CONFIG_X86_LOCAL_APIC
-	p += sprintf(p, "LOC: ");
+	seq_printf(p, "LOC: ");
 	for (j = 0; j < smp_num_cpus; j++)
-		p += sprintf(p, "%10u ",
-			apic_timer_irqs[cpu_logical_map(j)]);
-	p += sprintf(p, "\n");
+		seq_printf(p, "%10u ", apic_timer_irqs[cpu_logical_map(j)]);
+	seq_putc(p, '\n');
 #endif
-	p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 #ifdef CONFIG_X86_IO_APIC
 #ifdef APIC_MISMATCH_DEBUG
-	p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
 #endif
 #endif
-	return p - buf;
+	return 0;
 }
-
 
 /*
  * Global interrupt locks for SMP. Allow interrupts to come in on any
diff -u --recursive --new-file v2.5.0/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.5.0/linux/arch/i386/kernel/mtrr.c	Fri Nov  9 13:58:02 2001
+++ linux/arch/i386/kernel/mtrr.c	Fri Nov 30 08:26:04 2001
@@ -1788,7 +1788,6 @@
     unsigned int *fcount = file->private_data;
 
     if (fcount == NULL) return 0;
-    lock_kernel();
     max = get_num_var_ranges ();
     for (i = 0; i < max; ++i)
     {
@@ -1798,7 +1797,6 @@
 	    --fcount[i];
 	}
     }
-    unlock_kernel();
     kfree (fcount);
     file->private_data = NULL;
     return 0;
diff -u --recursive --new-file v2.5.0/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.5.0/linux/arch/i386/kernel/pci-pc.c	Fri Nov  9 13:58:02 2001
+++ linux/arch/i386/kernel/pci-pc.c	Fri Dec  7 16:26:13 2001
@@ -458,7 +458,7 @@
 	unsigned long flags;
 
 	__save_flags(flags); __cli();
-	__asm__("lcall (%%edi); cld"
+	__asm__("lcall *(%%edi); cld"
 		: "=a" (return_code),
 		  "=b" (address),
 		  "=c" (length),
@@ -499,7 +499,7 @@
 
 		__save_flags(flags); __cli();
 		__asm__(
-			"lcall (%%edi); cld\n\t"
+			"lcall *(%%edi); cld\n\t"
 			"jc 1f\n\t"
 			"xor %%ah, %%ah\n"
 			"1:"
@@ -544,7 +544,7 @@
 	unsigned short bx;
 	unsigned short ret;
 
-	__asm__("lcall (%%edi); cld\n\t"
+	__asm__("lcall *(%%edi); cld\n\t"
 		"jc 1f\n\t"
 		"xor %%ah, %%ah\n"
 		"1:"
@@ -573,7 +573,7 @@
 
 	switch (len) {
 	case 1:
-		__asm__("lcall (%%esi); cld\n\t"
+		__asm__("lcall *(%%esi); cld\n\t"
 			"jc 1f\n\t"
 			"xor %%ah, %%ah\n"
 			"1:"
@@ -585,7 +585,7 @@
 			  "S" (&pci_indirect));
 		break;
 	case 2:
-		__asm__("lcall (%%esi); cld\n\t"
+		__asm__("lcall *(%%esi); cld\n\t"
 			"jc 1f\n\t"
 			"xor %%ah, %%ah\n"
 			"1:"
@@ -597,7 +597,7 @@
 			  "S" (&pci_indirect));
 		break;
 	case 4:
-		__asm__("lcall (%%esi); cld\n\t"
+		__asm__("lcall *(%%esi); cld\n\t"
 			"jc 1f\n\t"
 			"xor %%ah, %%ah\n"
 			"1:"
@@ -628,7 +628,7 @@
 
 	switch (len) {
 	case 1:
-		__asm__("lcall (%%esi); cld\n\t"
+		__asm__("lcall *(%%esi); cld\n\t"
 			"jc 1f\n\t"
 			"xor %%ah, %%ah\n"
 			"1:"
@@ -640,7 +640,7 @@
 			  "S" (&pci_indirect));
 		break;
 	case 2:
-		__asm__("lcall (%%esi); cld\n\t"
+		__asm__("lcall *(%%esi); cld\n\t"
 			"jc 1f\n\t"
 			"xor %%ah, %%ah\n"
 			"1:"
@@ -652,7 +652,7 @@
 			  "S" (&pci_indirect));
 		break;
 	case 4:
-		__asm__("lcall (%%esi); cld\n\t"
+		__asm__("lcall *(%%esi); cld\n\t"
 			"jc 1f\n\t"
 			"xor %%ah, %%ah\n"
 			"1:"
@@ -875,7 +875,7 @@
 	__asm__("push %%es\n\t"
 		"push %%ds\n\t"
 		"pop  %%es\n\t"
-		"lcall (%%esi); cld\n\t"
+		"lcall *(%%esi); cld\n\t"
 		"pop %%es\n\t"
 		"jc 1f\n\t"
 		"xor %%ah, %%ah\n"
@@ -908,7 +908,7 @@
 {
 	int ret;
 
-	__asm__("lcall (%%esi); cld\n\t"
+	__asm__("lcall *(%%esi); cld\n\t"
 		"jc 1f\n\t"
 		"xor %%ah, %%ah\n"
 		"1:"
@@ -1114,17 +1114,26 @@
  * But it does seem to fix some unspecified problem
  * with 'movntq' copies on Athlons.
  *
- * VIA 8363 chipset:
- *  - bit 7 at offset 0x55: Debug (RW)
+ * VIA 8363,8622,8361 Northbridges:
+ *  - bits  5, 6, 7 at offset 0x55 need to be turned off
+ * VIA 8367 (KT266x) Northbridges:
+ *  - bits  5, 6, 7 at offset 0x95 need to be turned off
  */
 static void __init pci_fixup_via_athlon_bug(struct pci_dev *d)
 {
 	u8 v;
-	pci_read_config_byte(d, 0x55, &v);
-	if (v & 0x80) {
+	int where = 0x55;
+
+	if (d->device == PCI_DEVICE_ID_VIA_8367_0) {
+  	        where = 0x95; /* the memory write queue timer register is 
+                                 different for the kt266x's: 0x95 not 0x55 */
+	}
+
+        pci_read_config_byte(d, where, &v);
+	if (v & 0xe0) {
 		printk("Trying to stomp on Athlon bug...\n");
-		v &= 0x7f; /* clear bit 55.7 */
-		pci_write_config_byte(d, 0x55, v);
+		v &= 0x1f; /* clear bits 5, 6, 7 */
+		pci_write_config_byte(d, where, v);
 	}
 }
 
@@ -1138,6 +1147,9 @@
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5598,		pci_fixup_latency },
  	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	pci_fixup_piix4_acpi },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	pci_fixup_via_athlon_bug },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8622,	        pci_fixup_via_athlon_bug },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,	        pci_fixup_via_athlon_bug },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8367_0,	pci_fixup_via_athlon_bug },
 	{ 0 }
 };
 
diff -u --recursive --new-file v2.5.0/linux/arch/i386/kernel/semaphore.c linux/arch/i386/kernel/semaphore.c
--- v2.5.0/linux/arch/i386/kernel/semaphore.c	Fri Nov  9 13:58:02 2001
+++ linux/arch/i386/kernel/semaphore.c	Fri Nov 30 08:54:18 2001
@@ -238,31 +238,30 @@
  */
 #if defined(CONFIG_SMP)
 asm(
-"
-.align	4
-.globl	__write_lock_failed
-__write_lock_failed:
-	" LOCK "addl	$" RW_LOCK_BIAS_STR ",(%eax)
-1:	rep; nop
-	cmpl	$" RW_LOCK_BIAS_STR ",(%eax)
-	jne	1b
+".text\n"
+".align	4\n"
+".globl	__write_lock_failed\n"
+"__write_lock_failed:\n\t"
+	LOCK "addl	$" RW_LOCK_BIAS_STR ",(%eax)\n"
+"1:	rep; nop\n\t"
+	"cmpl	$" RW_LOCK_BIAS_STR ",(%eax)\n\t"
+	"jne	1b\n\t"
+	LOCK "subl	$" RW_LOCK_BIAS_STR ",(%eax)\n\t"
+	"jnz	__write_lock_failed\n\t"
+	"ret"
+);
 
-	" LOCK "subl	$" RW_LOCK_BIAS_STR ",(%eax)
-	jnz	__write_lock_failed
-	ret
-
-
-.align	4
-.globl	__read_lock_failed
-__read_lock_failed:
-	lock ; incl	(%eax)
-1:	rep; nop
-	cmpl	$1,(%eax)
-	js	1b
-
-	lock ; decl	(%eax)
-	js	__read_lock_failed
-	ret
-"
+asm(
+".text\n"
+".align	4\n"
+".globl	__read_lock_failed\n"
+"__read_lock_failed:\n\t"
+	LOCK "incl	(%eax)\n"
+"1:	rep; nop\n\t"
+	"cmpl	$1,(%eax)\n\t"
+	"js	1b\n\t"
+	LOCK "decl	(%eax)\n\t"
+	"js	__read_lock_failed\n\t"
+	"ret"
 );
 #endif
diff -u --recursive --new-file v2.5.0/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.5.0/linux/arch/i386/kernel/setup.c	Mon Nov 19 15:16:13 2001
+++ linux/arch/i386/kernel/setup.c	Tue Nov 27 09:23:27 2001
@@ -157,6 +157,7 @@
 extern void mcheck_init(struct cpuinfo_x86 *c);
 extern int root_mountflags;
 extern char _text, _etext, _edata, _end;
+extern int blk_nohighio;
 
 static int disable_x86_serial_nr __initdata = 1;
 static int disable_x86_fxsr __initdata = 0;
@@ -782,7 +783,7 @@
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long bootmap_size, low_mem_size;
-	unsigned long start_pfn, max_pfn, max_low_pfn;
+	unsigned long start_pfn, max_low_pfn;
 	int i;
 
 #ifdef CONFIG_VISWS
@@ -1067,6 +1068,14 @@
 __setup("notsc", tsc_setup);
 #endif
 
+static int __init highio_setup(char *str)
+{
+	printk("i386: disabling HIGHMEM block I/O\n");
+	blk_nohighio = 1;
+	return 1;
+}
+__setup("nohighio", highio_setup);
+ 
 static int __init get_model_name(struct cpuinfo_x86 *c)
 {
 	unsigned int *v;
diff -u --recursive --new-file v2.5.0/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.5.0/linux/arch/i386/kernel/traps.c	Sun Sep 30 12:26:08 2001
+++ linux/arch/i386/kernel/traps.c	Sun Nov 25 09:48:47 2001
@@ -697,7 +697,7 @@
  */
 asmlinkage void math_state_restore(struct pt_regs regs)
 {
-	__asm__ __volatile__("clts");		/* Allow maths ops (or we recurse) */
+	clts();		/* Allow maths ops (or we recurse) */
 
 	if (current->used_math) {
 		restore_fpu(current);
diff -u --recursive --new-file v2.5.0/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.5.0/linux/arch/i386/mm/init.c	Sun Nov 11 10:09:32 2001
+++ linux/arch/i386/mm/init.c	Sun Nov 25 09:48:47 2001
@@ -25,6 +25,7 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/bootmem.h>
+#include <linux/slab.h>
 
 #include <asm/processor.h>
 #include <asm/system.h>
@@ -333,7 +334,7 @@
 {
 	pagetable_init();
 
-	__asm__( "movl %%ecx,%%cr3\n" ::"c"(__pa(swapper_pg_dir)));
+	__asm__( "movl %0,%%cr3\n" ::"r"(__pa(swapper_pg_dir)));
 
 #if CONFIG_X86_PAE
 	/*
@@ -596,3 +597,17 @@
 	val->mem_unit = PAGE_SIZE;
 	return;
 }
+
+#if defined(CONFIG_X86_PAE)
+struct kmem_cache_s *pae_pgd_cachep;
+void __init pgtable_cache_init(void)
+{
+	/*
+	 * PAE pgds must be 16-byte aligned:
+	 */
+	pae_pgd_cachep = kmem_cache_create("pae_pgd", 32, 0,
+		SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
+	if (!pae_pgd_cachep)
+		panic("init_pae(): Cannot alloc pae_pgd SLAB cache");
+}
+#endif /* CONFIG_X86_PAE */
diff -u --recursive --new-file v2.5.0/linux/arch/ia64/kernel/efivars.c linux/arch/ia64/kernel/efivars.c
--- v2.5.0/linux/arch/ia64/kernel/efivars.c	Fri Nov  9 14:26:17 2001
+++ linux/arch/ia64/kernel/efivars.c	Mon Dec 10 13:52:53 2001
@@ -100,7 +100,7 @@
 	struct list_head        list;
 } efivar_entry_t;
 
-spinlock_t efivars_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t efivars_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(efivar_list);
 static struct proc_dir_entry *efi_vars_dir = NULL;
 
diff -u --recursive --new-file v2.5.0/linux/arch/ia64/kernel/irq.c linux/arch/ia64/kernel/irq.c
--- v2.5.0/linux/arch/ia64/kernel/irq.c	Fri Nov  9 14:26:17 2001
+++ linux/arch/ia64/kernel/irq.c	Wed Nov 28 13:22:25 2001
@@ -32,6 +32,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/atomic.h>
 #include <asm/io.h>
@@ -131,55 +132,54 @@
  * Generic, controller-independent functions:
  */
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 	int i, j;
 	struct irqaction * action;
 	irq_desc_t *idesc;
-	char *p = buf;
 
-	p += sprintf(p, "           ");
+	seq_puts(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
-		p += sprintf(p, "CPU%d       ",j);
-	*p++ = '\n';
+		seq_printf(p, "CPU%d       ",j);
+	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		idesc = irq_desc(i);
 		action = idesc->action;
 		if (!action)
 			continue;
-		p += sprintf(p, "%3d: ",i);
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < smp_num_cpus; j++)
-			p += sprintf(p, "%10u ",
+			seq_printf(p, "%10u ",
 				kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-		p += sprintf(p, " %14s", idesc->handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, " %14s", idesc->handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-			p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
+			seq_printf(p, ", %s", action->name);
+		seq_putc('\n');
 	}
-	p += sprintf(p, "NMI: ");
+	seq_puts(p, "NMI: ");
 	for (j = 0; j < smp_num_cpus; j++)
-		p += sprintf(p, "%10u ",
+		seq_printf(p, "%10u ",
 			nmi_count(cpu_logical_map(j)));
-	p += sprintf(p, "\n");
+	seq_putc(p, '\n');
 #if defined(CONFIG_SMP) && defined(CONFIG_X86)
-	p += sprintf(p, "LOC: ");
+	seq_puts(p, "LOC: ");
 	for (j = 0; j < smp_num_cpus; j++)
-		p += sprintf(p, "%10u ",
+		seq_printf(p, "%10u ",
 			apic_timer_irqs[cpu_logical_map(j)]);
-	p += sprintf(p, "\n");
+	seq_putc(p, '\n');
 #endif
-	p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 #if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG)
-	p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+	seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
 #endif
-	return p - buf;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/ia64/kernel/pci.c linux/arch/ia64/kernel/pci.c
--- v2.5.0/linux/arch/ia64/kernel/pci.c	Fri Nov  9 14:26:17 2001
+++ linux/arch/ia64/kernel/pci.c	Mon Dec 10 13:52:53 2001
@@ -46,7 +46,7 @@
  * This interrupt-safe spinlock protects all accesses to PCI
  * configuration space.
  */
-spinlock_t pci_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t pci_lock = SPIN_LOCK_UNLOCKED;
 
 struct pci_fixup pcibios_fixups[] = {
 	{ 0 }
diff -u --recursive --new-file v2.5.0/linux/arch/ia64/sn/io/hubspc.c linux/arch/ia64/sn/io/hubspc.c
--- v2.5.0/linux/arch/ia64/sn/io/hubspc.c	Thu Apr  5 12:51:47 2001
+++ linux/arch/ia64/sn/io/hubspc.c	Mon Dec 10 13:52:53 2001
@@ -61,7 +61,7 @@
 }cpuprom_info_t;
 
 static cpuprom_info_t	*cpuprom_head;
-spinlock_t	cpuprom_spinlock;
+static spinlock_t	cpuprom_spinlock;
 #define	PROM_LOCK()	mutex_spinlock(&cpuprom_spinlock)
 #define	PROM_UNLOCK(s)	mutex_spinunlock(&cpuprom_spinlock, (s))
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/amiga/amiints.c linux/arch/m68k/amiga/amiints.c
--- v2.5.0/linux/arch/m68k/amiga/amiints.c	Mon Nov 27 17:57:34 2000
+++ linux/arch/m68k/amiga/amiints.c	Wed Nov 28 13:22:25 2001
@@ -40,6 +40,7 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -53,7 +54,7 @@
                            unsigned long flags, const char *devname, void *dev_id);
 extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id);
 extern void cia_init_IRQ(struct ciabase *base);
-extern int cia_get_irq_list(struct ciabase *base, char *buf);
+extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p);
 
 /* irq node variables for amiga interrupt sources */
 static irq_node_t *ami_irq_list[AMI_STD_IRQS];
@@ -468,28 +469,28 @@
 	ami_int4, ami_int5, ami_badint, ami_int7
 };
 
-int amiga_get_irq_list(char *buf)
+int show_amiga_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	irq_node_t *node;
 
 	for (i = 0; i < AMI_STD_IRQS; i++) {
 		if (!(node = ami_irq_list[i]))
 			continue;
-		len += sprintf(buf+len, "ami  %2d: %10u ", i,
+		seq_printf(p, "ami  %2d: %10u ", i,
 		               kstat.irqs[0][SYS_IRQS + i]);
 		do {
 			if (node->flags & SA_INTERRUPT)
-				len += sprintf(buf+len, "F ");
+				seq_puts(p, "F ");
 			else
-				len += sprintf(buf+len, "  ");
-			len += sprintf(buf+len, "%s\n", node->devname);
+				seq_puts(p, "  ");
+			seq_printf(p, "%s\n", node->devname);
 			if ((node = node->next))
-				len += sprintf(buf+len, "                    ");
+				seq_puts(p, "                    ");
 		} while (node);
 	}
 
-	len += cia_get_irq_list(&ciaa_base, buf+len);
-	len += cia_get_irq_list(&ciab_base, buf+len);
-	return len;
+	cia_get_irq_list(&ciaa_base, p);
+	cia_get_irq_list(&ciab_base, p);
+	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/amiga/cia.c linux/arch/m68k/amiga/cia.c
--- v2.5.0/linux/arch/m68k/amiga/cia.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/amiga/cia.c	Wed Nov 28 13:22:25 2001
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/irq.h>
 #include <asm/amigahw.h>
@@ -158,16 +159,16 @@
 	custom.intena = IF_SETCLR | base->int_mask;
 }
 
-int cia_get_irq_list(struct ciabase *base, char *buf)
+int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
 {
-	int i, j, len = 0;
+	int i, j;
 
 	j = base->cia_irq;
 	for (i = 0; i < CIA_IRQS; i++) {
-		len += sprintf(buf+len, "cia  %2d: %10d ", j + i,
+		seq_printf(p, "cia  %2d: %10d ", j + i,
 			       kstat.irqs[0][SYS_IRQS + j + i]);
-			len += sprintf(buf+len, "  ");
-		len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
+		seq_puts(p, "  ");
+		seq_printf(p, "%s\n", base->irq_list[i].devname);
 	}
-	return len;
+	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.5.0/linux/arch/m68k/amiga/config.c	Thu Sep 13 15:21:32 2001
+++ linux/arch/m68k/amiga/config.c	Wed Nov 28 13:22:25 2001
@@ -86,7 +86,7 @@
 extern void amiga_disable_irq (unsigned int);
 static void amiga_get_model(char *model);
 static int amiga_get_hardware_list(char *buffer);
-extern int amiga_get_irq_list (char *);
+extern int show_amiga_interrupts (struct seq_file *, void *);
 /* amiga specific timer functions */
 static unsigned long amiga_gettimeoffset (void);
 static void a3000_gettod (int *, int *, int *, int *, int *, int *);
@@ -403,7 +403,7 @@
   disable_irq          = amiga_disable_irq;
   mach_get_model       = amiga_get_model;
   mach_get_hardware_list = amiga_get_hardware_list;
-  mach_get_irq_list    = amiga_get_irq_list;
+  mach_get_irq_list    = show_amiga_interrupts;
   mach_gettimeoffset   = amiga_gettimeoffset;
   if (AMIGAHW_PRESENT(A3000_CLK)){
     mach_gettod  = a3000_gettod;
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/apollo/config.c linux/arch/m68k/apollo/config.c
--- v2.5.0/linux/arch/m68k/apollo/config.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/apollo/config.c	Wed Nov 28 13:22:25 2001
@@ -31,7 +31,7 @@
 extern void dn_free_irq(unsigned int irq, void *dev_id);
 extern void dn_enable_irq(unsigned int);
 extern void dn_disable_irq(unsigned int);
-extern int dn_get_irq_list(char *);
+extern int show_dn_interrupts(struct seq_file *, void *);
 extern unsigned long dn_gettimeoffset(void);
 extern void dn_gettod(int *, int *, int *, int *, int *, int *);
 extern int dn_dummy_hwclk(int, struct hwclk_time *);
@@ -173,7 +173,7 @@
 	mach_free_irq        = dn_free_irq;
 	enable_irq      = dn_enable_irq;
 	disable_irq     = dn_disable_irq;
-	mach_get_irq_list    = dn_get_irq_list;
+	mach_get_irq_list    = show_dn_interrupts;
 	mach_gettimeoffset   = dn_gettimeoffset;
 	mach_gettod	     = dn_gettod; /* */
 	mach_max_dma_address = 0xffffffff;
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/apollo/dn_ints.c linux/arch/m68k/apollo/dn_ints.c
--- v2.5.0/linux/arch/m68k/apollo/dn_ints.c	Tue Mar  6 19:44:35 2001
+++ linux/arch/m68k/apollo/dn_ints.c	Wed Nov 28 13:22:25 2001
@@ -104,7 +104,7 @@
 
 }
 
-int dn_get_irq_list(char *buf) {
+int show_dn_interrupts(struct seq_file *p, void *v) {
 
   printk("dn get irq list\n");
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/atari/ataints.c linux/arch/m68k/atari/ataints.c
--- v2.5.0/linux/arch/m68k/atari/ataints.c	Fri Aug  4 16:15:37 2000
+++ linux/arch/m68k/atari/ataints.c	Wed Nov 28 13:22:25 2001
@@ -40,6 +40,7 @@
 #include <linux/ptrace.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/traps.h>
@@ -609,37 +610,37 @@
 }
 
 
-int atari_get_irq_list(char *buf)
+int show_atari_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 
 	for (i = 0; i < NUM_INT_SOURCES; ++i) {
 		if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
 			continue;
 		if (i < STMFP_SOURCE_BASE)
-			len += sprintf(buf+len, "auto %2d: %10u ",
+			seq_printf(p,, "auto %2d: %10u ",
 				       i, kstat.irqs[0][i]);
 		else
-			len += sprintf(buf+len, "vec $%02x: %10u ",
+			seq_printf(p,, "vec $%02x: %10u ",
 				       IRQ_SOURCE_TO_VECTOR(i),
 				       kstat.irqs[0][i]);
 
 		if (irq_handler[i].handler != atari_call_irq_list) {
-			len += sprintf(buf+len, "%s\n", irq_param[i].devname);
+			seq_printf(p,, "%s\n", irq_param[i].devname);
 		}
 		else {
 			irq_node_t *p;
 			for( p = (irq_node_t *)irq_handler[i].dev_id; p; p = p->next ) {
-				len += sprintf(buf+len, "%s\n", p->devname);
+				seq_printf(p,, "%s\n", p->devname);
 				if (p->next)
-					len += sprintf( buf+len, "                    " );
+					seq_puts(p,, "                    " );
 			}
 		}
 	}
 	if (num_spurious)
-		len += sprintf(buf+len, "spurio.: %10u\n", num_spurious);
+		seq_printf(p, "spurio.: %10u\n", num_spurious);
 	
-	return len;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c
--- v2.5.0/linux/arch/m68k/atari/config.c	Mon Nov 27 17:57:34 2000
+++ linux/arch/m68k/atari/config.c	Wed Nov 28 13:22:25 2001
@@ -70,7 +70,7 @@
 extern void atari_free_irq (unsigned int irq, void *dev_id);
 extern void atari_enable_irq (unsigned int);
 extern void atari_disable_irq (unsigned int);
-extern int atari_get_irq_list (char *buf);
+extern int show_atari_interrupts (struct seq_file *, void *);
 extern void atari_mksound( unsigned int count, unsigned int ticks );
 #ifdef CONFIG_HEARTBEAT
 static void atari_heartbeat( int on );
@@ -265,7 +265,7 @@
     disable_irq          = atari_disable_irq;
     mach_get_model	 = atari_get_model;
     mach_get_hardware_list = atari_get_hardware_list;
-    mach_get_irq_list	 = atari_get_irq_list;
+    mach_get_irq_list	 = show_atari_interrupts;
     mach_gettimeoffset   = atari_gettimeoffset;
     mach_reset           = atari_reset;
 #ifdef CONFIG_ATARI_FLOPPY
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/atari/joystick.c linux/arch/m68k/atari/joystick.c
--- v2.5.0/linux/arch/m68k/atari/joystick.c	Wed Jul 12 21:58:42 2000
+++ linux/arch/m68k/atari/joystick.c	Fri Nov 30 08:26:04 2001
@@ -61,13 +61,11 @@
 {
     int minor = DEVICE_NR(inode->i_rdev);
 
-    lock_kernel();
     joystick[minor].active = 0;
     joystick[minor].ready = 0;
 
     if ((joystick[0].active == 0) && (joystick[1].active == 0))
 	ikbd_joystick_disable();
-    unlock_kernel();
     return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/bvme6000/bvmeints.c linux/arch/m68k/bvme6000/bvmeints.c
--- v2.5.0/linux/arch/m68k/bvme6000/bvmeints.c	Thu Dec 17 09:06:29 1998
+++ linux/arch/m68k/bvme6000/bvmeints.c	Wed Nov 28 13:22:25 2001
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/seq_file.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -127,17 +128,17 @@
 	}
 }
 
-int bvme6000_get_irq_list (char *buf)
+int show_bvme6000_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 
 	for (i = 0; i < 256; i++) {
 		if (irq_tab[i].count)
-			len += sprintf (buf+len, "Vec 0x%02x: %8d  %s\n",
+			seq_printf(p, "Vec 0x%02x: %8d  %s\n",
 			    i, irq_tab[i].count,
 			    irq_tab[i].devname ? irq_tab[i].devname : "free");
 	}
-	return len;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/bvme6000/config.c linux/arch/m68k/bvme6000/config.c
--- v2.5.0/linux/arch/m68k/bvme6000/config.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/bvme6000/config.c	Wed Nov 28 13:22:25 2001
@@ -36,7 +36,7 @@
 extern void bvme6000_process_int (int level, struct pt_regs *regs);
 extern void bvme6000_init_IRQ (void);
 extern void bvme6000_free_irq (unsigned int, void *);
-extern int  bvme6000_get_irq_list (char *);
+extern int  show_bvme6000_interrupts(struct seq_file *, void *);
 extern void bvme6000_enable_irq (unsigned int);
 extern void bvme6000_disable_irq (unsigned int);
 static void bvme6000_get_model(char *model);
@@ -145,7 +145,7 @@
     mach_reset		 = bvme6000_reset;
     mach_free_irq	 = bvme6000_free_irq;
     mach_process_int	 = bvme6000_process_int;
-    mach_get_irq_list	 = bvme6000_get_irq_list;
+    mach_get_irq_list	 = show_bvme6000_interrupts;
     mach_request_irq	 = bvme6000_request_irq;
     enable_irq		 = bvme6000_enable_irq;
     disable_irq          = bvme6000_disable_irq;
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/hp300/config.c linux/arch/m68k/hp300/config.c
--- v2.5.0/linux/arch/m68k/hp300/config.c	Thu Aug 26 12:42:31 1999
+++ linux/arch/m68k/hp300/config.c	Wed Nov 28 13:22:25 2001
@@ -25,7 +25,7 @@
 
 extern void hp300_reset(void);
 extern void (*hp300_default_handler[])(int, void *, struct pt_regs *);
-extern int hp300_get_irq_list(char *buf);
+extern int show_hp300_interrupts(struct seq_file *, void *);
 
 #ifdef CONFIG_VT
 extern int hp300_keyb_init(void);
@@ -70,7 +70,7 @@
   mach_request_irq     = hp300_request_irq;
   mach_free_irq        = hp300_free_irq;
   mach_get_model       = hp300_get_model;
-  mach_get_irq_list    = hp300_get_irq_list;
+  mach_get_irq_list    = show_hp300_interrupts;
   mach_gettimeoffset   = hp300_gettimeoffset;
   mach_default_handler = &hp300_default_handler;
 #if 0
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/hp300/ints.c linux/arch/m68k/hp300/ints.c
--- v2.5.0/linux/arch/m68k/hp300/ints.c	Wed Sep  8 11:59:00 1999
+++ linux/arch/m68k/hp300/ints.c	Wed Nov 28 13:22:25 2001
@@ -148,7 +148,7 @@
 	spin_unlock_irqrestore(&irqlist_lock, flags);
 }
 
-int hp300_get_irq_list(char *buf)
+int show_hp300_interrupts(struct seq_file *p, void *v)
 {
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c
--- v2.5.0/linux/arch/m68k/kernel/ints.c	Tue Mar  6 19:44:36 2001
+++ linux/arch/m68k/kernel/ints.c	Wed Nov 28 13:22:25 2001
@@ -242,22 +242,22 @@
 	}
 }
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 
 	/* autovector interrupts */
 	if (mach_default_handler) {
 		for (i = 0; i < SYS_IRQS; i++) {
-			len += sprintf(buf+len, "auto %2d: %10u ", i,
+			seq_printf(p, "auto %2d: %10u ", i,
 			               i ? kstat.irqs[0][i] : num_spurious);
-				len += sprintf(buf+len, "  ");
-			len += sprintf(buf+len, "%s\n", irq_list[i].devname);
+			seq_puts(p, "  ");
+			seq_printf(p, "%s\n", irq_list[i].devname);
 		}
 	}
 
-	len += mach_get_irq_list(buf+len);
-	return len;
+	mach_get_irq_list(p, v);
+	return 0;
 }
 
 void init_irq_proc(void)
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c
--- v2.5.0/linux/arch/m68k/kernel/setup.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/kernel/setup.c	Wed Nov 28 13:22:25 2001
@@ -80,7 +80,7 @@
 void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
 void (*mach_get_model) (char *model) = NULL;
 int (*mach_get_hardware_list) (char *buffer) = NULL;
-int (*mach_get_irq_list) (char *) = NULL;
+int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
 void (*mach_process_int) (int, struct pt_regs *) = NULL;
 /* machine dependent timer functions */
 unsigned long (*mach_gettimeoffset) (void);
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c
--- v2.5.0/linux/arch/m68k/mac/config.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/mac/config.c	Wed Nov 28 13:22:25 2001
@@ -66,7 +66,7 @@
 extern unsigned long mac_gettimeoffset (void);
 extern int mac_hwclk (int, struct hwclk_time *);
 extern int mac_set_clock_mmss (unsigned long);
-extern int mac_get_irq_list(char *);
+extern int show_mac_interrupts(struct seq_file *, void *);
 extern void iop_preinit(void);
 extern void iop_init(void);
 extern void via_init(void);
@@ -241,7 +241,7 @@
 	disable_irq          = mac_disable_irq;
 	mach_get_model	 = mac_get_model;
 	mach_default_handler = &mac_handlers;
-	mach_get_irq_list    = mac_get_irq_list;
+	mach_get_irq_list    = show_mac_interrupts;
 	mach_gettimeoffset   = mac_gettimeoffset;
 	mach_gettod          = mac_gettod;
 	mach_hwclk           = mac_hwclk;
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c
--- v2.5.0/linux/arch/m68k/mac/macints.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/mac/macints.c	Wed Nov 28 13:22:25 2001
@@ -120,6 +120,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h> /* for intr_count */
 #include <linux/delay.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -576,9 +577,9 @@
  *		  displayed for us as autovector irq 0.
  */
 
-int mac_get_irq_list (char *buf)
+int show_mac_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	irq_node_t *node;
 	char *base;
 
@@ -618,25 +619,24 @@
 			case 8: base = "bbn";
 				break;
 		}
-		len += sprintf(buf+len, "%4s %2d: %10u ",
-				base, i, kstat.irqs[0][i]);
+		seq_printf(p, "%4s %2d: %10u ", base, i, kstat.irqs[0][i]);
 
 		do {
 			if (node->flags & IRQ_FLG_FAST) {
-				len += sprintf(buf+len, "F ");
+				seq_puts(p, "F ");
 			} else if (node->flags & IRQ_FLG_SLOW) {
-				len += sprintf(buf+len, "S ");
+				seq_puts(p, "S ");
 			} else {
-				len += sprintf(buf+len, "  ");
+				seq_puts(p, "  ");
 			}
-			len += sprintf(buf+len, "%s\n", node->devname);
+			seq_printf(p, "%s\n", node->devname);
 			if ((node = node->next)) {
-				len += sprintf(buf+len, "                    ");
+				seq_puts(p, "                    ");
 			}
 		} while(node);
 
 	}
-	return len;
+	return 0;
 }
 
 void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/mvme147/147ints.c linux/arch/m68k/mvme147/147ints.c
--- v2.5.0/linux/arch/m68k/mvme147/147ints.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/mvme147/147ints.c	Wed Nov 28 13:22:25 2001
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/seq_file.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -112,17 +113,17 @@
 	}
 }
 
-int mvme147_get_irq_list (char *buf)
+int show_mvme147_interrupts (struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 
 	for (i = 0; i < 256; i++) {
 		if (irq_tab[i].count)
-			len += sprintf (buf+len, "Vec 0x%02x: %8d  %s\n",
+			seq_printf(p, "Vec 0x%02x: %8d  %s\n",
 			    i, irq_tab[i].count,
 			    irq_tab[i].devname ? irq_tab[i].devname : "free");
 	}
-	return len;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c
--- v2.5.0/linux/arch/m68k/mvme147/config.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/mvme147/config.c	Wed Nov 28 13:22:25 2001
@@ -36,7 +36,7 @@
 extern void mvme147_process_int (int level, struct pt_regs *regs);
 extern void mvme147_init_IRQ (void);
 extern void mvme147_free_irq (unsigned int, void *);
-extern int  mvme147_get_irq_list (char *);
+extern int  show_mvme147_interrupts (struct seq_file *, void *);
 extern void mvme147_enable_irq (unsigned int);
 extern void mvme147_disable_irq (unsigned int);
 static void mvme147_get_model(char *model);
@@ -113,7 +113,7 @@
 	mach_reset		= mvme147_reset;
 	mach_free_irq		= mvme147_free_irq;
 	mach_process_int	= mvme147_process_int;
-	mach_get_irq_list	= mvme147_get_irq_list;
+	mach_get_irq_list	= show_mvme147_interrupts;
 	mach_request_irq	= mvme147_request_irq;
 	enable_irq		= mvme147_enable_irq;
 	disable_irq		= mvme147_disable_irq;
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/mvme16x/16xints.c linux/arch/m68k/mvme16x/16xints.c
--- v2.5.0/linux/arch/m68k/mvme16x/16xints.c	Thu Dec 17 09:06:30 1998
+++ linux/arch/m68k/mvme16x/16xints.c	Wed Nov 28 13:22:25 2001
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/ptrace.h>
@@ -114,17 +115,17 @@
 	}
 }
 
-int mvme16x_get_irq_list (char *buf)
+int show_mvme16x_interrupts (struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 
 	for (i = 0; i < 192; i++) {
 		if (irq_tab[i].count)
-			len += sprintf (buf+len, "Vec 0x%02x: %8d  %s\n",
+			seq_printf(p, "Vec 0x%02x: %8d  %s\n",
 			    i+64, irq_tab[i].count,
 			    irq_tab[i].devname ? irq_tab[i].devname : "free");
 	}
-	return len;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/mvme16x/config.c linux/arch/m68k/mvme16x/config.c
--- v2.5.0/linux/arch/m68k/mvme16x/config.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/mvme16x/config.c	Wed Nov 28 13:22:25 2001
@@ -40,7 +40,7 @@
 extern void mvme16x_process_int (int level, struct pt_regs *regs);
 extern void mvme16x_init_IRQ (void);
 extern void mvme16x_free_irq (unsigned int, void *);
-extern int  mvme16x_get_irq_list (char *);
+extern int show_mvme16x_interrupts (struct seq_file *, void *);
 extern void mvme16x_enable_irq (unsigned int);
 extern void mvme16x_disable_irq (unsigned int);
 static void mvme16x_get_model(char *model);
@@ -156,7 +156,7 @@
     mach_reset		 = mvme16x_reset;
     mach_free_irq	 = mvme16x_free_irq;
     mach_process_int	 = mvme16x_process_int;
-    mach_get_irq_list	 = mvme16x_get_irq_list;
+    mach_get_irq_list	 = show_mvme16x_interrupts;
     mach_request_irq	 = mvme16x_request_irq;
     enable_irq           = mvme16x_enable_irq;
     disable_irq          = mvme16x_disable_irq;
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/mvme16x/rtc.c linux/arch/m68k/mvme16x/rtc.c
--- v2.5.0/linux/arch/m68k/mvme16x/rtc.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/mvme16x/rtc.c	Fri Nov 30 08:26:04 2001
@@ -36,7 +36,7 @@
 static unsigned char days_in_mo[] =
 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
-static char rtc_status = 0;
+static atomic_t rtc_ready = ATOMIC_INIT(1);
 
 static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 		     unsigned long arg)
@@ -130,18 +130,18 @@
 
 static int rtc_open(struct inode *inode, struct file *file)
 {
-	if(rtc_status)
+	if( !atomic_dec_and_test(&rtc_ready) )
+	{
+		atomic_inc( &rtc_ready );
 		return -EBUSY;
+	}
 
-	rtc_status = 1;
 	return 0;
 }
 
 static int rtc_release(struct inode *inode, struct file *file)
 {
-	lock_kernel();
-	rtc_status = 0;
-	unlock_kernel();
+	atomic_inc( &rtc_ready );
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c
--- v2.5.0/linux/arch/m68k/q40/config.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/q40/config.c	Wed Nov 28 13:22:25 2001
@@ -45,7 +45,7 @@
 extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);  /* added just for debugging */
 extern void q40_init_IRQ (void);
 extern void q40_free_irq (unsigned int, void *);
-extern int  q40_get_irq_list (char *);
+extern int  show_q40_interrupts (struct seq_file *, void *);
 extern void q40_enable_irq (unsigned int);
 extern void q40_disable_irq (unsigned int);
 static void q40_get_model(char *model);
@@ -236,7 +236,7 @@
     mach_reset		 = q40_reset;
     mach_free_irq	 = q40_free_irq; 
     mach_process_int	 = q40_process_int;
-    mach_get_irq_list	 = q40_get_irq_list;
+    mach_get_irq_list	 = show_q40_interrupts;
     mach_request_irq	 = q40_request_irq;
     enable_irq		 = q40_enable_irq;
     disable_irq          = q40_disable_irq;
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/q40/q40ints.c linux/arch/m68k/q40/q40ints.c
--- v2.5.0/linux/arch/m68k/q40/q40ints.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/q40/q40ints.c	Wed Nov 28 13:22:25 2001
@@ -17,6 +17,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 
 #include <asm/rtc.h>
 #include <asm/ptrace.h>
@@ -431,21 +432,20 @@
 	  }
 }
 
-int q40_get_irq_list (char *buf)
+int show_q40_interrupts (struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 
-	for (i = 0; i <= Q40_IRQ_MAX; i++) 
-	  {
+	for (i = 0; i <= Q40_IRQ_MAX; i++) {
 		if (irq_tab[i].count)
-	      len += sprintf (buf+len, "%sIRQ %02d: %8d  %s%s\n",
+		      seq_printf(p, "%sIRQ %02d: %8d  %s%s\n",
 			      (i<=15) ? "ISA-" : "    " ,		
 			    i, irq_tab[i].count,
 			    irq_tab[i].devname[0] ? irq_tab[i].devname : "?",
 			    irq_tab[i].handler == q40_defhand ? 
 					" (now unassigned)" : "");
 	}
-	return len;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/sun3/config.c linux/arch/m68k/sun3/config.c
--- v2.5.0/linux/arch/m68k/sun3/config.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/sun3/config.c	Wed Nov 28 13:22:25 2001
@@ -36,7 +36,7 @@
 char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
 
 extern unsigned long sun3_gettimeoffset(void);
-extern int sun3_get_irq_list (char *);
+extern int show_sun3_interrupts (char *);
 extern void sun3_sched_init(void (*handler)(int, void *, struct pt_regs *));
 extern void sun3_get_model (char* model);
 extern void idprom_init (void);
@@ -145,7 +145,7 @@
 	enable_irq     	     =  sun3_enable_irq;
         disable_irq  	     =  sun3_disable_irq;
 	mach_process_int     =  sun3_process_int;
-        mach_get_irq_list    =  sun3_get_irq_list;
+        mach_get_irq_list    =  show_sun3_interrupts;
         mach_gettod          =  sun3_gettod;	
         mach_reset           =  sun3_reboot;
 	mach_gettimeoffset   =  sun3_gettimeoffset;
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/sun3/sun3ints.c linux/arch/m68k/sun3/sun3ints.c
--- v2.5.0/linux/arch/m68k/sun3/sun3ints.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/sun3/sun3ints.c	Wed Nov 28 13:22:25 2001
@@ -15,6 +15,7 @@
 #include <asm/intersil.h>
 #include <asm/oplib.h>
 #include <asm/sun3ints.h>
+#include <linux/seq_file.h>
 
 extern void sun3_leds (unsigned char);
 
@@ -62,7 +63,7 @@
 	*sun3_intreg |=  (1<<irq);
 }
 
-int sun3_get_irq_list(char *buf)
+int show_sun3_interrupts(struct seq_file *p, void *v)
 {
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/arch/m68k/sun3x/config.c linux/arch/m68k/sun3x/config.c
--- v2.5.0/linux/arch/m68k/sun3x/config.c	Mon Jun 11 19:15:27 2001
+++ linux/arch/m68k/sun3x/config.c	Wed Nov 28 13:22:25 2001
@@ -58,7 +58,7 @@
 
 	sun3x_prom_init();
 
-	mach_get_irq_list	 = sun3_get_irq_list;
+	mach_get_irq_list	 = show_sun3_interrupts;
 	mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
 
 	mach_keyb_init       = sun3x_keyb_init;
diff -u --recursive --new-file v2.5.0/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c
--- v2.5.0/linux/arch/mips/baget/irq.c	Sun Sep  9 10:43:01 2001
+++ linux/arch/mips/baget/irq.c	Wed Nov 28 13:22:25 2001
@@ -17,6 +17,7 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/delay.h>
+#include <linux/seq_file.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
@@ -141,27 +142,27 @@
  */
 static struct irqaction *irq_action[BAGET_IRQ_NR] = { NULL, };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	struct irqaction * action;
 
 	for (i = 0 ; i < BAGET_IRQ_NR ; i++) {
 		action = irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
+		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat.irqs[0][i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, "\n");
+		seq_putc(p, '\n');
 	}
-	return len;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/mips/dec/irq.c linux/arch/mips/dec/irq.c
--- v2.5.0/linux/arch/mips/dec/irq.c	Sun Sep  9 10:43:01 2001
+++ linux/arch/mips/dec/irq.c	Wed Nov 28 13:22:25 2001
@@ -15,6 +15,7 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/seq_file.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
@@ -92,27 +93,27 @@
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-    int i, len = 0;
-    struct irqaction *action;
+	int i;
+	struct irqaction *action;
 
-    for (i = 0; i < 32; i++) {
-	action = irq_action[i];
-	if (!action)
-	    continue;
-	len += sprintf(buf + len, "%2d: %8d %c %s",
-		       i, kstat.irqs[0][i],
-		       (action->flags & SA_INTERRUPT) ? '+' : ' ',
-		       action->name);
-	for (action = action->next; action; action = action->next) {
-	    len += sprintf(buf + len, ",%s %s",
-			   (action->flags & SA_INTERRUPT) ? " +" : "",
-			   action->name);
+	for (i = 0; i < 32; i++) {
+		action = irq_action[i];
+		if (!action)
+			continue;
+		seq_printf(p, "%2d: %8d %c %s",
+				i, kstat.irqs[0][i],
+				(action->flags & SA_INTERRUPT) ? '+' : ' ',
+				action->name);
+		for (action = action->next; action; action = action->next) {
+			seq_printf(p, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		seq_putc(p, '\n');
 	}
-	len += sprintf(buf + len, "\n");
-    }
-    return len;
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/arch/mips/ite-boards/generic/irq.c linux/arch/mips/ite-boards/generic/irq.c
--- v2.5.0/linux/arch/mips/ite-boards/generic/irq.c	Sun Sep  9 10:43:01 2001
+++ linux/arch/mips/ite-boards/generic/irq.c	Wed Nov 28 13:22:25 2001
@@ -46,6 +46,7 @@
 #include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/serial_reg.h>
+#include <linux/seq_file.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
@@ -217,34 +218,34 @@
 };
 
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-        int i, len = 0, j;
+        int i, j;
         struct irqaction * action;
 
-        len += sprintf(buf+len, "           ");
+        seq_printf(p, "           ");
         for (j=0; j<smp_num_cpus; j++)
-                len += sprintf(buf+len, "CPU%d       ",j);
-        *(char *)(buf+len++) = '\n';
+		seq_printf(p, "CPU%d       ",j);
+	seq_putc(p, '\n');
 
         for (i = 0 ; i < NR_IRQS ; i++) {
                 action = irq_desc[i].action;
                 if ( !action || !action->handler )
                         continue;
-                len += sprintf(buf+len, "%3d: ", i);		
-                len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+                seq_printf(p, "%3d: ", i);		
+                seq_printf(p, "%10u ", kstat_irqs(i));
                 if ( irq_desc[i].handler )		
-                        len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
+                        seq_printf(p, " %s ", irq_desc[i].handler->typename );
                 else
-                        len += sprintf(buf+len, "  None      ");
-                len += sprintf(buf+len, "    %s",action->name);
+                        seq_puts(p, "  None      ");
+                seq_printf(p, "    %s",action->name);
                 for (action=action->next; action; action = action->next) {
-                        len += sprintf(buf+len, ", %s", action->name);
+                        seq_printf(p, ", %s", action->name);
                 }
-                len += sprintf(buf+len, "\n");
+                seq_putc(p, '\n');
         }
-        len += sprintf(buf+len, "BAD: %10lu\n", spurious_count);
-        return len;
+        seq_printf(p, "BAD: %10lu\n", spurious_count);
+        return 0;
 }
 
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
diff -u --recursive --new-file v2.5.0/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- v2.5.0/linux/arch/mips/kernel/irq.c	Sun Sep  9 10:43:01 2001
+++ linux/arch/mips/kernel/irq.c	Wed Nov 28 13:22:25 2001
@@ -17,6 +17,7 @@
 #include <linux/mm.h>
 #include <linux/random.h>
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 
@@ -69,32 +70,31 @@
  * Generic, controller-independent functions:
  */
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 	struct irqaction * action;
-	char *p = buf;
 	int i;
 
-	p += sprintf(p, "           ");
+	seq_puts(p, "           ");
 	for (i=0; i < 1 /*smp_num_cpus*/; i++)
-		p += sprintf(p, "CPU%d       ", i);
-	*p++ = '\n';
+		seq_printf(p, "CPU%d       ", i);
+	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		action = irq_desc[i].action;
 		if (!action) 
 			continue;
-		p += sprintf(p, "%3d: ",i);
-		p += sprintf(p, "%10u ", kstat_irqs(i));
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, "%3d: ",i);
+		seq_printf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-			p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
+			seq_printf(p, ", %s", action->name);
+		seq_putc(p, '\n');
 	}
-	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
-	return p - buf;
+	seq_printf(p, "ERR: %10lu\n", irq_err_count);
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/arch/mips/kernel/old-irq.c linux/arch/mips/kernel/old-irq.c
--- v2.5.0/linux/arch/mips/kernel/old-irq.c	Sun Sep  9 10:43:01 2001
+++ linux/arch/mips/kernel/old-irq.c	Wed Nov 28 13:22:25 2001
@@ -24,6 +24,7 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/seq_file.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
@@ -123,27 +124,27 @@
 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	struct irqaction * action;
 
 	for (i = 0 ; i < 32 ; i++) {
 		action = irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
+		seq_printf(p, "%2d: %8d %c %s",
 			i, kstat.irqs[0][i],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, "\n");
+		seq_putc(p, '\n');
 	}
-	return len;
+	return 0;
 }
 
 static inline void i8259_mask_and_ack_irq(int irq)
diff -u --recursive --new-file v2.5.0/linux/arch/mips/mips-boards/atlas/atlas_int.c linux/arch/mips/mips-boards/atlas/atlas_int.c
--- v2.5.0/linux/arch/mips/mips-boards/atlas/atlas_int.c	Sun Sep  9 10:43:02 2001
+++ linux/arch/mips/mips-boards/atlas/atlas_int.c	Wed Nov 28 13:22:25 2001
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
 
 #include <asm/irq.h>
 #include <asm/mips-boards/atlas.h>
@@ -93,9 +94,9 @@
 	NULL
 };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	int num = 0;
 	struct irqaction *action;
 
@@ -103,18 +104,18 @@
 		action = irq_desc[i].action;
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
+		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat.irqs[0][num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, " [hw0]\n");
+		seq_printf(p, " [hw0]\n");
 	}
-	return len;
+	return 0;
 }
 
 int request_irq(unsigned int irq, 
diff -u --recursive --new-file v2.5.0/linux/arch/mips/philips/nino/irq.c linux/arch/mips/philips/nino/irq.c
--- v2.5.0/linux/arch/mips/philips/nino/irq.c	Sun Sep  9 10:43:02 2001
+++ linux/arch/mips/philips/nino/irq.c	Wed Nov 28 13:22:25 2001
@@ -23,6 +23,7 @@
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/seq_file.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
@@ -114,27 +115,27 @@
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-    int i, len = 0;
+    int i;
     struct irqaction *action;
 
     for (i = 0; i < NR_IRQS; i++) {
 	action = irq_action[i];
 	if (!action)
 	    continue;
-	len += sprintf(buf + len, "%2d: %8d %c %s",
+	seq_printf(p, "%2d: %8d %c %s",
 		       i, kstat.irqs[0][i],
 		       (action->flags & SA_INTERRUPT) ? '+' : ' ',
 		       action->name);
 	for (action = action->next; action; action = action->next) {
-	    len += sprintf(buf + len, ",%s %s",
+	    seq_printf(p, ",%s %s",
 			   (action->flags & SA_INTERRUPT) ? " +" : "",
 			   action->name);
 	}
-	len += sprintf(buf + len, "\n");
+	seq_putc(p, '\n');
     }
-    return len;
+    return 0;
 }
 
 atomic_t __mips_bh_counter;
diff -u --recursive --new-file v2.5.0/linux/arch/mips64/mips-boards/atlas/atlas_int.c linux/arch/mips64/mips-boards/atlas/atlas_int.c
--- v2.5.0/linux/arch/mips64/mips-boards/atlas/atlas_int.c	Sun Sep  9 10:43:02 2001
+++ linux/arch/mips64/mips-boards/atlas/atlas_int.c	Wed Nov 28 13:22:25 2001
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/seq_file.h>
 
 #include <asm/irq.h>
 #include <asm/mips-boards/atlas.h>
@@ -89,9 +90,9 @@
 	NULL
 };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	int num = 0;
 	struct irqaction *action;
 
@@ -99,18 +100,18 @@
 		action = irq_desc[i].action;
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
+		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat.irqs[0][num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, " [hw0]\n");
+		seq_puts(p, " [hw0]\n");
 	}
-	return len;
+	return 0;
 }
 
 int request_irq(unsigned int irq, 
diff -u --recursive --new-file v2.5.0/linux/arch/mips64/mips-boards/malta/malta_int.c linux/arch/mips64/mips-boards/malta/malta_int.c
--- v2.5.0/linux/arch/mips64/mips-boards/malta/malta_int.c	Sun Sep  9 10:43:02 2001
+++ linux/arch/mips64/mips-boards/malta/malta_int.c	Wed Nov 28 13:22:25 2001
@@ -32,6 +32,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
 #include <linux/random.h>
+#include <linux/seq_file.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -119,9 +120,9 @@
 }
 
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	int num = 0;
 	struct irqaction *action;
 
@@ -129,33 +130,33 @@
 		action = irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
+		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat.irqs[0][num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, " [on-chip]\n");
+		seq_puts(p, " [on-chip]\n");
 	}
 	for (i = 0; i < MALTAINT_END; i++, num++) {
 		action = hw0_irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
+		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat.irqs[0][num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, " [hw0]\n");
+		seq_puts(p, " [hw0]\n");
 	}
-	return len;
+	return 0;
 }
 
 int request_irq(unsigned int irq, 
diff -u --recursive --new-file v2.5.0/linux/arch/mips64/sgi-ip22/ip22-int.c linux/arch/mips64/sgi-ip22/ip22-int.c
--- v2.5.0/linux/arch/mips64/sgi-ip22/ip22-int.c	Sun Sep  9 10:43:02 2001
+++ linux/arch/mips64/sgi-ip22/ip22-int.c	Wed Nov 28 13:22:26 2001
@@ -8,6 +8,7 @@
  */
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
@@ -231,9 +232,9 @@
 	NULL, NULL, NULL, NULL
 };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	int num = 0;
 	struct irqaction * action;
 
@@ -241,33 +242,33 @@
 		action = irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
+		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat.irqs[0][num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, " [on-chip]\n");
+		seq_puts(p, " [on-chip]\n");
 	}
 	for (i = 0 ; i < 24 ; i++, num++) {
 		action = local_irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
+		seq_printf(p, "%2d: %8d %c %s",
 			num, kstat.irqs[0][num],
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, " [local]\n");
+		seq_puts(p, " [local]\n");
 	}
-	return len;
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/arch/mips64/sgi-ip27/ip27-irq.c linux/arch/mips64/sgi-ip27/ip27-irq.c
--- v2.5.0/linux/arch/mips64/sgi-ip27/ip27-irq.c	Sun Sep  9 10:43:02 2001
+++ linux/arch/mips64/sgi-ip27/ip27-irq.c	Wed Nov 28 13:22:26 2001
@@ -20,6 +20,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
+#include <linux/seq_file.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
@@ -136,27 +137,27 @@
 /* This is stupid for an Origin which can have thousands of IRQs ...  */
 static struct irqaction *irq_action[NR_IRQS];
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	struct irqaction * action;
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		action = irq_action[i];
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s", i, kstat.irqs[0][i],
+		seq_printf(p, "%2d: %8d %c %s", i, kstat.irqs[0][i],
 		               (action->flags & SA_INTERRUPT) ? '+' : ' ',
 		               action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 			               (action->flags & SA_INTERRUPT)
 			                ? " +" : "",
 			                action->name);
 		}
-		len += sprintf(buf+len, "\n");
+		seq_putc(p, '\n');
 	}
-	return len;
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/arch/mips64/sgi-ip27/ip27-rtc.c linux/arch/mips64/sgi-ip27/ip27-rtc.c
--- v2.5.0/linux/arch/mips64/sgi-ip27/ip27-rtc.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/sgi-ip27/ip27-rtc.c	Fri Nov 30 08:26:04 2001
@@ -53,14 +53,7 @@
 
 static void get_rtc_time(struct rtc_time *rtc_tm);
 
-/*
- *	Bits in rtc_status. (6 bits of room for future expansion)
- */
-
-#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
-#define RTC_TIMER_ON		0x02	/* missed irq timer active	*/
-
-static unsigned char rtc_status;	/* bitmapped status byte.	*/
+static atomic_t rtc_ready = ATOMIC_INIT(1);
 static unsigned long rtc_freq;	/* Current periodic IRQ rate	*/
 static struct m48t35_rtc *rtc;
 
@@ -166,23 +159,17 @@
 
 static int rtc_open(struct inode *inode, struct file *file)
 {
-	if(rtc_status & RTC_IS_OPEN)
+	if( atomic_dec_and_test( &rtc_ready ) ) 
+	{
+		atomic_inc( &rtc_ready );
 		return -EBUSY;
-
-	rtc_status |= RTC_IS_OPEN;
+	}
 	return 0;
 }
 
 static int rtc_release(struct inode *inode, struct file *file)
 {
-	/*
-	 * Turn off all interrupts once the device is no longer
-	 * in use, and clear the data.
-	 */
-
-	lock_kernel();
-	rtc_status &= ~RTC_IS_OPEN;
-	unlock_kernel();
+	atomic_inc( &rtc_ready );
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/arch/parisc/kernel/irq.c linux/arch/parisc/kernel/irq.c
--- v2.5.0/linux/arch/parisc/kernel/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/parisc/kernel/irq.c	Wed Nov 28 13:22:26 2001
@@ -39,6 +39,7 @@
 #include <linux/random.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/seq_file.h>
 
 #include <asm/cache.h>
 
@@ -160,19 +161,18 @@
 		BUG();
 }
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 #ifdef CONFIG_PROC_FS
-	char *p = buf;
 	int i, j;
 	int regnr, irq_no;
 	struct irq_region *region;
 	struct irqaction *action, *mainaction;
 
-	p += sprintf(p, "           ");
+	seq_puts(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
-		p += sprintf(p, "CPU%d       ",j);
-	*p++ = '\n';
+		seq_printf(p, "CPU%d       ",j);
+	seq_putc(p, '\n');
 
 	for (regnr = 0; regnr < NR_IRQ_REGS; regnr++) {
 	    region = irq_region[regnr];
@@ -188,40 +188,34 @@
 		
 		irq_no = IRQ_FROM_REGION(regnr) + i;
 		
-		p += sprintf(p, "%3d: ", irq_no);
+		seq_printf(p, "%3d: ", irq_no);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(irq_no));
+		seq_printf(p, "%10u ", kstat_irqs(irq_no));
 #else
 		for (j = 0; j < smp_num_cpus; j++)
-		    p += sprintf(p, "%10u ",
+		    seq_printf(p, "%10u ",
 			    kstat.irqs[cpu_logical_map(j)][irq_no]);
 #endif
-		p += sprintf(p, " %14s", 
+		seq_printf(p, " %14s", 
 			    region->data.name ? region->data.name : "N/A");
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-		    p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
+		    seq_printf(p, ", %s", action->name);
+		seq_putc(p, '\n');
 	    }	    	     
 	}  
 
-	p += sprintf(p, "\n");
+	seq_putc(p, '\n');
 #if CONFIG_SMP
-	p += sprintf(p, "LOC: ");
+	seq_puts(p, "LOC: ");
 	for (j = 0; j < smp_num_cpus; j++)
-		p += sprintf(p, "%10u ",
+		seq_printf(p, "%10u ",
 			apic_timer_irqs[cpu_logical_map(j)]);
-	p += sprintf(p, "\n");
+	seq_putc(p, '\n');
 #endif
-
-	return p - buf;
-
-#else	/* CONFIG_PROC_FS */
-
-	return 0;	
-
 #endif	/* CONFIG_PROC_FS */
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c
--- v2.5.0/linux/arch/ppc/amiga/amiints.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/amiga/amiints.c	Wed Nov 28 13:22:26 2001
@@ -44,6 +44,7 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -61,7 +62,7 @@
                            unsigned long flags, const char *devname, void *dev_id);
 extern void cia_free_irq(unsigned int irq, void *dev_id);
 extern void cia_init_IRQ(struct ciabase *base);
-extern int cia_get_irq_list(struct ciabase *base, char *buf);
+extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p);
 
 /* irq node variables for amiga interrupt sources */
 static irq_node_t *ami_irq_list[AMI_STD_IRQS];
@@ -480,28 +481,28 @@
 };
 #endif
 
-int amiga_get_irq_list(char *buf)
+int show_amiga_intreeupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	irq_node_t *node;
 
 	for (i = 0; i < AMI_STD_IRQS; i++) {
 		if (!(node = ami_irq_list[i]))
 			continue;
-		len += sprintf(buf+len, "ami  %2d: %10u ", i,
+		seq_printf(p, "ami  %2d: %10u ", i,
 		               kstat.irqs[0][SYS_IRQS + i]);
 		do {
 			if (node->flags & SA_INTERRUPT)
-				len += sprintf(buf+len, "F ");
+				seq_puts(p, "F ");
 			else
-				len += sprintf(buf+len, "  ");
-			len += sprintf(buf+len, "%s\n", node->devname);
+				seq_puts(p, "  ");
+			seq_printf(p, "%s\n", node->devname);
 			if ((node = node->next))
-				len += sprintf(buf+len, "                    ");
+				seq_puts(p, "                    ");
 		} while (node);
 	}
 
-	len += cia_get_irq_list(&ciaa_base, buf+len);
-	len += cia_get_irq_list(&ciab_base, buf+len);
+	cia_get_irq_list(&ciaa_base, p);
+	cia_get_irq_list(&ciab_base, p);
 	return len;
 }
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/amiga/cia.c linux/arch/ppc/amiga/cia.c
--- v2.5.0/linux/arch/ppc/amiga/cia.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/amiga/cia.c	Wed Nov 28 13:22:26 2001
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/irq.h>
 #include <asm/amigahw.h>
@@ -222,16 +223,16 @@
 	custom.intena = IF_SETCLR | base->int_mask;
 }
 
-int cia_get_irq_list(struct ciabase *base, char *buf)
+int cia_get_irq_list(struct ciabase *base, struct seq_file *p)
 {
-	int i, j, len = 0;
+	int i, j;
 
 	j = base->cia_irq;
 	for (i = 0; i < CIA_IRQS; i++) {
-		len += sprintf(buf+len, "cia  %2d: %10d ", j + i,
+		seq_printf(p, "cia  %2d: %10d ", j + i,
 			       kstat.irqs[0][SYS_IRQS + j + i]);
-			len += sprintf(buf+len, "  ");
-		len += sprintf(buf+len, "%s\n", base->irq_list[i].devname);
+		seq_puts(p, "  ");
+		seq_printf(p, "%s\n", base->irq_list[i].devname);
 	}
-	return len;
+	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c
--- v2.5.0/linux/arch/ppc/amiga/config.c	Thu Oct 11 09:04:57 2001
+++ linux/arch/ppc/amiga/config.c	Wed Nov 28 13:22:26 2001
@@ -28,6 +28,7 @@
 #ifdef CONFIG_ZORRO
 #include <linux/zorro.h>
 #endif
+#include <linux/seq_file.h>
 
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
@@ -91,7 +92,7 @@
 extern void amiga_disable_irq (unsigned int);
 static void amiga_get_model(char *model);
 static int amiga_get_hardware_list(char *buffer);
-extern int amiga_get_irq_list (char *);
+extern int show_amiga_interrupts (struct seq_file *, void *);
 /* amiga specific timer functions */
 static unsigned long amiga_gettimeoffset (void);
 static void a3000_gettod (int *, int *, int *, int *, int *, int *);
@@ -422,7 +423,7 @@
 #endif
   mach_get_model       = amiga_get_model;
   mach_get_hardware_list = amiga_get_hardware_list;
-  mach_get_irq_list    = amiga_get_irq_list;
+  mach_get_irq_list    = show_amiga_interrupts;
   mach_gettimeoffset   = amiga_gettimeoffset;
   if (AMIGAHW_PRESENT(A3000_CLK)){
     mach_gettod  = a3000_gettod;
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/amiga/ints.c linux/arch/ppc/amiga/ints.c
--- v2.5.0/linux/arch/ppc/amiga/ints.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/amiga/ints.c	Wed Nov 28 13:22:26 2001
@@ -13,6 +13,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/errno.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/setup.h>
 #include <asm/system.h>
@@ -143,20 +144,20 @@
 	}
 }
 
-int m68k_get_irq_list(char *buf)
+int m68k_get_irq_list(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 
 	/* autovector interrupts */
 	if (mach_default_handler) {
 		for (i = 0; i < SYS_IRQS; i++) {
-			len += sprintf(buf+len, "auto %2d: %10u ", i,
+			seq_printf(p, "auto %2d: %10u ", i,
 			               i ? kstat.irqs[0][i] : num_spurious);
-				len += sprintf(buf+len, "  ");
-			len += sprintf(buf+len, "%s\n", irq_list[i].devname);
+			seq_puts(p, "  ");
+			seq_printf(p, "%s\n", irq_list[i].devname);
 		}
 	}
 
-	len += mach_get_irq_list(buf+len);
-	return len;
+	mach_get_irq_list(p, v);
+	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.5.0/linux/arch/ppc/kernel/apus_setup.c	Fri Nov 16 10:10:08 2001
+++ linux/arch/ppc/kernel/apus_setup.c	Wed Nov 28 13:22:26 2001
@@ -95,7 +95,7 @@
 void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
 void (*mach_get_model) (char *model) = NULL;
 int (*mach_get_hardware_list) (char *buffer) = NULL;
-int (*mach_get_irq_list) (char *) = NULL;
+int (*mach_get_irq_list) (struct seq_file *, void *) = NULL;
 void (*mach_process_int) (int, struct pt_regs *) = NULL;
 /* machine dependent timer functions */
 unsigned long (*mach_gettimeoffset) (void);
@@ -671,12 +671,12 @@
 	return irq;
 }
 
-int apus_get_irq_list(char *buf)
+int show_apus_interrupts(struct seq_file *p, void *v)
 {
 #ifdef CONFIG_APUS
-	extern int amiga_get_irq_list(char *buf);
+	extern int show_amiga_interrupts(struct seq_file *p, void *v)
 	
-	return amiga_get_irq_list (buf);
+	return show_amiga_interrupts(p, v);
 #else
 	return 0;
 #endif
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/kernel/i8259.c linux/arch/ppc/kernel/i8259.c
--- v2.5.0/linux/arch/ppc/kernel/i8259.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/i8259.c	Mon Dec 10 13:52:53 2001
@@ -13,7 +13,7 @@
 #define cached_A1 (cached_8259[0])
 #define cached_21 (cached_8259[1])
 
-spinlock_t i8259_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t i8259_lock = SPIN_LOCK_UNLOCKED;
 
 int i8259_pic_irq_offset;
 
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.5.0/linux/arch/ppc/kernel/irq.c	Tue Aug 28 06:58:33 2001
+++ linux/arch/ppc/kernel/irq.c	Wed Nov 28 13:22:26 2001
@@ -47,6 +47,7 @@
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
 #include <linux/random.h>
+#include <linux/seq_file.h>
 
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -371,58 +372,58 @@
 	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 #ifdef CONFIG_APUS
-	return apus_get_irq_list (buf);
+	return show_apus_interrupts(p, v);
 #else
-	int i, len = 0, j;
+	int i, j;
 	struct irqaction * action;
 
-	len += sprintf(buf+len, "           ");
+	seq_puts(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
-		len += sprintf(buf+len, "CPU%d       ",j);
-	*(char *)(buf+len++) = '\n';
+		seq_printf(p, "CPU%d       ",j);
+	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++) {
 		action = irq_desc[i].action;
 		if ( !action || !action->handler )
 			continue;
-		len += sprintf(buf+len, "%3d: ", i);		
+		seq_printf(p, "%3d: ", i);		
 #ifdef CONFIG_SMP
 		for (j = 0; j < smp_num_cpus; j++)
-			len += sprintf(buf+len, "%10u ",
+			seq_printf(p, "%10u ",
 				kstat.irqs[cpu_logical_map(j)][i]);
 #else		
-		len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif /* CONFIG_SMP */
 		if ( irq_desc[i].handler )		
-			len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename );
+			seq_printf(p, " %s ", irq_desc[i].handler->typename );
 		else
-			len += sprintf(buf+len, "  None      ");
-		len += sprintf(buf+len, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge  ");
-		len += sprintf(buf+len, "    %s",action->name);
+			seq_puts(p, "  None      ");
+		seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge  ");
+		seq_printf(p, "    %s",action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ", %s", action->name);
+			seq_printf(p, ", %s", action->name);
 		}
-		len += sprintf(buf+len, "\n");
+		seq_putc(p, '\n');
 	}
 #ifdef CONFIG_TAU_INT
 	if (tau_initialized){
-		len += sprintf(buf+len, "TAU: ");
+		seq_puts(p, "TAU: ");
 		for (j = 0; j < smp_num_cpus; j++)
-			len += sprintf(buf+len, "%10u ",
+			seq_printf(p, "%10u ",
 					tau_interrupts(j));
-		len += sprintf(buf+len, "  PowerPC             Thermal Assist (cpu temp)\n");
+		seq_puts(p, "  PowerPC             Thermal Assist (cpu temp)\n");
 	}
 #endif
 #ifdef CONFIG_SMP
 	/* should this be per processor send/receive? */
-	len += sprintf(buf+len, "IPI (recv/sent): %10u/%u\n",
+	seq_printf(p, "IPI (recv/sent): %10u/%u\n",
 		       atomic_read(&ipi_recv), atomic_read(&ipi_sent));
 #endif		
-	len += sprintf(buf+len, "BAD: %10u\n", ppc_spurious_interrupts);
-	return len;
+	seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
+	return 0;
 #endif /* CONFIG_APUS */
 }
 
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.5.0/linux/arch/ppc/kernel/pmac_pic.c	Sat Sep  8 12:38:42 2001
+++ linux/arch/ppc/kernel/pmac_pic.c	Mon Dec 10 13:52:53 2001
@@ -36,7 +36,7 @@
 static int max_irqs;
 static int max_real_irqs;
 
-spinlock_t pmac_pic_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t pmac_pic_lock = SPIN_LOCK_UNLOCKED;
 
 
 #define GATWICK_IRQ_POOL_SIZE        10
diff -u --recursive --new-file v2.5.0/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.5.0/linux/arch/ppc/kernel/prom.c	Sat Sep  8 12:38:42 2001
+++ linux/arch/ppc/kernel/prom.c	Mon Dec 10 13:52:53 2001
@@ -1928,7 +1928,7 @@
 }
 #endif
 
-spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED;
 
 /* this can be called after setup -- Cort */
 int __openfirmware
diff -u --recursive --new-file v2.5.0/linux/arch/s390/kernel/irq.c linux/arch/s390/kernel/irq.c
--- v2.5.0/linux/arch/s390/kernel/irq.c	Wed Jul 25 14:12:01 2001
+++ linux/arch/s390/kernel/irq.c	Wed Nov 28 13:22:26 2001
@@ -28,6 +28,7 @@
 #include <linux/threads.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -59,22 +60,19 @@
 BUILD_SMP_INTERRUPT(spurious_interrupt)
 #endif
 
-#if 0
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 	int i, j;
 	struct irqaction * action;
-	char *p = buf;
 
-	p += sprintf(p, "           ");
+	seq_puts(p, "           ");
 
 	for (j=0; j<smp_num_cpus; j++)
-		p += sprintf(p, "CPU%d       ",j);
+		seq_printf(p, "CPU%d       ",j);
 
-	*p++ = '\n';
+	seq_putc(p, '\n');
 
-	for (i = 0 ; i < NR_IRQS ; i++)
-	{
+	for (i = 0 ; i < NR_IRQS ; i++) {
 		if (ioinfo[i] == INVALID_STORAGE_AREA)
 			continue;
 
@@ -83,35 +81,33 @@
   		if (!action)
 			continue;
 
-		p += sprintf(p, "%3d: ",i);
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j=0; j<smp_num_cpus; j++)
-			p += sprintf( p, "%10u ",
+			seq_printf( p, "%10u ",
 			              kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-		p += sprintf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
 		{
-			p += sprintf(p, ", %s", action->name);
+			seq_printf(p, ", %s", action->name);
 
 		} /* endfor */
 
-		*p++ = '\n';
+		seq_putc(p, '\n');
 	
 	} /* endfor */
 
-	p += sprintf(p, "NMI: %10u\n", nmi_counter);
+	seq_printf(p, "NMI: %10u\n", nmi_counter);
 #ifdef CONFIG_SMP
-	p += sprintf(p, "IPI: %10u\n", atomic_read(&ipi_count));
+	seq_printf(p, "IPI: %10u\n", atomic_read(&ipi_count));
 #endif
-
-	return p - buf;
+	return 0;
 }
-#endif
 
 /*
  * Global interrupt locks for SMP. Allow interrupts to come in on any
diff -u --recursive --new-file v2.5.0/linux/arch/s390x/kernel/irq.c linux/arch/s390x/kernel/irq.c
--- v2.5.0/linux/arch/s390x/kernel/irq.c	Wed Jul 25 14:12:01 2001
+++ linux/arch/s390x/kernel/irq.c	Wed Nov 28 13:22:26 2001
@@ -28,6 +28,7 @@
 #include <linux/threads.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -59,19 +60,17 @@
 BUILD_SMP_INTERRUPT(spurious_interrupt)
 #endif
 
-#if 0
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 	int i, j;
 	struct irqaction * action;
-	char *p = buf;
 
-	p += sprintf(p, "           ");
+	seq_puts(p, "           ");
 
 	for (j=0; j<smp_num_cpus; j++)
-		p += sprintf(p, "CPU%d       ",j);
+		seq_printf(p, "CPU%d       ",j);
 
-	*p++ = '\n';
+	seq_putc(p, '\n');
 
 	for (i = 0 ; i < NR_IRQS ; i++)
 	{
@@ -83,35 +82,34 @@
   		if (!action)
 			continue;
 
-		p += sprintf(p, "%3d: ",i);
+		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
-		p += sprintf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j=0; j<smp_num_cpus; j++)
-			p += sprintf( p, "%10u ",
+			seq_printf( p, "%10u ",
 			              kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-		p += sprintf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
 		{
-			p += sprintf(p, ", %s", action->name);
+			seq_printf(p, ", %s", action->name);
 
 		} /* endfor */
 
-		*p++ = '\n';
+		seq_putc(p, '\n');
 	
 	} /* endfor */
 
-	p += sprintf(p, "NMI: %10u\n", nmi_counter);
+	seq_printf(p, "NMI: %10u\n", nmi_counter);
 #ifdef CONFIG_SMP
-	p += sprintf(p, "IPI: %10u\n", atomic_read(&ipi_count));
+	seq_printf(p, "IPI: %10u\n", atomic_read(&ipi_count));
 #endif
 
-	return p - buf;
+	return 0;
 }
-#endif
 
 /*
  * Global interrupt locks for SMP. Allow interrupts to come in on any
diff -u --recursive --new-file v2.5.0/linux/arch/sh/config.in linux/arch/sh/config.in
--- v2.5.0/linux/arch/sh/config.in	Mon Oct 15 13:36:48 2001
+++ linux/arch/sh/config.in	Tue Dec 11 10:10:18 2001
@@ -189,7 +189,7 @@
    if [ "$CONFIG_PCI_GODIRECT" = "y" -o "$CONFIG_PCI_GOANY" = "y" ]; then
       define_bool CONFIG_PCI_DIRECT y
    fi
-   define_bool CONFIG_SH_PCIDMA_NONCOHERENT n
+   bool 'Cache and PCI noncoherent' CONFIG_SH_PCIDMA_NONCOHERENT n
 fi
 
 source drivers/pci/Config.in
diff -u --recursive --new-file v2.5.0/linux/arch/sh/kernel/io_7751se.c linux/arch/sh/kernel/io_7751se.c
--- v2.5.0/linux/arch/sh/kernel/io_7751se.c	Sat Sep  8 12:29:09 2001
+++ linux/arch/sh/kernel/io_7751se.c	Tue Dec 11 10:10:18 2001
@@ -17,7 +17,7 @@
 #include <asm/hitachi_7751se.h>
 #include <asm/addrspace.h>
 
-#include <asm/pci.h>
+#include <linux/pci.h>
 #include <asm/pci-sh7751.h>
 
 #if 0
@@ -70,7 +70,7 @@
 	else
 		return (volatile __u16 *) (PA_SUPERIO + (port << 1));
 #endif
-	maybebadio(name,port);
+	maybebadio(name,(unsigned long)port);
 	return (volatile __u16*)port;
 }
 
@@ -276,6 +276,7 @@
 /* ISA page descriptor.  */
 static __u32 sh_isa_memmap[256];
 
+#if 0
 static int
 sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
 {
@@ -286,12 +287,11 @@
 
 	idx = start >> 12;
 	sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
-#if 0
 	printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
 	       start, length, offset, idx, sh_isa_memmap[idx]);
-#endif
 	return 0;
 }
+#endif
 
 unsigned long
 sh7751se_isa_port2addr(unsigned long offset)
diff -u --recursive --new-file v2.5.0/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c
--- v2.5.0/linux/arch/sh/kernel/irq.c	Sat Sep  8 12:29:09 2001
+++ linux/arch/sh/kernel/irq.c	Wed Nov 28 13:22:26 2001
@@ -27,6 +27,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -84,31 +85,30 @@
  */
 
 #if defined(CONFIG_PROC_FS)
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
 	int i, j;
 	struct irqaction * action;
-	char *p = buf;
 
-	p += sprintf(p, "           ");
+	seq_puts(p, "           ");
 	for (j=0; j<smp_num_cpus; j++)
-		p += sprintf(p, "CPU%d       ",j);
-	*p++ = '\n';
+		seq_printf(p, "CPU%d       ",j);
+	seq_putc(p, '\n');
 
 	for (i = 0 ; i < ACTUAL_NR_IRQS ; i++) {
 		action = irq_desc[i].action;
 		if (!action) 
 			continue;
-		p += sprintf(p, "%3d: ",i);
-		p += sprintf(p, "%10u ", kstat_irqs(i));
-		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %s", action->name);
+		seq_printf(p, "%3d: ",i);
+		seq_printf(p, "%10u ", kstat_irqs(i));
+		seq_printf(p, " %14s", irq_desc[i].handler->typename);
+		seq_printf(p, "  %s", action->name);
 
 		for (action=action->next; action; action = action->next)
-			p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
+			seq_printf(p, ", %s", action->name);
+		seq_putc(p, '\n');
 	}
-	return p - buf;
+	return 0;
 }
 #endif
 
diff -u --recursive --new-file v2.5.0/linux/arch/sh/kernel/pci-7751se.c linux/arch/sh/kernel/pci-7751se.c
--- v2.5.0/linux/arch/sh/kernel/pci-7751se.c	Sat Sep  8 12:29:09 2001
+++ linux/arch/sh/kernel/pci-7751se.c	Tue Dec 11 10:10:18 2001
@@ -37,7 +37,6 @@
  */
 int __init pcibios_init_platform(void)
 {
-   unsigned long data;
    unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
    unsigned short bcr2;
 
diff -u --recursive --new-file v2.5.0/linux/arch/sh/kernel/traps.c linux/arch/sh/kernel/traps.c
--- v2.5.0/linux/arch/sh/kernel/traps.c	Sat Sep  8 12:29:09 2001
+++ linux/arch/sh/kernel/traps.c	Tue Dec 11 10:10:18 2001
@@ -560,3 +560,8 @@
 		}
 	}
 }
+
+void show_trace_task(struct task_struct *tsk)
+{
+	printk("Backtrace not yet implemented for SH.\n");
+}
diff -u --recursive --new-file v2.5.0/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.5.0/linux/arch/sparc/kernel/irq.c	Thu Jul 19 18:11:13 2001
+++ linux/arch/sparc/kernel/irq.c	Wed Nov 28 13:22:26 2001
@@ -27,6 +27,7 @@
 #include <linux/delay.h>
 #include <linux/threads.h>
 #include <linux/spinlock.h>
+#include <linux/seq_file.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -97,42 +98,42 @@
 	  NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL
 };
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	struct irqaction * action;
 #ifdef CONFIG_SMP
 	int j;
 #endif
 
 	if (sparc_cpu_model == sun4d) {
-		extern int sun4d_get_irq_list(char *);
+		extern int show_sun4d_interrupts(struct seq_file *, void *);
 		
-		return sun4d_get_irq_list(buf);
+		return show_sun4d_interrupts(p, v);
 	}
 	for (i = 0 ; i < (NR_IRQS+1) ; i++) {
 	        action = *(i + irq_action);
 		if (!action) 
 		        continue;
-		len += sprintf(buf+len, "%3d: ", i);
+		seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
-		len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < smp_num_cpus; j++)
-			len += sprintf(buf+len, "%10u ",
+			seq_printf(p, "%10u ",
 				kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-		len += sprintf(buf+len, " %c %s",
+		seq_printf(p, " %c %s",
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
+			seq_printf(p, ",%s %s",
 				(action->flags & SA_INTERRUPT) ? " +" : "",
 				action->name);
 		}
-		len += sprintf(buf+len, "\n");
+		seq_putc(p, '\n');
 	}
-	return len;
+	return 0;
 }
 
 void free_irq(unsigned int irq, void *dev_id)
diff -u --recursive --new-file v2.5.0/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c
--- v2.5.0/linux/arch/sparc/kernel/sun4d_irq.c	Thu Jul 19 18:11:13 2001
+++ linux/arch/sparc/kernel/sun4d_irq.c	Wed Nov 28 13:22:26 2001
@@ -20,6 +20,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
+#include <linux/seq_file.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -72,9 +73,9 @@
 spinlock_t sun4d_imsk_lock = SPIN_LOCK_UNLOCKED;
 #endif
 
-int sun4d_get_irq_list(char *buf)
+int show_sun4d_interrupts(struct seq_file *p, void *v)
 {
-	int i, j = 0, k = 0, len = 0, sbusl;
+	int i, j = 0, k = 0, sbusl;
 	struct irqaction * action;
 #ifdef CONFIG_SMP
 	int x;
@@ -94,21 +95,21 @@
 			}
 			continue;
 		}
-found_it:	len += sprintf(buf+len, "%3d: ", i);
+found_it:	seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
-		len += sprintf(buf+len, "%10u ", kstat_irqs(i));
+		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
 		for (x = 0; x < smp_num_cpus; x++)
-			len += sprintf(buf+len, "%10u ",
+			seq_printf(p, "%10u ",
 				       kstat.irqs[cpu_logical_map(x)][i]);
 #endif
-		len += sprintf(buf+len, "%c %s",
+		seq_printf(p, "%c %s",
 			(action->flags & SA_INTERRUPT) ? '+' : ' ',
 			action->name);
 		action = action->next;
 		for (;;) {
 			for (; action; action = action->next) {
-				len += sprintf(buf+len, ",%s %s",
+				seq_printf(p, ",%s %s",
 					(action->flags & SA_INTERRUPT) ? " +" : "",
 					action->name);
 			}
@@ -123,9 +124,9 @@
 				action = sbus_actions [(j << 5) + (sbusl << 2)].action;
 			}
 		}
-		len += sprintf(buf+len, "\n");
+		seq_putc(p, '\n');
 	}
-	return len;
+	return 0;
 }
 
 void sun4d_free_irq(unsigned int irq, void *dev_id)
diff -u --recursive --new-file v2.5.0/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.5.0/linux/arch/sparc64/kernel/irq.c	Tue Nov 13 09:16:05 2001
+++ linux/arch/sparc64/kernel/irq.c	Wed Nov 28 13:22:26 2001
@@ -18,6 +18,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 
 #include <asm/ptrace.h>
 #include <asm/processor.h>
@@ -104,9 +105,9 @@
 #define put_smpaff_in_irqaction(action, smpaff)	(action)->mask = (smpaff)
 #define get_smpaff_in_irqaction(action) 	((action)->mask)
 
-int get_irq_list(char *buf)
+int show_interrupts(struct seq_file *p, void *v)
 {
-	int i, len = 0;
+	int i;
 	struct irqaction *action;
 #ifdef CONFIG_SMP
 	int j;
@@ -115,23 +116,23 @@
 	for(i = 0; i < (NR_IRQS + 1); i++) {
 		if(!(action = *(i + irq_action)))
 			continue;
-		len += sprintf(buf + len, "%3d: ", i);
+		seq_print(p, "%3d: ", i);
 #ifndef CONFIG_SMP
-		len += sprintf(buf + len, "%10u ", kstat_irqs(i));
+		seq_print(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < smp_num_cpus; j++)
-			len += sprintf(buf + len, "%10u ",
+			seq_print(p, "%10u ",
 				       kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-		len += sprintf(buf + len, " %s:%lx", action->name, \
+		seq_print(p, " %s:%lx", action->name,
 						get_ino_in_irqaction(action));
 		for(action = action->next; action; action = action->next) {
-			len += sprintf(buf+len, ", %s:%lx", action->name, \
+			seq_print(p, ", %s:%lx", action->name,
 						get_ino_in_irqaction(action));
 		}
-		len += sprintf(buf + len, "\n");
+		seq_putc(p, '\n');
 	}
-	return len;
+	return 0;
 }
 
 /* Now these are always passed a true fully specified sun4u INO. */
diff -u --recursive --new-file v2.5.0/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c
--- v2.5.0/linux/arch/sparc64/solaris/socksys.c	Sun Feb 18 19:49:54 2001
+++ linux/arch/sparc64/solaris/socksys.c	Fri Nov 30 08:26:04 2001
@@ -118,7 +118,6 @@
         struct T_primsg *it;
 
 	/* XXX: check this */
-	lock_kernel();
 	sock = (struct sol_socket_struct *)filp->private_data;
 	SOLDD(("sock release %016lx(%016lx)\n", sock, filp));
 	it = sock->pfirst;
@@ -132,7 +131,6 @@
 	filp->private_data = NULL;
 	SOLDD(("socksys_release %016lx\n", sock));
 	mykfree((char*)sock);
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c
--- v2.5.0/linux/arch/sparc64/solaris/timod.c	Thu Sep 20 14:11:57 2001
+++ linux/arch/sparc64/solaris/timod.c	Mon Dec 10 13:52:53 2001
@@ -33,7 +33,7 @@
 	u32 arg);
 asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
 
-spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED;
+static spinlock_t timod_pagelock = SPIN_LOCK_UNLOCKED;
 static char * page = NULL ;
 
 #ifndef DEBUG_SOLARIS_KMALLOC
diff -u --recursive --new-file v2.5.0/linux/drivers/acorn/scsi/arxescsi.h linux/drivers/acorn/scsi/arxescsi.h
--- v2.5.0/linux/drivers/acorn/scsi/arxescsi.h	Fri May 12 11:21:20 2000
+++ linux/drivers/acorn/scsi/arxescsi.h	Wed Nov 28 10:22:26 2001
@@ -61,7 +61,6 @@
 eh_bus_reset_handler:		fas216_eh_bus_reset,	\
 eh_device_reset_handler:	fas216_eh_device_reset,	\
 eh_abort_handler:		fas216_eh_abort,	\
-use_new_eh_code:		1			\
 	}
 
 #ifndef HOSTS_C
diff -u --recursive --new-file v2.5.0/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c
--- v2.5.0/linux/drivers/acorn/scsi/cumana_2.c	Sun Nov  4 09:31:57 2001
+++ linux/drivers/acorn/scsi/cumana_2.c	Wed Nov 28 10:22:26 2001
@@ -575,7 +575,6 @@
 	eh_bus_reset_handler:		fas216_eh_bus_reset,
 	eh_device_reset_handler:	fas216_eh_device_reset,
 	eh_abort_handler:		fas216_eh_abort,
-	use_new_eh_code:		1
 };
 
 static int __init cumanascsi2_init(void)
diff -u --recursive --new-file v2.5.0/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c
--- v2.5.0/linux/drivers/acorn/scsi/eesox.c	Sun Nov  4 09:31:57 2001
+++ linux/drivers/acorn/scsi/eesox.c	Wed Nov 28 10:22:27 2001
@@ -577,7 +577,6 @@
 	eh_bus_reset_handler:		fas216_eh_bus_reset,
 	eh_device_reset_handler:	fas216_eh_device_reset,
 	eh_abort_handler:		fas216_eh_abort,
-	use_new_eh_code:		1
 };
 
 static int __init eesox_init(void)
diff -u --recursive --new-file v2.5.0/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c
--- v2.5.0/linux/drivers/acorn/scsi/powertec.c	Sun Nov  4 09:31:57 2001
+++ linux/drivers/acorn/scsi/powertec.c	Wed Nov 28 10:22:27 2001
@@ -477,7 +477,6 @@
 	eh_bus_reset_handler:		fas216_eh_bus_reset,
 	eh_device_reset_handler:	fas216_eh_device_reset,
 	eh_abort_handler:		fas216_eh_abort,
-	use_new_eh_code:		1
 };
 
 static int __init powertecscsi_init(void)
diff -u --recursive --new-file v2.5.0/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.5.0/linux/drivers/block/DAC960.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/block/DAC960.c	Sat Dec  8 20:02:47 2001
@@ -30,6 +30,7 @@
 #include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/blkpg.h>
 #include <linux/interrupt.h>
@@ -306,9 +307,9 @@
 
 static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
 {
-  spin_unlock_irq(&io_request_lock);
+  spin_unlock_irq(&Controller->RequestQueue->queue_lock);
   __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands);
-  spin_lock_irq(&io_request_lock);
+  spin_lock_irq(&Controller->RequestQueue->queue_lock);
 }
 
 
@@ -1922,76 +1923,6 @@
 
 
 /*
-  DAC960_BackMergeFunction is the Back Merge Function for the DAC960 driver.
-*/
-
-static int DAC960_BackMergeFunction(RequestQueue_T *RequestQueue,
-				    IO_Request_T *Request,
-				    BufferHeader_T *BufferHeader,
-				    int MaxSegments)
-{
-  DAC960_Controller_T *Controller =
-    (DAC960_Controller_T *) RequestQueue->queuedata;
-  if (Request->bhtail->b_data + Request->bhtail->b_size == BufferHeader->b_data)
-    return true;
-  if (Request->nr_segments < MaxSegments &&
-      Request->nr_segments < Controller->DriverScatterGatherLimit)
-    {
-      Request->nr_segments++;
-      return true;
-    }
-  return false;
-}
-
-
-/*
-  DAC960_FrontMergeFunction is the Front Merge Function for the DAC960 driver.
-*/
-
-static int DAC960_FrontMergeFunction(RequestQueue_T *RequestQueue,
-				     IO_Request_T *Request,
-				     BufferHeader_T *BufferHeader,
-				     int MaxSegments)
-{
-  DAC960_Controller_T *Controller =
-    (DAC960_Controller_T *) RequestQueue->queuedata;
-  if (BufferHeader->b_data + BufferHeader->b_size == Request->bh->b_data)
-    return true;
-  if (Request->nr_segments < MaxSegments &&
-      Request->nr_segments < Controller->DriverScatterGatherLimit)
-    {
-      Request->nr_segments++;
-      return true;
-    }
-  return false;
-}
-
-
-/*
-  DAC960_MergeRequestsFunction is the Merge Requests Function for the
-  DAC960 driver.
-*/
-
-static int DAC960_MergeRequestsFunction(RequestQueue_T *RequestQueue,
-					IO_Request_T *Request,
-					IO_Request_T *NextRequest,
-					int MaxSegments)
-{
-  DAC960_Controller_T *Controller =
-    (DAC960_Controller_T *) RequestQueue->queuedata;
-  int TotalSegments = Request->nr_segments + NextRequest->nr_segments;
-  if (Request->bhtail->b_data + Request->bhtail->b_size
-      == NextRequest->bh->b_data)
-    TotalSegments--;
-  if (TotalSegments > MaxSegments ||
-      TotalSegments > Controller->DriverScatterGatherLimit)
-    return false;
-  Request->nr_segments = TotalSegments;
-  return true;
-}
-
-
-/*
   DAC960_RegisterBlockDevice registers the Block Device structures
   associated with Controller.
 */
@@ -2016,14 +1947,13 @@
   */
   RequestQueue = BLK_DEFAULT_QUEUE(MajorNumber);
   blk_init_queue(RequestQueue, DAC960_RequestFunction);
-  blk_queue_headactive(RequestQueue, 0);
-  RequestQueue->back_merge_fn = DAC960_BackMergeFunction;
-  RequestQueue->front_merge_fn = DAC960_FrontMergeFunction;
-  RequestQueue->merge_requests_fn = DAC960_MergeRequestsFunction;
   RequestQueue->queuedata = Controller;
+  RequestQueue->max_segments = Controller->DriverScatterGatherLimit;
+  RequestQueue->max_sectors = Controller->MaxBlocksPerCommand;
   Controller->RequestQueue = RequestQueue;
   /*
-    Initialize the Max Sectors per Request array.
+    Initialize the Disk Partitions array, Partition Sizes array, Block Sizes
+    array, and Max Sectors per Request array.
   */
   for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++)
     Controller->MaxSectorsPerRequest[MinorNumber] =
@@ -2031,7 +1961,6 @@
   Controller->GenericDiskInfo.part = Controller->DiskPartitions;
   Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
   blksize_size[MajorNumber] = Controller->BlockSizes;
-  max_sectors[MajorNumber] = Controller->MaxSectorsPerRequest;
   /*
     Initialize Read Ahead to 128 sectors.
   */
@@ -2080,9 +2009,7 @@
   */
   Controller->GenericDiskInfo.part = NULL;
   Controller->GenericDiskInfo.sizes = NULL;
-  blk_size[MajorNumber] = NULL;
-  blksize_size[MajorNumber] = NULL;
-  max_sectors[MajorNumber] = NULL;
+  blk_clear(MajorNumber);
   /*
     Remove the Generic Disk Information structure from the list.
   */
@@ -2813,23 +2740,24 @@
       CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
       while (BufferHeader != NULL)
 	{
-	  if (BufferHeader->b_data == LastDataEndPointer)
+	  if (bio_data(BufferHeader) == LastDataEndPointer)
 	    {
 	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
-		BufferHeader->b_size;
-	      LastDataEndPointer += BufferHeader->b_size;
+		bio_size(BufferHeader);
+	      LastDataEndPointer += bio_size(BufferHeader);
 	    }
 	  else
 	    {
 	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus32(BufferHeader->b_data);
+		Virtual_to_Bus32(bio_data(BufferHeader));
 	      ScatterGatherList[SegmentNumber].SegmentByteCount =
-		BufferHeader->b_size;
-	      LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
+		bio_size(BufferHeader);
+	      LastDataEndPointer = bio_data(BufferHeader) +
+		bio_size(BufferHeader);
 	      if (SegmentNumber++ > Controller->DriverScatterGatherLimit)
 		panic("DAC960: Scatter/Gather Segment Overflow\n");
 	    }
-	  BufferHeader = BufferHeader->b_reqnext;
+	  BufferHeader = BufferHeader->bi_next;
 	}
       if (SegmentNumber != Command->SegmentCount)
 	panic("DAC960: SegmentNumber != SegmentCount\n");
@@ -2903,23 +2831,24 @@
 				 .ScatterGatherSegments;
       while (BufferHeader != NULL)
 	{
-	  if (BufferHeader->b_data == LastDataEndPointer)
+	  if (bio_data(BufferHeader) == LastDataEndPointer)
 	    {
 	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
-		BufferHeader->b_size;
-	      LastDataEndPointer += BufferHeader->b_size;
+		bio_size(BufferHeader);
+	      LastDataEndPointer += bio_size(BufferHeader);
 	    }
 	  else
 	    {
 	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus64(BufferHeader->b_data);
+		Virtual_to_Bus64(bio_data(BufferHeader));
 	      ScatterGatherList[SegmentNumber].SegmentByteCount =
-		BufferHeader->b_size;
-	      LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
+		bio_size(BufferHeader);
+	      LastDataEndPointer = bio_data(BufferHeader) +
+		bio_size(BufferHeader);
 	      if (SegmentNumber++ > Controller->DriverScatterGatherLimit)
 		panic("DAC960: Scatter/Gather Segment Overflow\n");
 	    }
-	  BufferHeader = BufferHeader->b_reqnext;
+	  BufferHeader = BufferHeader->bi_next;
 	}
       if (SegmentNumber != Command->SegmentCount)
 	panic("DAC960: SegmentNumber != SegmentCount\n");
@@ -2947,7 +2876,7 @@
   while (true)
     {
       if (list_empty(RequestQueueHead)) return false;
-      Request = blkdev_entry_next_request(RequestQueueHead);
+      Request = elv_next_request(RequestQueue);
       Command = DAC960_AllocateCommand(Controller);
       if (Command != NULL) break;
       if (!WaitForCommand) return false;
@@ -2958,12 +2887,10 @@
   else Command->CommandType = DAC960_WriteCommand;
   Command->Completion = Request->waiting;
   Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev);
-  Command->BlockNumber =
-    Request->sector
-    + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect;
+  Command->BlockNumber = Request->sector;
   Command->BlockCount = Request->nr_sectors;
   Command->SegmentCount = Request->nr_segments;
-  Command->BufferHeader = Request->bh;
+  Command->BufferHeader = Request->bio;
   Command->RequestBuffer = Request->buffer;
   blkdev_dequeue_request(Request);
   blkdev_release_request(Request);
@@ -3016,8 +2943,10 @@
 static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
 						 boolean SuccessfulIO)
 {
-  blk_finished_io(BufferHeader->b_size >> 9);
-  BufferHeader->b_end_io(BufferHeader, SuccessfulIO);
+  if (SuccessfulIO)
+    set_bit(BIO_UPTODATE, &BufferHeader->bi_flags);
+  blk_finished_io(bio_sectors(BufferHeader));
+  BufferHeader->bi_end_io(BufferHeader);
 }
 
 
@@ -3071,13 +3000,13 @@
 	       Controller, Controller->ControllerNumber,
 	       Command->LogicalDriveNumber, Command->BlockNumber,
 	       Command->BlockNumber + Command->BlockCount - 1);
-  if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
+  if (DAC960_PartitionNumber(Command->BufferHeader->bi_dev) > 0)
     DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
 		 Controller, Controller->ControllerNumber,
 		 Command->LogicalDriveNumber,
-		 DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
-		 Command->BufferHeader->b_rsector,
-		 Command->BufferHeader->b_rsector + Command->BlockCount - 1);
+		 DAC960_PartitionNumber(Command->BufferHeader->bi_dev),
+		 Command->BufferHeader->bi_sector,
+		 Command->BufferHeader->bi_sector + Command->BlockCount - 1);
 }
 
 
@@ -3104,8 +3033,8 @@
 	  */
 	  while (BufferHeader != NULL)
 	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-	      BufferHeader->b_reqnext = NULL;
+	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
+	      BufferHeader->bi_next = NULL;
 	      DAC960_ProcessCompletedBuffer(BufferHeader, true);
 	      BufferHeader = NextBufferHeader;
 	    }
@@ -3119,7 +3048,7 @@
       else if ((CommandStatus == DAC960_V1_IrrecoverableDataError ||
 		CommandStatus == DAC960_V1_BadDataEncountered) &&
 	       BufferHeader != NULL &&
-	       BufferHeader->b_reqnext != NULL)
+	       BufferHeader->bi_next != NULL)
 	{
 	  DAC960_V1_CommandMailbox_T *CommandMailbox =
 	    &Command->V1.CommandMailbox;
@@ -3133,10 +3062,10 @@
 	      Command->CommandType = DAC960_WriteRetryCommand;
 	      CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write;
 	    }
-	  Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits;
+	  Command->BlockCount = bio_size(BufferHeader) >> DAC960_BlockSizeBits;
 	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
 	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus32(BufferHeader->b_data);
+	    Virtual_to_Bus32(bio_data(BufferHeader));
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3149,8 +3078,8 @@
 	  */
 	  while (BufferHeader != NULL)
 	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-	      BufferHeader->b_reqnext = NULL;
+	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
+	      BufferHeader->bi_next = NULL;
 	      DAC960_ProcessCompletedBuffer(BufferHeader, false);
 	      BufferHeader = NextBufferHeader;
 	    }
@@ -3164,8 +3093,8 @@
   else if (CommandType == DAC960_ReadRetryCommand ||
 	   CommandType == DAC960_WriteRetryCommand)
     {
-      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-      BufferHeader->b_reqnext = NULL;
+      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
+      BufferHeader->bi_next = NULL;
       /*
 	Perform completion processing for this single buffer.
       */
@@ -3182,14 +3111,14 @@
 	  DAC960_V1_CommandMailbox_T *CommandMailbox =
 	    &Command->V1.CommandMailbox;
 	  Command->BlockNumber +=
-	    BufferHeader->b_size >> DAC960_BlockSizeBits;
+	    bio_size(BufferHeader) >> DAC960_BlockSizeBits;
 	  Command->BlockCount =
-	    NextBufferHeader->b_size >> DAC960_BlockSizeBits;
+	    bio_size(NextBufferHeader) >> DAC960_BlockSizeBits;
 	  Command->BufferHeader = NextBufferHeader;
 	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
 	  CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
 	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus32(NextBufferHeader->b_data);
+	    Virtual_to_Bus32(bio_data(NextBufferHeader));
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3935,13 +3864,13 @@
 	       Controller, Controller->ControllerNumber,
 	       Command->LogicalDriveNumber, Command->BlockNumber,
 	       Command->BlockNumber + Command->BlockCount - 1);
-  if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0)
+  if (DAC960_PartitionNumber(Command->BufferHeader->bi_dev) > 0)
     DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
 		 Controller, Controller->ControllerNumber,
 		 Command->LogicalDriveNumber,
-		 DAC960_PartitionNumber(Command->BufferHeader->b_rdev),
-		 Command->BufferHeader->b_rsector,
-		 Command->BufferHeader->b_rsector + Command->BlockCount - 1);
+		 DAC960_PartitionNumber(Command->BufferHeader->bi_dev),
+		 Command->BufferHeader->bi_sector,
+		 Command->BufferHeader->bi_sector + Command->BlockCount - 1);
 }
 
 
@@ -4210,8 +4139,8 @@
 	  */
 	  while (BufferHeader != NULL)
 	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-	      BufferHeader->b_reqnext = NULL;
+	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
+	      BufferHeader->bi_next = NULL;
 	      DAC960_ProcessCompletedBuffer(BufferHeader, true);
 	      BufferHeader = NextBufferHeader;
 	    }
@@ -4225,19 +4154,19 @@
       else if (Command->V2.RequestSense.SenseKey
 	       == DAC960_SenseKey_MediumError &&
 	       BufferHeader != NULL &&
-	       BufferHeader->b_reqnext != NULL)
+	       BufferHeader->bi_next != NULL)
 	{
 	  if (CommandType == DAC960_ReadCommand)
 	    Command->CommandType = DAC960_ReadRetryCommand;
 	  else Command->CommandType = DAC960_WriteRetryCommand;
-	  Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits;
+	  Command->BlockCount = bio_size(BufferHeader) >> DAC960_BlockSizeBits;
 	  CommandMailbox->SCSI_10.CommandControlBits
 				 .AdditionalScatterGatherListMemory = false;
 	  CommandMailbox->SCSI_10.DataTransferSize =
 	    Command->BlockCount << DAC960_BlockSizeBits;
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments[0].SegmentDataPointer =
-	    Virtual_to_Bus64(BufferHeader->b_data);
+	    Virtual_to_Bus64(bio_data(BufferHeader));
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments[0].SegmentByteCount =
 	    CommandMailbox->SCSI_10.DataTransferSize;
@@ -4255,8 +4184,8 @@
 	  */
 	  while (BufferHeader != NULL)
 	    {
-	      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-	      BufferHeader->b_reqnext = NULL;
+	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
+	      BufferHeader->bi_next = NULL;
 	      DAC960_ProcessCompletedBuffer(BufferHeader, false);
 	      BufferHeader = NextBufferHeader;
 	    }
@@ -4270,8 +4199,8 @@
   else if (CommandType == DAC960_ReadRetryCommand ||
 	   CommandType == DAC960_WriteRetryCommand)
     {
-      BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext;
-      BufferHeader->b_reqnext = NULL;
+      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
+      BufferHeader->bi_next = NULL;
       /*
 	Perform completion processing for this single buffer.
       */
@@ -4286,16 +4215,16 @@
       if (NextBufferHeader != NULL)
 	{
 	  Command->BlockNumber +=
-	    BufferHeader->b_size >> DAC960_BlockSizeBits;
+	    bio_size(BufferHeader) >> DAC960_BlockSizeBits;
 	  Command->BlockCount =
-	    NextBufferHeader->b_size >> DAC960_BlockSizeBits;
+	    bio_size(NextBufferHeader) >> DAC960_BlockSizeBits;
 	  Command->BufferHeader = NextBufferHeader;
 	  CommandMailbox->SCSI_10.DataTransferSize =
 	    Command->BlockCount << DAC960_BlockSizeBits;
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments[0]
 				 .SegmentDataPointer =
-	    Virtual_to_Bus64(NextBufferHeader->b_data);
+	    Virtual_to_Bus64(bio_data(NextBufferHeader));
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments[0]
 				 .SegmentByteCount =
@@ -5416,7 +5345,8 @@
   int LogicalDriveNumber = DAC960_LogicalDriveNumber(Inode->i_rdev);
   DiskGeometry_T Geometry, *UserGeometry;
   DAC960_Controller_T *Controller;
-  int PartitionNumber;
+  int res;
+
   if (File != NULL && (File->f_flags & O_NONBLOCK))
     return DAC960_UserIOCTL(Inode, File, Request, Argument);
   if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
@@ -5465,61 +5395,27 @@
 	    LogicalDeviceInfo->ConfigurableDeviceSize
 	    / (Geometry.heads * Geometry.sectors);
 	}
-      Geometry.start =
-	Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].start_sect;
+      Geometry.start = get_start_sect(Inode->i_rdev);
       return (copy_to_user(UserGeometry, &Geometry,
 			   sizeof(DiskGeometry_T)) ? -EFAULT : 0);
     case BLKGETSIZE:
-      /* Get Device Size. */
-      if ((unsigned long *) Argument == NULL) return -EINVAL;
-      return put_user(Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)]
-						 .nr_sects,
-		      (unsigned long *) Argument);
     case BLKGETSIZE64:
-      if ((u64 *) Argument == NULL) return -EINVAL;
-      return put_user((u64) Controller->GenericDiskInfo
-				       .part[MINOR(Inode->i_rdev)]
-				       .nr_sects << 9,
-		      (u64 *) Argument);
     case BLKRAGET:
     case BLKRASET:
     case BLKFLSBUF:
     case BLKBSZGET:
     case BLKBSZSET:
       return blk_ioctl(Inode->i_rdev, Request, Argument);
+
     case BLKRRPART:
       /* Re-Read Partition Table. */
       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
       if (Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 1)
 	return -EBUSY;
-      for (PartitionNumber = 0;
-	   PartitionNumber < DAC960_MaxPartitions;
-	   PartitionNumber++)
-	{
-	  KernelDevice_T Device = DAC960_KernelDevice(ControllerNumber,
-						      LogicalDriveNumber,
-						      PartitionNumber);
-	  int MinorNumber = DAC960_MinorNumber(LogicalDriveNumber,
-					       PartitionNumber);
-	  if (Controller->GenericDiskInfo.part[MinorNumber].nr_sects == 0)
-	    continue;
-	  /*
-	    Flush all changes and invalidate buffered state.
-	  */
-	  invalidate_device(Device, 1);
-	  /*
-	    Clear existing partition sizes.
-	  */
-	  if (PartitionNumber > 0)
-	    {
-	      Controller->GenericDiskInfo.part[MinorNumber].start_sect = 0;
-	      Controller->GenericDiskInfo.part[MinorNumber].nr_sects = 0;
-	    }
-	  /*
-	    Reset the Block Size so that the partition table can be read.
-	  */
-	  set_blocksize(Device, BLOCK_SIZE);
-	}
+      res = wipe_partitions(Inode->i_rdev);
+      if (res) /* nothing */
+	return res;
+
       DAC960_RegisterDisk(Controller, LogicalDriveNumber);
       return 0;
     }
@@ -5641,11 +5537,11 @@
 	    while (Controller->V1.DirectCommandActive[DCDB.Channel]
 						     [DCDB.TargetID])
 	      {
-		spin_unlock_irq(&io_request_lock);
+		spin_unlock_irq(&Controller->RequestQueue->queue_lock);
 		__wait_event(Controller->CommandWaitQueue,
 			     !Controller->V1.DirectCommandActive
 					     [DCDB.Channel][DCDB.TargetID]);
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&Controller->RequestQueue->queue_lock);
 	      }
 	    Controller->V1.DirectCommandActive[DCDB.Channel]
 					      [DCDB.TargetID] = true;
diff -u --recursive --new-file v2.5.0/linux/drivers/block/DAC960.h linux/drivers/block/DAC960.h
--- v2.5.0/linux/drivers/block/DAC960.h	Wed Oct 17 14:46:29 2001
+++ linux/drivers/block/DAC960.h	Tue Nov 27 09:23:27 2001
@@ -2191,7 +2191,7 @@
   of the Linux Kernel and I/O Subsystem.
 */
 
-typedef struct buffer_head BufferHeader_T;
+typedef struct bio BufferHeader_T;
 typedef struct file File_T;
 typedef struct block_device_operations BlockDeviceOperations_T;
 typedef struct completion Completion_T;
@@ -2475,7 +2475,6 @@
   DiskPartition_T DiskPartitions[DAC960_MinorCount];
   int PartitionSizes[DAC960_MinorCount];
   int BlockSizes[DAC960_MinorCount];
-  int MaxSectorsPerRequest[DAC960_MinorCount];
   unsigned char ProgressBuffer[DAC960_ProgressBufferSize];
   unsigned char UserStatusBuffer[DAC960_UserMessageSize];
 }
@@ -2509,7 +2508,7 @@
 void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
 				  ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+  spin_lock_irqsave(&Controller->RequestQueue->queue_lock, *ProcessorFlags);
 }
 
 
@@ -2521,13 +2520,13 @@
 void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
 				  ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(&Controller->RequestQueue->queue_lock, *ProcessorFlags);
 }
 
 
 /*
   DAC960_AcquireControllerLockRF acquires exclusive access to Controller,
-  but is only called from the request function with the io_request_lock held.
+  but is only called from the request function with the queue lock held.
 */
 
 static inline
@@ -2539,7 +2538,7 @@
 
 /*
   DAC960_ReleaseControllerLockRF releases exclusive access to Controller,
-  but is only called from the request function with the io_request_lock held.
+  but is only called from the request function with the queue lock held.
 */
 
 static inline
@@ -2558,7 +2557,7 @@
 void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
 				    ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(&io_request_lock, *ProcessorFlags);
+  spin_lock_irqsave(&Controller->RequestQueue->queue_lock, *ProcessorFlags);
 }
 
 
@@ -2571,7 +2570,7 @@
 void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
 				    ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(&io_request_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(&Controller->RequestQueue->queue_lock, *ProcessorFlags);
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.5.0/linux/drivers/block/Makefile	Sun Sep  9 12:00:55 2001
+++ linux/drivers/block/Makefile	Thu Dec  6 14:02:56 2001
@@ -10,9 +10,9 @@
 
 O_TARGET := block.o
 
-export-objs	:= ll_rw_blk.o blkpg.o loop.o DAC960.o genhd.o
+export-objs	:= elevator.o ll_rw_blk.o blkpg.o loop.o DAC960.o genhd.o block_ioctl.o
 
-obj-y	:= ll_rw_blk.o blkpg.o genhd.o elevator.o
+obj-y	:= elevator.o ll_rw_blk.o blkpg.o genhd.o block_ioctl.o
 
 obj-$(CONFIG_MAC_FLOPPY)	+= swim3.o
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy.o
diff -u --recursive --new-file v2.5.0/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.5.0/linux/drivers/block/acsi.c	Fri Nov  9 13:58:03 2001
+++ linux/drivers/block/acsi.c	Tue Nov 27 09:23:27 2001
@@ -1011,7 +1011,6 @@
 		goto repeat;
 	}
 	
-	block += acsi_part[dev].start_sect;
 	target = acsi_info[DEVICE_NR(dev)].target;
 	lun    = acsi_info[DEVICE_NR(dev)].lun;
 
@@ -1123,7 +1122,7 @@
 	    put_user( 64, &geo->heads );
 	    put_user( 32, &geo->sectors );
 	    put_user( acsi_info[dev].size >> 11, &geo->cylinders );
-		put_user( acsi_part[MINOR(inode->i_rdev)].start_sect, &geo->start );
+		put_user(get_start_sect(inode->i_rdev), &geo->start);
 		return 0;
 	  }
 		
@@ -1852,7 +1851,7 @@
 {
 	int device;
 	struct gendisk * gdev;
-	int max_p, start, i;
+	int res;
 	struct acsi_info_struct *aip;
 	
 	device = DEVICE_NR(MINOR(dev));
@@ -1867,16 +1866,7 @@
 	DEVICE_BUSY = 1;
 	sti();
 
-	max_p = gdev->max_p;
-	start = device << gdev->minor_shift;
-
-	for( i = max_p - 1; i >= 0 ; i-- ) {
-		if (gdev->part[start + i].nr_sects != 0) {
-			invalidate_device(MKDEV(MAJOR_NR, start + i), 1);
-			gdev->part[start + i].nr_sects = 0;
-		}
-		gdev->part[start+i].start_sect = 0;
-	};
+	res = wipe_partitions(dev);
 
 	stdma_lock( NULL, NULL );
 
@@ -1891,12 +1881,13 @@
 
 	ENABLE_IRQ();
 	stdma_release();
-	
-	grok_partitions(gdev, device, (aip->type==HARDDISK)?1<<4:1, aip->size);
+
+	if (!res)
+		grok_partitions(dev, aip->size);
 
 	DEVICE_BUSY = 0;
 	wake_up(&busy_wait);
-	return 0;
+	return res;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c
--- v2.5.0/linux/drivers/block/acsi_slm.c	Tue May 22 10:23:16 2001
+++ linux/drivers/block/acsi_slm.c	Fri Nov 30 08:26:04 2001
@@ -121,8 +121,8 @@
 static struct slm {
 	unsigned	target;			/* target number */
 	unsigned	lun;			/* LUN in target controller */
-	unsigned	wbusy : 1;		/* output part busy */
-	unsigned	rbusy : 1;		/* status part busy */
+	atomic_t	wr_ok; 			/* set to 0 if output part busy */
+	atomic_t	rd_ok;			/* set to 0 if status part busy */
 } slm_info[MAX_SLM];
 
 int N_SLM_Printers = 0;
@@ -778,15 +778,17 @@
 
 	if (file->f_mode & 2) {
 		/* open for writing is exclusive */
-		if (sip->wbusy)
+		if ( !atomic_dec_and_test(&sip->wr_ok) ) {
+			atomic_inc(&sip->wr_ok);	
 			return( -EBUSY );
-		sip->wbusy = 1;
+		}
 	}
 	if (file->f_mode & 1) {
-		/* open for writing is exclusive */
-		if (sip->rbusy)
-			return( -EBUSY );
-		sip->rbusy = 1;
+		/* open for reading is exclusive */
+                if ( !atomic_dec_and_test(&sip->rd_ok) ) {
+                        atomic_inc(&sip->rd_ok);
+                        return( -EBUSY );
+                }
 	}
 
 	return( 0 );
@@ -801,12 +803,10 @@
 	device = MINOR(inode->i_rdev);
 	sip = &slm_info[device];
 
-	lock_kernel();
 	if (file->f_mode & 2)
-		sip->wbusy = 0;
+		atomic_inc( &sip->wr_ok );
 	if (file->f_mode & 1)
-		sip->rbusy = 0;
-	unlock_kernel();
+		atomic_inc( &sip->rd_ok );
 	
 	return( 0 );
 }
@@ -983,8 +983,8 @@
 
 	slm_info[N_SLM_Printers].target = target;
 	slm_info[N_SLM_Printers].lun    = lun;
-	slm_info[N_SLM_Printers].wbusy  = 0;
-	slm_info[N_SLM_Printers].rbusy  = 0;
+	atomic_set(&slm_info[N_SLM_Printers].wr_ok, 1 ); 
+	atomic_set(&slm_info[N_SLM_Printers].rd_ok, 1 );
 	
 	printk( KERN_INFO "  Printer: %s\n", SLMBuffer );
 	printk( KERN_INFO "Detected slm%d at id %d lun %d\n",
diff -u --recursive --new-file v2.5.0/linux/drivers/block/amiflop.c linux/drivers/block/amiflop.c
--- v2.5.0/linux/drivers/block/amiflop.c	Thu Oct 25 13:58:34 2001
+++ linux/drivers/block/amiflop.c	Tue Nov 27 09:23:27 2001
@@ -1895,10 +1895,9 @@
 	free_irq(IRQ_AMIGA_DSKBLK, NULL);
 	custom.dmacon = DMAF_DISK; /* disable DMA */
 	amiga_chip_free(raw_buf);
-	blk_size[MAJOR_NR] = NULL;
-	blksize_size[MAJOR_NR] = NULL;
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 	release_mem_region(CUSTOM_PHYSADDR+0x20, 8);
 	unregister_blkdev(MAJOR_NR, "fd");
+	blk_clear(MAJOR_NR);
 }
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/block/blkpg.c linux/drivers/block/blkpg.c
--- v2.5.0/linux/drivers/block/blkpg.c	Sun Nov 11 10:20:21 2001
+++ linux/drivers/block/blkpg.c	Thu Dec  6 14:02:56 2001
@@ -63,7 +63,8 @@
  *                 or has the same number as an existing one
  *          0: all OK.
  */
-int add_partition(kdev_t dev, struct blkpg_partition *p) {
+int add_partition(kdev_t dev, struct blkpg_partition *p)
+{
 	struct gendisk *g;
 	long long ppstart, pplength;
 	long pstart, plength;
@@ -123,7 +124,8 @@
  *
  * Note that the dev argument refers to the entire disk, not the partition.
  */
-int del_partition(kdev_t dev, struct blkpg_partition *p) {
+int del_partition(kdev_t dev, struct blkpg_partition *p)
+{
 	struct gendisk *g;
 	kdev_t devp;
 	int drive, first_minor, minor;
@@ -192,16 +194,21 @@
 /*
  * Common ioctl's for block devices
  */
-
+extern int block_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg);
 int blk_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
 {
+	request_queue_t *q;
 	struct gendisk *g;
 	u64 ullval = 0;
-	int intval;
+	int intval, *iptr;
 
 	if (!dev)
 		return -EINVAL;
 
+	intval = block_ioctl(dev, cmd, arg);
+	if (intval != -ENOTTY)
+		return intval;
+
 	switch (cmd) {
 		case BLKROSET:
 			if (!capable(CAP_SYS_ADMIN))
@@ -226,8 +233,26 @@
 				return -EINVAL;
 			return put_user(read_ahead[MAJOR(dev)], (long *) arg);
 
+		case BLKFRASET:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EACCES;
+			if (!(iptr = max_readahead[MAJOR(dev)]))
+				return -EINVAL;
+			iptr[MINOR(dev)] = arg;
+			return 0;
+
+		case BLKFRAGET:
+			if (!(iptr = max_readahead[MAJOR(dev)]))
+				return -EINVAL;
+			return put_user(iptr[MINOR(dev)], (long *) arg);
+
+		case BLKSECTGET:
+			if ((q = blk_get_queue(dev)))
+				return put_user(q->max_sectors, (unsigned short *)arg);
+			return -EINVAL;
+
 		case BLKFLSBUF:
-			if(!capable(CAP_SYS_ADMIN))
+			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
 			fsync_dev(dev);
 			invalidate_buffers(dev);
@@ -246,8 +271,7 @@
 
 			if (cmd == BLKGETSIZE)
 				return put_user((unsigned long)ullval, (unsigned long *)arg);
-			else
-				return put_user(ullval, (u64 *)arg);
+			return put_user(ullval, (u64 *)arg);
 #if 0
 		case BLKRRPART: /* Re-read partition tables */
 			if (!capable(CAP_SYS_ADMIN)) 
@@ -258,34 +282,34 @@
 		case BLKPG:
 			return blkpg_ioctl(dev, (struct blkpg_ioctl_arg *) arg);
 			
+		/*
+		 * deprecated, use the /proc/iosched interface instead
+		 */
 		case BLKELVGET:
-			return blkelvget_ioctl(&blk_get_queue(dev)->elevator,
-					       (blkelv_ioctl_arg_t *) arg);
 		case BLKELVSET:
-			return blkelvset_ioctl(&blk_get_queue(dev)->elevator,
-					       (blkelv_ioctl_arg_t *) arg);
+			return -ENOTTY;
 
 		case BLKBSZGET:
 			/* get the logical block size (cf. BLKSSZGET) */
 			intval = BLOCK_SIZE;
 			if (blksize_size[MAJOR(dev)])
 				intval = blksize_size[MAJOR(dev)][MINOR(dev)];
-			return put_user (intval, (int *) arg);
+			return put_user(intval, (int *) arg);
 
 		case BLKBSZSET:
 			/* set the logical block size */
-			if (!capable (CAP_SYS_ADMIN))
+			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
-			if (!dev || !arg)
+			if (!arg)
 				return -EINVAL;
-			if (get_user (intval, (int *) arg))
+			if (get_user(intval, (int *) arg))
 				return -EFAULT;
 			if (intval > PAGE_SIZE || intval < 512 ||
 			    (intval & (intval - 1)))
 				return -EINVAL;
-			if (is_mounted (dev) || is_swap_partition (dev))
+			if (is_mounted(dev) || is_swap_partition(dev))
 				return -EBUSY;
-			set_blocksize (dev, intval);
+			set_blocksize(dev, intval);
 			return 0;
 
 		default:
diff -u --recursive --new-file v2.5.0/linux/drivers/block/block_ioctl.c linux/drivers/block/block_ioctl.c
--- v2.5.0/linux/drivers/block/block_ioctl.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/block_ioctl.c	Sat Dec  8 20:02:47 2001
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 Licens
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+ *
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/config.h>
+#include <linux/locks.h>
+#include <linux/swap.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/module.h>
+#include <linux/blk.h>
+
+#include <linux/cdrom.h>
+
+int blk_do_rq(request_queue_t *q, struct request *rq)
+{
+	DECLARE_COMPLETION(wait);
+	int err = 0;
+
+	rq->flags |= REQ_BARRIER;
+	rq->waiting = &wait;
+	elv_add_request(q, rq, 1);
+	generic_unplug_device(q);
+	wait_for_completion(&wait);
+
+	/*
+	 * for now, never retry anything
+	 */
+	if (rq->errors)
+		err = -EIO;
+
+	return err;
+}
+
+int block_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
+{
+	request_queue_t *q;
+	struct request *rq;
+	int close = 0, err;
+
+	q = blk_get_queue(dev);
+	if (!q)
+		return -ENXIO;
+
+	switch (cmd) {
+		case CDROMCLOSETRAY:
+			close = 1;
+		case CDROMEJECT:
+			rq = blk_get_request(q, WRITE, __GFP_WAIT);
+			rq->flags = REQ_BLOCK_PC;
+			memset(rq->cmd, 0, sizeof(rq->cmd));
+			rq->cmd[0] = GPCMD_START_STOP_UNIT;
+			rq->cmd[4] = 0x02 + (close != 0);
+			err = blk_do_rq(q, rq);
+			blk_put_request(rq);
+			break;
+		default:
+			err = -ENOTTY;
+	}
+
+	return err;
+}
diff -u --recursive --new-file v2.5.0/linux/drivers/block/cciss.c linux/drivers/block/cciss.c
--- v2.5.0/linux/drivers/block/cciss.c	Fri Nov  9 14:28:46 2001
+++ linux/drivers/block/cciss.c	Sat Dec  8 20:02:47 2001
@@ -84,7 +84,7 @@
 #define MAX_CONFIG_WAIT 1000 
 
 #define READ_AHEAD 	 128
-#define NR_CMDS		 128 /* #commands that can be outstanding */
+#define NR_CMDS		 384 /* #commands that can be outstanding */
 #define MAX_CTLR 8
 
 #define CCISS_DMA_MASK	0xFFFFFFFF	/* 32 bit DMA */
@@ -147,7 +147,6 @@
                 "       IRQ: %d\n"
                 "       Logical drives: %d\n"
                 "       Current Q depth: %d\n"
-		"       Current # commands on controller %d\n"
                 "       Max Q depth since init: %d\n"
 		"       Max # commands on controller since init: %d\n"
 		"       Max SG entries since init: %d\n\n",
@@ -158,8 +157,7 @@
                 (unsigned long)h->vaddr,
                 (unsigned int)h->intr,
                 h->num_luns, 
-                h->Qdepth, h->commands_outstanding,
-		h->maxQsinceinit, h->max_outstanding, h->maxSG);
+                h->Qdepth, h->maxQsinceinit, h->max_outstanding, h->maxSG);
 
         pos += size; len += size;
 	for(i=0; i<h->num_luns; i++) {
@@ -237,7 +235,7 @@
                 	i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
                         if (i == NR_CMDS)
                                 return NULL;
-                } while(test_and_set_bit(i%32, h->cmd_pool_bits+(i/32)) != 0);
+                } while(test_and_set_bit(i & 31, h->cmd_pool_bits+(i/32)) != 0);
 #ifdef CCISS_DEBUG
 		printk(KERN_DEBUG "cciss: using command buffer %d\n", i);
 #endif
@@ -308,13 +306,10 @@
 
 		/* for each partition */ 
 		for(j=0; j<MAX_PART; j++)
-		{
 			hba[ctlr]->blocksizes[(i<<NWD_SHIFT) + j] = 1024; 
 
-			hba[ctlr]->hardsizes[ (i<<NWD_SHIFT) + j] = 
-				drv->block_size;
-		}
 		hba[ctlr]->gendisk.nr_real++;
+		(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->block_size;
 	}
 }
 /*
@@ -377,8 +372,6 @@
 {
 	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;
 	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;
-	int diskinfo[4];
-	struct hd_geometry *geo = (struct hd_geometry *)arg;
 
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss_ioctl: Called with cmd=%x %lx\n", cmd, arg);
@@ -386,6 +379,10 @@
 	
 	switch(cmd) {
 	case HDIO_GETGEO:
+	{
+		struct hd_geometry *geo = (struct hd_geometry *)arg;
+		int diskinfo[4];
+
 		if (hba[ctlr]->drv[dsk].cylinders) {
 			diskinfo[0] = hba[ctlr]->drv[dsk].heads;
 			diskinfo[1] = hba[ctlr]->drv[dsk].sectors;
@@ -393,20 +390,18 @@
 		} else {
 			diskinfo[0] = 0xff;
 			diskinfo[1] = 0x3f;
-			diskinfo[2] = hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f);		}
+			diskinfo[2] = hba[ctlr]->drv[dsk].nr_blocks / (0xff*0x3f);
+		}
 		put_user(diskinfo[0], &geo->heads);
 		put_user(diskinfo[1], &geo->sectors);
 		put_user(diskinfo[2], &geo->cylinders);
-		put_user(hba[ctlr]->hd[MINOR(inode->i_rdev)].start_sect, &geo->start);
-		return 0;
-	case BLKGETSIZE:
-		put_user(hba[ctlr]->hd[MINOR(inode->i_rdev)].nr_sects, (unsigned long *)arg);
-		return 0;
-	case BLKGETSIZE64:
-		put_user((u64)hba[ctlr]->hd[MINOR(inode->i_rdev)].nr_sects << 9, (u64*)arg);
+		put_user(get_start_sect(inode->i_rdev), &geo->start);
 		return 0;
+	}
 	case BLKRRPART:
 		return revalidate_logvol(inode->i_rdev, 1);
+	case BLKGETSIZE:
+	case BLKGETSIZE64:
 	case BLKFLSBUF:
 	case BLKBSZSET:
 	case BLKBSZGET:
@@ -415,9 +410,7 @@
 	case BLKRASET:
 	case BLKRAGET:
 	case BLKPG:
-	case BLKELVGET:
-	case BLKELVSET:
-		return( blk_ioctl(inode->i_rdev, cmd, arg));
+		return blk_ioctl(inode->i_rdev, cmd, arg);
 	case CCISS_GETPCIINFO:
 	{
 		cciss_pci_info_struct pciinfo;
@@ -459,16 +452,7 @@
 //			printk("cciss_ioctl: delay and count cannot be 0\n");
 			return( -EINVAL);
 		}
-		spin_lock_irqsave(&io_request_lock, flags);
-		/* Can only safely update if no commands outstanding */ 
-		if (c->commands_outstanding > 0 )
-		{
-//			printk("cciss_ioctl: cannot change coalasing "
-//				"%d commands outstanding on controller\n", 
-//					c->commands_outstanding);
-			spin_unlock_irqrestore(&io_request_lock, flags);
-			return(-EINVAL);
-		}
+		spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
 		/* Update the field, and then ring the doorbell */ 
 		writel( intinfo.delay, 
 			&(c->cfgtable->HostWrite.CoalIntDelay));
@@ -484,7 +468,7 @@
 			/* delay and try again */
 			udelay(1000);
 		}	
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
 		if (i >= MAX_CONFIG_WAIT)
 			return( -EFAULT);
                 return(0);
@@ -515,7 +499,7 @@
 		if (copy_from_user(NodeName, (void *) arg, sizeof( NodeName_type)))
 			return -EFAULT;
 
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
 
 			/* Update the field, and then ring the doorbell */ 
 		for(i=0;i<16;i++)
@@ -531,7 +515,7 @@
 			/* delay and try again */
 			udelay(1000);
 		}	
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
 		if (i >= MAX_CONFIG_WAIT)
 			return( -EFAULT);
                 return(0);
@@ -658,11 +642,11 @@
 			c->SG[0].Ext = 0;  // we are not chaining
 		}
 		/* Put the request on the tail of the request queue */
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
 		addQ(&h->reqQ, c);
 		h->Qdepth++;
 		start_io(h);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
 
 		/* Wait for completion */
 		while(c->cmd_type != CMD_IOCTL_DONE)
@@ -710,42 +694,32 @@
         int ctlr, target;
         struct gendisk *gdev;
         unsigned long flags;
-        int max_p;
-        int start;
-        int i;
+        int res;
 
         target = MINOR(dev) >> NWD_SHIFT;
         ctlr = MAJOR(dev) - MAJOR_NR;
         gdev = &(hba[ctlr]->gendisk);
 
-        spin_lock_irqsave(&io_request_lock, flags);
+        spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
         if (hba[ctlr]->drv[target].usage_count > maxusage) {
-                spin_unlock_irqrestore(&io_request_lock, flags);
+                spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
                 printk(KERN_WARNING "cciss: Device busy for "
                         "revalidation (usage=%d)\n",
                         hba[ctlr]->drv[target].usage_count);
                 return -EBUSY;
         }
         hba[ctlr]->drv[target].usage_count++;
-        spin_unlock_irqrestore(&io_request_lock, flags);
-
-        max_p = gdev->max_p;
-        start = target << gdev->minor_shift;
+        spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
 
-        for(i=max_p-1; i>=0; i--) {
-                int minor = start+i;
-                invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1);
-                gdev->part[minor].start_sect = 0;
-                gdev->part[minor].nr_sects = 0;
+	res = wipe_partitions(dev);
+	if (res)
+		goto leave;
 
-                /* reset the blocksize so we can read the partition table */
-                blksize_size[MAJOR_NR+ctlr][minor] = 1024;
-        }
 	/* setup partitions per disk */
-	grok_partitions(gdev, target, MAX_PART, 
-			hba[ctlr]->drv[target].nr_blocks);
+	grok_partitions(dev, hba[ctlr]->drv[target].nr_blocks);
+leave:
         hba[ctlr]->drv[target].usage_count--;
-        return 0;
+        return res;
 }
 
 static int frevalidate_logvol(kdev_t dev)
@@ -776,15 +750,15 @@
         if (MINOR(dev) != 0)
                 return -ENXIO;
 
-        spin_lock_irqsave(&io_request_lock, flags);
+        spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
         if (hba[ctlr]->usage_count > 1) {
-                spin_unlock_irqrestore(&io_request_lock, flags);
+                spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
                 printk(KERN_WARNING "cciss: Device busy for volume"
                         " revalidation (usage=%d)\n", hba[ctlr]->usage_count);
                 return -EBUSY;
         }
-        spin_unlock_irqrestore(&io_request_lock, flags);
         hba[ctlr]->usage_count++;
+	spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
 
         /*
          * Set the partition and block size structures for all volumes
@@ -793,7 +767,6 @@
 	memset(hba[ctlr]->hd,         0, sizeof(struct hd_struct) * 256);
         memset(hba[ctlr]->sizes,      0, sizeof(int) * 256);
         memset(hba[ctlr]->blocksizes, 0, sizeof(int) * 256);
-        memset(hba[ctlr]->hardsizes,  0, sizeof(int) * 256);
         memset(hba[ctlr]->drv,        0, sizeof(drive_info_struct)
 						* CISS_MAX_LUN);
         hba[ctlr]->gendisk.nr_real = 0;
@@ -1089,11 +1062,11 @@
 	while(( c = h->reqQ) != NULL )
 	{
 		/* can't do anything if fifo is full */
-		if ((h->access.fifo_full(h)))
-		{
-			printk(KERN_WARNING "cciss: fifo full \n");
-			return;
+		if ((h->access.fifo_full(h))) {
+			printk(KERN_WARNING "cciss: fifo full\n");
+			break;
 		}
+
 		/* Get the frist entry from the Request Q */ 
 		removeQ(&(h->reqQ), c);
 		h->Qdepth--;
@@ -1106,18 +1079,18 @@
 	}
 }
 
-static inline void complete_buffers( struct buffer_head *bh, int status)
+static inline void complete_buffers(struct bio *bio, int status)
 {
-	struct buffer_head *xbh;
-	
-	while(bh)
-	{
-		xbh = bh->b_reqnext; 
-		bh->b_reqnext = NULL; 
-		blk_finished_io(bh->b_size >> 9);
-		bh->b_end_io(bh, status);
-		bh = xbh;
+	while (bio) {
+		int nsecs = bio_sectors(bio);
+
+		struct bio *xbh = bio->bi_next; 
+		bio->bi_next = NULL; 
+		blk_finished_io(nsecs);
+		bio_endio(bio, status, nsecs);
+		bio = xbh;
 	}
+
 } 
 /* checks the status of the job and calls complete buffers to mark all 
  * buffers for the completed job. 
@@ -1135,7 +1108,7 @@
 	{
 		temp64.val32.lower = cmd->SG[i].Addr.lower;
 		temp64.val32.upper = cmd->SG[i].Addr.upper;
-		pci_unmap_single(hba[cmd->ctlr]->pdev,
+		pci_unmap_page(hba[cmd->ctlr]->pdev,
 			temp64.val, cmd->SG[i].Len, 
 			(cmd->Request.Type.Direction == XFER_READ) ? 
 				PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
@@ -1214,83 +1187,38 @@
 				status=0;
 		}
 	}
-	complete_buffers(cmd->rq->bh, status);
+
+	complete_buffers(cmd->rq->bio, status);
 
 #ifdef CCISS_DEBUG
 	printk("Done with %p\n", cmd->rq);
 #endif /* CCISS_DEBUG */ 
-	end_that_request_last(cmd->rq);
-}
-
-
-static inline int cpq_new_segment(request_queue_t *q, struct request *rq,
-                                  int max_segments)
-{
-        if (rq->nr_segments < MAXSGENTRIES) {
-                rq->nr_segments++;
-                return 1;
-        }
-        return 0;
-}
 
-static int cpq_back_merge_fn(request_queue_t *q, struct request *rq,
-                             struct buffer_head *bh, int max_segments)
-{
-        if (rq->bhtail->b_data + rq->bhtail->b_size == bh->b_data)
-                return 1;
-        return cpq_new_segment(q, rq, max_segments);
-}
-
-static int cpq_front_merge_fn(request_queue_t *q, struct request *rq,
-                             struct buffer_head *bh, int max_segments)
-{
-        if (bh->b_data + bh->b_size == rq->bh->b_data)
-                return 1;
-        return cpq_new_segment(q, rq, max_segments);
-}
-
-static int cpq_merge_requests_fn(request_queue_t *q, struct request *rq,
-                                 struct request *nxt, int max_segments)
-{
-        int total_segments = rq->nr_segments + nxt->nr_segments;
-
-        if (rq->bhtail->b_data + rq->bhtail->b_size == nxt->bh->b_data)
-                total_segments--;
-
-        if (total_segments > MAXSGENTRIES)
-                return 0;
-
-        rq->nr_segments = total_segments;
-        return 1;
+	end_that_request_last(cmd->rq);
 }
 
 /* 
  * Get a request and submit it to the controller. 
- * Currently we do one request at a time.  Ideally we would like to send
- * everything to the controller on the first call, but there is a danger
- * of holding the io_request_lock for to long.  
  */
 static void do_cciss_request(request_queue_t *q)
 {
 	ctlr_info_t *h= q->queuedata; 
 	CommandList_struct *c;
 	int log_unit, start_blk, seg;
-	char *lastdataend;
-	struct buffer_head *bh;
 	struct list_head *queue_head = &q->queue_head;
 	struct request *creq;
 	u64bit temp64;
-	struct my_sg tmp_sg[MAXSGENTRIES];
-	int i;
+	struct scatterlist tmp_sg[MAXSGENTRIES];
+	int i, dir;
 
-	if (q->plugged)
+	if (blk_queue_plugged(q))
 		goto startio;
 
-queue_next:
+queue:
 	if (list_empty(queue_head))
 		goto startio;
 
-	creq =	blkdev_entry_next_request(queue_head); 
+	creq = elv_next_request(q);
 	if (creq->nr_segments > MAXSGENTRIES)
                 BUG();
 
@@ -1299,7 +1227,7 @@
                 printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
                                 h->ctlr, creq->rq_dev, creq);
                 blkdev_dequeue_request(creq);
-                complete_buffers(creq->bh, 0);
+                complete_buffers(creq->bio, 0);
 		end_that_request_last(creq);
 		goto startio;
         }
@@ -1309,10 +1237,9 @@
 
 	blkdev_dequeue_request(creq);
 
-	spin_unlock_irq(&io_request_lock);
+	spin_unlock_irq(&q->queue_lock);
 
-	c->cmd_type = CMD_RWREQ;      
-	bh = creq->bh;
+	c->cmd_type = CMD_RWREQ;
 	c->rq = creq;
 	
 	/* fill in the request */ 
@@ -1325,44 +1252,29 @@
 	c->Request.Type.Type =  TYPE_CMD; // It is a command. 
 	c->Request.Type.Attribute = ATTR_SIMPLE; 
 	c->Request.Type.Direction = 
-		(creq->cmd == READ) ? XFER_READ: XFER_WRITE; 
+		(rq_data_dir(creq) == READ) ? XFER_READ: XFER_WRITE; 
 	c->Request.Timeout = 0; // Don't time out	
-	c->Request.CDB[0] = (creq->cmd == READ) ? CCISS_READ : CCISS_WRITE;
-	start_blk = hba[h->ctlr]->hd[MINOR(creq->rq_dev)].start_sect + creq->sector;
+	c->Request.CDB[0] = (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
+	start_blk = creq->sector;
 #ifdef CCISS_DEBUG
-	if (bh == NULL)
-		panic("cciss: bh== NULL?");
 	printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n",(int) creq->sector,
 		(int) creq->nr_sectors);	
 #endif /* CCISS_DEBUG */
-	seg = 0; 
-	lastdataend = NULL;
-	while(bh)
-	{
-		if (bh->b_data == lastdataend)
-		{  // tack it on to the last segment 
-			tmp_sg[seg-1].len +=bh->b_size;
-			lastdataend += bh->b_size;
-		} else
-		{
-			if (seg == MAXSGENTRIES)
-				BUG();
-			tmp_sg[seg].len = bh->b_size;
-			tmp_sg[seg].start_addr = bh->b_data;
-			lastdataend = bh->b_data + bh->b_size;
-			seg++;
-		}
-		bh = bh->b_reqnext;
-	}
+
+	seg = blk_rq_map_sg(q, creq, tmp_sg);
+
 	/* get the DMA records for the setup */ 
+	if (c->Request.Type.Direction == XFER_READ)
+		dir = PCI_DMA_FROMDEVICE;
+	else
+		dir = PCI_DMA_TODEVICE;
+
 	for (i=0; i<seg; i++)
 	{
-		c->SG[i].Len = tmp_sg[i].len;
-		temp64.val = (__u64) pci_map_single( h->pdev,
-			tmp_sg[i].start_addr,
-			tmp_sg[i].len,
-			(c->Request.Type.Direction == XFER_READ) ? 
-                                PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+		c->SG[i].Len = tmp_sg[i].length;
+		temp64.val = (__u64) pci_map_page(h->pdev, tmp_sg[i].page,
+			 		  tmp_sg[i].offset, tmp_sg[i].length,
+					  dir);
 		c->SG[i].Addr.lower = temp64.val32.lower;
                 c->SG[i].Addr.upper = temp64.val32.upper;
                 c->SG[i].Ext = 0;  // we are not chaining
@@ -1386,14 +1298,14 @@
 	c->Request.CDB[8]= creq->nr_sectors & 0xff; 
 	c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
 
-	spin_lock_irq(&io_request_lock);
+	spin_lock_irq(&q->queue_lock);
 
 	addQ(&(h->reqQ),c);
 	h->Qdepth++;
 	if(h->Qdepth > h->maxQsinceinit)
 		h->maxQsinceinit = h->Qdepth; 
 
-	goto queue_next;
+	goto queue;
 startio:
 	start_io(h);
 }
@@ -1414,7 +1326,7 @@
 	 * If there are completed commands in the completion queue,
 	 * we had better do something about it.
 	 */
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
 	while( h->access.intr_pending(h))
 	{
 		while((a = h->access.command_completed(h)) != FIFO_EMPTY) 
@@ -1447,11 +1359,12 @@
 			}
 		}
 	}
+
 	/*
 	 * See if we can queue up some more IO
 	 */
 	do_cciss_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 }
 /* 
  *  We cannot read the structure directly, for portablity we must use 
@@ -1873,7 +1786,18 @@
 	sprintf(hba[i]->devname, "cciss%d", i);
 	hba[i]->ctlr = i;
 	hba[i]->pdev = pdev;
-			
+
+	/* configure PCI DMA stuff */
+	if (!pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff))
+		printk("cciss: using DAC cycles\n");
+	else if (!pci_set_dma_mask(pdev, 0xffffffff))
+		printk("cciss: not using DAC cycles\n");
+	else {
+		printk("cciss: no suitable DMA available\n");
+		free_hba(i);
+		return -ENODEV;
+	}
+
 	if( register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops))
 	{
 		printk(KERN_ERR "cciss:  Unable to get major number "
@@ -1943,19 +1867,14 @@
 	q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
         q->queuedata = hba[i];
         blk_init_queue(q, do_cciss_request);
-        blk_queue_headactive(q, 0);		
+	blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
+	blk_queue_max_segments(q, MAXSGENTRIES);
+	blk_queue_max_sectors(q, 512);
 
 	/* fill in the other Kernel structs */
 	blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
-        hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
         read_ahead[MAJOR_NR+i] = READ_AHEAD;
 
-	/* Set the pointers to queue functions */ 
-	q->back_merge_fn = cpq_back_merge_fn;
-        q->front_merge_fn = cpq_front_merge_fn;
-        q->merge_requests_fn = cpq_merge_requests_fn;
-
-
 	/* Fill in the gendisk data */ 	
 	hba[i]->gendisk.major = MAJOR_NR + i;
 	hba[i]->gendisk.major_name = "cciss";
@@ -2004,12 +1923,11 @@
 	unregister_blkdev(MAJOR_NR+i, hba[i]->devname);
 	remove_proc_entry(hba[i]->devname, proc_cciss);	
 	
-
 	/* remove it from the disk list */
 	del_gendisk(&(hba[i]->gendisk));
 
-	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct), 
-		hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
+	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
+			    hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
 	pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof( ErrorInfo_struct),
 		hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
 	kfree(hba[i]->cmd_pool_bits);
@@ -2017,32 +1935,31 @@
 }	
 
 static struct pci_driver cciss_pci_driver = {
-	 name:   "cciss",
-	probe:  cciss_init_one,
-	remove:  cciss_remove_one,
-	id_table:  cciss_pci_device_id, /* id_table */
+	name:		"cciss",
+	probe:		cciss_init_one,
+	remove:		cciss_remove_one,
+	id_table:	cciss_pci_device_id, /* id_table */
 };
 
 /*
-*  This is it.  Register the PCI driver information for the cards we control
-*  the OS will call our registered routines when it finds one of our cards. 
-*/
+ *  This is it.  Register the PCI driver information for the cards we control
+ *  the OS will call our registered routines when it finds one of our cards. 
+ */
 int __init cciss_init(void)
 {
-
 	printk(KERN_INFO DRIVER_NAME "\n");
+
 	/* Register for out PCI devices */
 	if (pci_register_driver(&cciss_pci_driver) > 0 )
 		return 0;
 	else 
 		return -ENODEV;
 
- }
+}
 
 EXPORT_NO_SYMBOLS;
 static int __init init_cciss_module(void)
 {
-
 	return ( cciss_init());
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/block/cciss.h linux/drivers/block/cciss.h
--- v2.5.0/linux/drivers/block/cciss.h	Tue May 22 10:23:16 2001
+++ linux/drivers/block/cciss.h	Tue Nov 27 09:23:27 2001
@@ -15,11 +15,6 @@
 
 #define MAJOR_NR COMPAQ_CISS_MAJOR 
 
-struct my_sg {
-	int len;
-	char *start_addr;
-};
-
 struct ctlr_info;
 typedef struct ctlr_info ctlr_info_t;
 
@@ -85,9 +80,8 @@
 	struct gendisk   gendisk;
 	   // indexed by minor numbers
 	struct hd_struct hd[256];
-	int              sizes[256];
+	int		 sizes[256];
 	int              blocksizes[256];
-	int              hardsizes[256];
 };
 
 /*  Defining the diffent access_menthods */
@@ -247,5 +241,8 @@
 	char	*product_name;
 	struct access_method *access;
 };
+
+#define CCISS_LOCK(i)	(&((BLK_DEFAULT_QUEUE(MAJOR_NR + i))->queue_lock))
+
 #endif /* CCISS_H */
 
diff -u --recursive --new-file v2.5.0/linux/drivers/block/cciss_cmd.h linux/drivers/block/cciss_cmd.h
--- v2.5.0/linux/drivers/block/cciss_cmd.h	Fri Nov  2 17:45:42 2001
+++ linux/drivers/block/cciss_cmd.h	Tue Nov 27 09:23:27 2001
@@ -7,7 +7,7 @@
 
 //general boundary defintions
 #define SENSEINFOBYTES          32//note that this value may vary between host implementations
-#define MAXSGENTRIES            31
+#define MAXSGENTRIES            32
 #define MAXREPLYQS              256
 
 //Command Status value
diff -u --recursive --new-file v2.5.0/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.5.0/linux/drivers/block/cpqarray.c	Fri Nov  9 14:28:46 2001
+++ linux/drivers/block/cpqarray.c	Sat Dec  8 20:02:47 2001
@@ -100,7 +100,6 @@
 static struct hd_struct * ida;
 static int * ida_sizes;
 static int * ida_blocksizes;
-static int * ida_hardsizes;
 static struct gendisk ida_gendisk[MAX_CTLR];
 
 static struct proc_dir_entry *proc_array;
@@ -145,7 +144,7 @@
 
 static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
 static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c);
-static inline void complete_buffers(struct buffer_head *bh, int ok);
+static inline void complete_buffers(struct bio *bio, int ok);
 static inline void complete_command(cmdlist_t *cmd, int timeout);
 
 static void do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
@@ -176,12 +175,11 @@
 		ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)] =
 				drv->nr_blks;
 
-		for(j=0; j<16; j++) {
+		for(j=0; j<16; j++)
 			ida_blocksizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)+j] =
 				1024;
-			ida_hardsizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)+j] =
-				drv->blk_size;
-		}
+
+		(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->blk_size;
 		ida_gendisk[ctlr].nr_real++;
 	}
 
@@ -341,52 +339,10 @@
 	remove_proc_entry("cpqarray", proc_root_driver);
 	kfree(ida);
 	kfree(ida_sizes);
-	kfree(ida_hardsizes);
 	kfree(ida_blocksizes);
 }
 #endif /* MODULE */
 
-static inline int cpq_new_segment(request_queue_t *q, struct request *rq,
-				  int max_segments)
-{
-	if (rq->nr_segments < SG_MAX) {
-		rq->nr_segments++;
-		return 1;
-	}
-	return 0;
-}
-
-static int cpq_back_merge_fn(request_queue_t *q, struct request *rq,
-			     struct buffer_head *bh, int max_segments)
-{
-	if (rq->bhtail->b_data + rq->bhtail->b_size == bh->b_data)
-		return 1;
-	return cpq_new_segment(q, rq, max_segments);
-}
-
-static int cpq_front_merge_fn(request_queue_t *q, struct request *rq,
-			     struct buffer_head *bh, int max_segments)
-{
-	if (bh->b_data + bh->b_size == rq->bh->b_data)
-		return 1;
-	return cpq_new_segment(q, rq, max_segments);
-}
-
-static int cpq_merge_requests_fn(request_queue_t *q, struct request *rq,
-				 struct request *nxt, int max_segments)
-{
-	int total_segments = rq->nr_segments + nxt->nr_segments;
-
-	if (rq->bhtail->b_data + rq->bhtail->b_size == nxt->bh->b_data)
-		total_segments--;
-
-	if (total_segments > SG_MAX)
-		return 0;
-
-	rq->nr_segments = total_segments;
-	return 1;
-}
-
 /*
  *  This is it.  Find all the controllers and register them.  I really hate
  *  stealing all these major device numbers.
@@ -433,20 +389,9 @@
 		return(num_cntlrs_reg);
 	}
 
-	ida_hardsizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
-	if(ida_hardsizes==NULL)
-	{
-		kfree(ida);
-		kfree(ida_sizes); 
-		kfree(ida_blocksizes);
-		printk( KERN_ERR "cpqarray: out of memory");
-		return(num_cntlrs_reg);
-	}
-
 	memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16);
 	memset(ida_sizes, 0, sizeof(int)*nr_ctlr*NWD*16);
 	memset(ida_blocksizes, 0, sizeof(int)*nr_ctlr*NWD*16);
-	memset(ida_hardsizes, 0, sizeof(int)*nr_ctlr*NWD*16);
 	memset(ida_gendisk, 0, sizeof(struct gendisk)*MAX_CTLR);
 
 		/* 
@@ -504,7 +449,6 @@
 			{
 				kfree(ida);
 				kfree(ida_sizes);
-				kfree(ida_hardsizes);
 				kfree(ida_blocksizes);
 			}
                 	return(num_cntlrs_reg);
@@ -524,15 +468,11 @@
 		q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
 		q->queuedata = hba[i];
 		blk_init_queue(q, do_ida_request);
-		blk_queue_headactive(q, 0);
+		blk_queue_bounce_limit(q, hba[i]->pci_dev->dma_mask);
+		blk_queue_max_segments(q, SG_MAX);
 		blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);
-		hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256);
 		read_ahead[MAJOR_NR+i] = READ_AHEAD;
 
-		q->back_merge_fn = cpq_back_merge_fn;
-		q->front_merge_fn = cpq_front_merge_fn;
-		q->merge_requests_fn = cpq_merge_requests_fn;
-
 		ida_gendisk[i].major = MAJOR_NR + i;
 		ida_gendisk[i].major_name = "ida";
 		ida_gendisk[i].minor_shift = NWD_SHIFT;
@@ -911,21 +851,19 @@
 {
 	ctlr_info_t *h = q->queuedata;
 	cmdlist_t *c;
-	char *lastdataend;
 	struct list_head * queue_head = &q->queue_head;
-	struct buffer_head *bh;
 	struct request *creq;
-	struct my_sg tmp_sg[SG_MAX];
-	int i, seg;
+	struct scatterlist tmp_sg[SG_MAX];
+	int i, dir, seg;
 
-	if (q->plugged)
+	if (blk_queue_plugged(q))
 		goto startio;
 
 queue_next:
 	if (list_empty(queue_head))
 		goto startio;
 
-	creq = blkdev_entry_next_request(queue_head);
+	creq = elv_next_request(q);
 	if (creq->nr_segments > SG_MAX)
 		BUG();
 
@@ -934,7 +872,7 @@
 		printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
 				h->ctlr, creq->rq_dev, creq);
 		blkdev_dequeue_request(creq);
-		complete_buffers(creq->bh, 0);
+		complete_buffers(creq->bio, 0);
 		end_that_request_last(creq);
 		goto startio;
 	}
@@ -944,55 +882,40 @@
 
 	blkdev_dequeue_request(creq);
 
-	spin_unlock_irq(&io_request_lock);
-
-	bh = creq->bh;
+	spin_unlock_irq(&q->queue_lock);
 
 	c->ctlr = h->ctlr;
 	c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;
 	c->hdr.size = sizeof(rblk_t) >> 2;
 	c->size += sizeof(rblk_t);
 
-	c->req.hdr.blk = ida[(h->ctlr<<CTLR_SHIFT) + MINOR(creq->rq_dev)].start_sect + creq->sector;
+	c->req.hdr.blk = creq->sector;
 	c->rq = creq;
 DBGPX(
-	if (bh == NULL)
-		panic("bh == NULL?");
-	
 	printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors);
 );
-	seg = 0; lastdataend = NULL;
-	while(bh) {
-		if (bh->b_data == lastdataend) {
-			tmp_sg[seg-1].size += bh->b_size;
-			lastdataend += bh->b_size;
-		} else {
-			if (seg == SG_MAX)
-				BUG();
-			tmp_sg[seg].size = bh->b_size;
-			tmp_sg[seg].start_addr = bh->b_data;
-			lastdataend = bh->b_data + bh->b_size;
-			seg++;
-		}
-		bh = bh->b_reqnext;
-	}
+	seg = blk_rq_map_sg(q, creq, tmp_sg);
+
 	/* Now do all the DMA Mappings */
+	if (rq_data_dir(creq) == READ)
+		dir = PCI_DMA_FROMDEVICE;
+	else
+		dir = PCI_DMA_TODEVICE;
 	for( i=0; i < seg; i++)
 	{
-		c->req.sg[i].size = tmp_sg[i].size;
-		c->req.sg[i].addr = (__u32) pci_map_single(
-                		h->pci_dev, tmp_sg[i].start_addr, 
-				tmp_sg[i].size,
-                                (creq->cmd == READ) ? 
-					PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
+		c->req.sg[i].size = tmp_sg[i].length;
+		c->req.sg[i].addr = (__u32) pci_map_page(h->pci_dev,
+						 tmp_sg[i].page,
+						 tmp_sg[i].offset,
+						 tmp_sg[i].length, dir);
 	}
-DBGPX(	printk("Submitting %d sectors in %d segments\n", sect, seg); );
+DBGPX(	printk("Submitting %d sectors in %d segments\n", creq->nr_sectors, seg); );
 	c->req.hdr.sg_cnt = seg;
 	c->req.hdr.blk_cnt = creq->nr_sectors;
-	c->req.hdr.cmd = (creq->cmd == READ) ? IDA_READ : IDA_WRITE;
+	c->req.hdr.cmd = (rq_data_dir(creq) == READ) ? IDA_READ : IDA_WRITE;
 	c->type = CMD_RWREQ;
 
-	spin_lock_irq(&io_request_lock);
+	spin_lock_irq(&q->queue_lock);
 
 	/* Put the request on the tail of the request queue */
 	addQ(&h->reqQ, c);
@@ -1033,17 +956,19 @@
 	}
 }
 
-static inline void complete_buffers(struct buffer_head *bh, int ok)
+static inline void complete_buffers(struct bio *bio, int ok)
 {
-	struct buffer_head *xbh;
-	while(bh) {
-		xbh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
+	struct bio *xbh;
+	while(bio) {
+		int nsecs = bio_sectors(bio);
+
+		xbh = bio->bi_next;
+		bio->bi_next = NULL;
 		
-		blk_finished_io(bh->b_size >> 9);
-		bh->b_end_io(bh, ok);
+		blk_finished_io(nsecs);
+		bio_endio(bio, ok, nsecs);
 
-		bh = xbh;
+		bio = xbh;
 	}
 }
 /*
@@ -1052,7 +977,7 @@
 static inline void complete_command(cmdlist_t *cmd, int timeout)
 {
 	int ok=1;
-	int i;
+	int i, ddir;
 
 	if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
 	   (hba[cmd->ctlr]->misc_tflags & MISC_NONFATAL_WARN) == 0) {
@@ -1074,19 +999,18 @@
 	}
 	if (timeout) ok = 0;
 	/* unmap the DMA mapping for all the scatter gather elements */
+	if (cmd->req.hdr.cmd == IDA_READ)
+		ddir = PCI_DMA_FROMDEVICE;
+	else
+		ddir = PCI_DMA_TODEVICE;
         for(i=0; i<cmd->req.hdr.sg_cnt; i++)
-        {
-                pci_unmap_single(hba[cmd->ctlr]->pci_dev,
-                        cmd->req.sg[i].addr, cmd->req.sg[i].size,
-                        (cmd->req.hdr.cmd == IDA_READ) ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-        }
+                pci_unmap_page(hba[cmd->ctlr]->pci_dev, cmd->req.sg[i].addr,
+				cmd->req.sg[i].size, ddir);
 
-	complete_buffers(cmd->rq->bh, ok);
+	complete_buffers(cmd->rq->bio, ok);
 
-	DBGPX(printk("Done with %p\n", cmd->rq););
+        DBGPX(printk("Done with %p\n", cmd->rq););
 	end_that_request_last(cmd->rq);
-
-
 }
 
 /*
@@ -1111,7 +1035,7 @@
 	 * If there are completed commands in the completion queue,
 	 * we had better do something about it.
 	 */
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(IDA_LOCK(h->ctlr), flags);
 	if (istat & FIFO_NOT_EMPTY) {
 		while((a = h->access.command_completed(h))) {
 			a1 = a; a &= ~3;
@@ -1155,7 +1079,7 @@
 	 * See if we can queue up some more IO
 	 */
 	do_ida_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(IDA_LOCK(h->ctlr), flags);
 }
 
 /*
@@ -1201,14 +1125,10 @@
 		put_user(diskinfo[0], &geo->heads);
 		put_user(diskinfo[1], &geo->sectors);
 		put_user(diskinfo[2], &geo->cylinders);
-		put_user(ida[(ctlr<<CTLR_SHIFT)+MINOR(inode->i_rdev)].start_sect, &geo->start);
+		put_user(get_start_sect(inode->i_rdev), &geo->start);
 		return 0;
 	case IDAGETDRVINFO:
 		return copy_to_user(&io->c.drv,&hba[ctlr]->drv[dsk],sizeof(drv_info_t));
-	case BLKGETSIZE:
-		return put_user(ida[(ctlr<<CTLR_SHIFT)+MINOR(inode->i_rdev)].nr_sects, (unsigned long *)arg);
-	case BLKGETSIZE64:
-		return put_user((u64)(ida[(ctlr<<CTLR_SHIFT)+MINOR(inode->i_rdev)].nr_sects) << 9, (u64*)arg);
 	case BLKRRPART:
 		return revalidate_logvol(inode->i_rdev, 1);
 	case IDAPASSTHRU:
@@ -1244,6 +1164,8 @@
 		return(0);
 	}	
 
+	case BLKGETSIZE:
+	case BLKGETSIZE64:
 	case BLKFLSBUF:
 	case BLKBSZSET:
 	case BLKBSZGET:
@@ -1251,8 +1173,6 @@
 	case BLKROGET:
 	case BLKRASET:
 	case BLKRAGET:
-	case BLKELVGET:
-	case BLKELVSET:
 	case BLKPG:
 		return blk_ioctl(inode->i_rdev, cmd, arg);
 
@@ -1352,11 +1272,11 @@
 	}
 	
 	/* Put the request on the tail of the request queue */
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(IDA_LOCK(ctlr), flags);
 	addQ(&h->reqQ, c);
 	h->Qdepth++;
 	start_io(h);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
 
 	/* Wait for completion */
 	while(c->type != CMD_IOCTL_DONE)
@@ -1570,15 +1490,15 @@
 	if (MINOR(dev) != 0)
 		return -ENXIO;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(IDA_LOCK(ctlr), flags);
 	if (hba[ctlr]->usage_count > 1) {
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
 		printk(KERN_WARNING "cpqarray: Device busy for volume"
 			" revalidation (usage=%d)\n", hba[ctlr]->usage_count);
 		return -EBUSY;
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
 	hba[ctlr]->usage_count++;
+	spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
 
 	/*
 	 * Set the partition and block size structures for all volumes
@@ -1587,7 +1507,6 @@
 	memset(ida+(ctlr*256),            0, sizeof(struct hd_struct)*NWD*16);
 	memset(ida_sizes+(ctlr*256),      0, sizeof(int)*NWD*16);
 	memset(ida_blocksizes+(ctlr*256), 0, sizeof(int)*NWD*16);
-	memset(ida_hardsizes+(ctlr*256),  0, sizeof(int)*NWD*16);
 	memset(hba[ctlr]->drv,            0, sizeof(drv_info_t)*NWD);
 	ida_gendisk[ctlr].nr_real = 0;
 
@@ -1615,17 +1534,15 @@
 	int ctlr, target;
 	struct gendisk *gdev;
 	unsigned long flags;
-	int max_p;
-	int start;
-	int i;
+	int res;
 
 	target = DEVICE_NR(dev);
 	ctlr = MAJOR(dev) - MAJOR_NR;
 	gdev = &ida_gendisk[ctlr];
 	
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(IDA_LOCK(ctlr), flags);
 	if (hba[ctlr]->drv[target].usage_count > maxusage) {
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
 		printk(KERN_WARNING "cpqarray: Device busy for "
 			"revalidation (usage=%d)\n",
 			hba[ctlr]->drv[target].usage_count);
@@ -1633,25 +1550,14 @@
 	}
 
 	hba[ctlr]->drv[target].usage_count++;
-	spin_unlock_irqrestore(&io_request_lock, flags);
-
-	max_p = gdev->max_p;
-	start = target << gdev->minor_shift;
+	spin_unlock_irqrestore(IDA_LOCK(ctlr), flags);
 
-	for(i=max_p-1; i>=0; i--) {
-		int minor = start+i;
-		invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1);
-		gdev->part[minor].start_sect = 0;	
-		gdev->part[minor].nr_sects = 0;	
+	res = wipe_partitions(dev);
+	if (!res)
+		grok_partitions(dev, hba[ctlr]->drv[target].nr_blks);
 
-		/* reset the blocksize so we can read the partition table */
-		blksize_size[MAJOR_NR+ctlr][minor] = 1024;
-	}
-
-	/* 16 minors per disk... */
-	grok_partitions(gdev, target, 16, hba[ctlr]->drv[target].nr_blks);
 	hba[ctlr]->drv[target].usage_count--;
-	return 0;
+	return res;
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/drivers/block/cpqarray.h linux/drivers/block/cpqarray.h
--- v2.5.0/linux/drivers/block/cpqarray.h	Tue May 22 10:23:16 2001
+++ linux/drivers/block/cpqarray.h	Tue Nov 27 09:23:27 2001
@@ -56,11 +56,6 @@
 
 #ifdef __KERNEL__
 
-struct my_sg {
-	int size;
-	char *start_addr;
-};
-
 struct ctlr_info;
 typedef struct ctlr_info ctlr_info_t;
 
@@ -121,6 +116,9 @@
 	struct timer_list timer;
 	unsigned int misc_tflags;
 };
+
+#define IDA_LOCK(i)	(&((BLK_DEFAULT_QUEUE(MAJOR_NR + i))->queue_lock))
+
 #endif
 
 #endif /* CPQARRAY_H */
diff -u --recursive --new-file v2.5.0/linux/drivers/block/elevator.c linux/drivers/block/elevator.c
--- v2.5.0/linux/drivers/block/elevator.c	Thu Jul 19 20:59:41 2001
+++ linux/drivers/block/elevator.c	Fri Dec  7 16:32:26 2001
@@ -18,48 +18,70 @@
  * Removed tests for max-bomb-segments, which was breaking elvtune
  *  when run without -bN
  *
+ * Jens:
+ * - Rework again to work with bio instead of buffer_heads
+ * - loose bi_dev comparisons, partition handling is right now
+ * - completely modularize elevator setup and teardown
+ *
  */
-
+#include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/blkdev.h>
 #include <linux/elevator.h>
 #include <linux/blk.h>
+#include <linux/config.h>
 #include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/compiler.h>
+
 #include <asm/uaccess.h>
 
 /*
- * This is a bit tricky. It's given that bh and rq are for the same
+ * This is a bit tricky. It's given that bio and rq are for the same
  * device, but the next request might of course not be. Run through
  * the tests below to check if we want to insert here if we can't merge
- * bh into an existing request
+ * bio into an existing request
  */
-inline int bh_rq_in_between(struct buffer_head *bh, struct request *rq,
-			    struct list_head *head)
+inline int bio_rq_in_between(struct bio *bio, struct request *rq,
+			     struct list_head *head)
 {
 	struct list_head *next;
 	struct request *next_rq;
 
-	next = rq->queue.next;
+	/*
+	 * if .next is a valid request
+	 */
+	next = rq->queuelist.next;
 	if (next == head)
 		return 0;
 
+	next_rq = list_entry(next, struct request, queuelist);
+
+	BUG_ON(next_rq->flags & REQ_STARTED);
+
+	/*
+	 * not a sector based request
+	 */
+	if (!(next_rq->flags & REQ_CMD))
+		return 0;
+
 	/*
-	 * if the device is different (usually on a different partition),
-	 * just check if bh is after rq
+	 * if the device is different (not a normal case) just check if
+	 * bio is after rq
 	 */
-	next_rq = blkdev_entry_to_request(next);
 	if (next_rq->rq_dev != rq->rq_dev)
-		return bh->b_rsector > rq->sector;
+		return bio->bi_sector > rq->sector;
 
 	/*
-	 * ok, rq, next_rq and bh are on the same device. if bh is in between
+	 * ok, rq, next_rq and bio are on the same device. if bio is in between
 	 * the two, this is the sweet spot
 	 */
-	if (bh->b_rsector < next_rq->sector && bh->b_rsector > rq->sector)
+	if (bio->bi_sector < next_rq->sector && bio->bi_sector > rq->sector)
 		return 1;
 
 	/*
-	 * next_rq is ordered wrt rq, but bh is not in between the two
+	 * next_rq is ordered wrt rq, but bio is not in between the two
 	 */
 	if (next_rq->sector > rq->sector)
 		return 0;
@@ -68,47 +90,77 @@
 	 * next_rq and rq not ordered, if we happen to be either before
 	 * next_rq or after rq insert here anyway
 	 */
-	if (bh->b_rsector > rq->sector || bh->b_rsector < next_rq->sector)
+	if (bio->bi_sector > rq->sector || bio->bi_sector < next_rq->sector)
 		return 1;
 
 	return 0;
 }
 
+/*
+ * can we safely merge with this request?
+ */
+inline int elv_rq_merge_ok(struct request *rq, struct bio *bio)
+{
+	if (!(rq->flags & REQ_CMD))
+		return 0;
+
+	/*
+	 * different data direction or already started, don't merge
+	 */
+	if (bio_data_dir(bio) != rq_data_dir(rq))
+		return 0;
+	if (rq->flags & REQ_NOMERGE)
+		return 0;
+
+	/*
+	 * same device and no special stuff set, merge is ok
+	 */
+	if (rq->rq_dev == bio->bi_dev && !rq->waiting && !rq->special)
+		return 1;
+
+	return 0;
+}
 
 int elevator_linus_merge(request_queue_t *q, struct request **req,
-			 struct list_head * head,
-			 struct buffer_head *bh, int rw,
-			 int max_sectors)
+			 struct list_head *head, struct bio *bio)
 {
+	unsigned int count = bio_sectors(bio);
 	struct list_head *entry = &q->queue_head;
-	unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE;
+	int ret = ELEVATOR_NO_MERGE;
+	struct request *__rq;
 
+	entry = &q->queue_head;
 	while ((entry = entry->prev) != head) {
-		struct request *__rq = blkdev_entry_to_request(entry);
+		__rq = list_entry_rq(entry);
+
+		prefetch(list_entry_rq(entry->prev));
 
 		/*
 		 * simply "aging" of requests in queue
 		 */
 		if (__rq->elevator_sequence-- <= 0)
 			break;
-
-		if (__rq->waiting)
-			continue;
-		if (__rq->rq_dev != bh->b_rdev)
+		if (__rq->flags & (REQ_BARRIER | REQ_STARTED))
+			break;
+		if (!(__rq->flags & REQ_CMD))
 			continue;
-		if (!*req && bh_rq_in_between(bh, __rq, &q->queue_head))
+
+		if (!*req && bio_rq_in_between(bio, __rq, &q->queue_head))
 			*req = __rq;
-		if (__rq->cmd != rw)
-			continue;
-		if (__rq->nr_sectors + count > max_sectors)
+		if (!elv_rq_merge_ok(__rq, bio))
 			continue;
+
 		if (__rq->elevator_sequence < count)
 			break;
-		if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
+
+		/*
+		 * we can merge and sequence is ok, check if it's possible
+		 */
+		if (__rq->sector + __rq->nr_sectors == bio->bi_sector) {
 			ret = ELEVATOR_BACK_MERGE;
 			*req = __rq;
 			break;
-		} else if (__rq->sector - count == bh->b_rsector) {
+		} else if (__rq->sector - count == bio->bi_sector) {
 			ret = ELEVATOR_FRONT_MERGE;
 			__rq->elevator_sequence -= count;
 			*req = __rq;
@@ -121,13 +173,18 @@
 
 void elevator_linus_merge_cleanup(request_queue_t *q, struct request *req, int count)
 {
-	struct list_head *entry = &req->queue, *head = &q->queue_head;
+	struct list_head *entry;
+
+	BUG_ON(req->q != q);
 
 	/*
 	 * second pass scan of requests that got passed over, if any
 	 */
-	while ((entry = entry->next) != head) {
-		struct request *tmp = blkdev_entry_to_request(entry);
+	entry = &req->queuelist;
+	while ((entry = entry->next) != &q->queue_head) {
+		struct request *tmp;
+		prefetch(list_entry_rq(entry->next));
+		tmp = list_entry_rq(entry);
 		tmp->elevator_sequence -= count;
 	}
 }
@@ -138,42 +195,66 @@
 		req->elevator_sequence = next->elevator_sequence;
 }
 
+void elv_add_request_fn(request_queue_t *q, struct request *rq,
+			       struct list_head *insert_here)
+{
+	list_add(&rq->queuelist, insert_here);
+}
+
+struct request *elv_next_request_fn(request_queue_t *q)
+{
+	if (!blk_queue_empty(q))
+		return list_entry(q->queue_head.next, struct request, queuelist);
+
+	return NULL;
+}
+
+int elv_linus_init(request_queue_t *q, elevator_t *e)
+{
+	return 0;
+}
+
+void elv_linus_exit(request_queue_t *q, elevator_t *e)
+{
+}
+
 /*
  * See if we can find a request that this buffer can be coalesced with.
  */
 int elevator_noop_merge(request_queue_t *q, struct request **req,
-			struct list_head * head,
-			struct buffer_head *bh, int rw,
-			int max_sectors)
+			struct list_head *head, struct bio *bio)
 {
-	struct list_head *entry;
-	unsigned int count = bh->b_size >> 9;
-
-	if (list_empty(&q->queue_head))
-		return ELEVATOR_NO_MERGE;
+	unsigned int count = bio_sectors(bio);
+	struct list_head *entry = &q->queue_head;
+	struct request *__rq;
 
 	entry = &q->queue_head;
 	while ((entry = entry->prev) != head) {
-		struct request *__rq = blkdev_entry_to_request(entry);
+		__rq = list_entry_rq(entry);
 
-		if (__rq->cmd != rw)
-			continue;
-		if (__rq->rq_dev != bh->b_rdev)
-			continue;
-		if (__rq->nr_sectors + count > max_sectors)
+		prefetch(list_entry_rq(entry->prev));
+
+		if (__rq->flags & (REQ_BARRIER | REQ_STARTED))
+			break;
+
+		if (!(__rq->flags & REQ_CMD))
 			continue;
-		if (__rq->waiting)
+
+		if (!elv_rq_merge_ok(__rq, bio))
 			continue;
-		if (__rq->sector + __rq->nr_sectors == bh->b_rsector) {
+
+		/*
+		 * we can merge and sequence is ok, check if it's possible
+		 */
+		if (__rq->sector + __rq->nr_sectors == bio->bi_sector) {
 			*req = __rq;
 			return ELEVATOR_BACK_MERGE;
-		} else if (__rq->sector - count == bh->b_rsector) {
+		} else if (__rq->sector - count == bio->bi_sector) {
 			*req = __rq;
 			return ELEVATOR_FRONT_MERGE;
 		}
 	}
 
-	*req = blkdev_entry_to_request(q->queue_head.prev);
 	return ELEVATOR_NO_MERGE;
 }
 
@@ -181,42 +262,27 @@
 
 void elevator_noop_merge_req(struct request *req, struct request *next) {}
 
-int blkelvget_ioctl(elevator_t * elevator, blkelv_ioctl_arg_t * arg)
+int elevator_init(request_queue_t *q, elevator_t *e, elevator_t type)
 {
-	blkelv_ioctl_arg_t output;
+	*e = type;
 
-	output.queue_ID			= elevator->queue_ID;
-	output.read_latency		= elevator->read_latency;
-	output.write_latency		= elevator->write_latency;
-	output.max_bomb_segments	= 0;
+	INIT_LIST_HEAD(&q->queue_head);
 
-	if (copy_to_user(arg, &output, sizeof(blkelv_ioctl_arg_t)))
-		return -EFAULT;
+	if (e->elevator_init_fn)
+		return e->elevator_init_fn(q, e);
 
 	return 0;
 }
 
-int blkelvset_ioctl(elevator_t * elevator, const blkelv_ioctl_arg_t * arg)
+void elevator_exit(request_queue_t *q, elevator_t *e)
 {
-	blkelv_ioctl_arg_t input;
-
-	if (copy_from_user(&input, arg, sizeof(blkelv_ioctl_arg_t)))
-		return -EFAULT;
-
-	if (input.read_latency < 0)
-		return -EINVAL;
-	if (input.write_latency < 0)
-		return -EINVAL;
-
-	elevator->read_latency		= input.read_latency;
-	elevator->write_latency		= input.write_latency;
-	return 0;
+	if (e->elevator_exit_fn)
+		e->elevator_exit_fn(q, e);
 }
 
-void elevator_init(elevator_t * elevator, elevator_t type)
+int elevator_global_init(void)
 {
-	static unsigned int queue_ID;
-
-	*elevator = type;
-	elevator->queue_ID = queue_ID++;
+	return 0;
 }
+
+module_init(elevator_global_init);
diff -u --recursive --new-file v2.5.0/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.5.0/linux/drivers/block/floppy.c	Thu Oct 25 13:58:34 2001
+++ linux/drivers/block/floppy.c	Thu Dec  6 20:14:02 2001
@@ -576,7 +576,7 @@
 static struct floppy_struct *_floppy = floppy_type;
 static unsigned char current_drive;
 static long current_count_sectors;
-static unsigned char sector_t; /* sector in track */
+static unsigned char fsector_t; /* sector in track */
 static unsigned char in_sector_offset;	/* offset within physical sector,
 					 * expressed in units of 512 bytes */
 
@@ -2276,8 +2276,8 @@
  * logical buffer */
 static void request_done(int uptodate)
 {
-	int block;
 	unsigned long flags;
+	int block;
 
 	probing = 0;
 	reschedule_timeout(MAXTIMEOUT, "request done %d", uptodate);
@@ -2296,7 +2296,7 @@
 			DRS->maxtrack = 1;
 
 		/* unlock chained buffers */
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&QUEUE->queue_lock, flags);
 		while (current_count_sectors && !QUEUE_EMPTY &&
 		       current_count_sectors >= CURRENT->current_nr_sectors){
 			current_count_sectors -= CURRENT->current_nr_sectors;
@@ -2304,7 +2304,7 @@
 			CURRENT->sector += CURRENT->current_nr_sectors;
 			end_request(1);
 		}
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock, flags);
 
 		if (current_count_sectors && !QUEUE_EMPTY){
 			/* "unlock" last subsector */
@@ -2319,7 +2319,7 @@
 			DPRINT("request list destroyed in floppy request done\n");
 
 	} else {
-		if (CURRENT->cmd == WRITE) {
+		if (rq_data_dir(CURRENT) == WRITE) {
 			/* record write error information */
 			DRWE->write_errors++;
 			if (DRWE->write_errors == 1) {
@@ -2329,9 +2329,9 @@
 			DRWE->last_error_sector = CURRENT->sector;
 			DRWE->last_error_generation = DRS->generation;
 		}
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&QUEUE->queue_lock, flags);
 		end_request(0);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock, flags);
 	}
 }
 
@@ -2377,7 +2377,7 @@
 		printk("rt=%d t=%d\n", R_TRACK, TRACK);
 		printk("heads=%d eoc=%d\n", heads, eoc);
 		printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
-		       sector_t, ssize);
+		       fsector_t, ssize);
 		printk("in_sector_offset=%d\n", in_sector_offset);
 	}
 #endif
@@ -2424,7 +2424,7 @@
 	} else if (CT(COMMAND) == FD_READ){
 		buffer_track = raw_cmd->track;
 		buffer_drive = current_drive;
-		INFBOUND(buffer_max, nr_sectors + sector_t);
+		INFBOUND(buffer_max, nr_sectors + fsector_t);
 	}
 	cont->redo();
 }
@@ -2432,34 +2432,33 @@
 /* Compute maximal contiguous buffer size. */
 static int buffer_chain_size(void)
 {
-	struct buffer_head *bh;
+	struct bio *bio;
 	int size;
 	char *base;
 
 	base = CURRENT->buffer;
-	size = CURRENT->current_nr_sectors << 9;
-	bh = CURRENT->bh;
+	size = 0;
 
-	if (bh){
-		bh = bh->b_reqnext;
-		while (bh && bh->b_data == base + size){
-			size += bh->b_size;
-			bh = bh->b_reqnext;
-		}
+	rq_for_each_bio(bio, CURRENT) {
+		if (bio_data(bio) != base + size)
+			break;
+
+		size += bio->bi_size;
 	}
+
 	return size >> 9;
 }
 
 /* Compute the maximal transfer size */
 static int transfer_size(int ssize, int max_sector, int max_size)
 {
-	SUPBOUND(max_sector, sector_t + max_size);
+	SUPBOUND(max_sector, fsector_t + max_size);
 
 	/* alignment */
 	max_sector -= (max_sector % _floppy->sect) % ssize;
 
 	/* transfer size, beginning not aligned */
-	current_count_sectors = max_sector - sector_t ;
+	current_count_sectors = max_sector - fsector_t ;
 
 	return max_sector;
 }
@@ -2470,7 +2469,7 @@
 static void copy_buffer(int ssize, int max_sector, int max_sector_2)
 {
 	int remaining; /* number of transferred 512-byte sectors */
-	struct buffer_head *bh;
+	struct bio *bio;
 	char *buffer, *dma_buffer;
 	int size;
 
@@ -2479,8 +2478,8 @@
 				   CURRENT->nr_sectors);
 
 	if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE &&
-	    buffer_max > sector_t + CURRENT->nr_sectors)
-		current_count_sectors = minimum(buffer_max - sector_t,
+	    buffer_max > fsector_t + CURRENT->nr_sectors)
+		current_count_sectors = minimum(buffer_max - fsector_t,
 						CURRENT->nr_sectors);
 
 	remaining = current_count_sectors << 9;
@@ -2491,7 +2490,7 @@
 		printk("current_count_sectors=%ld\n", current_count_sectors);
 		printk("remaining=%d\n", remaining >> 9);
 		printk("CURRENT->nr_sectors=%ld\n",CURRENT->nr_sectors);
-		printk("CURRENT->current_nr_sectors=%ld\n",
+		printk("CURRENT->current_nr_sectors=%u\n",
 		       CURRENT->current_nr_sectors);
 		printk("max_sector=%d\n", max_sector);
 		printk("ssize=%d\n", ssize);
@@ -2500,9 +2499,9 @@
 
 	buffer_max = maximum(max_sector, buffer_max);
 
-	dma_buffer = floppy_track_buffer + ((sector_t - buffer_min) << 9);
+	dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9);
 
-	bh = CURRENT->bh;
+	bio = CURRENT->bio;
 	size = CURRENT->current_nr_sectors << 9;
 	buffer = CURRENT->buffer;
 
@@ -2514,8 +2513,8 @@
 		    dma_buffer < floppy_track_buffer){
 			DPRINT("buffer overrun in copy buffer %d\n",
 				(int) ((floppy_track_buffer - dma_buffer) >>9));
-			printk("sector_t=%d buffer_min=%d\n",
-			       sector_t, buffer_min);
+			printk("fsector_t=%d buffer_min=%d\n",
+			       fsector_t, buffer_min);
 			printk("current_count_sectors=%ld\n",
 			       current_count_sectors);
 			if (CT(COMMAND) == FD_READ)
@@ -2536,15 +2535,15 @@
 			break;
 
 		dma_buffer += size;
-		bh = bh->b_reqnext;
+		bio = bio->bi_next;
 #ifdef FLOPPY_SANITY_CHECK
-		if (!bh){
+		if (!bio){
 			DPRINT("bh=null in copy buffer after copy\n");
 			break;
 		}
 #endif
-		size = bh->b_size;
-		buffer = bh->b_data;
+		size = bio->bi_size;
+		buffer = bio_data(bio);
 	}
 #ifdef FLOPPY_SANITY_CHECK
 	if (remaining){
@@ -2622,10 +2621,10 @@
 	raw_cmd->flags = FD_RAW_SPIN | FD_RAW_NEED_DISK | FD_RAW_NEED_DISK |
 		FD_RAW_NEED_SEEK;
 	raw_cmd->cmd_count = NR_RW;
-	if (CURRENT->cmd == READ){
+	if (rq_data_dir(CURRENT) == READ) {
 		raw_cmd->flags |= FD_RAW_READ;
 		COMMAND = FM_MODE(_floppy,FD_READ);
-	} else if (CURRENT->cmd == WRITE){
+	} else if (rq_data_dir(CURRENT) == WRITE){
 		raw_cmd->flags |= FD_RAW_WRITE;
 		COMMAND = FM_MODE(_floppy,FD_WRITE);
 	} else {
@@ -2636,7 +2635,7 @@
 	max_sector = _floppy->sect * _floppy->head;
 
 	TRACK = CURRENT->sector / max_sector;
-	sector_t = CURRENT->sector % max_sector;
+	fsector_t = CURRENT->sector % max_sector;
 	if (_floppy->track && TRACK >= _floppy->track) {
 		if (CURRENT->current_nr_sectors & 1) {
 			current_count_sectors = 1;
@@ -2644,17 +2643,17 @@
 		} else
 			return 0;
 	}
-	HEAD = sector_t / _floppy->sect;
+	HEAD = fsector_t / _floppy->sect;
 
 	if (((_floppy->stretch & FD_SWAPSIDES) || TESTF(FD_NEED_TWADDLE)) &&
-	    sector_t < _floppy->sect)
+	    fsector_t < _floppy->sect)
 		max_sector = _floppy->sect;
 
 	/* 2M disks have phantom sectors on the first track */
 	if ((_floppy->rate & FD_2M) && (!TRACK) && (!HEAD)){
 		max_sector = 2 * _floppy->sect / 3;
-		if (sector_t >= max_sector){
-			current_count_sectors = minimum(_floppy->sect - sector_t,
+		if (fsector_t >= max_sector){
+			current_count_sectors = minimum(_floppy->sect - fsector_t,
 							CURRENT->nr_sectors);
 			return 1;
 		}
@@ -2676,7 +2675,7 @@
 	GAP = _floppy->gap;
 	CODE2SIZE;
 	SECT_PER_TRACK = _floppy->sect << 2 >> SIZECODE;
-	SECTOR = ((sector_t % _floppy->sect) << 2 >> SIZECODE) + 1;
+	SECTOR = ((fsector_t % _floppy->sect) << 2 >> SIZECODE) + 1;
 
 	/* tracksize describes the size which can be filled up with sectors
 	 * of size ssize.
@@ -2684,11 +2683,11 @@
 	tracksize = _floppy->sect - _floppy->sect % ssize;
 	if (tracksize < _floppy->sect){
 		SECT_PER_TRACK ++;
-		if (tracksize <= sector_t % _floppy->sect)
+		if (tracksize <= fsector_t % _floppy->sect)
 			SECTOR--;
 
 		/* if we are beyond tracksize, fill up using smaller sectors */
-		while (tracksize <= sector_t % _floppy->sect){
+		while (tracksize <= fsector_t % _floppy->sect){
 			while(tracksize + ssize > _floppy->sect){
 				SIZECODE--;
 				ssize >>= 1;
@@ -2704,12 +2703,12 @@
 		max_sector = _floppy->sect;
 	}
 
-	in_sector_offset = (sector_t % _floppy->sect) % ssize;
-	aligned_sector_t = sector_t - in_sector_offset;
+	in_sector_offset = (fsector_t % _floppy->sect) % ssize;
+	aligned_sector_t = fsector_t - in_sector_offset;
 	max_size = CURRENT->nr_sectors;
 	if ((raw_cmd->track == buffer_track) && 
 	    (current_drive == buffer_drive) &&
-	    (sector_t >= buffer_min) && (sector_t < buffer_max)) {
+	    (fsector_t >= buffer_min) && (fsector_t < buffer_max)) {
 		/* data already in track buffer */
 		if (CT(COMMAND) == FD_READ) {
 			copy_buffer(1, max_sector, buffer_max);
@@ -2717,8 +2716,8 @@
 		}
 	} else if (in_sector_offset || CURRENT->nr_sectors < ssize){
 		if (CT(COMMAND) == FD_WRITE){
-			if (sector_t + CURRENT->nr_sectors > ssize &&
-			    sector_t + CURRENT->nr_sectors < ssize + ssize)
+			if (fsector_t + CURRENT->nr_sectors > ssize &&
+			    fsector_t + CURRENT->nr_sectors < ssize + ssize)
 				max_size = ssize + ssize;
 			else
 				max_size = ssize;
@@ -2731,7 +2730,7 @@
 		int direct, indirect;
 
 		indirect= transfer_size(ssize,max_sector,max_buffer_sectors*2) -
-			sector_t;
+			fsector_t;
 
 		/*
 		 * Do NOT use minimum() here---MAX_DMA_ADDRESS is 64 bits wide
@@ -2746,7 +2745,7 @@
 		if (CROSS_64KB(CURRENT->buffer, max_size << 9))
 			max_size = (K_64 - 
 				    ((unsigned long)CURRENT->buffer) % K_64)>>9;
-		direct = transfer_size(ssize,max_sector,max_size) - sector_t;
+		direct = transfer_size(ssize,max_sector,max_size) - fsector_t;
 		/*
 		 * We try to read tracks, but if we get too many errors, we
 		 * go back to reading just one sector at a time.
@@ -2765,8 +2764,8 @@
 			raw_cmd->length = current_count_sectors << 9;
 			if (raw_cmd->length == 0){
 				DPRINT("zero dma transfer attempted from make_raw_request\n");
-				DPRINT("indirect=%d direct=%d sector_t=%d",
-					indirect, direct, sector_t);
+				DPRINT("indirect=%d direct=%d fsector_t=%d",
+					indirect, direct, fsector_t);
 				return 0;
 			}
 /*			check_dma_crossing(raw_cmd->kernel_data, 
@@ -2784,12 +2783,12 @@
 	/* claim buffer track if needed */
 	if (buffer_track != raw_cmd->track ||  /* bad track */
 	    buffer_drive !=current_drive || /* bad drive */
-	    sector_t > buffer_max ||
-	    sector_t < buffer_min ||
+	    fsector_t > buffer_max ||
+	    fsector_t < buffer_min ||
 	    ((CT(COMMAND) == FD_READ ||
 	      (!in_sector_offset && CURRENT->nr_sectors >= ssize))&&
 	     max_sector > 2 * max_buffer_sectors + buffer_min &&
-	     max_size + sector_t > 2 * max_buffer_sectors + buffer_min)
+	     max_size + fsector_t > 2 * max_buffer_sectors + buffer_min)
 	    /* not enough space */){
 		buffer_track = -1;
 		buffer_drive = current_drive;
@@ -2836,7 +2835,7 @@
 				       floppy_track_buffer) >> 9),
 			       current_count_sectors);
 		printk("st=%d ast=%d mse=%d msi=%d\n",
-		       sector_t, aligned_sector_t, max_sector, max_size);
+		       fsector_t, aligned_sector_t, max_sector, max_size);
 		printk("ssize=%x SIZECODE=%d\n", ssize, SIZECODE);
 		printk("command=%x SECTOR=%d HEAD=%d, TRACK=%d\n",
 		       COMMAND, SECTOR, HEAD, TRACK);
@@ -2854,8 +2853,8 @@
 		    raw_cmd->kernel_data + raw_cmd->length >
 		    floppy_track_buffer + (max_buffer_sectors  << 10)){
 			DPRINT("buffer overrun in schedule dma\n");
-			printk("sector_t=%d buffer_min=%d current_count=%ld\n",
-			       sector_t, buffer_min,
+			printk("fsector_t=%d buffer_min=%d current_count=%ld\n",
+			       fsector_t, buffer_min,
 			       raw_cmd->length >> 9);
 			printk("current_count_sectors=%ld\n",
 			       current_count_sectors);
@@ -2908,8 +2907,6 @@
 		}
 		if (MAJOR(CURRENT->rq_dev) != MAJOR_NR)
 			panic(DEVICE_NAME ": request list destroyed");
-		if (CURRENT->bh && !buffer_locked(CURRENT->bh))
-			panic(DEVICE_NAME ": block not locked");
 
 		device = CURRENT->rq_dev;
 		set_fdc(DRIVE(device));
@@ -2977,7 +2974,7 @@
 
 	if (usage_count == 0) {
 		printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT);
-		printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
+		printk("sect=%ld flags=%lx\n", CURRENT->sector, CURRENT->flags);
 		return;
 	}
 	if (fdc_busy){
@@ -3917,7 +3914,7 @@
     {NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in};
 
     base_minor = (drive < 4) ? drive : (124 + drive);
-    if (UDP->cmos <= NUMBER(default_drive_params)) {
+    if (UDP->cmos < NUMBER(default_drive_params)) {
 	i = 0;
 	do {
 	    char name[16];
diff -u --recursive --new-file v2.5.0/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.5.0/linux/drivers/block/genhd.c	Wed Oct 17 14:46:29 2001
+++ linux/drivers/block/genhd.c	Sat Dec  8 09:49:52 2001
@@ -28,14 +28,8 @@
 
 /*
  * Global kernel list of partitioning information.
- *
- * XXX: you should _never_ access this directly.
- *	the only reason this is exported is source compatiblity.
  */
-/*static*/ struct gendisk *gendisk_head;
-
-EXPORT_SYMBOL(gendisk_head);
-
+static struct gendisk *gendisk_head;
 
 /**
  * add_gendisk - add partitioning information to kernel list
@@ -123,6 +117,30 @@
 EXPORT_SYMBOL(get_gendisk);
 
 
+unsigned long
+get_start_sect(kdev_t dev)
+{
+	struct gendisk *gp;
+
+	gp = get_gendisk(dev);
+	if (gp)
+		return gp->part[MINOR(dev)].start_sect;
+	return 0;
+}
+
+EXPORT_SYMBOL(get_start_sect);
+
+unsigned long
+get_nr_sects(kdev_t dev)
+{
+	struct gendisk *gp;
+
+	gp = get_gendisk(dev);
+	if (gp)
+		return gp->part[MINOR(dev)].nr_sects;
+	return 0;
+}
+
 #ifdef CONFIG_PROC_FS
 int
 get_partition_list(char *page, char **start, off_t offset, int count)
@@ -165,7 +183,6 @@
 extern int fusion_init(void);
 #endif
 extern int net_dev_init(void);
-extern void console_map_init(void);
 extern int soc_probe(void);
 extern int atmdev_init(void);
 extern int i2o_init(void);
@@ -194,9 +211,6 @@
 #endif
 #ifdef CONFIG_ATM
 	(void) atmdev_init();
-#endif
-#ifdef CONFIG_VT
-	console_map_init();
 #endif
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/block/ida_cmd.h linux/drivers/block/ida_cmd.h
--- v2.5.0/linux/drivers/block/ida_cmd.h	Fri Nov  2 17:45:42 2001
+++ linux/drivers/block/ida_cmd.h	Thu Dec  6 14:02:56 2001
@@ -67,7 +67,7 @@
 	__u8	reserved;
 } rhdr_t;
 
-#define SG_MAX			32
+#define SG_MAX			31
 typedef struct {
 	rhdr_t	hdr;
 	sg_t	sg[SG_MAX];
diff -u --recursive --new-file v2.5.0/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.5.0/linux/drivers/block/ll_rw_blk.c	Mon Oct 29 12:11:17 2001
+++ linux/drivers/block/ll_rw_blk.c	Tue Dec 11 09:44:13 2001
@@ -6,6 +6,7 @@
  * Elevator latency, (C) 2000  Andrea Arcangeli <andrea@suse.de> SuSE
  * Queue request tables / lock, selectable elevator, Jens Axboe <axboe@suse.de>
  * kernel-doc documentation started by NeilBrown <neilb@cse.unsw.edu.au> -  July2000
+ * bio rewrite, highmem i/o, etc, Jens Axboe <axboe@suse.de> - may 2001
  */
 
 /*
@@ -22,7 +23,10 @@
 #include <linux/swap.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/bootmem.h>
 #include <linux/completion.h>
+#include <linux/compiler.h>
+#include <scsi/scsi.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -50,27 +54,13 @@
  */
 DECLARE_TASK_QUEUE(tq_disk);
 
-/*
- * Protect the request list against multiple users..
- *
- * With this spinlock the Linux block IO subsystem is 100% SMP threaded
- * from the IRQ event side, and almost 100% SMP threaded from the syscall
- * side (we still have protect against block device array operations, and
- * the do_request() side is casually still unsafe. The kernel lock protects
- * this part currently.).
- *
- * there is a fair chance that things will work just OK if these functions
- * are called with no global kernel lock held ...
- */
-spinlock_t io_request_lock = SPIN_LOCK_UNLOCKED;
-
 /* This specifies how many sectors to read ahead on the disk. */
 
 int read_ahead[MAX_BLKDEV];
 
 /* blk_dev_struct is:
- *	*request_fn
- *	*current_request
+ *	request_queue
+ *	*queue
  */
 struct blk_dev_struct blk_dev[MAX_BLKDEV]; /* initialized by blk_dev_init() */
 
@@ -94,42 +84,29 @@
 int * blksize_size[MAX_BLKDEV];
 
 /*
- * hardsect_size contains the size of the hardware sector of a device.
- *
- * hardsect_size[MAJOR][MINOR]
- *
- * if (!hardsect_size[MAJOR])
- *		then 512 bytes is assumed.
- * else
- *		sector_size is hardsect_size[MAJOR][MINOR]
- * This is currently set by some scsi devices and read by the msdos fs driver.
- * Other uses may appear later.
- */
-int * hardsect_size[MAX_BLKDEV];
-
-/*
  * The following tunes the read-ahead algorithm in mm/filemap.c
  */
 int * max_readahead[MAX_BLKDEV];
 
 /*
- * Max number of sectors per request
- */
-int * max_sectors[MAX_BLKDEV];
-
-/*
  * How many reqeusts do we allocate per queue,
  * and how many do we "batch" on freeing them?
  */
-static int queue_nr_requests, batch_requests;
-
-static inline int get_max_sectors(kdev_t dev)
-{
-	if (!max_sectors[MAJOR(dev)])
-		return MAX_SECTORS;
-	return max_sectors[MAJOR(dev)][MINOR(dev)];
-}
+int queue_nr_requests, batch_requests;
+unsigned long blk_max_low_pfn, blk_max_pfn;
+int blk_nohighio = 0;
 
+/**
+ * blk_get_queue: - return the queue that matches the given device
+ * @dev:    device
+ *
+ * Description:
+ *     Given a specific device, return the queue that will hold I/O
+ *     for it. This is either a &struct blk_dev_struct lookup and a
+ *     call to the ->queue() function defined, or the default queue
+ *     stored in the same location.
+ *
+ **/
 inline request_queue_t *blk_get_queue(kdev_t dev)
 {
 	struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
@@ -140,144 +117,364 @@
 		return &blk_dev[MAJOR(dev)].request_queue;
 }
 
-static int __blk_cleanup_queue(struct request_list *list)
+/**
+ * blk_queue_make_request - define an alternate make_request function for a device
+ * @q:  the request queue for the device to be affected
+ * @mfn: the alternate make_request function
+ *
+ * Description:
+ *    The normal way for &struct bios to be passed to a device
+ *    driver is for them to be collected into requests on a request
+ *    queue, and then to allow the device driver to select requests
+ *    off that queue when it is ready.  This works well for many block
+ *    devices. However some block devices (typically virtual devices
+ *    such as md or lvm) do not benefit from the processing on the
+ *    request queue, and are served best by having the requests passed
+ *    directly to them.  This can be achieved by providing a function
+ *    to blk_queue_make_request().
+ *
+ * Caveat:
+ *    The driver that does this *must* be able to deal appropriately
+ *    with buffers in "highmemory". This can be accomplished by either calling
+ *    bio_kmap() to get a temporary kernel mapping, or by calling
+ *    blk_queue_bounce() to create a buffer in normal memory.
+ **/
+void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
 {
-	struct list_head *head = &list->free;
-	struct request *rq;
-	int i = 0;
-
-	while (!list_empty(head)) {
-		rq = list_entry(head->next, struct request, queue);
-		list_del(&rq->queue);
-		kmem_cache_free(request_cachep, rq);
-		i++;
-	};
-
-	if (i != list->count)
-		printk("request list leak!\n");
+	/*
+	 * set defaults
+	 */
+	q->max_segments = MAX_SEGMENTS;
+	q->make_request_fn = mfn;
+	blk_queue_max_sectors(q, MAX_SECTORS);
+	blk_queue_hardsect_size(q, 512);
 
-	list->count = 0;
-	return i;
+	init_waitqueue_head(&q->queue_wait);
 }
 
 /**
- * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed
- * @q:    the request queue to be released
+ * blk_queue_bounce_limit - set bounce buffer limit for queue
+ * @q:  the request queue for the device
+ * @dma_addr:   bus address limit
  *
  * Description:
- *     blk_cleanup_queue is the pair to blk_init_queue().  It should
- *     be called when a request queue is being released; typically
- *     when a block device is being de-registered.  Currently, its
- *     primary task it to free all the &struct request structures that
- *     were allocated to the queue.
- * Caveat: 
- *     Hopefully the low level driver will have finished any
- *     outstanding requests first...
+ *    Different hardware can have different requirements as to what pages
+ *    it can do I/O directly to. A low level driver can call
+ *    blk_queue_bounce_limit to have lower memory pages allocated as bounce
+ *    buffers for doing I/O to pages residing above @page. By default
+ *    the block layer sets this to the highest numbered "low" memory page.
  **/
-void blk_cleanup_queue(request_queue_t * q)
+void blk_queue_bounce_limit(request_queue_t *q, u64 dma_addr)
 {
-	int count = queue_nr_requests;
-
-	count -= __blk_cleanup_queue(&q->rq[READ]);
-	count -= __blk_cleanup_queue(&q->rq[WRITE]);
+	unsigned long bounce_pfn = dma_addr >> PAGE_SHIFT;
+	unsigned long mb = dma_addr >> 20;
+	static request_queue_t *last_q;
 
-	if (count)
-		printk("blk_cleanup_queue: leaked requests (%d)\n", count);
+	/*
+	 * keep this for debugging for now...
+	 */
+	if (dma_addr != BLK_BOUNCE_HIGH && q != last_q) {
+		printk("blk: queue %p, ", q);
+		if (dma_addr == BLK_BOUNCE_ANY)
+			printk("no I/O memory limit\n");
+		else
+			printk("I/O limit %luMb (mask 0x%Lx)\n", mb, (u64) dma_addr);
+	}
 
-	memset(q, 0, sizeof(*q));
+	q->bounce_pfn = bounce_pfn;
+	last_q = q;
 }
 
+
 /**
- * blk_queue_headactive - indicate whether head of request queue may be active
- * @q:       The queue which this applies to.
- * @active:  A flag indication where the head of the queue is active.
+ * blk_queue_max_sectors - set max sectors for a request for this queue
+ * @q:  the request queue for the device
+ * @max_sectors:  max sectors in the usual 512b unit
  *
  * Description:
- *    The driver for a block device may choose to leave the currently active
- *    request on the request queue, removing it only when it has completed.
- *    The queue handling routines assume this by default for safety reasons
- *    and will not involve the head of the request queue in any merging or
- *    reordering of requests when the queue is unplugged (and thus may be
- *    working on this particular request).
- *
- *    If a driver removes requests from the queue before processing them, then
- *    it may indicate that it does so, there by allowing the head of the queue
- *    to be involved in merging and reordering.  This is done be calling
- *    blk_queue_headactive() with an @active flag of %0.
- *
- *    If a driver processes several requests at once, it must remove them (or
- *    at least all but one of them) from the request queue.
+ *    Enables a low level driver to set an upper limit on the size of
+ *    received requests.
+ **/
+void blk_queue_max_sectors(request_queue_t *q, unsigned short max_sectors)
+{
+	q->max_sectors = max_sectors;
+}
+
+/**
+ * blk_queue_max_segments - set max segments for a request for this queue
+ * @q:  the request queue for the device
+ * @max_segments:  max number of segments
  *
- *    When a queue is plugged the head will be assumed to be inactive.
+ * Description:
+ *    Enables a low level driver to set an upper limit on the number of
+ *    data segments in a request
  **/
- 
-void blk_queue_headactive(request_queue_t * q, int active)
+void blk_queue_max_segments(request_queue_t *q, unsigned short max_segments)
 {
-	q->head_active = active;
+	q->max_segments = max_segments;
 }
 
 /**
- * blk_queue_make_request - define an alternate make_request function for a device
- * @q:  the request queue for the device to be affected
- * @mfn: the alternate make_request function
+ * blk_queue_max_segment_size - set max segment size for blk_rq_map_sg
+ * @q:  the request queue for the device
+ * @max_size:  max size of segment in bytes
  *
  * Description:
- *    The normal way for &struct buffer_heads to be passed to a device
- *    driver is for them to be collected into requests on a request
- *    queue, and then to allow the device driver to select requests
- *    off that queue when it is ready.  This works well for many block
- *    devices. However some block devices (typically virtual devices
- *    such as md or lvm) do not benefit from the processing on the
- *    request queue, and are served best by having the requests passed
- *    directly to them.  This can be achieved by providing a function
- *    to blk_queue_make_request().
+ *    Enables a low level driver to set an upper limit on the size of a
+ *    coalesced segment
+ **/
+void blk_queue_max_segment_size(request_queue_t *q, unsigned int max_size)
+{
+	q->max_segment_size = max_size;
+}
+
+/**
+ * blk_queue_hardsect_size - set hardware sector size for the queue
+ * @q:  the request queue for the device
+ * @size:  the hardware sector size, in bytes
  *
- * Caveat:
- *    The driver that does this *must* be able to deal appropriately
- *    with buffers in "highmemory", either by calling bh_kmap() to get
- *    a kernel mapping, to by calling create_bounce() to create a
- *    buffer in normal memory.
+ * Description:
+ *   This should typically be set to the lowest possible sector size
+ *   that the hardware can operate on (possible without reverting to
+ *   even internal read-modify-write operations). Usually the default
+ *   of 512 covers most hardware.
  **/
+void blk_queue_hardsect_size(request_queue_t *q, unsigned short size)
+{
+	q->hardsect_size = size;
+}
 
-void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
+/**
+ * blk_queue_segment_boundary - set boundary rules for segment merging
+ * @q:  the request queue for the device
+ * @mask:  the memory boundary mask
+ **/
+void blk_queue_segment_boundary(request_queue_t *q, unsigned long mask)
 {
-	q->make_request_fn = mfn;
+	q->seg_boundary_mask = mask;
 }
 
-static inline int ll_new_segment(request_queue_t *q, struct request *req, int max_segments)
+static char *rq_flags[] = { "REQ_RW", "REQ_RW_AHEAD", "REQ_BARRIER",
+			   "REQ_CMD", "REQ_NOMERGE", "REQ_STARTED",
+			   "REQ_DONTPREP", "REQ_DRIVE_CMD", "REQ_DRIVE_TASK",
+			   "REQ_PC", "REQ_BLOCK_PC", "REQ_SENSE",
+			   "REQ_SPECIAL" };
+
+void blk_dump_rq_flags(struct request *rq, char *msg)
 {
-	if (req->nr_segments < max_segments) {
-		req->nr_segments++;
+	int bit;
+
+	printk("%s: dev %x: ", msg, rq->rq_dev);
+	bit = 0;
+	do {
+		if (rq->flags & (1 << bit))
+			printk("%s ", rq_flags[bit]);
+		bit++;
+	} while (bit < __REQ_NR_BITS);
+
+	if (rq->flags & REQ_CMD)
+		printk("sector %lu, nr/cnr %lu/%u\n", rq->sector,
+						       rq->nr_sectors,
+						       rq->current_nr_sectors);
+
+	printk("\n");
+}
+
+/*
+ * standard prep_rq_fn that builds 10 byte cmds
+ */
+static int ll_10byte_cmd_build(request_queue_t *q, struct request *rq)
+{
+	int hard_sect = get_hardsect_size(rq->rq_dev);
+	sector_t block = rq->hard_sector / (hard_sect >> 9);
+	unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9);
+
+	if (!(rq->flags & REQ_CMD))
+		return 0;
+
+	memset(rq->cmd, 0, sizeof(rq->cmd));
+
+	if (rq_data_dir(rq) == READ)
+		rq->cmd[0] = READ_10;
+	else 
+		rq->cmd[0] = WRITE_10;
+
+	/*
+	 * fill in lba
+	 */
+	rq->cmd[2] = (block >> 24) & 0xff;
+	rq->cmd[3] = (block >> 16) & 0xff;
+	rq->cmd[4] = (block >>  8) & 0xff;
+	rq->cmd[5] = block & 0xff;
+
+	/*
+	 * and transfer length
+	 */
+	rq->cmd[7] = (blocks >> 8) & 0xff;
+	rq->cmd[8] = blocks & 0xff;
+
+	return 0;
+}
+
+void blk_recount_segments(request_queue_t *q, struct bio *bio)
+{
+	struct bio_vec *bv, *bvprv = NULL;
+	int i, nr_segs, seg_size, cluster;
+
+	if (unlikely(!bio->bi_io_vec))
+		return;
+
+	cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
+	seg_size = nr_segs = 0;
+	bio_for_each_segment(bv, bio, i) {
+		if (bvprv && cluster) {
+			if (seg_size + bv->bv_len > q->max_segment_size)
+				goto new_segment;
+			if (!BIOVEC_MERGEABLE(bvprv, bv))
+				goto new_segment;
+			if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bv))
+				goto new_segment;
+
+			seg_size += bv->bv_len;
+			bvprv = bv;
+			continue;
+		}
+new_segment:
+		nr_segs++;
+		bvprv = bv;
+		seg_size = 0;
+	}
+
+	bio->bi_hw_seg = nr_segs;
+	bio->bi_flags |= (1 << BIO_SEG_VALID);
+}
+
+
+inline int blk_contig_segment(request_queue_t *q, struct bio *bio,
+			    struct bio *nxt)
+{
+	if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
+		return 0;
+
+	if (!BIO_CONTIG(bio, nxt))
+		return 0;
+	if (bio->bi_size + nxt->bi_size > q->max_segment_size)
+		return 0;
+
+	/*
+	 * bio and nxt are contigous in memory, check if the queue allows
+	 * these two to be merged into one
+	 */
+	if (BIO_SEG_BOUNDARY(q, bio, nxt))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * map a request to scatterlist, return number of sg entries setup. Caller
+ * must make sure sg can hold rq->nr_segments entries
+ */
+int blk_rq_map_sg(request_queue_t *q, struct request *rq, struct scatterlist *sg)
+{
+	struct bio_vec *bvec, *bvprv;
+	struct bio *bio;
+	int nsegs, i, cluster;
+
+	nsegs = 0;
+	cluster = q->queue_flags & (1 << QUEUE_FLAG_CLUSTER);
+
+	/*
+	 * for each bio in rq
+	 */
+	bvprv = NULL;
+	rq_for_each_bio(bio, rq) {
+		/*
+		 * for each segment in bio
+		 */
+		bio_for_each_segment(bvec, bio, i) {
+			int nbytes = bvec->bv_len;
+
+			if (bvprv && cluster) {
+				if (sg[nsegs - 1].length + nbytes > q->max_segment_size)
+					goto new_segment;
+
+				if (!BIOVEC_MERGEABLE(bvprv, bvec))
+					goto new_segment;
+				if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
+					goto new_segment;
+
+				sg[nsegs - 1].length += nbytes;
+			} else {
+new_segment:
+				if (nsegs >= q->max_segments) {
+					printk("map: %d >= %d, i %d, segs %d, size %ld\n", nsegs, q->max_segments, i, rq->nr_segments, rq->nr_sectors);
+					BUG();
+				}
+
+				sg[nsegs].address = NULL;
+				sg[nsegs].page = bvec->bv_page;
+				sg[nsegs].length = nbytes;
+				sg[nsegs].offset = bvec->bv_offset;
+
+				nsegs++;
+			}
+			bvprv = bvec;
+		} /* segments in bio */
+	} /* bios in rq */
+
+	return nsegs;
+}
+
+/*
+ * the standard queue merge functions, can be overridden with device
+ * specific ones if so desired
+ */
+static inline int ll_new_segment(request_queue_t *q, struct request *req,
+				 struct bio *bio)
+{
+	int nr_segs = bio_hw_segments(q, bio);
+
+	if (req->nr_segments + nr_segs <= q->max_segments) {
+		req->nr_segments += nr_segs;
 		return 1;
 	}
+
+	req->flags |= REQ_NOMERGE;
 	return 0;
 }
 
 static int ll_back_merge_fn(request_queue_t *q, struct request *req, 
-			    struct buffer_head *bh, int max_segments)
+			    struct bio *bio)
 {
-	if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data)
-		return 1;
-	return ll_new_segment(q, req, max_segments);
+	if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
+		req->flags |= REQ_NOMERGE;
+		return 0;
+	}
+
+	return ll_new_segment(q, req, bio);
 }
 
 static int ll_front_merge_fn(request_queue_t *q, struct request *req, 
-			     struct buffer_head *bh, int max_segments)
+			     struct bio *bio)
 {
-	if (bh->b_data + bh->b_size == req->bh->b_data)
-		return 1;
-	return ll_new_segment(q, req, max_segments);
+	if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
+		req->flags |= REQ_NOMERGE;
+		return 0;
+	}
+
+	return ll_new_segment(q, req, bio);
 }
 
 static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
-				struct request *next, int max_segments)
+				struct request *next)
 {
 	int total_segments = req->nr_segments + next->nr_segments;
 
-	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
+	if (blk_contig_segment(q, req->biotail, next->bio))
 		total_segments--;
     
-	if (total_segments > max_segments)
+	if (total_segments > q->max_segments)
 		return 0;
 
 	req->nr_segments = total_segments;
@@ -292,16 +489,16 @@
  * This is called with interrupts off and no requests on the queue.
  * (and with the request spinlock acquired)
  */
-static void generic_plug_device(request_queue_t *q, kdev_t dev)
+void blk_plug_device(request_queue_t *q)
 {
 	/*
-	 * no need to replug device
+	 * common case
 	 */
-	if (!list_empty(&q->queue_head) || q->plugged)
+	if (!elv_queue_empty(q))
 		return;
 
-	q->plugged = 1;
-	queue_task(&q->plug_tq, &tq_disk);
+	if (!test_and_set_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
+		queue_task(&q->plug_tq, &tq_disk);
 }
 
 /*
@@ -309,25 +506,93 @@
  */
 static inline void __generic_unplug_device(request_queue_t *q)
 {
-	if (q->plugged) {
-		q->plugged = 0;
-		if (!list_empty(&q->queue_head))
-			q->request_fn(q);
-	}
+	/*
+	 * not plugged
+	 */
+	if (!test_and_clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags))
+		return;
+
+	/*
+	 * was plugged, fire request_fn if queue has stuff to do
+	 */
+	if (!elv_queue_empty(q))
+		q->request_fn(q);
 }
 
+/**
+ * generic_unplug_device - fire a request queue
+ * @q:    The &request_queue_t in question
+ *
+ * Description:
+ *   Linux uses plugging to build bigger requests queues before letting
+ *   the device have at them. If a queue is plugged, the I/O scheduler
+ *   is still adding and merging requests on the queue. Once the queue
+ *   gets unplugged (either by manually calling this function, or by
+ *   running the tq_disk task queue), the request_fn defined for the
+ *   queue is invoked and transfers started.
+ **/
 void generic_unplug_device(void *data)
 {
 	request_queue_t *q = (request_queue_t *) data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&q->queue_lock, flags);
 	__generic_unplug_device(q);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&q->queue_lock, flags);
 }
 
-static void blk_init_free_list(request_queue_t *q)
+static int __blk_cleanup_queue(struct request_list *list)
 {
+	struct list_head *head = &list->free;
+	struct request *rq;
+	int i = 0;
+
+	while (!list_empty(head)) {
+		rq = list_entry(head->next, struct request, queuelist);
+		list_del(&rq->queuelist);
+		kmem_cache_free(request_cachep, rq);
+		i++;
+	}
+
+	if (i != list->count)
+		printk("request list leak!\n");
+
+	list->count = 0;
+	return i;
+}
+
+/**
+ * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed
+ * @q:    the request queue to be released
+ *
+ * Description:
+ *     blk_cleanup_queue is the pair to blk_init_queue().  It should
+ *     be called when a request queue is being released; typically
+ *     when a block device is being de-registered.  Currently, its
+ *     primary task it to free all the &struct request structures that
+ *     were allocated to the queue.
+ * Caveat: 
+ *     Hopefully the low level driver will have finished any
+ *     outstanding requests first...
+ **/
+void blk_cleanup_queue(request_queue_t * q)
+{
+	int count = queue_nr_requests;
+
+	count -= __blk_cleanup_queue(&q->rq[READ]);
+	count -= __blk_cleanup_queue(&q->rq[WRITE]);
+
+	if (count)
+		printk("blk_cleanup_queue: leaked requests (%d)\n", count);
+
+	elevator_exit(q, &q->elevator);
+
+	memset(q, 0, sizeof(*q));
+}
+
+static int blk_init_free_list(request_queue_t *q)
+{
+	struct request_list *rl;
 	struct request *rq;
 	int i;
 
@@ -339,24 +604,34 @@
 	/*
 	 * Divide requests in half between read and write
 	 */
+	rl = &q->rq[READ];
 	for (i = 0; i < queue_nr_requests; i++) {
 		rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL);
-		if (rq == NULL) {
-			/* We'll get a `leaked requests' message from blk_cleanup_queue */
-			printk(KERN_EMERG "blk_init_free_list: error allocating requests\n");
-			break;
-		}
+		if (!rq)
+			goto nomem;
+
+		/*
+		 * half way through, switch to WRITE list
+		 */
+		if (i == queue_nr_requests / 2)
+			rl = &q->rq[WRITE];
+
 		memset(rq, 0, sizeof(struct request));
 		rq->rq_status = RQ_INACTIVE;
-		list_add(&rq->queue, &q->rq[i&1].free);
-		q->rq[i&1].count++;
+		list_add(&rq->queuelist, &rl->free);
+		rl->count++;
 	}
 
-	init_waitqueue_head(&q->wait_for_request);
+	init_waitqueue_head(&q->rq[READ].wait);
+	init_waitqueue_head(&q->rq[WRITE].wait);
 	spin_lock_init(&q->queue_lock);
+	return 0;
+nomem:
+	blk_cleanup_queue(q);
+	return 1;
 }
 
-static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh);
+static int __make_request(request_queue_t *, struct bio *);
 
 /**
  * blk_init_queue  - prepare a request queue for use with a block device
@@ -379,45 +654,50 @@
  *    requests on the queue, it is responsible for arranging that the requests
  *    get dealt with eventually.
  *
- *    A global spin lock $io_request_lock must be held while manipulating the
- *    requests on the request queue.
- *
- *    The request on the head of the queue is by default assumed to be
- *    potentially active, and it is not considered for re-ordering or merging
- *    whenever the given queue is unplugged. This behaviour can be changed with
- *    blk_queue_headactive().
+ *    The queue spin lock must be held while manipulating the requests on the
+ *    request queue.
  *
  * Note:
  *    blk_init_queue() must be paired with a blk_cleanup_queue() call
  *    when the block device is deactivated (such as at module unload).
  **/
-void blk_init_queue(request_queue_t * q, request_fn_proc * rfn)
+int blk_init_queue(request_queue_t *q, request_fn_proc *rfn)
 {
-	INIT_LIST_HEAD(&q->queue_head);
-	elevator_init(&q->elevator, ELEVATOR_LINUS);
-	blk_init_free_list(q);
-	q->request_fn     	= rfn;
+	int ret;
+
+	if (blk_init_free_list(q))
+		return -ENOMEM;
+
+	if ((ret = elevator_init(q, &q->elevator, ELEVATOR_LINUS))) {
+		blk_cleanup_queue(q);
+		return ret;
+	}
+
+	q->request_fn		= rfn;
 	q->back_merge_fn       	= ll_back_merge_fn;
 	q->front_merge_fn      	= ll_front_merge_fn;
 	q->merge_requests_fn	= ll_merge_requests_fn;
-	q->make_request_fn	= __make_request;
+	q->prep_rq_fn		= ll_10byte_cmd_build;
 	q->plug_tq.sync		= 0;
 	q->plug_tq.routine	= &generic_unplug_device;
 	q->plug_tq.data		= q;
-	q->plugged        	= 0;
+	q->queue_flags		= (1 << QUEUE_FLAG_CLUSTER);
+	
 	/*
-	 * These booleans describe the queue properties.  We set the
-	 * default (and most common) values here.  Other drivers can
-	 * use the appropriate functions to alter the queue properties.
-	 * as appropriate.
+	 * by default assume old behaviour and bounce for any highmem page
 	 */
-	q->plug_device_fn 	= generic_plug_device;
-	q->head_active    	= 1;
+	blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
+
+	blk_queue_segment_boundary(q, 0xffffffff);
+
+	blk_queue_make_request(q, __make_request);
+	blk_queue_max_segment_size(q, MAX_SEGMENT_SIZE);
+	return 0;
 }
 
-#define blkdev_free_rq(list) list_entry((list)->next, struct request, queue);
+#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
 /*
- * Get a free request. io_request_lock must be held and interrupts
+ * Get a free request. queue lock must be held and interrupts
  * disabled on the way in.
  */
 static inline struct request *get_request(request_queue_t *q, int rw)
@@ -427,11 +707,13 @@
 
 	if (!list_empty(&rl->free)) {
 		rq = blkdev_free_rq(&rl->free);
-		list_del(&rq->queue);
+		list_del(&rq->queuelist);
 		rl->count--;
+		rq->flags = 0;
 		rq->rq_status = RQ_ACTIVE;
 		rq->special = NULL;
 		rq->q = q;
+		rq->rl = rl;
 	}
 
 	return rq;
@@ -440,36 +722,46 @@
 /*
  * No available requests for this queue, unplug the device.
  */
-static struct request *__get_request_wait(request_queue_t *q, int rw)
+static struct request *get_request_wait(request_queue_t *q, int rw)
 {
-	register struct request *rq;
 	DECLARE_WAITQUEUE(wait, current);
+	struct request_list *rl = &q->rq[rw];
+	struct request *rq;
+
+	spin_lock_prefetch(&q->queue_lock);
 
 	generic_unplug_device(q);
-	add_wait_queue(&q->wait_for_request, &wait);
+	add_wait_queue(&rl->wait, &wait);
 	do {
 		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (q->rq[rw].count < batch_requests)
+		if (rl->count < batch_requests)
 			schedule();
-		spin_lock_irq(&io_request_lock);
-		rq = get_request(q,rw);
-		spin_unlock_irq(&io_request_lock);
+		spin_lock_irq(&q->queue_lock);
+		rq = get_request(q, rw);
+		spin_unlock_irq(&q->queue_lock);
 	} while (rq == NULL);
-	remove_wait_queue(&q->wait_for_request, &wait);
+	remove_wait_queue(&rl->wait, &wait);
 	current->state = TASK_RUNNING;
 	return rq;
 }
 
-static inline struct request *get_request_wait(request_queue_t *q, int rw)
+struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
 {
-	register struct request *rq;
+	struct request *rq;
+
+	BUG_ON(rw != READ && rw != WRITE);
 
-	spin_lock_irq(&io_request_lock);
 	rq = get_request(q, rw);
-	spin_unlock_irq(&io_request_lock);
-	if (rq)
-		return rq;
-	return __get_request_wait(q, rw);
+
+	if (!rq && (gfp_mask & __GFP_WAIT))
+		rq = get_request_wait(q, rw);
+
+	return rq;
+}
+
+void blk_put_request(struct request *rq)
+{
+	blkdev_release_request(rq);
 }
 
 /* RO fail safe mechanism */
@@ -497,13 +789,13 @@
 	else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31));
 }
 
-inline void drive_stat_acct (kdev_t dev, int rw,
-				unsigned long nr_sectors, int new_io)
+void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
 {
-	unsigned int major = MAJOR(dev);
+	unsigned int major = MAJOR(rq->rq_dev);
+	int rw = rq_data_dir(rq);
 	unsigned int index;
 
-	index = disk_index(dev);
+	index = disk_index(rq->rq_dev);
 	if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR))
 		return;
 
@@ -520,204 +812,229 @@
 
 /*
  * add-request adds a request to the linked list.
- * io_request_lock is held and interrupts disabled, as we muck with the
+ * queue lock is held and interrupts disabled, as we muck with the
  * request queue list.
- *
- * By this point, req->cmd is always either READ/WRITE, never READA,
- * which is important for drive_stat_acct() above.
  */
 static inline void add_request(request_queue_t * q, struct request * req,
 			       struct list_head *insert_here)
 {
-	drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1);
+	drive_stat_acct(req, req->nr_sectors, 1);
 
-	if (!q->plugged && q->head_active && insert_here == &q->queue_head) {
-		spin_unlock_irq(&io_request_lock);
-		BUG();
+	/*
+	 * debug stuff...
+	 */
+	if (insert_here == &q->queue_head) {
+		struct request *__rq = __elv_next_request(q);
+
+		BUG_ON(__rq && (__rq->flags & REQ_STARTED));
 	}
 
 	/*
 	 * elevator indicated where it wants this request to be
 	 * inserted at elevator_merge time
 	 */
-	list_add(&req->queue, insert_here);
+	q->elevator.elevator_add_req_fn(q, req, insert_here);
 }
 
 /*
- * Must be called with io_request_lock held and interrupts disabled
+ * Must be called with queue lock held and interrupts disabled
  */
-inline void blkdev_release_request(struct request *req)
+void blkdev_release_request(struct request *req)
 {
-	request_queue_t *q = req->q;
-	int rw = req->cmd;
+	struct request_list *rl = req->rl;
 
 	req->rq_status = RQ_INACTIVE;
 	req->q = NULL;
+	req->rl = NULL;
 
 	/*
 	 * Request may not have originated from ll_rw_blk. if not,
-	 * assume it has free buffers and check waiters
+	 * it didn't come out of our reserved rq pools
 	 */
-	if (q) {
-		list_add(&req->queue, &q->rq[rw].free);
-		if (++q->rq[rw].count >= batch_requests && waitqueue_active(&q->wait_for_request))
-			wake_up(&q->wait_for_request);
+	if (rl) {
+		list_add(&req->queuelist, &rl->free);
+
+		if (++rl->count >= batch_requests &&waitqueue_active(&rl->wait))
+			wake_up(&rl->wait);
 	}
 }
 
 /*
  * Has to be called with the request spinlock acquired
  */
-static void attempt_merge(request_queue_t * q,
-			  struct request *req,
-			  int max_sectors,
-			  int max_segments)
-{
-	struct request *next;
-  
-	next = blkdev_next_request(req);
+static void attempt_merge(request_queue_t *q, struct request *req)
+{
+	struct request *next = blkdev_next_request(req);
+
+	/*
+	 * not a rw command
+	 */
+	if (!(next->flags & REQ_CMD))
+		return;
+
+	/*
+	 * not contigious
+	 */
 	if (req->sector + req->nr_sectors != next->sector)
 		return;
-	if (req->cmd != next->cmd
+
+	/*
+	 * don't touch NOMERGE rq, or one that has been started by driver
+	 */
+	if (next->flags & (REQ_NOMERGE | REQ_STARTED))
+		return;
+
+	if (rq_data_dir(req) != rq_data_dir(next)
 	    || req->rq_dev != next->rq_dev
-	    || req->nr_sectors + next->nr_sectors > max_sectors
-	    || next->waiting)
+	    || req->nr_sectors + next->nr_sectors > q->max_sectors
+	    || next->waiting || next->special)
 		return;
+
 	/*
 	 * If we are not allowed to merge these requests, then
 	 * return.  If we are allowed to merge, then the count
 	 * will have been updated to the appropriate number,
 	 * and we shouldn't do it here too.
 	 */
-	if (!q->merge_requests_fn(q, req, next, max_segments))
-		return;
+	if (q->merge_requests_fn(q, req, next)) {
+		q->elevator.elevator_merge_req_fn(req, next);
+
+		blkdev_dequeue_request(next);
+
+		req->biotail->bi_next = next->bio;
+		req->biotail = next->biotail;
 
-	q->elevator.elevator_merge_req_fn(req, next);
-	req->bhtail->b_reqnext = next->bh;
-	req->bhtail = next->bhtail;
-	req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
-	list_del(&next->queue);
-	blkdev_release_request(next);
+		req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
+
+		blkdev_release_request(next);
+	}
 }
 
-static inline void attempt_back_merge(request_queue_t * q,
-				      struct request *req,
-				      int max_sectors,
-				      int max_segments)
+static inline void attempt_back_merge(request_queue_t *q, struct request *rq)
 {
-	if (&req->queue == q->queue_head.prev)
-		return;
-	attempt_merge(q, req, max_sectors, max_segments);
+	if (&rq->queuelist != q->queue_head.prev)
+		attempt_merge(q, rq);
 }
 
-static inline void attempt_front_merge(request_queue_t * q,
-				       struct list_head * head,
-				       struct request *req,
-				       int max_sectors,
-				       int max_segments)
+static inline void attempt_front_merge(request_queue_t *q,
+				       struct list_head *head,
+				       struct request *rq)
 {
-	struct list_head * prev;
+	struct list_head *prev = rq->queuelist.prev;
 
-	prev = req->queue.prev;
-	if (head == prev)
-		return;
-	attempt_merge(q, blkdev_entry_to_request(prev), max_sectors, max_segments);
+	if (prev != head)
+		attempt_merge(q, blkdev_entry_to_request(prev));
 }
 
-static int __make_request(request_queue_t * q, int rw,
-				  struct buffer_head * bh)
+static inline void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
 {
-	unsigned int sector, count;
-	int max_segments = MAX_SEGMENTS;
-	struct request * req, *freereq = NULL;
-	int rw_ahead, max_sectors, el_ret;
-	struct list_head *head, *insert_here;
-	int latency;
-	elevator_t *elevator = &q->elevator;
+	if (rq->queuelist.next != &q->queue_head)
+		attempt_merge(q, rq);
+}
 
-	count = bh->b_size >> 9;
-	sector = bh->b_rsector;
+/**
+ * blk_attempt_remerge  - attempt to remerge active head with next request
+ * @q:    The &request_queue_t belonging to the device
+ * @rq:   The head request (usually)
+ *
+ * Description:
+ *    For head-active devices, the queue can easily be unplugged so quickly
+ *    that proper merging is not done on the front request. This may hurt
+ *    performance greatly for some devices. The block layer cannot safely
+ *    do merging on that first request for these queues, but the driver can
+ *    call this function and make it happen any way. Only the driver knows
+ *    when it is safe to do so.
+ **/
+void blk_attempt_remerge(request_queue_t *q, struct request *rq)
+{
+	unsigned long flags;
 
-	rw_ahead = 0;	/* normal case; gets changed below for READA */
-	switch (rw) {
-		case READA:
-			rw_ahead = 1;
-			rw = READ;	/* drop into READ */
-		case READ:
-		case WRITE:
-			latency = elevator_request_latency(elevator, rw);
-			break;
-		default:
-			BUG();
-			goto end_io;
-	}
+	spin_lock_irqsave(&q->queue_lock, flags);
+	__blk_attempt_remerge(q, rq);
+	spin_unlock_irqrestore(&q->queue_lock, flags);
+}
 
-	/* We'd better have a real physical mapping!
-	   Check this bit only if the buffer was dirty and just locked
-	   down by us so at this point flushpage will block and
-	   won't clear the mapped bit under us. */
-	if (!buffer_mapped(bh))
-		BUG();
+static int __make_request(request_queue_t *q, struct bio *bio)
+{
+	struct request *req, *freereq = NULL;
+	int el_ret, latency = 0, rw, nr_sectors, cur_nr_sectors, barrier;
+	struct list_head *head, *insert_here;
+	elevator_t *elevator = &q->elevator;
+	sector_t sector;
 
-	/*
-	 * Temporary solution - in 2.5 this will be done by the lowlevel
-	 * driver. Create a bounce buffer if the buffer data points into
-	 * high memory - keep the original buffer otherwise.
-	 */
-#if CONFIG_HIGHMEM
-	bh = create_bounce(rw, bh);
-#endif
+	sector = bio->bi_sector;
+	nr_sectors = bio_sectors(bio);
+	cur_nr_sectors = bio_iovec(bio)->bv_len >> 9;
+	rw = bio_data_dir(bio);
 
-/* look for a free request. */
 	/*
-	 * Try to coalesce the new request with old requests
+	 * low level driver can indicate that it wants pages above a
+	 * certain limit bounced to low memory (ie for highmem, or even
+	 * ISA dma in theory)
 	 */
-	max_sectors = get_max_sectors(bh->b_rdev);
+	blk_queue_bounce(q, &bio);
+
+	spin_lock_prefetch(&q->queue_lock);
+
+	latency = elevator_request_latency(elevator, rw);
+	barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw);
 
 again:
 	req = NULL;
 	head = &q->queue_head;
-	/*
-	 * Now we acquire the request spinlock, we have to be mega careful
-	 * not to schedule or do something nonatomic
-	 */
-	spin_lock_irq(&io_request_lock);
+
+	spin_lock_irq(&q->queue_lock);
 
 	insert_here = head->prev;
-	if (list_empty(head)) {
-		q->plug_device_fn(q, bh->b_rdev); /* is atomic */
+	if (blk_queue_empty(q) || barrier) {
+		blk_plug_device(q);
 		goto get_rq;
-	} else if (q->head_active && !q->plugged)
-		head = head->next;
+	} else if ((req = __elv_next_request(q))) {
+		if (req->flags & REQ_STARTED)
+			head = head->next;
 
-	el_ret = elevator->elevator_merge_fn(q, &req, head, bh, rw,max_sectors);
-	switch (el_ret) {
+		req = NULL;
+	}
 
+	el_ret = elevator->elevator_merge_fn(q, &req, head, bio);
+	switch (el_ret) {
 		case ELEVATOR_BACK_MERGE:
-			if (!q->back_merge_fn(q, req, bh, max_segments))
+			BUG_ON(req->flags & REQ_STARTED);
+			BUG_ON(req->flags & REQ_NOMERGE);
+			if (!q->back_merge_fn(q, req, bio))
 				break;
-			elevator->elevator_merge_cleanup_fn(q, req, count);
-			req->bhtail->b_reqnext = bh;
-			req->bhtail = bh;
-			req->nr_sectors = req->hard_nr_sectors += count;
-			blk_started_io(count);
-			drive_stat_acct(req->rq_dev, req->cmd, count, 0);
-			attempt_back_merge(q, req, max_sectors, max_segments);
+
+			elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
+
+			req->biotail->bi_next = bio;
+			req->biotail = bio;
+			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+			drive_stat_acct(req, nr_sectors, 0);
+			attempt_back_merge(q, req);
 			goto out;
 
 		case ELEVATOR_FRONT_MERGE:
-			if (!q->front_merge_fn(q, req, bh, max_segments))
+			BUG_ON(req->flags & REQ_STARTED);
+			BUG_ON(req->flags & REQ_NOMERGE);
+			if (!q->front_merge_fn(q, req, bio))
 				break;
-			elevator->elevator_merge_cleanup_fn(q, req, count);
-			bh->b_reqnext = req->bh;
-			req->bh = bh;
-			req->buffer = bh->b_data;
-			req->current_nr_sectors = count;
+
+			elevator->elevator_merge_cleanup_fn(q, req, nr_sectors);
+
+			bio->bi_next = req->bio;
+			req->bio = bio;
+			/*
+			 * may not be valid. if the low level driver said
+			 * it didn't need a bounce buffer then it better
+			 * not touch req->buffer either...
+			 */
+			req->buffer = bio_data(bio);
+			req->current_nr_sectors = cur_nr_sectors;
+			req->hard_cur_sectors = cur_nr_sectors;
 			req->sector = req->hard_sector = sector;
-			req->nr_sectors = req->hard_nr_sectors += count;
-			blk_started_io(count);
-			drive_stat_acct(req->rq_dev, req->cmd, count, 0);
-			attempt_front_merge(q, head, req, max_sectors, max_segments);
+			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+			drive_stat_acct(req, nr_sectors, 0);
+			attempt_front_merge(q, head, req);
 			goto out;
 
 		/*
@@ -730,14 +1047,14 @@
 			 * of the queue
 			 */
 			if (req)
-				insert_here = &req->queue;
+				insert_here = &req->queuelist;
 			break;
 
 		default:
 			printk("elevator returned crap (%d)\n", el_ret);
 			BUG();
 	}
-		
+
 	/*
 	 * Grab a free request from the freelist - if that is empty, check
 	 * if we are doing read ahead and abort instead of blocking for
@@ -748,107 +1065,140 @@
 		req = freereq;
 		freereq = NULL;
 	} else if ((req = get_request(q, rw)) == NULL) {
-		spin_unlock_irq(&io_request_lock);
-		if (rw_ahead)
+
+		spin_unlock_irq(&q->queue_lock);
+
+		/*
+		 * READA bit set
+		 */
+		if (bio->bi_rw & (1 << BIO_RW_AHEAD)) {
+			set_bit(BIO_RW_BLOCK, &bio->bi_flags);
 			goto end_io;
+		}
 
-		freereq = __get_request_wait(q, rw);
+		freereq = get_request_wait(q, rw);
 		goto again;
 	}
 
-/* fill up the request-info, and add it to the queue */
+	/*
+	 * fill up the request-info, and add it to the queue
+	 */
 	req->elevator_sequence = latency;
-	req->cmd = rw;
+
+	/*
+	 * first three bits are identical in rq->flags and bio->bi_rw,
+	 * see bio.h and blkdev.h
+	 */
+	req->flags = (bio->bi_rw & 7) | REQ_CMD;
+
+	/*
+	 * REQ_BARRIER implies no merging, but lets make it explicit
+	 */
+	if (barrier)
+		req->flags |= (REQ_BARRIER | REQ_NOMERGE);
+
 	req->errors = 0;
 	req->hard_sector = req->sector = sector;
-	req->hard_nr_sectors = req->nr_sectors = count;
-	req->current_nr_sectors = count;
-	req->nr_segments = 1; /* Always 1 for a new request. */
-	req->nr_hw_segments = 1; /* Always 1 for a new request. */
-	req->buffer = bh->b_data;
+	req->hard_nr_sectors = req->nr_sectors = nr_sectors;
+	req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors;
+	req->nr_segments = bio->bi_vcnt;
+	req->nr_hw_segments = bio_hw_segments(q, bio);
+	req->buffer = bio_data(bio);	/* see ->buffer comment above */
 	req->waiting = NULL;
-	req->bh = bh;
-	req->bhtail = bh;
-	req->rq_dev = bh->b_rdev;
-	blk_started_io(count);
+	req->bio = req->biotail = bio;
+	req->rq_dev = bio->bi_dev;
 	add_request(q, req, insert_here);
 out:
 	if (freereq)
 		blkdev_release_request(freereq);
-	spin_unlock_irq(&io_request_lock);
+	spin_unlock_irq(&q->queue_lock);
 	return 0;
+
 end_io:
-	bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
+	bio->bi_end_io(bio, nr_sectors);
 	return 0;
 }
 
+
+/*
+ * If bio->bi_dev is a partition, remap the location
+ */
+static inline void blk_partition_remap(struct bio *bio)
+{
+	int major, minor, drive, minor0;
+	struct gendisk *g;
+	kdev_t dev0;
+
+	major = MAJOR(bio->bi_dev);
+	if ((g = get_gendisk(bio->bi_dev))) {
+		minor = MINOR(bio->bi_dev);
+		drive = (minor >> g->minor_shift);
+		minor0 = (drive << g->minor_shift); /* whole disk device */
+		/* that is, minor0 = (minor & ~((1<<g->minor_shift)-1)); */
+		dev0 = MKDEV(major, minor0);
+		if (dev0 != bio->bi_dev) {
+			bio->bi_dev = dev0;
+			bio->bi_sector += g->part[minor].start_sect;
+		}
+		/* lots of checks are possible */
+	}
+}
+
 /**
- * generic_make_request: hand a buffer head to it's device driver for I/O
- * @rw:  READ, WRITE, or READA - what sort of I/O is desired.
- * @bh:  The buffer head describing the location in memory and on the device.
+ * generic_make_request: hand a buffer to it's device driver for I/O
+ * @bio:  The bio describing the location in memory and on the device.
  *
  * generic_make_request() is used to make I/O requests of block
- * devices. It is passed a &struct buffer_head and a &rw value.  The
- * %READ and %WRITE options are (hopefully) obvious in meaning.  The
- * %READA value means that a read is required, but that the driver is
- * free to fail the request if, for example, it cannot get needed
- * resources immediately.
+ * devices. It is passed a &struct bio, which describes the I/O that needs
+ * to be done.
  *
  * generic_make_request() does not return any status.  The
  * success/failure status of the request, along with notification of
- * completion, is delivered asynchronously through the bh->b_end_io
+ * completion, is delivered asynchronously through the bio->bi_end_io
  * function described (one day) else where.
  *
- * The caller of generic_make_request must make sure that b_page,
- * b_addr, b_size are set to describe the memory buffer, that b_rdev
- * and b_rsector are set to describe the device address, and the
- * b_end_io and optionally b_private are set to describe how
- * completion notification should be signaled.  BH_Mapped should also
- * be set (to confirm that b_dev and b_blocknr are valid).
- *
- * generic_make_request and the drivers it calls may use b_reqnext,
- * and may change b_rdev and b_rsector.  So the values of these fields
+ * The caller of generic_make_request must make sure that bi_io_vec
+ * are set to describe the memory buffer, and that bi_dev and bi_sector are
+ * set to describe the device address, and the
+ * bi_end_io and optionally bi_private are set to describe how
+ * completion notification should be signaled.
+ *
+ * generic_make_request and the drivers it calls may use bi_next if this
+ * bio happens to be merged with someone else, and may change bi_dev and
+ * bi_sector for remaps as it sees fit.  So the values of these fields
  * should NOT be depended on after the call to generic_make_request.
- * Because of this, the caller should record the device address
- * information in b_dev and b_blocknr.
  *
- * Apart from those fields mentioned above, no other fields, and in
- * particular, no other flags, are changed by generic_make_request or
- * any lower level drivers.
  * */
-void generic_make_request (int rw, struct buffer_head * bh)
+void generic_make_request(struct bio *bio)
 {
-	int major = MAJOR(bh->b_rdev);
-	int minorsize = 0;
+	int major = MAJOR(bio->bi_dev);
+	int minor = MINOR(bio->bi_dev);
 	request_queue_t *q;
+	sector_t minorsize = 0;
+	int nr_sectors = bio_sectors(bio);
 
-	if (!bh->b_end_io)
-		BUG();
-
-	/* Test device size, when known. */
+	/* Test device or partition size, when known. */
 	if (blk_size[major])
-		minorsize = blk_size[major][MINOR(bh->b_rdev)];
+		minorsize = blk_size[major][minor];
 	if (minorsize) {
 		unsigned long maxsector = (minorsize << 1) + 1;
-		unsigned long sector = bh->b_rsector;
-		unsigned int count = bh->b_size >> 9;
+		unsigned long sector = bio->bi_sector;
 
-		if (maxsector < count || maxsector - count < sector) {
-			/* Yecch */
-			bh->b_state &= (1 << BH_Lock) | (1 << BH_Mapped);
-
-			/* This may well happen - the kernel calls bread()
-			   without checking the size of the device, e.g.,
-			   when mounting a device. */
-			printk(KERN_INFO
-			       "attempt to access beyond end of device\n");
-			printk(KERN_INFO "%s: rw=%d, want=%ld, limit=%d\n",
-			       kdevname(bh->b_rdev), rw,
-			       (sector + count)>>1, minorsize);
-
-			/* Yecch again */
-			bh->b_end_io(bh, 0);
-			return;
+		if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
+			if (blk_size[major][minor]) {
+				
+				/* This may well happen - the kernel calls
+				 * bread() without checking the size of the
+				 * device, e.g., when mounting a device. */
+				printk(KERN_INFO
+				       "attempt to access beyond end of device\n");
+				printk(KERN_INFO "%s: rw=%ld, want=%ld, limit=%Lu\n",
+				       kdevname(bio->bi_dev), bio->bi_rw,
+				       (sector + nr_sectors)>>1,
+				       (u64) blk_size[major][minor]);
+			}
+			set_bit(BIO_EOF, &bio->bi_flags);
+			goto end_io;
 		}
 	}
 
@@ -856,63 +1206,115 @@
 	 * Resolve the mapping until finished. (drivers are
 	 * still free to implement/resolve their own stacking
 	 * by explicitly returning 0)
-	 */
-	/* NOTE: we don't repeat the blk_size check for each new device.
+	 *
+	 * NOTE: we don't repeat the blk_size check for each new device.
 	 * Stacking drivers are expected to know what they are doing.
 	 */
 	do {
-		q = blk_get_queue(bh->b_rdev);
+		q = blk_get_queue(bio->bi_dev);
 		if (!q) {
 			printk(KERN_ERR
-			       "generic_make_request: Trying to access "
-			       "nonexistent block-device %s (%ld)\n",
-			       kdevname(bh->b_rdev), bh->b_rsector);
-			buffer_IO_error(bh);
+			       "generic_make_request: Trying to access nonexistent block-device %s (%Lu)\n",
+			       kdevname(bio->bi_dev), (u64) bio->bi_sector);
+end_io:
+			bio->bi_end_io(bio, nr_sectors);
 			break;
 		}
-	} while (q->make_request_fn(q, rw, bh));
+
+		BUG_ON(bio_sectors(bio) > q->max_sectors);
+
+		/*
+		 * If this device has partitions, remap block n
+		 * of partition p to block n+start(p) of the disk.
+		 */
+		blk_partition_remap(bio);
+
+	} while (q->make_request_fn(q, bio));
 }
 
+/*
+ * our default bio end_io callback handler for a buffer_head mapping.
+ */
+static int end_bio_bh_io_sync(struct bio *bio, int nr_sectors)
+{
+	struct buffer_head *bh = bio->bi_private;
+
+	BIO_BUG_ON(nr_sectors != (bh->b_size >> 9));
+
+	bh->b_end_io(bh, test_bit(BIO_UPTODATE, &bio->bi_flags));
+	bio_put(bio);
+	return 0;
+}
 
 /**
- * submit_bh: submit a buffer_head to the block device later for I/O
+ * submit_bio: submit a bio to the block device layer for I/O
  * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead)
- * @bh: The &struct buffer_head which describes the I/O
+ * @bio: The &struct bio which describes the I/O
  *
- * submit_bh() is very similar in purpose to generic_make_request(), and
- * uses that function to do most of the work.
+ * submit_bio() is very similar in purpose to generic_make_request(), and
+ * uses that function to do most of the work. Both are fairly rough
+ * interfaces, @bio must be presetup and ready for I/O.
  *
- * The extra functionality provided by submit_bh is to determine
- * b_rsector from b_blocknr and b_size, and to set b_rdev from b_dev.
- * This is is appropriate for IO requests that come from the buffer
- * cache and page cache which (currently) always use aligned blocks.
  */
-void submit_bh(int rw, struct buffer_head * bh)
+int submit_bio(int rw, struct bio *bio)
+{
+	int count = bio_sectors(bio);
+
+	/*
+	 * do some validity checks...
+	 */
+	BUG_ON(!bio->bi_end_io);
+
+	BIO_BUG_ON(!bio->bi_size);
+	BIO_BUG_ON(!bio->bi_io_vec);
+
+	bio->bi_rw = rw;
+
+	if (rw & WRITE)
+		kstat.pgpgout += count;
+	else
+		kstat.pgpgin += count;
+
+	generic_make_request(bio);
+	return 1;
+}
+
+/**
+ * submit_bh: submit a buffer_head to the block device layer for I/O
+ * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead)
+ * @bh: The &struct buffer_head which describes the I/O
+ *
+ **/
+int submit_bh(int rw, struct buffer_head * bh)
 {
-	int count = bh->b_size >> 9;
+	struct bio *bio;
 
-	if (!test_bit(BH_Lock, &bh->b_state))
-		BUG();
+	BUG_ON(!test_bit(BH_Lock, &bh->b_state));
+	BUG_ON(!buffer_mapped(bh));
+	BUG_ON(!bh->b_end_io);
 
 	set_bit(BH_Req, &bh->b_state);
 
 	/*
-	 * First step, 'identity mapping' - RAID or LVM might
-	 * further remap this.
+	 * from here on down, it's all bio -- do the initial mapping,
+	 * submit_bio -> generic_make_request may further map this bio around
 	 */
-	bh->b_rdev = bh->b_dev;
-	bh->b_rsector = bh->b_blocknr * count;
+	bio = bio_alloc(GFP_NOIO, 1);
 
-	generic_make_request(rw, bh);
+	bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9);
+	bio->bi_dev = bh->b_dev;
+	bio->bi_io_vec[0].bv_page = bh->b_page;
+	bio->bi_io_vec[0].bv_len = bh->b_size;
+	bio->bi_io_vec[0].bv_offset = bh_offset(bh);
+
+	bio->bi_vcnt = 1;
+	bio->bi_idx = 0;
+	bio->bi_size = bh->b_size;
 
-	switch (rw) {
-		case WRITE:
-			kstat.pgpgout += count;
-			break;
-		default:
-			kstat.pgpgin += count;
-			break;
-	}
+	bio->bi_end_io = end_bio_bh_io_sync;
+	bio->bi_private = bh;
+
+	return submit_bio(rw, bio);
 }
 
 /**
@@ -944,8 +1346,9 @@
  *
  * Caveat:
  *  All of the buffers must be for the same device, and must also be
- *  of the current approved size for the device.  */
-
+ *  a multiple of the current approved size for the device.
+ *
+ **/
 void ll_rw_block(int rw, int nr, struct buffer_head * bhs[])
 {
 	unsigned int major;
@@ -963,7 +1366,7 @@
 	/* Verify requested block sizes. */
 	for (i = 0; i < nr; i++) {
 		struct buffer_head *bh = bhs[i];
-		if (bh->b_size % correct_size) {
+		if (bh->b_size & (correct_size - 1)) {
 			printk(KERN_NOTICE "ll_rw_block: device %s: "
 			       "only %d-char blocks implemented (%u)\n",
 			       kdevname(bhs[0]->b_dev),
@@ -1024,12 +1427,33 @@
 extern int stram_device_init (void);
 #endif
 
+inline void blk_recalc_request(struct request *rq, int nsect)
+{
+	rq->hard_sector += nsect;
+	rq->hard_nr_sectors -= nsect;
+	rq->sector = rq->hard_sector;
+	rq->nr_sectors = rq->hard_nr_sectors;
+
+	rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
+	rq->hard_cur_sectors = rq->current_nr_sectors;
+
+	/*
+	 * if total number of sectors is less than the first segment
+	 * size, something has gone terribly wrong
+	 */
+	if (rq->nr_sectors < rq->current_nr_sectors) {
+		printk("blk: request botched\n");
+		rq->nr_sectors = rq->current_nr_sectors;
+	}
+
+	rq->buffer = bio_data(rq->bio);
+}
 
 /**
  * end_that_request_first - end I/O on one buffer.
  * @req:      the request being processed
  * @uptodate: 0 for I/O error
- * @name:     the name printed for an I/O error
+ * @nr_sectors: number of sectors to end I/O on
  *
  * Description:
  *     Ends I/O on the first buffer attached to @req, and sets it up
@@ -1038,49 +1462,72 @@
  * Return:
  *     0 - we are done with this request, call end_that_request_last()
  *     1 - still buffers pending for this request
- *
- * Caveat: 
- *     Drivers implementing their own end_request handling must call
- *     blk_finished_io() appropriately.
  **/
 
-int end_that_request_first (struct request *req, int uptodate, char *name)
+int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
 {
-	struct buffer_head * bh;
-	int nsect;
+	int nsect, total_nsect;
+	struct bio *bio;
 
 	req->errors = 0;
 	if (!uptodate)
-		printk("end_request: I/O error, dev %s (%s), sector %lu\n",
-			kdevname(req->rq_dev), name, req->sector);
+		printk("end_request: I/O error, dev %s, sector %lu\n",
+			kdevname(req->rq_dev), req->sector);
 
-	if ((bh = req->bh) != NULL) {
-		nsect = bh->b_size >> 9;
-		blk_finished_io(nsect);
-		req->bh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
-		bh->b_end_io(bh, uptodate);
-		if ((bh = req->bh) != NULL) {
-			req->hard_sector += nsect;
-			req->hard_nr_sectors -= nsect;
-			req->sector = req->hard_sector;
-			req->nr_sectors = req->hard_nr_sectors;
-
-			req->current_nr_sectors = bh->b_size >> 9;
-			if (req->nr_sectors < req->current_nr_sectors) {
-				req->nr_sectors = req->current_nr_sectors;
-				printk("end_request: buffer-list destroyed\n");
-			}
-			req->buffer = bh->b_data;
+	total_nsect = 0;
+	while ((bio = req->bio)) {
+		nsect = bio_iovec(bio)->bv_len >> 9;
+
+		BIO_BUG_ON(bio_iovec(bio)->bv_len > bio->bi_size);
+
+		/*
+		 * not a complete bvec done
+		 */
+		if (unlikely(nsect > nr_sectors)) {
+			int residual = (nsect - nr_sectors) << 9;
+
+			bio->bi_size -= residual;
+			bio_iovec(bio)->bv_offset += residual;
+			bio_iovec(bio)->bv_len -= residual;
+			blk_recalc_request(req, nr_sectors);
 			return 1;
 		}
+
+		/*
+		 * account transfer
+		 */
+		bio->bi_size -= bio_iovec(bio)->bv_len;
+		bio->bi_idx++;
+
+		nr_sectors -= nsect;
+		total_nsect += nsect;
+
+		if (!bio->bi_size) {
+			req->bio = bio->bi_next;
+
+			if (unlikely(bio_endio(bio, uptodate, total_nsect)))
+				BUG();
+
+			total_nsect = 0;
+		}
+
+		if ((bio = req->bio)) {
+			blk_recalc_request(req, nsect);
+
+			/*
+			 * end more in this run, or just return 'not-done'
+			 */
+			if (unlikely(nr_sectors <= 0))
+				return 1;
+		}
 	}
+
 	return 0;
 }
 
 void end_that_request_last(struct request *req)
 {
-	if (req->waiting != NULL)
+	if (req->waiting)
 		complete(req->waiting);
 
 	blkdev_release_request(req);
@@ -1105,7 +1552,6 @@
 
 	memset(ro_bits,0,sizeof(ro_bits));
 	memset(max_readahead, 0, sizeof(max_readahead));
-	memset(max_sectors, 0, sizeof(max_sectors));
 
 	total_ram = nr_free_pages() << (PAGE_SHIFT - 10);
 
@@ -1115,129 +1561,50 @@
 	 */
 	queue_nr_requests = 64;
 	if (total_ram > MB(32))
-		queue_nr_requests = 128;
+		queue_nr_requests = 256;
 
 	/*
 	 * Batch frees according to queue length
 	 */
-	batch_requests = queue_nr_requests/4;
+	if ((batch_requests = queue_nr_requests / 4) > 32)
+		batch_requests = 32;
 	printk("block: %d slots per queue, batch=%d\n", queue_nr_requests, batch_requests);
 
-#ifdef CONFIG_AMIGA_Z2RAM
-	z2_init();
-#endif
-#ifdef CONFIG_STRAM_SWAP
-	stram_device_init();
-#endif
-#ifdef CONFIG_BLK_DEV_RAM
-	rd_init();
-#endif
-#ifdef CONFIG_ISP16_CDI
-	isp16_init();
-#endif
+	blk_max_low_pfn = max_low_pfn;
+	blk_max_pfn = max_pfn;
+
 #if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_IDE)
 	ide_init();		/* this MUST precede hd_init */
 #endif
 #if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_HD)
 	hd_init();
 #endif
-#ifdef CONFIG_BLK_DEV_PS2
-	ps2esdi_init();
-#endif
-#ifdef CONFIG_BLK_DEV_XD
-	xd_init();
-#endif
-#ifdef CONFIG_BLK_DEV_MFM
-	mfm_init();
-#endif
-#ifdef CONFIG_PARIDE
-	{ extern void paride_init(void); paride_init(); };
-#endif
-#ifdef CONFIG_MAC_FLOPPY
-	swim3_init();
-#endif
-#ifdef CONFIG_BLK_DEV_SWIM_IOP
-	swimiop_init();
-#endif
-#ifdef CONFIG_AMIGA_FLOPPY
-	amiga_floppy_init();
-#endif
-#ifdef CONFIG_ATARI_FLOPPY
-	atari_floppy_init();
-#endif
-#ifdef CONFIG_BLK_DEV_FD
-	floppy_init();
-#else
 #if defined(__i386__)	/* Do we even need this? */
 	outb_p(0xc, 0x3f2);
 #endif
-#endif
-#ifdef CONFIG_CDU31A
-	cdu31a_init();
-#endif
-#ifdef CONFIG_ATARI_ACSI
-	acsi_init();
-#endif
-#ifdef CONFIG_MCD
-	mcd_init();
-#endif
-#ifdef CONFIG_MCDX
-	mcdx_init();
-#endif
-#ifdef CONFIG_SBPCD
-	sbpcd_init();
-#endif
-#ifdef CONFIG_AZTCD
-	aztcd_init();
-#endif
-#ifdef CONFIG_CDU535
-	sony535_init();
-#endif
-#ifdef CONFIG_GSCD
-	gscd_init();
-#endif
-#ifdef CONFIG_CM206
-	cm206_init();
-#endif
-#ifdef CONFIG_OPTCD
-	optcd_init();
-#endif
-#ifdef CONFIG_SJCD
-	sjcd_init();
-#endif
-#ifdef CONFIG_APBLOCK
-	ap_init();
-#endif
-#ifdef CONFIG_DDV
-	ddv_init();
-#endif
-#ifdef CONFIG_MDISK
-	mdisk_init();
-#endif
-#ifdef CONFIG_DASD
-	dasd_init();
-#endif
-#if defined(CONFIG_S390_TAPE) && defined(CONFIG_S390_TAPE_BLOCK)
-	tapeblock_init();
-#endif
-#ifdef CONFIG_BLK_DEV_XPRAM
-        xpram_init();
-#endif
 
-#ifdef CONFIG_SUN_JSFLASH
-	jsfd_init();
-#endif
 	return 0;
 };
 
-EXPORT_SYMBOL(io_request_lock);
 EXPORT_SYMBOL(end_that_request_first);
 EXPORT_SYMBOL(end_that_request_last);
 EXPORT_SYMBOL(blk_init_queue);
 EXPORT_SYMBOL(blk_get_queue);
 EXPORT_SYMBOL(blk_cleanup_queue);
-EXPORT_SYMBOL(blk_queue_headactive);
 EXPORT_SYMBOL(blk_queue_make_request);
+EXPORT_SYMBOL(blk_queue_bounce_limit);
 EXPORT_SYMBOL(generic_make_request);
 EXPORT_SYMBOL(blkdev_release_request);
 EXPORT_SYMBOL(generic_unplug_device);
+EXPORT_SYMBOL(blk_attempt_remerge);
+EXPORT_SYMBOL(blk_max_low_pfn);
+EXPORT_SYMBOL(blk_queue_max_sectors);
+EXPORT_SYMBOL(blk_queue_max_segments);
+EXPORT_SYMBOL(blk_queue_max_segment_size);
+EXPORT_SYMBOL(blk_queue_hardsect_size);
+EXPORT_SYMBOL(blk_queue_segment_boundary);
+EXPORT_SYMBOL(blk_rq_map_sg);
+EXPORT_SYMBOL(blk_nohighio);
+EXPORT_SYMBOL(blk_dump_rq_flags);
+EXPORT_SYMBOL(submit_bio);
+EXPORT_SYMBOL(blk_contig_segment);
diff -u --recursive --new-file v2.5.0/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.5.0/linux/drivers/block/loop.c	Mon Nov 19 14:48:02 2001
+++ linux/drivers/block/loop.c	Fri Nov 30 08:33:50 2001
@@ -168,8 +168,7 @@
 					lo->lo_device);
 }
 
-static int lo_send(struct loop_device *lo, struct buffer_head *bh, int bsize,
-		   loff_t pos)
+static int lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
 {
 	struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
 	struct address_space *mapping = file->f_dentry->d_inode->i_mapping;
@@ -183,8 +182,8 @@
 	down(&mapping->host->i_sem);
 	index = pos >> PAGE_CACHE_SHIFT;
 	offset = pos & (PAGE_CACHE_SIZE - 1);
-	len = bh->b_size;
-	data = bh->b_data;
+	len = bio->bi_size;
+	data = bio_data(bio);
 	while (len > 0) {
 		int IV = index * (PAGE_CACHE_SIZE/bsize) + offset/bsize;
 		int transfer_result;
@@ -263,18 +262,17 @@
 	return size;
 }
 
-static int lo_receive(struct loop_device *lo, struct buffer_head *bh, int bsize,
-		      loff_t pos)
+static int lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
 {
 	struct lo_read_data cookie;
 	read_descriptor_t desc;
 	struct file *file;
 
 	cookie.lo = lo;
-	cookie.data = bh->b_data;
+	cookie.data = bio_data(bio);
 	cookie.bsize = bsize;
 	desc.written = 0;
-	desc.count = bh->b_size;
+	desc.count = bio->bi_size;
 	desc.buf = (char*)&cookie;
 	desc.error = 0;
 	spin_lock_irq(&lo->lo_lock);
@@ -310,46 +308,52 @@
 	return IV;
 }
 
-static int do_bh_filebacked(struct loop_device *lo, struct buffer_head *bh, int rw)
+static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
 {
 	loff_t pos;
 	int ret;
 
-	pos = ((loff_t) bh->b_rsector << 9) + lo->lo_offset;
+	pos = ((loff_t) bio->bi_sector << 9) + lo->lo_offset;
 
-	if (rw == WRITE)
-		ret = lo_send(lo, bh, loop_get_bs(lo), pos);
-	else
-		ret = lo_receive(lo, bh, loop_get_bs(lo), pos);
+	do {
+		if (bio_rw(bio) == WRITE)
+			ret = lo_send(lo, bio, loop_get_bs(lo), pos);
+		else
+			ret = lo_receive(lo, bio, loop_get_bs(lo), pos);
+
+	} while (++bio->bi_idx < bio->bi_vcnt);
 
 	return ret;
 }
 
-static void loop_end_io_transfer(struct buffer_head *bh, int uptodate);
-static void loop_put_buffer(struct buffer_head *bh)
+static int loop_end_io_transfer(struct bio *, int);
+static void loop_put_buffer(struct bio *bio)
 {
 	/*
-	 * check b_end_io, may just be a remapped bh and not an allocated one
+	 * check bi_end_io, may just be a remapped bio
 	 */
-	if (bh && bh->b_end_io == loop_end_io_transfer) {
-		__free_page(bh->b_page);
-		kmem_cache_free(bh_cachep, bh);
+	if (bio && bio->bi_end_io == loop_end_io_transfer) {
+		int i;
+		for (i = 0; i < bio->bi_vcnt; i++)
+			__free_page(bio->bi_io_vec[i].bv_page);
+
+		bio_put(bio);
 	}
 }
 
 /*
- * Add buffer_head to back of pending list
+ * Add bio to back of pending list
  */
-static void loop_add_bh(struct loop_device *lo, struct buffer_head *bh)
+static void loop_add_bio(struct loop_device *lo, struct bio *bio)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&lo->lo_lock, flags);
-	if (lo->lo_bhtail) {
-		lo->lo_bhtail->b_reqnext = bh;
-		lo->lo_bhtail = bh;
+	if (lo->lo_biotail) {
+		lo->lo_biotail->bi_next = bio;
+		lo->lo_biotail = bio;
 	} else
-		lo->lo_bh = lo->lo_bhtail = bh;
+		lo->lo_bio = lo->lo_biotail = bio;
 	spin_unlock_irqrestore(&lo->lo_lock, flags);
 
 	up(&lo->lo_bh_mutex);
@@ -358,112 +362,84 @@
 /*
  * Grab first pending buffer
  */
-static struct buffer_head *loop_get_bh(struct loop_device *lo)
+static struct bio *loop_get_bio(struct loop_device *lo)
 {
-	struct buffer_head *bh;
+	struct bio *bio;
 
 	spin_lock_irq(&lo->lo_lock);
-	if ((bh = lo->lo_bh)) {
-		if (bh == lo->lo_bhtail)
-			lo->lo_bhtail = NULL;
-		lo->lo_bh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
+	if ((bio = lo->lo_bio)) {
+		if (bio == lo->lo_biotail)
+			lo->lo_biotail = NULL;
+		lo->lo_bio = bio->bi_next;
+		bio->bi_next = NULL;
 	}
 	spin_unlock_irq(&lo->lo_lock);
 
-	return bh;
+	return bio;
 }
 
 /*
- * when buffer i/o has completed. if BH_Dirty is set, this was a WRITE
- * and lo->transfer stuff has already been done. if not, it was a READ
- * so queue it for the loop thread and let it do the transfer out of
- * b_end_io context (we don't want to do decrypt of a page with irqs
+ * if this was a WRITE lo->transfer stuff has already been done. for READs,
+ * queue it for the loop thread and let it do the transfer out of
+ * bi_end_io context (we don't want to do decrypt of a page with irqs
  * disabled)
  */
-static void loop_end_io_transfer(struct buffer_head *bh, int uptodate)
+static int loop_end_io_transfer(struct bio *bio, int nr_sectors)
 {
-	struct loop_device *lo = &loop_dev[MINOR(bh->b_dev)];
+	struct loop_device *lo = &loop_dev[MINOR(bio->bi_dev)];
+	int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
 
-	if (!uptodate || test_bit(BH_Dirty, &bh->b_state)) {
-		struct buffer_head *rbh = bh->b_private;
+	if (!uptodate || bio_rw(bio) == WRITE) {
+		struct bio *rbh = bio->bi_private;
 
-		rbh->b_end_io(rbh, uptodate);
+		bio_endio(rbh, uptodate, nr_sectors);
 		if (atomic_dec_and_test(&lo->lo_pending))
 			up(&lo->lo_bh_mutex);
-		loop_put_buffer(bh);
+		loop_put_buffer(bio);
 	} else
-		loop_add_bh(lo, bh);
+		loop_add_bio(lo, bio);
+
+	return 0;
 }
 
-static struct buffer_head *loop_get_buffer(struct loop_device *lo,
-					   struct buffer_head *rbh)
+static struct bio *loop_get_buffer(struct loop_device *lo, struct bio *rbh)
 {
-	struct buffer_head *bh;
+	struct bio *bio;
 
 	/*
 	 * for xfer_funcs that can operate on the same bh, do that
 	 */
 	if (lo->lo_flags & LO_FLAGS_BH_REMAP) {
-		bh = rbh;
+		bio = rbh;
 		goto out_bh;
 	}
 
-	do {
-		bh = kmem_cache_alloc(bh_cachep, SLAB_NOIO);
-		if (bh)
-			break;
-
-		run_task_queue(&tq_disk);
-		schedule_timeout(HZ);
-	} while (1);
-	memset(bh, 0, sizeof(*bh));
-
-	bh->b_size = rbh->b_size;
-	bh->b_dev = rbh->b_rdev;
-	bh->b_state = (1 << BH_Req) | (1 << BH_Mapped) | (1 << BH_Lock);
+	bio = bio_copy(rbh, GFP_NOIO, rbh->bi_rw & WRITE);
 
-	/*
-	 * easy way out, although it does waste some memory for < PAGE_SIZE
-	 * blocks... if highmem bounce buffering can get away with it,
-	 * so can we :-)
-	 */
-	do {
-		bh->b_page = alloc_page(GFP_NOIO);
-		if (bh->b_page)
-			break;
-
-		run_task_queue(&tq_disk);
-		schedule_timeout(HZ);
-	} while (1);
-
-	bh->b_data = page_address(bh->b_page);
-	bh->b_end_io = loop_end_io_transfer;
-	bh->b_private = rbh;
-	init_waitqueue_head(&bh->b_wait);
+	bio->bi_end_io = loop_end_io_transfer;
+	bio->bi_private = rbh;
 
 out_bh:
-	bh->b_rsector = rbh->b_rsector + (lo->lo_offset >> 9);
+	bio->bi_sector = rbh->bi_sector + (lo->lo_offset >> 9);
+	bio->bi_rw = rbh->bi_rw;
 	spin_lock_irq(&lo->lo_lock);
-	bh->b_rdev = lo->lo_device;
+	bio->bi_dev = lo->lo_device;
 	spin_unlock_irq(&lo->lo_lock);
 
-	return bh;
+	return bio;
 }
 
-static int loop_make_request(request_queue_t *q, int rw, struct buffer_head *rbh)
+static int loop_make_request(request_queue_t *q, struct bio *rbh)
 {
-	struct buffer_head *bh = NULL;
+	struct bio *bh = NULL;
 	struct loop_device *lo;
 	unsigned long IV;
+	int rw = bio_rw(rbh);
 
-	if (!buffer_locked(rbh))
-		BUG();
-
-	if (MINOR(rbh->b_rdev) >= max_loop)
+	if (MINOR(rbh->bi_dev) >= max_loop)
 		goto out;
 
-	lo = &loop_dev[MINOR(rbh->b_rdev)];
+	lo = &loop_dev[MINOR(rbh->bi_dev)];
 	spin_lock_irq(&lo->lo_lock);
 	if (lo->lo_state != Lo_bound)
 		goto inactive;
@@ -476,25 +452,17 @@
 	} else if (rw == READA) {
 		rw = READ;
 	} else if (rw != READ) {
-		printk(KERN_ERR "loop: unknown command (%d)\n", rw);
+		printk(KERN_ERR "loop: unknown command (%x)\n", rw);
 		goto err;
 	}
 
-#if CONFIG_HIGHMEM
-	rbh = create_bounce(rw, rbh);
-#endif
+	blk_queue_bounce(q, &rbh);
 
 	/*
 	 * file backed, queue for loop_thread to handle
 	 */
 	if (lo->lo_flags & LO_FLAGS_DO_BMAP) {
-		/*
-		 * rbh locked at this point, noone else should clear
-		 * the dirty flag
-		 */
-		if (rw == WRITE)
-			set_bit(BH_Dirty, &rbh->b_state);
-		loop_add_bh(lo, rbh);
+		loop_add_bio(lo, rbh);
 		return 0;
 	}
 
@@ -502,15 +470,14 @@
 	 * piggy old buffer on original, and submit for I/O
 	 */
 	bh = loop_get_buffer(lo, rbh);
-	IV = loop_get_iv(lo, rbh->b_rsector);
+	IV = loop_get_iv(lo, rbh->bi_sector);
 	if (rw == WRITE) {
-		set_bit(BH_Dirty, &bh->b_state);
-		if (lo_do_transfer(lo, WRITE, bh->b_data, rbh->b_data,
-				   bh->b_size, IV))
+		if (lo_do_transfer(lo, WRITE, bio_data(bh), bio_data(rbh),
+				   bh->bi_size, IV))
 			goto err;
 	}
 
-	generic_make_request(rw, bh);
+	generic_make_request(bh);
 	return 0;
 
 err:
@@ -518,14 +485,32 @@
 		up(&lo->lo_bh_mutex);
 	loop_put_buffer(bh);
 out:
-	buffer_IO_error(rbh);
+	bio_io_error(rbh);
 	return 0;
 inactive:
 	spin_unlock_irq(&lo->lo_lock);
 	goto out;
 }
 
-static inline void loop_handle_bh(struct loop_device *lo,struct buffer_head *bh)
+static int do_bio_blockbacked(struct loop_device *lo, struct bio *bio,
+			      struct bio *rbh)
+{
+	unsigned long IV = loop_get_iv(lo, rbh->bi_sector);
+	struct bio_vec *to;
+	char *vto, *vfrom;
+	int ret = 0, i;
+
+	bio_for_each_segment(to, bio, i) {
+		vfrom = page_address(rbh->bi_io_vec[i].bv_page) + rbh->bi_io_vec[i].bv_offset;
+		vto = page_address(to->bv_page) + to->bv_offset;
+		ret |= lo_do_transfer(lo, bio_data_dir(bio), vto, vfrom,
+					to->bv_len, IV);
+	}
+
+	return ret;
+}
+
+static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
 {
 	int ret;
 
@@ -533,19 +518,15 @@
 	 * For block backed loop, we know this is a READ
 	 */
 	if (lo->lo_flags & LO_FLAGS_DO_BMAP) {
-		int rw = !!test_and_clear_bit(BH_Dirty, &bh->b_state);
-
-		ret = do_bh_filebacked(lo, bh, rw);
-		bh->b_end_io(bh, !ret);
+		ret = do_bio_filebacked(lo, bio);
+		bio_endio(bio, !ret, bio_sectors(bio));
 	} else {
-		struct buffer_head *rbh = bh->b_private;
-		unsigned long IV = loop_get_iv(lo, rbh->b_rsector);
+		struct bio *rbh = bio->bi_private;
 
-		ret = lo_do_transfer(lo, READ, bh->b_data, rbh->b_data,
-				     bh->b_size, IV);
+		ret = do_bio_blockbacked(lo, bio, rbh);
 
-		rbh->b_end_io(rbh, !ret);
-		loop_put_buffer(bh);
+		bio_endio(rbh, !ret, bio_sectors(bio));
+		loop_put_buffer(bio);
 	}
 }
 
@@ -558,7 +539,7 @@
 static int loop_thread(void *data)
 {
 	struct loop_device *lo = data;
-	struct buffer_head *bh;
+	struct bio *bio;
 
 	daemonize();
 	exit_files(current);
@@ -592,12 +573,12 @@
 		if (!atomic_read(&lo->lo_pending))
 			break;
 
-		bh = loop_get_bh(lo);
-		if (!bh) {
-			printk("loop: missing bh\n");
+		bio = loop_get_bio(lo);
+		if (!bio) {
+			printk("loop: missing bio\n");
 			continue;
 		}
-		loop_handle_bh(lo, bh);
+		loop_handle_bio(lo, bio);
 
 		/*
 		 * upped both for pending work and tear-down, lo_pending
@@ -683,7 +664,7 @@
 
 	set_blocksize(dev, bs);
 
-	lo->lo_bh = lo->lo_bhtail = NULL;
+	lo->lo_bio = lo->lo_biotail = NULL;
 	kernel_thread(loop_thread, lo, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 	down(&lo->lo_sem);
 
@@ -873,7 +854,7 @@
 			err = -ENXIO;
 			break;
 		}
-		err = put_user((unsigned long)loop_sizes[lo->lo_number] << 1, (unsigned long *) arg);
+		err = put_user((unsigned long) loop_sizes[lo->lo_number] << 1, (unsigned long *) arg);
 		break;
 	case BLKGETSIZE64:
 		if (lo->lo_state != Lo_bound) {
@@ -1019,11 +1000,11 @@
 
 	loop_sizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL);
 	if (!loop_sizes)
-		goto out_sizes;
+		goto out_mem;
 
 	loop_blksizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL);
 	if (!loop_blksizes)
-		goto out_blksizes;
+		goto out_mem;
 
 	blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), loop_make_request);
 
@@ -1047,9 +1028,8 @@
 	printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
 	return 0;
 
-out_sizes:
+out_mem:
 	kfree(loop_dev);
-out_blksizes:
 	kfree(loop_sizes);
 	printk(KERN_ERR "loop: ran out of memory\n");
 	return -ENOMEM;
diff -u --recursive --new-file v2.5.0/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.5.0/linux/drivers/block/nbd.c	Fri Oct 26 15:39:02 2001
+++ linux/drivers/block/nbd.c	Sat Dec  8 20:02:47 2001
@@ -149,30 +149,41 @@
 
 void nbd_send_req(struct socket *sock, struct request *req)
 {
-	int result;
+	int result, rw, i, flags;
 	struct nbd_request request;
 	unsigned long size = req->nr_sectors << 9;
 
 	DEBUG("NBD: sending control, ");
 	request.magic = htonl(NBD_REQUEST_MAGIC);
-	request.type = htonl(req->cmd);
+	request.type = htonl(req->flags);
 	request.from = cpu_to_be64( (u64) req->sector << 9);
 	request.len = htonl(size);
 	memcpy(request.handle, &req, sizeof(req));
 
-	result = nbd_xmit(1, sock, (char *) &request, sizeof(request), req->cmd == WRITE ? MSG_MORE : 0);
+	rw = rq_data_dir(req);
+
+	result = nbd_xmit(1, sock, (char *) &request, sizeof(request), rw & WRITE ? MSG_MORE : 0);
 	if (result <= 0)
 		FAIL("Sendmsg failed for control.");
 
-	if (req->cmd == WRITE) {
-		struct buffer_head *bh = req->bh;
-		DEBUG("data, ");
-		do {
-			result = nbd_xmit(1, sock, bh->b_data, bh->b_size, bh->b_reqnext == NULL ? 0 : MSG_MORE);
-			if (result <= 0)
-				FAIL("Send data failed.");
-			bh = bh->b_reqnext;
-		} while(bh);
+	if (rw & WRITE) {
+		struct bio *bio;
+		/*
+		 * we are really probing at internals to determine
+		 * whether to set MSG_MORE or not...
+		 */
+		rq_for_each_bio(bio, req) {
+			struct bio_vec *bvec;
+			bio_for_each_segment(bvec, bio, i) {
+				flags = 0;
+				if ((i < (bio->bi_vcnt - 1)) || bio->bi_next)
+					flags = MSG_MORE;
+				DEBUG("data, ");
+				result = nbd_xmit(1, sock, page_address(bvec->bv_page) + bvec->bv_offset, bvec->bv_len, flags);
+				if (result <= 0)
+					FAIL("Send data failed.");
+			}
+		}
 	}
 	return;
 
@@ -204,15 +215,15 @@
 		HARDFAIL("Not enough magic.");
 	if (ntohl(reply.error))
 		FAIL("Other side returned error.");
-	if (req->cmd == READ) {
-		struct buffer_head *bh = req->bh;
+	if (rq_data_dir(req) == READ) {
+		struct bio *bio = req->bio;
 		DEBUG("data, ");
 		do {
-			result = nbd_xmit(0, lo->sock, bh->b_data, bh->b_size, MSG_WAITALL);
+			result = nbd_xmit(0, lo->sock, bio_data(bio), bio->bi_size, MSG_WAITALL);
 			if (result <= 0)
 				HARDFAIL("Recv data failed.");
-			bh = bh->b_reqnext;
-		} while(bh);
+			bio = bio->bi_next;
+		} while(bio);
 	}
 	DEBUG("done.\n");
 	return req;
@@ -250,7 +261,7 @@
 			goto out;
 		}
 #endif
-		list_del(&req->queue);
+		blkdev_dequeue_request(req);
 		up (&lo->queue_lock);
 		
 		nbd_end_request(req);
@@ -285,7 +296,7 @@
 		}
 #endif
 		req->errors++;
-		list_del(&req->queue);
+		blkdev_dequeue_request(req);
 		up(&lo->queue_lock);
 
 		nbd_end_request(req);
@@ -321,10 +332,13 @@
 		if (dev >= MAX_NBD)
 			FAIL("Minor too big.");		/* Probably can not happen */
 #endif
+		if (!(req->flags & REQ_CMD))
+			goto error_out;
+
 		lo = &nbd_dev[dev];
 		if (!lo->file)
 			FAIL("Request when not-ready.");
-		if ((req->cmd == WRITE) && (lo->flags & NBD_READ_ONLY))
+		if ((rq_data_dir(req) == WRITE) && (lo->flags & NBD_READ_ONLY))
 			FAIL("Write on read-only");
 #ifdef PARANOIA
 		if (lo->magic != LO_MAGIC)
@@ -333,22 +347,22 @@
 #endif
 		req->errors = 0;
 		blkdev_dequeue_request(req);
-		spin_unlock_irq(&io_request_lock);
+		spin_unlock_irq(&q->queue_lock);
 
 		down (&lo->queue_lock);
-		list_add(&req->queue, &lo->queue_head);
+		list_add(&req->queuelist, &lo->queue_head);
 		nbd_send_req(lo->sock, req);	/* Why does this block?         */
 		up (&lo->queue_lock);
 
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&q->queue_lock);
 		continue;
 
 	      error_out:
 		req->errors++;
 		blkdev_dequeue_request(req);
-		spin_unlock(&io_request_lock);
+		spin_unlock(&q->queue_lock);
 		nbd_end_request(req);
-		spin_lock(&io_request_lock);
+		spin_lock(&q->queue_lock);
 	}
 	return;
 }
@@ -374,7 +388,7 @@
 	switch (cmd) {
 	case NBD_DISCONNECT:
 	        printk("NBD_DISCONNECT\n") ;
-                sreq.cmd=2 ; /* shutdown command */
+		sreq.flags = REQ_SPECIAL; /* FIXME: interpet as shutdown cmd */
                 if (!lo->sock) return -EINVAL ;
                 nbd_send_req(lo->sock,&sreq) ;
                 return 0 ;
@@ -502,7 +516,6 @@
 	blksize_size[MAJOR_NR] = nbd_blksizes;
 	blk_size[MAJOR_NR] = nbd_sizes;
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
-	blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
 	for (i = 0; i < MAX_NBD; i++) {
 		nbd_dev[i].refcnt = 0;
 		nbd_dev[i].file = NULL;
diff -u --recursive --new-file v2.5.0/linux/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c
--- v2.5.0/linux/drivers/block/paride/pcd.c	Sat Oct 27 02:03:47 2001
+++ linux/drivers/block/paride/pcd.c	Thu Dec  6 14:02:56 2001
@@ -768,7 +768,7 @@
         while (1) {
 	    if (QUEUE_EMPTY || (CURRENT->rq_status == RQ_INACTIVE)) return;
 	    INIT_REQUEST;
-	    if (CURRENT->cmd == READ) {
+	    if (rq_data_dir(CURRENT) == READ) {
 		unit = MINOR(CURRENT->rq_dev);
 		if (unit != pcd_unit) {
 			pcd_bufblk = -1;
@@ -821,11 +821,11 @@
 
 	if (pcd_command(unit,rd_cmd,2048,"read block")) {
 		pcd_bufblk = -1; 
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
 		pcd_busy = 0;
 		end_request(0);
 		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 		return;
 	}
 
@@ -845,11 +845,11 @@
 	pcd_retries = 0;
 	pcd_transfer();
 	if (!pcd_count) {
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
 		end_request(1);
 		pcd_busy = 0;
 		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 		return;
 	}
 
@@ -868,19 +868,19 @@
 			pi_do_claimed(PI,pcd_start);
                         return;
                         }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
 		pcd_busy = 0;
 		pcd_bufblk = -1;
 		end_request(0);
 		do_pcd_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 		return;
 	}
 
 	do_pcd_read();
-	spin_lock_irqsave(&io_request_lock,saved_flags);
+	spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
 	do_pcd_request(NULL);
-	spin_unlock_irqrestore(&io_request_lock,saved_flags); 
+	spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags); 
 }
 
 /* the audio_ioctl stuff is adapted from sr_ioctl.c */
diff -u --recursive --new-file v2.5.0/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.5.0/linux/drivers/block/paride/pd.c	Fri Nov  9 13:58:03 2001
+++ linux/drivers/block/paride/pd.c	Thu Dec  6 14:02:56 2001
@@ -287,7 +287,6 @@
 static struct hd_struct pd_hd[PD_DEVS];
 static int pd_sizes[PD_DEVS];
 static int pd_blocksizes[PD_DEVS];
-static int pd_maxsectors[PD_DEVS];
 
 #define PD_NAMELEN	8
 
@@ -330,7 +329,6 @@
 static int pd_cmd;			/* current command READ/WRITE */
 static int pd_unit;			/* unit of current request */
 static int pd_dev;			/* minor of current request */
-static int pd_poffs;			/* partition offset of current minor */
 static char * pd_buf;                   /* buffer for request in progress */
 
 static DECLARE_WAIT_QUEUE_HEAD(pd_wait_open);
@@ -397,6 +395,7 @@
         }
 	q = BLK_DEFAULT_QUEUE(MAJOR_NR);
 	blk_init_queue(q, DEVICE_REQUEST);
+	blk_queue_max_sectors(q, cluster);
         read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read ahead */
         
 	pd_gendisk.major = major;
@@ -406,9 +405,6 @@
 	for(i=0;i<PD_DEVS;i++) pd_blocksizes[i] = 1024;
 	blksize_size[MAJOR_NR] = pd_blocksizes;
 
-	for(i=0;i<PD_DEVS;i++) pd_maxsectors[i] = cluster;
-	max_sectors[MAJOR_NR] = pd_maxsectors;
-
 	printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
 		name,name,PD_VERSION,major,cluster,nice);
 	pd_init_units();
@@ -444,41 +440,41 @@
 
 static int pd_ioctl(struct inode *inode,struct file *file,
                     unsigned int cmd, unsigned long arg)
+{
+	struct hd_geometry *geo = (struct hd_geometry *) arg;
+	int err, unit;
 
-{       struct hd_geometry *geo = (struct hd_geometry *) arg;
-        int dev, err, unit;
-
-        if ((!inode) || (!inode->i_rdev)) return -EINVAL;
-        dev = MINOR(inode->i_rdev);
+	if (!inode || !inode->i_rdev)
+		return -EINVAL;
 	unit = DEVICE_NR(inode->i_rdev);
-        if (dev >= PD_DEVS) return -EINVAL;
-	if (!PD.present) return -ENODEV;
+	if (!PD.present)
+		return -ENODEV;
 
-        switch (cmd) {
+	switch (cmd) {
 	    case CDROMEJECT:
 		if (PD.access == 1) pd_eject(unit);
 		return 0;
-            case HDIO_GETGEO:
-                if (!geo) return -EINVAL;
-                err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
-                if (err) return err;
+	    case HDIO_GETGEO:
+		if (!geo) return -EINVAL;
+		err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
+		if (err) return err;
 
 		if (PD.alt_geom) {
-                    put_user(PD.capacity/(PD_LOG_HEADS*PD_LOG_SECTS), 
+		    put_user(PD.capacity/(PD_LOG_HEADS*PD_LOG_SECTS), 
 		    		(short *) &geo->cylinders);
-                    put_user(PD_LOG_HEADS, (char *) &geo->heads);
-                    put_user(PD_LOG_SECTS, (char *) &geo->sectors);
+		    put_user(PD_LOG_HEADS, (char *) &geo->heads);
+		    put_user(PD_LOG_SECTS, (char *) &geo->sectors);
 		} else {
-                    put_user(PD.cylinders, (short *) &geo->cylinders);
-                    put_user(PD.heads, (char *) &geo->heads);
-                    put_user(PD.sectors, (char *) &geo->sectors);
+		    put_user(PD.cylinders, (short *) &geo->cylinders);
+		    put_user(PD.heads, (char *) &geo->heads);
+		    put_user(PD.sectors, (char *) &geo->sectors);
 		}
-                put_user(pd_hd[dev].start_sect,(long *)&geo->start);
-                return 0;
-            case BLKRRPART:
+		put_user(get_start_sect(inode->i_rdev), (long *)&geo->start);
+		return 0;
+	    case BLKRRPART:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-                return pd_revalidate(inode->i_rdev);
+		return pd_revalidate(inode->i_rdev);
 	    case BLKGETSIZE:
 	    case BLKGETSIZE64:
 	    case BLKROSET:
@@ -488,9 +484,9 @@
 	    case BLKFLSBUF:
 	    case BLKPG:
 		return blk_ioctl(inode->i_rdev, cmd, arg);
-            default:
-                return -EINVAL;
-        }
+	    default:
+		return -EINVAL;
+	}
 }
 
 static int pd_release (struct inode *inode, struct file *file)
@@ -526,36 +522,32 @@
 }
 
 static int pd_revalidate(kdev_t dev)
+{
+	int unit, res;
+	long flags;
 
-{       int p, unit, minor;
-        long flags;
-
-        unit = DEVICE_NR(dev);
-        if ((unit >= PD_UNITS) || (!PD.present)) return -ENODEV;
+	unit = DEVICE_NR(dev);
+	if ((unit >= PD_UNITS) || !PD.present)
+		return -ENODEV;
 
-        save_flags(flags);
-        cli(); 
-        if (PD.access > 1) {
-                restore_flags(flags);
-                return -EBUSY;
-        }
-        pd_valid = 0;
-        restore_flags(flags);   
-
-        for (p=(PD_PARTNS-1);p>=0;p--) {
-		minor = p + unit*PD_PARTNS;
-                invalidate_device(MKDEV(MAJOR_NR, minor), 1);
-                pd_hd[minor].start_sect = 0;
-                pd_hd[minor].nr_sects = 0;
-        }
+	save_flags(flags);
+	cli(); 
+	if (PD.access > 1) {
+		restore_flags(flags);
+		return -EBUSY;
+	}
+	pd_valid = 0;
+	restore_flags(flags);   
 
-	if (pd_identify(unit))
-		grok_partitions(&pd_gendisk,unit,1<<PD_BITS,PD.capacity);
+	res = wipe_partitions(dev);
 
-        pd_valid = 1;
-        wake_up(&pd_wait_open);
+	if (res == 0 && pd_identify(unit))
+		grok_partitions(dev, PD.capacity);
 
-        return 0;
+	pd_valid = 1;
+	wake_up(&pd_wait_open);
+ 
+        return res;
 }
 
 #ifdef MODULE
@@ -580,15 +572,13 @@
 {
 	int unit;
 
-        devfs_unregister_blkdev(MAJOR_NR,name);
+	devfs_unregister_blkdev(MAJOR_NR, name);
 	del_gendisk(&pd_gendisk);
 
-	for (unit=0;unit<PD_UNITS;unit++) 
-	   if (PD.present) pi_release(PI);
-
-	max_sectors[MAJOR_NR] = NULL;
+	for (unit=0; unit<PD_UNITS; unit++) 
+		if (PD.present)
+			pi_release(PI);
 }
-
 #endif
 
 #define	WR(c,r,v)	pi_write_regr(PI,c,r,v)
@@ -848,8 +838,7 @@
 }
 
 static void do_pd_request (request_queue_t * q)
-
-{       struct buffer_head * bh;
+{
 	int	unit;
 
         if (pd_busy) return;
@@ -863,17 +852,13 @@
         pd_run = CURRENT->nr_sectors;
         pd_count = CURRENT->current_nr_sectors;
 
-	bh = CURRENT->bh;
-
         if ((pd_dev >= PD_DEVS) || 
 	    ((pd_block+pd_count) > pd_hd[pd_dev].nr_sects)) {
                 end_request(0);
                 goto repeat;
         }
 
-	pd_cmd = CURRENT->cmd;
-	pd_poffs = pd_hd[pd_dev].start_sect;
-        pd_block += pd_poffs;
+	pd_cmd = rq_data_dir(CURRENT);
         pd_buf = CURRENT->buffer;
         pd_retries = 0;
 
@@ -890,25 +875,25 @@
 
 {	long	saved_flags;
 
-	spin_lock_irqsave(&io_request_lock,saved_flags);
+	spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
 	end_request(1);
-	if (!pd_run) {  spin_unlock_irqrestore(&io_request_lock,saved_flags);
+	if (!pd_run) {  spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 			return; 
 	}
 	
 /* paranoia */
 
 	if (QUEUE_EMPTY ||
-	    (CURRENT->cmd != pd_cmd) ||
+	    (rq_data_dir(CURRENT) != pd_cmd) ||
 	    (MINOR(CURRENT->rq_dev) != pd_dev) ||
 	    (CURRENT->rq_status == RQ_INACTIVE) ||
-	    (CURRENT->sector+pd_poffs != pd_block)) 
+	    (CURRENT->sector != pd_block)) 
 		printk("%s: OUCH: request list changed unexpectedly\n",
 			PD.name);
 
 	pd_count = CURRENT->current_nr_sectors;
 	pd_buf = CURRENT->buffer;
-	spin_unlock_irqrestore(&io_request_lock,saved_flags);
+	spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 }
 
 static void do_pd_read( void )
@@ -931,11 +916,11 @@
                         pi_do_claimed(PI,do_pd_read_start);
 			return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pd_busy = 0;
 		do_pd_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
         }
         pd_ide_command(unit,IDE_READ,pd_block,pd_run);
@@ -955,11 +940,11 @@
                         pi_do_claimed(PI,do_pd_read_start);
                         return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pd_busy = 0;
 		do_pd_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
             }
             pi_read_block(PI,pd_buf,512);
@@ -970,11 +955,11 @@
 	    if (!pd_count) pd_next_buf(unit);
         }
         pi_disconnect(PI);
-	spin_lock_irqsave(&io_request_lock,saved_flags);
+	spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
         end_request(1);
         pd_busy = 0;
 	do_pd_request(NULL);
-	spin_unlock_irqrestore(&io_request_lock,saved_flags);
+	spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 }
 
 static void do_pd_write( void )
@@ -997,11 +982,11 @@
 			pi_do_claimed(PI,do_pd_write_start);
                         return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pd_busy = 0;
 		do_pd_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
         }
         pd_ide_command(unit,IDE_WRITE,pd_block,pd_run);
@@ -1013,11 +998,11 @@
                         pi_do_claimed(PI,do_pd_write_start);
                         return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pd_busy = 0;
 		do_pd_request(NULL);
-                spin_unlock_irqrestore(&io_request_lock,saved_flags);
+                spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 		return;
             }
             pi_write_block(PI,pd_buf,512);
@@ -1042,19 +1027,19 @@
                         pi_do_claimed(PI,do_pd_write_start);
                         return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pd_busy = 0;
 		do_pd_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
         }
         pi_disconnect(PI);
-	spin_lock_irqsave(&io_request_lock,saved_flags);
+	spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
         end_request(1);
         pd_busy = 0;
 	do_pd_request(NULL);
-	spin_unlock_irqrestore(&io_request_lock,saved_flags);
+	spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 }
 
 /* end of pd.c */
diff -u --recursive --new-file v2.5.0/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- v2.5.0/linux/drivers/block/paride/pf.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/block/paride/pf.c	Thu Dec  6 14:02:56 2001
@@ -340,56 +340,6 @@
         }
 } 
 
-static inline int pf_new_segment(request_queue_t *q, struct request *req, int max_segments)
-{
-	if (max_segments > cluster)
-		max_segments = cluster;
-
-	if (req->nr_segments < max_segments) {
-		req->nr_segments++;
-		return 1;
-	}
-	return 0;
-}
-
-static int pf_back_merge_fn(request_queue_t *q, struct request *req, 
-			    struct buffer_head *bh, int max_segments)
-{
-	if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data)
-		return 1;
-	return pf_new_segment(q, req, max_segments);
-}
-
-static int pf_front_merge_fn(request_queue_t *q, struct request *req, 
-			     struct buffer_head *bh, int max_segments)
-{
-	if (bh->b_data + bh->b_size == req->bh->b_data)
-		return 1;
-	return pf_new_segment(q, req, max_segments);
-}
-
-static int pf_merge_requests_fn(request_queue_t *q, struct request *req,
-				struct request *next, int max_segments)
-{
-	int total_segments = req->nr_segments + next->nr_segments;
-	int same_segment;
-
-	if (max_segments > cluster)
-		max_segments = cluster;
-
-	same_segment = 0;
-	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) {
-		total_segments--;
-		same_segment = 1;
-	}
-    
-	if (total_segments > max_segments)
-		return 0;
-
-	req->nr_segments = total_segments;
-	return 1;
-}
-
 int pf_init (void)      /* preliminary initialisation */
 
 {       int i;
@@ -409,9 +359,7 @@
         }
 	q = BLK_DEFAULT_QUEUE(MAJOR_NR);
 	blk_init_queue(q, DEVICE_REQUEST);
-	q->back_merge_fn = pf_back_merge_fn;
-	q->front_merge_fn = pf_front_merge_fn;
-	q->merge_requests_fn = pf_merge_requests_fn;
+	blk_queue_max_segments(q, cluster);
         read_ahead[MAJOR_NR] = 8;       /* 8 sector (4kB) read ahead */
         
 	for (i=0;i<PF_UNITS;i++) pf_blocksizes[i] = 1024;
@@ -458,7 +406,7 @@
 		if (PF.access == 1) {
 			pf_eject(unit);
 			return 0;
-			}
+		}
 	    case HDIO_GETGEO:
                 if (!geo) return -EINVAL;
                 err = verify_area(VERIFY_WRITE,geo,sizeof(*geo));
@@ -893,8 +841,7 @@
 }
 
 static void do_pf_request (request_queue_t * q)
-
-{       struct buffer_head * bh;
+{
 	int unit;
 
         if (pf_busy) return;
@@ -907,14 +854,12 @@
         pf_run = CURRENT->nr_sectors;
         pf_count = CURRENT->current_nr_sectors;
 
-	bh = CURRENT->bh;
-
         if ((pf_unit >= PF_UNITS) || (pf_block+pf_count > PF.capacity)) {
                 end_request(0);
                 goto repeat;
         }
 
-	pf_cmd = CURRENT->cmd;
+	pf_cmd = rq_data_dir(CURRENT);
         pf_buf = CURRENT->buffer;
         pf_retries = 0;
 
@@ -931,16 +876,16 @@
 
 {	long	saved_flags;
 
-	spin_lock_irqsave(&io_request_lock,saved_flags);
+	spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
 	end_request(1);
-	if (!pf_run) { spin_unlock_irqrestore(&io_request_lock,saved_flags);
+	if (!pf_run) { spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 		       return; 
 	}
 	
 /* paranoia */
 
 	if (QUEUE_EMPTY ||
-	    (CURRENT->cmd != pf_cmd) ||
+	    (rq_data_dir(CURRENT) != pf_cmd) ||
 	    (DEVICE_NR(CURRENT->rq_dev) != pf_unit) ||
 	    (CURRENT->rq_status == RQ_INACTIVE) ||
 	    (CURRENT->sector != pf_block)) 
@@ -949,7 +894,7 @@
 
 	pf_count = CURRENT->current_nr_sectors;
 	pf_buf = CURRENT->buffer;
-	spin_unlock_irqrestore(&io_request_lock,saved_flags);
+	spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 }
 
 static void do_pf_read( void )
@@ -973,11 +918,11 @@
                         pi_do_claimed(PI,do_pf_read_start);
 			return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pf_busy = 0;
 		do_pf_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
         }
 	pf_mask = STAT_DRQ;
@@ -999,11 +944,11 @@
                         pi_do_claimed(PI,do_pf_read_start);
                         return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pf_busy = 0;
 		do_pf_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
             }
             pi_read_block(PI,pf_buf,512);
@@ -1014,11 +959,11 @@
 	    if (!pf_count) pf_next_buf(unit);
         }
         pi_disconnect(PI);
-	spin_lock_irqsave(&io_request_lock,saved_flags); 
+	spin_lock_irqsave(&QUEUE->queue_lock,saved_flags); 
         end_request(1);
         pf_busy = 0;
 	do_pf_request(NULL);
-	spin_unlock_irqrestore(&io_request_lock,saved_flags);
+	spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 }
 
 static void do_pf_write( void )
@@ -1040,11 +985,11 @@
                         pi_do_claimed(PI,do_pf_write_start);
 			return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pf_busy = 0;
 		do_pf_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
         }
 
@@ -1057,11 +1002,11 @@
                         pi_do_claimed(PI,do_pf_write_start);
                         return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pf_busy = 0;
 		do_pf_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
             }
             pi_write_block(PI,pf_buf,512);
@@ -1087,19 +1032,19 @@
 			pi_do_claimed(PI,do_pf_write_start);
                         return;
                 }
-		spin_lock_irqsave(&io_request_lock,saved_flags);
+		spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
                 end_request(0);
                 pf_busy = 0;
 		do_pf_request(NULL);
-		spin_unlock_irqrestore(&io_request_lock,saved_flags);
+		spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
                 return;
         }
         pi_disconnect(PI);
-	spin_lock_irqsave(&io_request_lock,saved_flags);
+	spin_lock_irqsave(&QUEUE->queue_lock,saved_flags);
         end_request(1);
         pf_busy = 0;
 	do_pf_request(NULL);
-	spin_unlock_irqrestore(&io_request_lock,saved_flags);
+	spin_unlock_irqrestore(&QUEUE->queue_lock,saved_flags);
 }
 
 /* end of pf.c */
diff -u --recursive --new-file v2.5.0/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c
--- v2.5.0/linux/drivers/block/paride/pg.c	Thu Oct 11 09:04:57 2001
+++ linux/drivers/block/paride/pg.c	Fri Nov 30 08:26:04 2001
@@ -276,7 +276,7 @@
 	pg_drive_count = 0;
 	for (unit=0;unit<PG_UNITS;unit++) {
 		PG.pi = & PG.pia;
-		PG.access = 0;
+		set_bit( 0, &PG.access );
 		PG.busy = 0;
 		PG.present = 0;
 		PG.bufptr = NULL;
@@ -573,10 +573,7 @@
 
 	if ((unit >= PG_UNITS) || (!PG.present)) return -ENODEV;
 
-	PG.access++;
-
-	if (PG.access > 1) {
-		PG.access--;
+	if ( test_and_set_bit(0, &PG.access) ) {
 		return -EBUSY;
 	}
 
@@ -590,7 +587,7 @@
 
 	PG.bufptr = kmalloc(PG_MAX_DATA,GFP_KERNEL);
 	if (PG.bufptr == NULL) {
-		PG.access--;
+		clear_bit( 0, &PG.access ) ;
 		printk("%s: buffer allocation failed\n",PG.name);
 		return -ENOMEM;
 	}
@@ -602,15 +599,13 @@
 {
 	int	unit = DEVICE_NR(inode->i_rdev);
 
-	if ((unit >= PG_UNITS) || (PG.access <= 0)) 
+	if ( unit >= PG_UNITS || !test_bit(0,&PG.access) )
 		return -EINVAL;
 
-	lock_kernel();
-	PG.access--;
+	clear_bit( 0, &PG.access);
 
 	kfree(PG.bufptr);
 	PG.bufptr = NULL;
-	unlock_kernel();
 
 	return 0;
 
diff -u --recursive --new-file v2.5.0/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c
--- v2.5.0/linux/drivers/block/paride/pt.c	Thu Oct 11 09:04:57 2001
+++ linux/drivers/block/paride/pt.c	Fri Nov 30 08:26:04 2001
@@ -244,7 +244,7 @@
 	int flags;        	  /* various state flags */
 	int last_sense;		  /* result of last request sense */
 	int drive;		  /* drive */
-	int access;               /* count of active opens ... */
+	atomic_t available;       /* 1 if access is available 0 otherwise */
 	int bs;			  /* block size */
 	int capacity;             /* Size of tape in KB */
 	int present;		  /* device present ? */
@@ -279,7 +279,7 @@
         pt_drive_count = 0;
         for (unit=0;unit<PT_UNITS;unit++) {
                 PT.pi = & PT.pia;
-                PT.access = 0;
+                atomic_set( &PT.available, 1 );
                 PT.flags = 0;
 		PT.last_sense = 0;
                 PT.present = 0;
@@ -696,22 +696,20 @@
 
         if ((unit >= PT_UNITS) || (!PT.present)) return -ENODEV;
 
-        PT.access++;
-
-	if (PT.access > 1) {
-		PT.access--;
+	if ( !atomic_dec_and_test(&PT.available) ) {
+		atomic_inc( &PT.available );
 		return -EBUSY;
 	}
 
 	pt_identify(unit);
 
 	if (!PT.flags & PT_MEDIA) {
-		PT.access--;
+		atomic_inc( &PT.available );
 		return -ENODEV;
 		}
 
 	if ((!PT.flags & PT_WRITE_OK) && (file ->f_mode & 2)) {
-		PT.access--;
+		atomic_inc( &PT.available );
 		return -EROFS;
 		}
 
@@ -720,7 +718,7 @@
 
 	PT.bufptr = kmalloc(PT_BUFSIZE,GFP_KERNEL);
 	if (PT.bufptr == NULL) {
-		PT.access--;
+		atomic_inc( &PT.available );
 		printk("%s: buffer allocation failed\n",PT.name);
 		return -ENOMEM;
 	}
@@ -775,20 +773,18 @@
 {
         int	unit = DEVICE_NR(inode->i_rdev);
 
-        if ((unit >= PT_UNITS) || (PT.access <= 0)) 
+        if ((unit >= PT_UNITS) || (atomic_read(&PT.available) > 1)) 
                 return -EINVAL;
 
-	lock_kernel();
 	if (PT.flags & PT_WRITING) pt_write_fm(unit);
 
 	if (PT.flags & PT_REWIND) pt_rewind(unit);	
 
-	PT.access--;
-
 	kfree(PT.bufptr);
 	PT.bufptr = NULL;
-	unlock_kernel();
 
+	atomic_inc( &PT.available );
+	
 	return 0;
 
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.5.0/linux/drivers/block/ps2esdi.c	Fri Nov  9 14:01:21 2001
+++ linux/drivers/block/ps2esdi.c	Mon Dec 10 14:15:19 2001
@@ -66,6 +66,7 @@
 #define TYPE_0_CMD_BLK_LENGTH 2
 #define TYPE_1_CMD_BLK_LENGTH 4
 
+#define PS2ESDI_LOCK (&((BLK_DEFAULT_QUEUE(MAJOR_NR))->queue_lock))
 
 static void reset_ctrl(void);
 
@@ -118,7 +119,6 @@
 static char ps2esdi_valid[MAX_HD];
 static int ps2esdi_sizes[MAX_HD << 6];
 static int ps2esdi_blocksizes[MAX_HD << 6];
-static int ps2esdi_maxsect[MAX_HD << 6];
 static int ps2esdi_drives;
 static struct hd_struct ps2esdi[MAX_HD << 6];
 static u_short io_base;
@@ -221,8 +221,7 @@
 }
 
 void
-cleanup_module(void)
-{
+cleanup_module(void) {
 	if(ps2esdi_slot) {
 		mca_mark_as_unused(ps2esdi_slot);
 		mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL);
@@ -231,8 +230,9 @@
 	free_dma(dma_arb_level);
   	free_irq(PS2ESDI_IRQ, NULL);
 	devfs_unregister_blkdev(MAJOR_NR, "ed");
-	del_gendisk(&ps2esdi_gendisk);
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	del_gendisk(&ps2esdi_gendisk);
+	blk_clear(MAJOR_NR);
 }
 #endif /* MODULE */
 
@@ -415,16 +415,13 @@
 
 	ps2esdi_gendisk.nr_real = ps2esdi_drives;
 
-	/* 128 was old default, maybe maxsect=255 is ok too? - Paul G. */
-	for (i = 0; i < (MAX_HD << 6); i++) {
-		ps2esdi_maxsect[i] = 128;
+	for (i = 0; i < (MAX_HD << 6); i++)
 		ps2esdi_blocksizes[i] = 1024;
-	}
 
 	request_dma(dma_arb_level, "ed");
 	request_region(io_base, 4, "ed");
 	blksize_size[MAJOR_NR] = ps2esdi_blocksizes;
-	max_sectors[MAJOR_NR] = ps2esdi_maxsect;
+	blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 128);
 
 	for (i = 0; i < ps2esdi_drives; i++) {
 		register_disk(&ps2esdi_gendisk,MKDEV(MAJOR_NR,i<<6),1<<6,
@@ -486,7 +483,8 @@
 	}			/* check for above 16Mb dmas */
 	else if ((CURRENT_DEV < ps2esdi_drives) &&
 	    (CURRENT->sector + CURRENT->current_nr_sectors <=
-	     ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects)) {
+	     ps2esdi[MINOR(CURRENT->rq_dev)].nr_sects) &&
+	    	CURRENT->flags & REQ_CMD) {
 #if 0
 		printk("%s:got request. device : %d minor : %d command : %d  sector : %ld count : %ld\n",
 		       DEVICE_NAME,
@@ -495,14 +493,10 @@
 		       CURRENT->current_nr_sectors);
 #endif
 
-
-		block = CURRENT->sector + ps2esdi[MINOR(CURRENT->rq_dev)].start_sect;
-
-#if 0
-		printk("%s: blocknumber : %d\n", DEVICE_NAME, block);
-#endif
+		block = CURRENT->sector;
 		count = CURRENT->current_nr_sectors;
-		switch (CURRENT->cmd) {
+
+		switch (rq_data_dir(CURRENT)) {
 		case READ:
 			ps2esdi_readwrite(READ, CURRENT_DEV, block, count);
 			break;
@@ -958,10 +952,10 @@
 		break;
 	}
 	if(ending != -1) {
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(PS2ESDI_LOCK, flags);
 		end_request(ending);
 		do_ps2esdi_request(BLK_DEFAULT_QUEUE(MAJOR_NR));
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(PS2ESDI_LOCK, flags);
 	}
 }				/* handle interrupts */
 
@@ -1100,10 +1094,10 @@
 				put_user(ps2esdi_info[dev].head, (char *) &geometry->heads);
 				put_user(ps2esdi_info[dev].sect, (char *) &geometry->sectors);
 				put_user(ps2esdi_info[dev].cyl, (short *) &geometry->cylinders);
-				put_user(ps2esdi[MINOR(inode->i_rdev)].start_sect,
+				put_user(get_start_sect(inode->i_rdev),
 					    (long *) &geometry->start);
 
-				return (0);
+				return 0;
 			}
 			break;
 
@@ -1132,8 +1126,7 @@
 static int ps2esdi_reread_partitions(kdev_t dev)
 {
 	int target = DEVICE_NR(dev);
-	int start = target << ps2esdi_gendisk.minor_shift;
-	int partition;
+	int res;
 
 	cli();
 	ps2esdi_valid[target] = (access_count[target] != 1);
@@ -1141,21 +1134,16 @@
 	if (ps2esdi_valid[target])
 		return (-EBUSY);
 
-	for (partition = ps2esdi_gendisk.max_p - 1;
-	     partition >= 0; partition--) {
-		int minor = (start | partition);
-		invalidate_device(MKDEV(MAJOR_NR, minor), 1);
-		ps2esdi_gendisk.part[minor].start_sect = 0;
-		ps2esdi_gendisk.part[minor].nr_sects = 0;
-	}
-
-	grok_partitions(&ps2esdi_gendisk, target, 1<<6, 
-		ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect);
-
+	res = wipe_partitions(dev);
+	if (res == 0)
+		grok_partitions(dev, ps2esdi_info[target].head
+				* ps2esdi_info[target].cyl
+				* ps2esdi_info[target].sect);
+ 
 	ps2esdi_valid[target] = 1;
 	wake_up(&ps2esdi_wait_open);
 
-	return (0);
+	return (res);
 }
 
 static void ps2esdi_reset_timer(unsigned long unused)
diff -u --recursive --new-file v2.5.0/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.5.0/linux/drivers/block/rd.c	Fri Nov  9 14:15:00 2001
+++ linux/drivers/block/rd.c	Thu Dec  6 14:02:56 2001
@@ -89,6 +89,7 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 static int initrd_users;
+static spinlock_t initrd_users_lock = SPIN_LOCK_UNLOCKED;
 #endif
 #endif
 
@@ -98,7 +99,7 @@
 static unsigned long rd_length[NUM_RAMDISKS];	/* Size of RAM disks in bytes   */
 static int rd_hardsec[NUM_RAMDISKS];		/* Size of real blocks in bytes */
 static int rd_blocksizes[NUM_RAMDISKS];		/* Size of 1024 byte blocks :)  */
-static int rd_kbsize[NUM_RAMDISKS];		/* Size in blocks of 1024 bytes */
+static int rd_kbsize[NUM_RAMDISKS];	/* Size in blocks of 1024 bytes */
 static devfs_handle_t devfs_handle;
 static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */
 
@@ -227,19 +228,19 @@
 	commit_write: ramdisk_commit_write,
 };
 
-static int rd_blkdev_pagecache_IO(int rw, struct buffer_head * sbh, int minor)
+static int rd_blkdev_pagecache_IO(int rw, struct bio_vec *vec,
+				  sector_t sector, int minor)
 {
 	struct address_space * mapping;
 	unsigned long index;
 	int offset, size, err;
 
-	err = -EIO;
 	err = 0;
 	mapping = rd_bdev[minor]->bd_inode->i_mapping;
 
-	index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9);
-	offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK;
-	size = sbh->b_size;
+	index = sector >> (PAGE_CACHE_SHIFT - 9);
+	offset = (sector << 9) & ~PAGE_CACHE_MASK;
+	size = vec->bv_len;
 
 	do {
 		int count;
@@ -276,18 +277,18 @@
 		if (rw == READ) {
 			src = kmap(page);
 			src += offset;
-			dst = bh_kmap(sbh);
+			dst = kmap(vec->bv_page) + vec->bv_offset;
 		} else {
 			dst = kmap(page);
 			dst += offset;
-			src = bh_kmap(sbh);
+			src = kmap(vec->bv_page) + vec->bv_offset;
 		}
 		offset = 0;
 
 		memcpy(dst, src, count);
 
 		kunmap(page);
-		bh_kunmap(sbh);
+		kunmap(vec->bv_page);
 
 		if (rw == READ) {
 			flush_dcache_page(page);
@@ -303,6 +304,22 @@
 	return err;
 }
 
+static int rd_blkdev_bio_IO(struct bio *bio, unsigned int minor)
+{
+	struct bio_vec *bvec;
+	sector_t sector;
+	int ret = 0, i, rw;
+
+	sector = bio->bi_sector;
+	rw = bio_data_dir(bio);
+	bio_for_each_segment(bvec, bio, i) {
+		ret |= rd_blkdev_pagecache_IO(rw, bvec, sector, minor);
+		sector += bvec->bv_len >> 9;
+	}
+
+	return ret;
+}
+
 /*
  *  Basically, my strategy here is to set up a buffer-head which can't be
  *  deleted, and make that my Ramdisk.  If the request is outside of the
@@ -311,19 +328,19 @@
  * 19-JAN-1998  Richard Gooch <rgooch@atnf.csiro.au>  Added devfs support
  *
  */
-static int rd_make_request(request_queue_t * q, int rw, struct buffer_head *sbh)
+static int rd_make_request(request_queue_t * q, struct bio *sbh)
 {
 	unsigned int minor;
 	unsigned long offset, len;
+	int rw = sbh->bi_rw;
 
-	minor = MINOR(sbh->b_rdev);
+	minor = MINOR(sbh->bi_dev);
 
 	if (minor >= NUM_RAMDISKS)
 		goto fail;
 
-	
-	offset = sbh->b_rsector << 9;
-	len = sbh->b_size;
+	offset = sbh->bi_sector << 9;
+	len = sbh->bi_size;
 
 	if ((offset + len) > rd_length[minor])
 		goto fail;
@@ -335,13 +352,14 @@
 		goto fail;
 	}
 
-	if (rd_blkdev_pagecache_IO(rw, sbh, minor))
+	if (rd_blkdev_bio_IO(sbh, minor))
 		goto fail;
 
-	sbh->b_end_io(sbh,1);
+	set_bit(BIO_UPTODATE, &sbh->bi_flags);
+	sbh->bi_end_io(sbh, len >> 9);
 	return 0;
  fail:
-	sbh->b_end_io(sbh,0);
+	bio_io_error(sbh);
 	return 0;
 } 
 
@@ -408,12 +426,15 @@
 {
 	extern void free_initrd_mem(unsigned long, unsigned long);
 
-	lock_kernel();
+	spin_lock(&initrd_users_lock);
 	if (!--initrd_users) {
+		spin_unlock(&initrd_users_lock);
 		free_initrd_mem(initrd_start, initrd_end);
 		initrd_start = 0;
+	} else {
+		spin_unlock(&initrd_users_lock);
 	}
-	unlock_kernel();
+		
 	blkdev_put(inode->i_bdev, BDEV_FILE);
 	return 0;
 }
@@ -433,8 +454,11 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (unit == INITRD_MINOR) {
-		if (!initrd_start) return -ENODEV;
+		spin_lock(&initrd_users_lock);
 		initrd_users++;
+		spin_unlock(&initrd_users_lock);
+		if (!initrd_start) 
+			return -ENODEV;
 		filp->f_op = &initrd_fops;
 		return 0;
 	}
@@ -461,7 +485,6 @@
 	ioctl:		rd_ioctl,
 };
 
-#ifdef MODULE
 /* Before freeing the module, invalidate all of the protected buffers! */
 static void __exit rd_cleanup (void)
 {
@@ -477,11 +500,8 @@
 
 	devfs_unregister (devfs_handle);
 	unregister_blkdev( MAJOR_NR, "ramdisk" );
-	hardsect_size[MAJOR_NR] = NULL;
-	blksize_size[MAJOR_NR] = NULL;
-	blk_size[MAJOR_NR] = NULL;
+	blk_clear(MAJOR_NR);
 }
-#endif
 
 /* This is the registration and initialization section of the RAM disk driver */
 int __init rd_init (void)
@@ -524,7 +544,6 @@
 	register_disk(NULL, MKDEV(MAJOR_NR,INITRD_MINOR), 1, &rd_bd_op, rd_size<<1);
 #endif
 
-	hardsect_size[MAJOR_NR] = rd_hardsec;		/* Size of the RAM disk blocks */
 	blksize_size[MAJOR_NR] = rd_blocksizes;		/* Avoid set_blocksize() check */
 	blk_size[MAJOR_NR] = rd_kbsize;			/* Size of the RAM disk in kB  */
 
@@ -536,10 +555,8 @@
 	return 0;
 }
 
-#ifdef MODULE
 module_init(rd_init);
 module_exit(rd_cleanup);
-#endif
 
 /* loadable module support */
 MODULE_PARM     (rd_size, "1i");
diff -u --recursive --new-file v2.5.0/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.5.0/linux/drivers/block/xd.c	Fri Nov  9 14:01:21 2001
+++ linux/drivers/block/xd.c	Sat Dec  8 20:29:55 2001
@@ -121,7 +121,6 @@
 static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
 static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES];
 static int xd_blocksizes[XD_MAXDRIVES << 6];
-static int xd_maxsect[XD_MAXDRIVES << 6];
 
 extern struct block_device_operations xd_fops;
 
@@ -246,8 +245,7 @@
 	}
 
 	/* xd_maxsectors depends on controller - so set after detection */
-	for(i=0; i<(XD_MAXDRIVES << 6); i++) xd_maxsect[i] = xd_maxsectors;
-	max_sectors[MAJOR_NR] = xd_maxsect;
+	blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), xd_maxsectors);
 
 	for (i = 0; i < xd_drives; i++) {
 		xd_valid[i] = 1;
@@ -257,7 +255,6 @@
 	}
 
 	xd_gendisk.nr_real = xd_drives;
-
 }
 
 /* xd_open: open a device */
@@ -292,14 +289,14 @@
 		if (CURRENT_DEV < xd_drives
 		    && CURRENT->sector + CURRENT->nr_sectors
 		         <= xd_struct[MINOR(CURRENT->rq_dev)].nr_sects) {
-			block = CURRENT->sector + xd_struct[MINOR(CURRENT->rq_dev)].start_sect;
+			block = CURRENT->sector;
 			count = CURRENT->nr_sectors;
 
-			switch (CURRENT->cmd) {
+			switch (rq_data_dir(CURRENT)) {
 				case READ:
 				case WRITE:
 					for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
-						code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
+						code = xd_readwrite(rq_data_dir(CURRENT),CURRENT_DEV,CURRENT->buffer,block,count);
 					break;
 				default:
 					printk("do_xd_request: unknown request\n");
@@ -329,7 +326,7 @@
 			g.heads = xd_info[dev].heads;
 			g.sectors = xd_info[dev].sectors;
 			g.cylinders = xd_info[dev].cylinders;
-			g.start = xd_struct[MINOR(inode->i_rdev)].start_sect;
+			g.start = get_start_sect(inode->i_rdev);
 			return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
 		}
 		case HDIO_SET_DMA:
@@ -337,7 +334,8 @@
 			if (xdc_busy) return -EBUSY;
 			nodma = !arg;
 			if (nodma && xd_dma_buffer) {
-				xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
+				xd_dma_mem_free((unsigned long)xd_dma_buffer,
+						xd_maxsectors * 0x200);
 				xd_dma_buffer = 0;
 			}
 			return 0;
@@ -378,11 +376,9 @@
 static int xd_reread_partitions(kdev_t dev)
 {
 	int target;
-	int start;
-	int partition;
+	int res;
 	
 	target = DEVICE_NR(dev);
- 	start = target << xd_gendisk.minor_shift;
 
 	cli();
 	xd_valid[target] = (xd_access[target] != 1);
@@ -390,20 +386,16 @@
 	if (xd_valid[target])
 		return -EBUSY;
 
-	for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
-		int minor = (start | partition);
-		invalidate_device(MKDEV(MAJOR_NR, minor), 1);
-		xd_gendisk.part[minor].start_sect = 0;
-		xd_gendisk.part[minor].nr_sects = 0;
-	};
-
-	grok_partitions(&xd_gendisk, target, 1<<6,
-			xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors);
+	res = wipe_partitions(dev);
+	if (!res)
+		grok_partitions(dev, xd_info[target].heads
+				* xd_info[target].cylinders
+				* xd_info[target].sectors);
 
 	xd_valid[target] = 1;
 	wake_up(&xd_wait_open);
 
-	return 0;
+	return res;
 }
 
 /* xd_readwrite: handle a read/write request */
@@ -1105,12 +1097,9 @@
 
 static void xd_done (void)
 {
-	blksize_size[MAJOR_NR] = NULL;
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-	blk_size[MAJOR_NR] = NULL;
-	hardsect_size[MAJOR_NR] = NULL;
-	read_ahead[MAJOR_NR] = 0;
 	del_gendisk(&xd_gendisk);
+	blk_clear(MAJOR_NR);
 	release_region(xd_iobase,4);
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.5.0/linux/drivers/cdrom/cdrom.c	Fri Nov 16 10:14:08 2001
+++ linux/drivers/cdrom/cdrom.c	Thu Dec  6 14:02:56 2001
@@ -247,7 +247,7 @@
 
 /* Define this to remove _all_ the debugging messages */
 /* #define ERRLOGMASK CD_NOTHING */
-#define ERRLOGMASK (CD_WARNING)
+#define ERRLOGMASK CD_WARNING
 /* #define ERRLOGMASK (CD_WARNING|CD_OPEN|CD_COUNT_TRACKS|CD_CLOSE) */
 /* #define ERRLOGMASK (CD_WARNING|CD_REG_UNREG|CD_DO_IOCTL|CD_OPEN|CD_CLOSE|CD_COUNT_TRACKS) */
 
@@ -1987,7 +1987,7 @@
 			return -EINVAL;
 
 		/* FIXME: we need upper bound checking, too!! */
-		if (lba < 0 || ra.nframes <= 0)
+		if (lba < 0 || ra.nframes <= 0 || ra.nframes > 64)
 			return -EINVAL;
 
 		/*
diff -u --recursive --new-file v2.5.0/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v2.5.0/linux/drivers/cdrom/cdu31a.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/cdrom/cdu31a.c	Tue Nov 27 09:23:27 2001
@@ -1583,7 +1583,10 @@
 	/* Make sure we have a valid TOC. */
 	sony_get_toc();
 
-	spin_unlock_irq(&io_request_lock);
+	/*
+	 * jens: driver has lots of races
+	 */
+	spin_unlock_irq(&q->queue_lock);
 
 	/* Make sure the timer is cancelled. */
 	del_timer(&cdu31a_abort_timer);
@@ -1730,7 +1733,7 @@
 	}
 
       end_do_cdu31a_request:
-	spin_lock_irq(&io_request_lock);
+	spin_lock_irq(&q->queue_lock);
 #if 0
 	/* After finished, cancel any pending operations. */
 	abort_read();
diff -u --recursive --new-file v2.5.0/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c
--- v2.5.0/linux/drivers/cdrom/cm206.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/cdrom/cm206.c	Tue Nov 27 09:23:27 2001
@@ -866,7 +866,7 @@
 			end_request(0);
 			continue;
 		}
-		spin_unlock_irq(&io_request_lock);
+		spin_unlock_irq(&q->queue_lock);
 		error = 0;
 		for (i = 0; i < CURRENT->nr_sectors; i++) {
 			int e1, e2;
@@ -893,7 +893,7 @@
 				debug(("cm206_request: %d %d\n", e1, e2));
 			}
 		}
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&q->queue_lock);
 		end_request(!error);
 	}
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.5.0/linux/drivers/cdrom/sbpcd.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/cdrom/sbpcd.c	Sat Dec  8 20:02:47 2001
@@ -4930,7 +4930,7 @@
 		sbpcd_end_request(req, 0);
 	if (req -> sector == -1)
 		sbpcd_end_request(req, 0);
-	spin_unlock_irq(&io_request_lock);
+	spin_unlock_irq(&q->queue_lock);
 
 	down(&ioctl_read_sem);
 	if (req->cmd != READ)
@@ -4970,7 +4970,7 @@
 			xnr, req, req->sector, req->nr_sectors, jiffies);
 #endif
 		up(&ioctl_read_sem);
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&q->queue_lock);
 		sbpcd_end_request(req, 1);
 		goto request_loop;
 	}
@@ -5011,7 +5011,7 @@
 				xnr, req, req->sector, req->nr_sectors, jiffies);
 #endif
 			up(&ioctl_read_sem);
-			spin_lock_irq(&io_request_lock);
+			spin_lock_irq(&q->queue_lock);
 			sbpcd_end_request(req, 1);
 			goto request_loop;
 		}
@@ -5027,7 +5027,7 @@
 #endif
 	up(&ioctl_read_sem);
 	sbp_sleep(0);    /* wait a bit, try again */
-	spin_lock_irq(&io_request_lock);
+	spin_lock_irq(&q->queue_lock);
 	sbpcd_end_request(req, 0);
 	goto request_loop;
 }
@@ -5870,7 +5870,6 @@
 	(BLK_DEFAULT_QUEUE(MAJOR_NR))->front_merge_fn = dont_bh_merge_fn;
 	(BLK_DEFAULT_QUEUE(MAJOR_NR))->merge_requests_fn = dont_merge_requests_fn;
 #endif
-	blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
 	read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512);
 	
 	request_region(CDo_command,4,major_name);
diff -u --recursive --new-file v2.5.0/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- v2.5.0/linux/drivers/char/acquirewdt.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/acquirewdt.c	Fri Nov 30 08:26:04 2001
@@ -141,7 +141,6 @@
 
 static int acq_close(struct inode *inode, struct file *file)
 {
-	lock_kernel();
 	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 		spin_lock(&acq_lock);
@@ -151,7 +150,6 @@
 		acq_is_open=0;
 		spin_unlock(&acq_lock);
 	}
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/advantechwdt.c linux/drivers/char/advantechwdt.c
--- v2.5.0/linux/drivers/char/advantechwdt.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/advantechwdt.c	Fri Nov 30 08:26:04 2001
@@ -151,7 +151,6 @@
 static int
 advwdt_close(struct inode *inode, struct file *file)
 {
-	lock_kernel();
 	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&advwdt_lock);
 #ifndef CONFIG_WATCHDOG_NOWAYOUT	
@@ -160,7 +159,6 @@
 		advwdt_is_open = 0;
 		spin_unlock(&advwdt_lock);
 	}
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h
--- v2.5.0/linux/drivers/char/agp/agp.h	Fri Nov  9 14:01:21 2001
+++ linux/drivers/char/agp/agp.h	Tue Nov 27 16:46:57 2001
@@ -276,6 +276,8 @@
 #define I830_RDRAM_ND(x)           (((x) & 0x20) >> 5)
 #define I830_RDRAM_DDT(x)          (((x) & 0x18) >> 3)
 
+#define INTEL_I830_ERRSTS          0x92
+
 /* intel i820 registers */
 #define INTEL_I820_RDCR     0x51
 #define INTEL_I820_ERRSTS   0xc8
diff -u --recursive --new-file v2.5.0/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c
--- v2.5.0/linux/drivers/char/agp/agpgart_be.c	Fri Nov 16 10:11:22 2001
+++ linux/drivers/char/agp/agpgart_be.c	Fri Nov 30 08:52:41 2001
@@ -1399,10 +1399,6 @@
 }
 
 #endif /* CONFIG_AGP_I810 */
- 
- #ifdef CONFIG_AGP_INTEL
-
-#endif /* CONFIG_AGP_I810 */
 
 #ifdef CONFIG_AGP_INTEL
 
@@ -1705,6 +1701,38 @@
 	return 0;
 }
 
+static int intel_830mp_configure(void)
+{
+	u32 temp;
+	u16 temp2;
+	aper_size_info_8 *current_size;
+
+	current_size = A_SIZE_8(agp_bridge.current_size);
+
+	/* aperture size */
+	pci_write_config_byte(agp_bridge.dev, INTEL_APSIZE,
+			      current_size->size_value);
+
+	/* address to map to */
+	pci_read_config_dword(agp_bridge.dev, INTEL_APBASE, &temp);
+	agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+	/* attbase - aperture base */
+	pci_write_config_dword(agp_bridge.dev, INTEL_ATTBASE,
+			       agp_bridge.gatt_bus_addr);
+
+	/* agpctrl */
+	pci_write_config_dword(agp_bridge.dev, INTEL_AGPCTRL, 0x0000);
+
+	/* gmch */
+	pci_read_config_word(agp_bridge.dev, INTEL_NBXCFG, &temp2);
+	pci_write_config_word(agp_bridge.dev, INTEL_NBXCFG,
+			      temp2 | (1 << 9));
+	/* clear any possible AGP-related error conditions */
+	pci_write_config_word(agp_bridge.dev, INTEL_I830_ERRSTS, 0x1c);
+	return 0;
+}
+
 static unsigned long intel_mask_memory(unsigned long addr, int type)
 {
 	/* Memory type is ignored */
@@ -1745,6 +1773,14 @@
 	{4, 1024, 0, 63}
 };
 
+static aper_size_info_8 intel_830mp_sizes[4] = 
+{
+  {256, 65536, 6, 0},
+  {128, 32768, 5, 32},
+  {64, 16384, 4, 48},
+  {32, 8192, 3, 56}
+};
+
 static int __init intel_generic_setup (struct pci_dev *pdev)
 {
 	agp_bridge.masks = intel_generic_masks;
@@ -1809,6 +1845,35 @@
        (void) pdev; /* unused */
 }
 
+static int __init intel_830mp_setup (struct pci_dev *pdev)
+{
+       agp_bridge.masks = intel_generic_masks;
+       agp_bridge.num_of_masks = 1;
+       agp_bridge.aperture_sizes = (void *) intel_830mp_sizes;
+       agp_bridge.size_type = U8_APER_SIZE;
+       agp_bridge.num_aperture_sizes = 4;
+       agp_bridge.dev_private_data = NULL;
+       agp_bridge.needs_scratch_page = FALSE;
+       agp_bridge.configure = intel_830mp_configure;
+       agp_bridge.fetch_size = intel_8xx_fetch_size;
+       agp_bridge.cleanup = intel_8xx_cleanup;
+       agp_bridge.tlb_flush = intel_8xx_tlbflush;
+       agp_bridge.mask_memory = intel_mask_memory;
+       agp_bridge.agp_enable = agp_generic_agp_enable;
+       agp_bridge.cache_flush = global_cache_flush;
+       agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
+       agp_bridge.free_gatt_table = agp_generic_free_gatt_table;
+       agp_bridge.insert_memory = agp_generic_insert_memory;
+       agp_bridge.remove_memory = agp_generic_remove_memory;
+       agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
+       agp_bridge.free_by_type = agp_generic_free_by_type;
+       agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+       agp_bridge.agp_destroy_page = agp_generic_destroy_page;
+
+       return 0;
+
+       (void) pdev; /* unused */
+}
 
 static int __init intel_840_setup (struct pci_dev *pdev)
 {
@@ -3495,12 +3560,6 @@
 		"AMD",
 		"Irongate",
 		amd_irongate_setup },
-	{ PCI_DEVICE_ID_AMD_762_0,
-		PCI_VENDOR_ID_AMD,
-		AMD_IRONGATE,
-		"AMD",
-		"AMD 760MP",
-		amd_irongate_setup },
 	{ PCI_DEVICE_ID_AMD_761_0,
 		PCI_VENDOR_ID_AMD,
 		AMD_761,
@@ -3557,7 +3616,7 @@
 		INTEL_I830_M,
 		"Intel",
 		"i830M",
-		intel_generic_setup },
+		intel_830mp_setup },
 	{ PCI_DEVICE_ID_INTEL_840_0,
 		PCI_VENDOR_ID_INTEL,
 		INTEL_I840,
@@ -3879,18 +3938,17 @@
 			i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
 									   PCI_DEVICE_ID_INTEL_830_M_1,
 									   NULL);
-			if(PCI_FUNC(i810_dev->devfn) != 0) {
+			if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) {
 				i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
 										   PCI_DEVICE_ID_INTEL_830_M_1,
 										   i810_dev);
 			}
 
 			if (i810_dev == NULL) {
-				printk(KERN_ERR PFX "Detected an "
-					   "Intel 830M, but could not find the"
-					   " secondary device.\n");
-				agp_bridge.type = NOT_SUPPORTED;
-				return -ENODEV;
+			        /* Intel 830MP with external graphic card */
+			        /* It will be initialized later */
+				agp_bridge.type = INTEL_I830_M;
+				break;
 			}
 			printk(KERN_INFO PFX "Detected an Intel "
 				   "830M Chipset.\n");
diff -u --recursive --new-file v2.5.0/linux/drivers/char/agp/agpgart_fe.c linux/drivers/char/agp/agpgart_fe.c
--- v2.5.0/linux/drivers/char/agp/agpgart_fe.c	Sun Aug 12 10:38:48 2001
+++ linux/drivers/char/agp/agpgart_fe.c	Fri Nov 30 08:26:04 2001
@@ -606,17 +606,14 @@
 	agp_file_private *priv = (agp_file_private *) file->private_data;
 	agp_kern_info kerninfo;
 
-	lock_kernel();
 	AGP_LOCK();
 
 	if (agp_fe.backend_acquired != TRUE) {
 		AGP_UNLOCK();
-		unlock_kernel();
 		return -EPERM;
 	}
 	if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags))) {
 		AGP_UNLOCK();
-		unlock_kernel();
 		return -EPERM;
 	}
 	agp_copy_info(&kerninfo);
@@ -628,51 +625,42 @@
 	if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) {
 		if ((size + offset) > current_size) {
 			AGP_UNLOCK();
-			unlock_kernel();
 			return -EINVAL;
 		}
 		client = agp_find_client_by_pid(current->pid);
 
 		if (client == NULL) {
 			AGP_UNLOCK();
-			unlock_kernel();
 			return -EPERM;
 		}
 		if (!agp_find_seg_in_client(client, offset,
 					    size, vma->vm_page_prot)) {
 			AGP_UNLOCK();
-			unlock_kernel();
 			return -EINVAL;
 		}
 		if (remap_page_range(vma->vm_start,
 				     (kerninfo.aper_base + offset),
 				     size, vma->vm_page_prot)) {
 			AGP_UNLOCK();
-			unlock_kernel();
 			return -EAGAIN;
 		}
 		AGP_UNLOCK();
-		unlock_kernel();
 		return 0;
 	}
 	if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
 		if (size != current_size) {
 			AGP_UNLOCK();
-			unlock_kernel();
 			return -EINVAL;
 		}
 		if (remap_page_range(vma->vm_start, kerninfo.aper_base,
 				     size, vma->vm_page_prot)) {
 			AGP_UNLOCK();
-			unlock_kernel();
 			return -EAGAIN;
 		}
 		AGP_UNLOCK();
-		unlock_kernel();
 		return 0;
 	}
 	AGP_UNLOCK();
-	unlock_kernel();
 	return -EPERM;
 }
 
@@ -680,7 +668,6 @@
 {
 	agp_file_private *priv = (agp_file_private *) file->private_data;
 
-	lock_kernel();
 	AGP_LOCK();
 
 	if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) {
@@ -702,7 +689,6 @@
 	agp_remove_file_private(priv);
 	kfree(priv);
 	AGP_UNLOCK();
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.5.0/linux/drivers/char/busmouse.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/busmouse.c	Fri Nov 30 08:26:04 2001
@@ -171,6 +171,7 @@
 	lock_kernel();
 	busmouse_fasync(-1, file, 0);
 
+	down(&mouse_sem); /* to protect mse->active */
 	if (--mse->active == 0) {
 		if (mse->ops->release)
 			ret = mse->ops->release(inode, file);
@@ -179,7 +180,8 @@
 		mse->ready = 0;
 	}
 	unlock_kernel();
-
+	up( &mouse_sem);
+	
 	return ret;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/dtlk.c linux/drivers/char/dtlk.c
--- v2.5.0/linux/drivers/char/dtlk.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/dtlk.c	Fri Nov 30 08:26:04 2001
@@ -328,10 +328,8 @@
 		break;
 	}
 	TRACE_RET;
-
-	lock_kernel();
+	
 	del_timer(&dtlk_timer);
-	unlock_kernel();
 
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/char/ftape/zftape/zftape-init.c linux/drivers/char/ftape/zftape/zftape-init.c
--- v2.5.0/linux/drivers/char/ftape/zftape/zftape-init.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/ftape/zftape/zftape-init.c	Fri Nov 30 12:33:17 2001
@@ -68,7 +68,8 @@
 
 /*      Local vars.
  */
-static int busy_flag = 0;
+static int busy_flag;
+
 static sigset_t orig_sigmask;
 
 /*  the interface to the kernel vfs layer
@@ -113,14 +114,13 @@
 	TRACE_FUN(ft_t_flow);
 
 	TRACE(ft_t_flow, "called for minor %d", MINOR(ino->i_rdev));
-	if (busy_flag) {
+	if ( test_and_set_bit(0,&busy_flag) ) {
 		TRACE_ABORT(-EBUSY, ft_t_warn, "failed: already busy");
 	}
-	busy_flag = 1;
 	if ((MINOR(ino->i_rdev) & ~(ZFT_MINOR_OP_MASK | FTAPE_NO_REWIND))
 	     > 
 	    FTAPE_SEL_D) {
-		busy_flag = 0;
+		clear_bit(0,&busy_flag);
 		TRACE_ABORT(-ENXIO, ft_t_err, "failed: illegal unit nr");
 	}
 	orig_sigmask = current->blocked;
@@ -128,7 +128,7 @@
 	result = _zft_open(MINOR(ino->i_rdev), filep->f_flags & O_ACCMODE);
 	if (result < 0) {
 		current->blocked = orig_sigmask; /* restore mask */
-		busy_flag = 0;
+		clear_bit(0,&busy_flag);
 		TRACE_ABORT(result, ft_t_err, "_ftape_open failed");
 	} else {
 		/* Mask signals that will disturb proper operation of the
@@ -147,10 +147,8 @@
 	int result;
 	TRACE_FUN(ft_t_flow);
 
-	lock_kernel();
-	if (!busy_flag || MINOR(ino->i_rdev) != zft_unit) {
+	if ( !test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit) {
 		TRACE(ft_t_err, "failed: not busy or wrong unit");
-		unlock_kernel();
 		TRACE_EXIT 0;
 	}
 	sigfillset(&current->blocked);
@@ -159,8 +157,7 @@
 		TRACE(ft_t_err, "_zft_close failed");
 	}
 	current->blocked = orig_sigmask; /* restore before open state */
-	busy_flag = 0;
-	unlock_kernel();
+	clear_bit(0,&busy_flag);
 	TRACE_EXIT 0;
 }
 
@@ -173,7 +170,7 @@
 	sigset_t old_sigmask;
 	TRACE_FUN(ft_t_flow);
 
-	if (!busy_flag || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+	if ( !test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
 		TRACE_ABORT(-EIO, ft_t_err,
 			    "failed: not busy, failure or wrong unit");
 	}
@@ -193,7 +190,7 @@
 	sigset_t old_sigmask;
 	TRACE_FUN(ft_t_flow);
 
-	if (!busy_flag || 
+	if ( !test_bit(0,&busy_flag) || 
 	    MINOR(filep->f_dentry->d_inode->i_rdev) != zft_unit || 
 	    ft_failure)
 	{
@@ -202,14 +199,12 @@
 	}
 	old_sigmask = current->blocked; /* save mask */
 	sigfillset(&current->blocked);
-	lock_kernel();
 	if ((result = ftape_mmap(vma)) >= 0) {
 #ifndef MSYNC_BUG_WAS_FIXED
 		static struct vm_operations_struct dummy = { NULL, };
 		vma->vm_ops = &dummy;
 #endif
 	}
-	unlock_kernel();
 	current->blocked = old_sigmask; /* restore mask */
 	TRACE_EXIT result;
 }
@@ -225,7 +220,7 @@
 	TRACE_FUN(ft_t_flow);
 
 	TRACE(ft_t_data_flow, "called with count: %ld", (unsigned long)req_len);
-	if (!busy_flag || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+	if (!test_bit(0,&busy_flag)  || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
 		TRACE_ABORT(-EIO, ft_t_err,
 			    "failed: not busy, failure or wrong unit");
 	}
@@ -248,7 +243,7 @@
 	TRACE_FUN(ft_t_flow);
 
 	TRACE(ft_t_flow, "called with count: %ld", (unsigned long)req_len);
-	if (!busy_flag || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
+	if (!test_bit(0,&busy_flag) || MINOR(ino->i_rdev) != zft_unit || ft_failure) {
 		TRACE_ABORT(-EIO, ft_t_err,
 			    "failed: not busy, failure or wrong unit");
 	}
@@ -403,7 +398,7 @@
  */
 static int can_unload(void)
 {
-	return (GET_USE_COUNT(THIS_MODULE)||zft_dirty()||busy_flag)?-EBUSY:0;
+	return (GET_USE_COUNT(THIS_MODULE)||zft_dirty()||test_bit(0,&busy_flag))?-EBUSY:0;
 }
 /* Called by modules package when installing the driver
  */
diff -u --recursive --new-file v2.5.0/linux/drivers/char/joystick/ns558.c linux/drivers/char/joystick/ns558.c
--- v2.5.0/linux/drivers/char/joystick/ns558.c	Wed Sep 12 15:34:06 2001
+++ linux/drivers/char/joystick/ns558.c	Sun Nov 25 09:43:42 2001
@@ -153,11 +153,7 @@
 	return port;
 }
 
-#if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
-#define NSS558_ISAPNP
-#endif
-
-#ifdef NSS558_ISAPNP
+#ifdef __ISAPNP__
 
 static struct isapnp_device_id pnp_devids[] = {
 	{ ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('@','P','@'), ISAPNP_DEVICE(0x0001), 0 },
@@ -229,7 +225,7 @@
 int __init ns558_init(void)
 {
 	int i = 0;
-#ifdef NSS558_ISAPNP
+#ifdef __ISAPNP__
 	struct isapnp_device_id *devid;
 	struct pci_dev *dev = NULL;
 #endif
@@ -245,7 +241,7 @@
  * Probe for PnP ports.
  */
 
-#ifdef NSS558_ISAPNP
+#ifdef __ISAPNP__
 	for (devid = pnp_devids; devid->vendor; devid++) {
 		while ((dev = isapnp_find_dev(NULL, devid->vendor, devid->function, dev))) {
 			ns558 = ns558_pnp_probe(dev, ns558);
@@ -264,7 +260,7 @@
 		gameport_unregister_port(&port->gameport);
 		switch (port->type) {
 
-#ifdef NSS558_ISAPNP
+#ifdef __ISAPNP__
 			case NS558_PNP:
 				if (port->dev->deactivate)
 					port->dev->deactivate(port->dev);
diff -u --recursive --new-file v2.5.0/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.5.0/linux/drivers/char/lp.c	Thu Oct 25 00:07:39 2001
+++ linux/drivers/char/lp.c	Fri Nov 30 08:26:04 2001
@@ -494,11 +494,9 @@
 	parport_negotiate (lp_table[minor].dev->port, IEEE1284_MODE_COMPAT);
 	lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
 	lp_release_parport (&lp_table[minor]);
-	lock_kernel();
 	kfree(lp_table[minor].lp_buffer);
 	lp_table[minor].lp_buffer = NULL;
 	LP_F(minor) &= ~LP_BUSY;
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/mixcomwd.c linux/drivers/char/mixcomwd.c
--- v2.5.0/linux/drivers/char/mixcomwd.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/mixcomwd.c	Fri Nov 30 08:26:04 2001
@@ -101,11 +101,9 @@
 static int mixcomwd_release(struct inode *inode, struct file *file)
 {
 
-	lock_kernel();
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
 	if(mixcomwd_timer_alive) {
 		printk(KERN_ERR "mixcomwd: release called while internal timer alive");
-		unlock_kernel();
 		return -EBUSY;
 	}
 	init_timer(&mixcomwd_timer);
@@ -117,7 +115,6 @@
 #endif
 
 	clear_bit(0,&mixcomwd_opened);
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/nvram.c linux/drivers/char/nvram.c
--- v2.5.0/linux/drivers/char/nvram.c	Fri Sep 14 14:40:00 2001
+++ linux/drivers/char/nvram.c	Fri Nov 30 08:26:04 2001
@@ -108,7 +108,10 @@
 #include <asm/system.h>
 
 static int nvram_open_cnt;	/* #times opened */
-static int nvram_open_mode;		/* special open modes */
+static int nvram_open_mode;	/* special open modes */
+static spinlock_t nvram_open_lock = SPIN_LOCK_UNLOCKED;
+                               /* guards nvram_open_cnt and
+                                         nvram_open_mode */
 #define	NVRAM_WRITE		1		/* opened for writing (exclusive) */
 #define	NVRAM_EXCL		2		/* opened with O_EXCL */
 
@@ -326,29 +329,33 @@
 
 static int nvram_open( struct inode *inode, struct file *file )
 {
+	spin_lock( &nvram_open_lock );
 	if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
 		(nvram_open_mode & NVRAM_EXCL) ||
 		((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE)))
+	{	
+		spin_unlock( &nvram_open_lock );
 		return( -EBUSY );
+	}
 
 	if (file->f_flags & O_EXCL)
 		nvram_open_mode |= NVRAM_EXCL;
 	if (file->f_mode & 2)
 		nvram_open_mode |= NVRAM_WRITE;
 	nvram_open_cnt++;
+	spin_unlock( &nvram_open_lock );
 	return( 0 );
 }
 
 static int nvram_release( struct inode *inode, struct file *file )
 {
-	lock_kernel();
+	spin_lock( &nvram_open_lock );
 	nvram_open_cnt--;
 	if (file->f_flags & O_EXCL)
 		nvram_open_mode &= ~NVRAM_EXCL;
 	if (file->f_mode & 2)
 		nvram_open_mode &= ~NVRAM_WRITE;
-	unlock_kernel();
-
+	spin_unlock( &nvram_open_lock );
 	return( 0 );
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c
--- v2.5.0/linux/drivers/char/pc110pad.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/pc110pad.c	Wed Nov 28 21:46:03 2001
@@ -68,7 +68,9 @@
 /* driver/filesystem interface management */
 static wait_queue_head_t queue;
 static struct fasync_struct *asyncptr;
-static int active;	/* number of concurrent open()s */
+static int active_count = 0; 	/* number of concurrent open()s */
+static spinlock_t pc110_lock = SPIN_LOCK_UNLOCKED;
+/* this lock should be held when referencing active_count */
 static struct semaphore reader_lock;
 
 /**
@@ -480,15 +482,14 @@
 	int thisd, thisdd, thisx, thisy;
 	int b;
 	unsigned long flags;
-	
-	save_flags(flags);
-	cli();
+
+	spin_lock_irqsave(&pc110_lock, flags);	
 	read_raw_pad(&thisd, &thisdd, &thisx, &thisy);
 	d[0]=(thisd?0x80:0) | (thisdd?0x40:0) | bounce;
 	d[1]=(recent_transition?0x80:0)+transition_count;
 	read_button(&b);
 	d[2]=(synthesize_tap<<4) | (b?0x01:0);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pc110_lock, flags);
 }
 
 /**
@@ -584,11 +585,12 @@
  
 static int close_pad(struct inode * inode, struct file * file)
 {
-	lock_kernel();
+	unsigned long flags;
 	fasync_pad(-1, file, 0);
-	if (!--active)
+	spin_lock_irqsave(&pc110_lock, flags);
+	if (!--active_count)
 		outb(0x30, current_params.io+2);  /* switch off digitiser */
-	unlock_kernel();
+	spin_unlock_irqrestore(&active_lock, flags);	
 	return 0;
 }
 
@@ -608,11 +610,13 @@
 {
 	unsigned long flags;
 	
-	if (active++)
+       	spin_lock_irqsave(&pc110_lock, flags);
+	if (active_count++)
+        {
+        	spin_unlock_irqrestore(&pc110_lock, flags);
 		return 0;
+	}
 
-	save_flags(flags);
-	cli();
 	outb(0x30, current_params.io+2);	/* switch off digitiser */
 	pad_irq(0,0,0);		/* read to flush any pending bytes */
 	pad_irq(0,0,0);		/* read to flush any pending bytes */
@@ -627,7 +631,7 @@
 	synthesize_tap=0;
 	del_timer(&bounce_timer);
 	del_timer(&tap_timer);
-	restore_flags(flags);
+       spin_unlock_irqrestore(&pc110_lock, flags);
 
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.5.0/linux/drivers/char/pc_keyb.c	Fri Nov  9 14:01:21 2001
+++ linux/drivers/char/pc_keyb.c	Fri Dec  7 16:21:05 2001
@@ -90,6 +90,7 @@
  
 static struct aux_queue *queue;	/* Mouse data buffer. */
 static int aux_count;
+static spinlock_t aux_count_lock = SPIN_LOCK_UNLOCKED;
 /* used when we send commands to the mouse that expect an ACK. */
 static unsigned char mouse_reply_expected;
 
@@ -405,8 +406,9 @@
 
        if (rqst == PM_RESUME) {
                if (queue) {                    /* Aux port detected */
-                       if (aux_count == 0) {   /* Mouse not in use */ 
-                               spin_lock_irqsave(&kbd_controller_lock, flags);
+		       spin_lock_irqsave(&aux_count_lock, flags);
+              	       if ( aux_count == 0) {   /* Mouse not in use */ 
+                               spin_lock(&kbd_controller_lock);
 			       /*
 				* Dell Lat. C600 A06 enables mouse after resume.
 				* When user touches the pad, it posts IRQ 12
@@ -418,8 +420,9 @@
 			       kbd_write_command(KBD_CCMD_WRITE_MODE);
 			       kb_wait();
 			       kbd_write_output(AUX_INTS_OFF);
-			       spin_unlock_irqrestore(&kbd_controller_lock, flags);
+			       spin_unlock(&kbd_controller_lock);
 		       }
+		       spin_unlock_irqrestore(&aux_count_lock, flags);
 	       }
        }
 #endif
@@ -430,6 +433,7 @@
 static inline void handle_mouse_event(unsigned char scancode)
 {
 #ifdef CONFIG_PSMOUSE
+	unsigned long flags;
 	static unsigned char prev_code;
 	if (mouse_reply_expected) {
 		if (scancode == AUX_ACK) {
@@ -448,7 +452,8 @@
 
 	prev_code = scancode;
 	add_mouse_randomness(scancode);
-	if (aux_count) {
+	spin_lock_irqsave(&aux_count_lock, flags);
+	if ( aux_count ) {
 		int head = queue->head;
 
 		queue->buf[head] = scancode;
@@ -459,6 +464,7 @@
 			wake_up_interruptible(&queue->proc_list);
 		}
 	}
+	spin_unlock_irqrestore(&aux_count_lock, flags);
 #endif
 }
 
@@ -1046,16 +1052,17 @@
 
 static int release_aux(struct inode * inode, struct file * file)
 {
-	lock_kernel();
+	unsigned long flags;
 	fasync_aux(-1, file, 0);
-	if (--aux_count) {
-		unlock_kernel();
+	spin_lock_irqsave(&aux_count_lock, flags);
+	if ( --aux_count ) {
+		spin_unlock_irqrestore(&aux_count_lock, flags);
 		return 0;
 	}
+	spin_unlock_irqrestore(&aux_count_lock, flags);
 	kbd_write_cmd(AUX_INTS_OFF);			    /* Disable controller ints */
 	kbd_write_command_w(KBD_CCMD_MOUSE_DISABLE);
 	aux_free_irq(AUX_DEV);
-	unlock_kernel();
 	return 0;
 }
 
@@ -1066,14 +1073,24 @@
 
 static int open_aux(struct inode * inode, struct file * file)
 {
-	if (aux_count++) {
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&aux_count_lock, flags);
+	if ( aux_count++ ) {
+		spin_unlock_irqrestore(&aux_count_lock, flags);
 		return 0;
 	}
 	queue->head = queue->tail = 0;		/* Flush input queue */
-	if (aux_request_irq(keyboard_interrupt, AUX_DEV)) {
+	spin_unlock_irqrestore(&aux_count_lock, flags);
+	ret = aux_request_irq(keyboard_interrupt, AUX_DEV);
+	spin_lock_irqsave(&aux_count_lock, flags);
+	if (ret) {
 		aux_count--;
+		spin_unlock_irqrestore(&aux_count_lock, flags);
 		return -EBUSY;
 	}
+	spin_unlock_irqrestore(&aux_count_lock, flags);
 	kbd_write_command_w(KBD_CCMD_MOUSE_ENABLE);	/* Enable the
 							   auxiliary port on
 							   controller. */
@@ -1083,7 +1100,6 @@
 	mdelay(2);			/* Ensure we follow the kbc access delay rules.. */
 
 	send_data(KBD_CMD_ENABLE);	/* try to workaround toshiba4030cdt problem */
-
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.5.0/linux/drivers/char/pcwd.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/pcwd.c	Fri Nov 30 08:26:04 2001
@@ -100,7 +100,8 @@
 #define WD_SRLY2                0x80	/* Software external relay triggered */
 
 static int current_readport, revision, temp_panic;
-static int is_open, initial_status, supports_temp, mode_debug;
+static atomic_t open_allowed = ATOMIC_INIT(1);
+static int initial_status, supports_temp, mode_debug;
 static spinlock_t io_lock;
 
 /*
@@ -402,9 +403,12 @@
         switch (MINOR(ino->i_rdev))
         {
                 case WATCHDOG_MINOR:
-                    if (is_open)
+                    if ( !atomic_dec_and_test(&open_allowed) )
+		    {
+			atomic_inc( &open_allowed );
                         return -EBUSY;
-                    MOD_INC_USE_COUNT;
+                    }
+		    MOD_INC_USE_COUNT;
                     /*  Enable the port  */
                     if (revision == PCWD_REVISION_C)
                     {
@@ -412,7 +416,6 @@
                     	outb_p(0x00, current_readport + 3);
                     	spin_unlock(&io_lock);
                     }
-                    is_open = 1;
                     return(0);
                 case TEMP_MINOR:
                     return(0);
@@ -452,8 +455,6 @@
 {
 	if (MINOR(ino->i_rdev)==WATCHDOG_MINOR)
 	{
-		lock_kernel();
-	        is_open = 0;
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
 		/*  Disable the board  */
 		if (revision == PCWD_REVISION_C) {
@@ -462,8 +463,8 @@
 			outb_p(0xA5, current_readport + 3);
 			spin_unlock(&io_lock);
 		}
+	        atomic_inc( &open_allowed );
 #endif
-		unlock_kernel();
 	}
 	return 0;
 }
@@ -574,7 +575,7 @@
 	printk("pcwd: v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER);
 
 	/* Initial variables */
-	is_open = 0;
+	set_bit( 0, &open_allowed );
 	supports_temp = 0;
 	mode_debug = 0;
 	temp_panic = 0;
diff -u --recursive --new-file v2.5.0/linux/drivers/char/ppdev.c linux/drivers/char/ppdev.c
--- v2.5.0/linux/drivers/char/ppdev.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/ppdev.c	Fri Nov 30 08:26:04 2001
@@ -646,7 +646,6 @@
 	struct pp_struct *pp = file->private_data;
 	int compat_negot;
 
-	lock_kernel();
 	compat_negot = 0;
 	if (!(pp->flags & PP_CLAIMED) && pp->pdev &&
 	    (pp->state.mode != IEEE1284_MODE_COMPAT)) {
@@ -695,7 +694,6 @@
 		printk (KERN_DEBUG CHRDEV "%x: unregistered pardevice\n",
 			minor);
 	}
-	unlock_kernel();
 
 	kfree (pp);
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/qpmouse.c linux/drivers/char/qpmouse.c
--- v2.5.0/linux/drivers/char/qpmouse.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/qpmouse.c	Fri Nov 30 08:26:04 2001
@@ -111,6 +111,7 @@
 
 static int qp_present;
 static int qp_count;
+static spinlock_t qp_count_lock = SPIN_LOCK_UNLOCKED;
 static int qp_data = QP_DATA;
 static int qp_status = QP_STATUS;
 
@@ -141,8 +142,8 @@
 {
 	unsigned char status;
 
-	lock_kernel();
 	fasync_qp(-1, file, 0);
+ 	spin_lock( &qp_count_lock );	
 	if (!--qp_count) {
 		if (!poll_qp_status())
 			printk(KERN_WARNING "Warning: Mouse device busy in release_qp()\n");
@@ -152,7 +153,7 @@
 			printk(KERN_WARNING "Warning: Mouse device busy in release_qp()\n");
 		free_irq(QP_IRQ, NULL);
 	}
-	unlock_kernel();
+	spin_unlock( &qp_count_lock );
 	return 0;
 }
 
@@ -168,8 +169,13 @@
 	if (!qp_present)
 		return -EINVAL;
 
+	spin_lock( &qp_count_lock );
 	if (qp_count++)
+	{
+		spin_unlock( &qp_count_lock );
 		return 0;
+	}
+	spin_unlock( &qp_count_lock );
 
 	if (request_irq(QP_IRQ, qp_interrupt, 0, "PS/2 Mouse", NULL)) {
 		qp_count--;
diff -u --recursive --new-file v2.5.0/linux/drivers/char/qtronix.c linux/drivers/char/qtronix.c
--- v2.5.0/linux/drivers/char/qtronix.c	Sun Sep  9 10:43:02 2001
+++ linux/drivers/char/qtronix.c	Fri Nov 30 08:26:04 2001
@@ -492,10 +492,8 @@
 
 static int release_aux(struct inode * inode, struct file * file)
 {
-	lock_kernel();
 	fasync_aux(-1, file, 0);
 	aux_count--;
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/raw.c linux/drivers/char/raw.c
--- v2.5.0/linux/drivers/char/raw.c	Sat Sep 22 20:35:43 2001
+++ linux/drivers/char/raw.c	Tue Nov 27 09:23:27 2001
@@ -126,10 +126,8 @@
 	if (is_mounted(rdev)) {
 		if (blksize_size[MAJOR(rdev)])
 			sector_size = blksize_size[MAJOR(rdev)][MINOR(rdev)];
-	} else {
-		if (hardsect_size[MAJOR(rdev)])
-			sector_size = hardsect_size[MAJOR(rdev)][MINOR(rdev)];
-	}
+	} else
+		sector_size = get_hardsect_size(rdev);
 
 	set_blocksize(rdev, sector_size);
 	raw_devices[minor].sector_size = sector_size;
@@ -273,16 +271,14 @@
 	struct kiobuf * iobuf;
 	int		new_iobuf;
 	int		err = 0;
-	unsigned long	blocknr, blocks;
+	unsigned long	blocks;
 	size_t		transferred;
 	int		iosize;
-	int		i;
 	int		minor;
 	kdev_t		dev;
 	unsigned long	limit;
-
 	int		sector_size, sector_bits, sector_mask;
-	int		max_sectors;
+	sector_t	blocknr;
 	
 	/*
 	 * First, a few checks on device size limits 
@@ -307,7 +303,6 @@
 	sector_size = raw_devices[minor].sector_size;
 	sector_bits = raw_devices[minor].sector_bits;
 	sector_mask = sector_size- 1;
-	max_sectors = KIO_MAX_SECTORS >> (sector_bits - 9);
 	
 	if (blk_size[MAJOR(dev)])
 		limit = (((loff_t) blk_size[MAJOR(dev)][MINOR(dev)]) << BLOCK_SIZE_BITS) >> sector_bits;
@@ -325,18 +320,10 @@
 	if ((*offp >> sector_bits) >= limit)
 		goto out_free;
 
-	/*
-	 * Split the IO into KIO_MAX_SECTORS chunks, mapping and
-	 * unmapping the single kiobuf as we go to perform each chunk of
-	 * IO.  
-	 */
-
 	transferred = 0;
 	blocknr = *offp >> sector_bits;
 	while (size > 0) {
 		blocks = size >> sector_bits;
-		if (blocks > max_sectors)
-			blocks = max_sectors;
 		if (blocks > limit - blocknr)
 			blocks = limit - blocknr;
 		if (!blocks)
@@ -348,10 +335,7 @@
 		if (err)
 			break;
 
-		for (i=0; i < blocks; i++) 
-			iobuf->blocks[i] = blocknr++;
-		
-		err = brw_kiovec(rw, 1, &iobuf, dev, iobuf->blocks, sector_size);
+		err = brw_kiovec(rw, 1, &iobuf, dev, &blocknr, sector_size);
 
 		if (rw == READ && err > 0)
 			mark_dirty_kiobuf(iobuf, err);
@@ -361,6 +345,8 @@
 			size -= err;
 			buf += err;
 		}
+
+		blocknr += blocks;
 
 		unmap_kiobuf(iobuf);
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/sbc60xxwdt.c linux/drivers/char/sbc60xxwdt.c
--- v2.5.0/linux/drivers/char/sbc60xxwdt.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/sbc60xxwdt.c	Fri Nov 30 08:26:04 2001
@@ -214,7 +214,6 @@
 
 static int fop_close(struct inode * inode, struct file * file)
 {
-	lock_kernel();
 	if(MINOR(inode->i_rdev) == WATCHDOG_MINOR) 
 	{
 		if(wdt_expect_close)
@@ -225,7 +224,6 @@
 		}
 	}
 	wdt_is_open = 0;
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.5.0/linux/drivers/char/serial.c	Fri Nov  9 14:12:55 2001
+++ linux/drivers/char/serial.c	Sun Nov 25 09:43:42 2001
@@ -122,7 +122,7 @@
 #define ENABLE_SERIAL_ACPI
 #endif
 
-#if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
+#ifdef __ISAPNP__
 #ifndef ENABLE_SERIAL_PNP
 #define ENABLE_SERIAL_PNP
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/char/shwdt.c linux/drivers/char/shwdt.c
--- v2.5.0/linux/drivers/char/shwdt.c	Mon Oct 15 13:36:48 2001
+++ linux/drivers/char/shwdt.c	Tue Dec 11 10:10:18 2001
@@ -10,7 +10,6 @@
  * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -177,7 +176,7 @@
  * 	sh_wdt_read - Read from Device
  *
  * 	@file: file handle of device
- * 	@char: buffer to write to
+ * 	@buf: buffer to write to
  * 	@count: length of buffer
  * 	@ppos: offset
  *
@@ -193,7 +192,7 @@
  * 	sh_wdt_write - Write to Device
  *
  * 	@file: file handle of device
- * 	@char: buffer to write
+ * 	@buf: buffer to write
  * 	@count: length of buffer
  * 	@ppos: offset
  *
@@ -269,7 +268,7 @@
 static int sh_wdt_notify_sys(struct notifier_block *this,
 			     unsigned long code, void *unused)
 {
-	if (code == SYS_DOWN || SYS_HALT) {
+	if (code == SYS_DOWN || code == SYS_HALT) {
 		sh_wdt_stop();
 	}
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/softdog.c linux/drivers/char/softdog.c
--- v2.5.0/linux/drivers/char/softdog.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/char/softdog.c	Fri Nov 30 08:26:04 2001
@@ -100,12 +100,10 @@
 	 *	Shut off the timer.
 	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
 	 */
-	 lock_kernel();
 #ifndef CONFIG_WATCHDOG_NOWAYOUT	 
 	del_timer(&watchdog_ticktock);
 #endif	
 	timer_alive=0;
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/sonypi.c linux/drivers/char/sonypi.c
--- v2.5.0/linux/drivers/char/sonypi.c	Mon Oct 15 08:38:31 2001
+++ linux/drivers/char/sonypi.c	Thu Nov 29 07:53:34 2001
@@ -617,8 +617,11 @@
 		goto out3;
 	}
 
+#if !defined(CONFIG_ACPI)
+	/* Enable ACPI mode to get Fn key events */
 	if (fnkeyinit)
 		outb(0xf0, 0xb2);
+#endif
 
 	if (sonypi_device.model == SONYPI_DEVICE_MODEL_TYPE2)
 		sonypi_type2_srs();
@@ -666,6 +669,11 @@
 		sonypi_type2_dis();
 	else
 		sonypi_type1_dis();
+#if !defined(CONFIG_ACPI)
+	/* disable ACPI mode */
+	if (fnkeyinit)
+		outb(0xf1, 0xb2);
+#endif
 	free_irq(sonypi_device.irq, sonypi_irq);
 	release_region(sonypi_device.ioport1, sonypi_device.region_size);
 	misc_deregister(&sonypi_misc_device);
diff -u --recursive --new-file v2.5.0/linux/drivers/char/sonypi.h linux/drivers/char/sonypi.h
--- v2.5.0/linux/drivers/char/sonypi.h	Mon Oct 15 08:38:31 2001
+++ linux/drivers/char/sonypi.h	Thu Nov 29 07:53:34 2001
@@ -35,7 +35,7 @@
 #ifdef __KERNEL__
 
 #define SONYPI_DRIVER_MAJORVERSION	1
-#define SONYPI_DRIVER_MINORVERSION	7
+#define SONYPI_DRIVER_MINORVERSION	8
 
 #include <linux/types.h>
 #include <linux/pci.h>
diff -u --recursive --new-file v2.5.0/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c
--- v2.5.0/linux/drivers/char/sysrq.c	Tue Oct  2 09:20:37 2001
+++ linux/drivers/char/sysrq.c	Mon Dec 10 13:52:53 2001
@@ -336,7 +336,7 @@
 
 
 /* Key Operations table and lock */
-spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED;
 #define SYSRQ_KEY_TABLE_LENGTH 36
 static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
 /* 0 */	&sysrq_loglevel_op,
diff -u --recursive --new-file v2.5.0/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.5.0/linux/drivers/char/tpqic02.c	Fri Sep 14 14:40:00 2001
+++ linux/drivers/char/tpqic02.c	Fri Nov 30 08:26:04 2001
@@ -2395,7 +2395,6 @@
 {
 	kdev_t dev = inode->i_rdev;
 
-	lock_kernel();
 	if (TP_DIAGS(dev)) {
 		printk("qic02_tape_release: dev=%s\n", kdevname(dev));
 	}
@@ -2419,7 +2418,6 @@
 			(void) do_qic_cmd(QCMD_REWIND, TIM_R);
 		}
 	}
-	unlock_kernel();
 	return 0;
 }				/* qic02_tape_release */
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.5.0/linux/drivers/char/tty_io.c	Fri Nov  2 17:26:17 2001
+++ linux/drivers/char/tty_io.c	Thu Nov 29 20:48:58 2001
@@ -102,10 +102,6 @@
 
 #include <linux/kmod.h>
 
-#ifdef CONFIG_VT
-extern void con_init_devfs (void);
-#endif
-
 #define CONSOLE_DEV MKDEV(TTY_MAJOR,0)
 #define TTY_DEV MKDEV(TTYAUX_MAJOR,0)
 #define SYSCONS_DEV MKDEV(TTYAUX_MAJOR,1)
@@ -2246,6 +2242,8 @@
 static struct tty_driver dev_ptmx_driver;
 #endif
 #ifdef CONFIG_VT
+extern void con_init_devfs (void);
+extern void console_map_init(void);
 static struct tty_driver dev_console_driver;
 #endif
 
@@ -2317,7 +2315,9 @@
 	if (tty_register_driver(&dev_console_driver))
 		panic("Couldn't register /dev/tty0 driver\n");
 
+	vcs_init();
 	kbd_init();
+	console_map_init();
 #endif
 
 #ifdef CONFIG_ESPSERIAL  /* init ESP before rs, so rs doesn't see the port */
@@ -2363,9 +2363,6 @@
 #ifdef CONFIG_MOXA_INTELLIO
 	moxa_init();
 #endif	
-#ifdef CONFIG_VT
-	vcs_init();
-#endif
 #ifdef CONFIG_TN3270
 	tub3270_init();
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/char/w83877f_wdt.c linux/drivers/char/w83877f_wdt.c
--- v2.5.0/linux/drivers/char/w83877f_wdt.c	Thu Sep 13 15:21:32 2001
+++ linux/drivers/char/w83877f_wdt.c	Fri Nov 30 08:26:04 2001
@@ -214,7 +214,6 @@
 
 static int fop_close(struct inode * inode, struct file * file)
 {
-	lock_kernel();
 	if(MINOR(inode->i_rdev) == WATCHDOG_MINOR) 
 	{
 		if(wdt_expect_close)
@@ -225,7 +224,6 @@
 		}
 	}
 	wdt_is_open = 0;
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.5.0/linux/drivers/char/wdt.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/wdt.c	Fri Nov 30 08:26:04 2001
@@ -50,7 +50,7 @@
 #include <linux/reboot.h>
 #include <linux/init.h>
 
-static int wdt_is_open;
+static unsigned long wdt_is_open;
 
 /*
  *	You must set these - there is no sane way to probe for this board.
@@ -337,13 +337,12 @@
 	switch(MINOR(inode->i_rdev))
 	{
 		case WATCHDOG_MINOR:
-			if(wdt_is_open)
+			if(test_and_set_bit(0, &wdt_is_open))
 				return -EBUSY;
 			/*
 			 *	Activate 
 			 */
 	 
-			wdt_is_open=1;
 			inb_p(WDT_DC);		/* Disable */
 			wdt_ctr_mode(0,3);
 			wdt_ctr_mode(1,2);
@@ -374,16 +373,14 @@
  
 static int wdt_release(struct inode *inode, struct file *file)
 {
-	lock_kernel();
 	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 #ifndef CONFIG_WATCHDOG_NOWAYOUT	
 		inb_p(WDT_DC);		/* Disable counters */
 		wdt_ctr_load(2,0);	/* 0 length reset pulses now */
 #endif		
-		wdt_is_open=0;
+		clear_bit(0, &wdt_is_open);
 	}
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/char/wdt285.c linux/drivers/char/wdt285.c
--- v2.5.0/linux/drivers/char/wdt285.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/wdt285.c	Fri Nov 30 08:26:04 2001
@@ -94,10 +94,8 @@
 static int watchdog_release(struct inode *inode, struct file *file)
 {
 #ifdef ONLY_TESTING
-	lock_kernel();
 	free_irq(IRQ_TIMER4, NULL);
 	timer_alive = 0;
-	unlock_kernel();
 #else
 	/*
 	 *	It's irreversible!
diff -u --recursive --new-file v2.5.0/linux/drivers/char/wdt977.c linux/drivers/char/wdt977.c
--- v2.5.0/linux/drivers/char/wdt977.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/wdt977.c	Fri Nov 30 08:26:04 2001
@@ -92,7 +92,6 @@
 	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
 	 */
 #ifndef CONFIG_WATCHDOG_NOWAYOUT
-	lock_kernel();
 
 	// unlock the SuperIO chip
 	outb(0x87,0x370); 
@@ -124,7 +123,6 @@
 	outb(0xAA,0x370);
 
 	timer_alive=0;
-	unlock_kernel();
 
 	printk(KERN_INFO "Watchdog: shutdown.\n");
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c
--- v2.5.0/linux/drivers/char/wdt_pci.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/char/wdt_pci.c	Fri Nov 30 08:26:04 2001
@@ -71,7 +71,7 @@
 #define PCI_DEVICE_ID_WDG_CSM 0x22c0
 #endif
 
-static int wdt_is_open;
+static unsigned long wdt_is_open;
 
 /*
  *	You must set these - there is no sane way to probe for this board.
@@ -353,16 +353,16 @@
 	switch(MINOR(inode->i_rdev))
 	{
 		case WATCHDOG_MINOR:
-			if(wdt_is_open)
+			if( test_and_set_bit(0,&wdt_is_open) ) 
+			{
 				return -EBUSY;
+			}
 #ifdef CONFIG_WATCHDOG_NOWAYOUT	
 			MOD_INC_USE_COUNT;
 #endif
 			/*
 			 *	Activate 
 			 */
-	 
-			wdt_is_open=1;
 
 			inb_p(WDT_DC);		/* Disable */
 
@@ -412,13 +412,11 @@
 {
 	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
 	{
-		lock_kernel();
 #ifndef CONFIG_WATCHDOG_NOWAYOUT	
 		inb_p(WDT_DC);		/* Disable counters */
 		wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
 #endif		
-		wdt_is_open=0;
-		unlock_kernel();
+		clear_bit(0, &wdt_is_open );
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/i2c/i2c-dev.c linux/drivers/i2c/i2c-dev.c
--- v2.5.0/linux/drivers/i2c/i2c-dev.c	Thu Oct 11 08:05:47 2001
+++ linux/drivers/i2c/i2c-dev.c	Fri Nov 30 08:26:04 2001
@@ -423,14 +423,9 @@
 #endif
 #if LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0)
 	MOD_DEC_USE_COUNT;
-#else /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
-	lock_kernel();
 #endif /* LINUX_KERNEL_VERSION < KERNEL_VERSION(2,4,0) */
 	if (i2cdev_adaps[minor]->dec_use)
 		i2cdev_adaps[minor]->dec_use(i2cdev_adaps[minor]);
-#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
-	unlock_kernel();
-#endif /* LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0) */
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/aec62xx.c linux/drivers/ide/aec62xx.c
--- v2.5.0/linux/drivers/ide/aec62xx.c	Tue Jun 20 07:52:36 2000
+++ linux/drivers/ide/aec62xx.c	Tue Nov 27 09:23:27 2001
@@ -557,6 +557,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base)
 		hwif->dmaproc = &aec62xx_dmaproc;
+	hwif->highmem = 1;
 #else /* !CONFIG_BLK_DEV_IDEDMA */
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/amd74xx.c linux/drivers/ide/amd74xx.c
--- v2.5.0/linux/drivers/ide/amd74xx.c	Mon Aug 13 14:56:19 2001
+++ linux/drivers/ide/amd74xx.c	Tue Nov 27 09:23:27 2001
@@ -75,7 +75,8 @@
 {
 	unsigned int class_rev;
 
-	if (dev->device == PCI_DEVICE_ID_AMD_VIPER_7411)
+	if ((dev->device == PCI_DEVICE_ID_AMD_VIPER_7411) ||
+	    (dev->device == PCI_DEVICE_ID_AMD_VIPER_7441))
 		return 0;
 
 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
@@ -122,8 +123,8 @@
 	pci_read_config_byte(dev, 0x4c, &pio_timing);
 
 #ifdef DEBUG
-	printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
-		drive->name, ultra_timing, dma_pio_timing, pio_timing);
+	printk("%s:%d: Speed 0x%02x UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
+		drive->name, drive->dn, speed, ultra_timing, dma_pio_timing, pio_timing);
 #endif
 
 	ultra_timing	&= ~0xC7;
@@ -131,22 +132,19 @@
 	pio_timing	&= ~(0x03 << drive->dn);
 
 #ifdef DEBUG
-	printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
-		ultra_timing, dma_pio_timing, pio_timing);
+	printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
+		drive->name, ultra_timing, dma_pio_timing, pio_timing);
 #endif
 
 	switch(speed) {
 #ifdef CONFIG_BLK_DEV_IDEDMA
+		case XFER_UDMA_7:
+		case XFER_UDMA_6:
+			speed = XFER_UDMA_5;
 		case XFER_UDMA_5:
-#undef __CAN_MODE_5
-#ifdef __CAN_MODE_5
 			ultra_timing |= 0x46;
 			dma_pio_timing |= 0x20;
 			break;
-#else
-			printk("%s: setting to mode 4, driver problems in mode 5.\n", drive->name);
-			speed = XFER_UDMA_4;
-#endif /* __CAN_MODE_5 */
 		case XFER_UDMA_4:
 			ultra_timing |= 0x45;
 			dma_pio_timing |= 0x20;
@@ -222,8 +220,8 @@
 	pci_write_config_byte(dev, 0x4c, pio_timing);
 
 #ifdef DEBUG
-	printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
-		ultra_timing, dma_pio_timing, pio_timing);
+	printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x\n",
+		drive->name, ultra_timing, dma_pio_timing, pio_timing);
 #endif
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -303,11 +301,12 @@
 	struct pci_dev *dev	= hwif->pci_dev;
 	struct hd_driveid *id	= drive->id;
 	byte udma_66		= eighty_ninty_three(drive);
-	byte udma_100		= (dev->device==PCI_DEVICE_ID_AMD_VIPER_7411) ? 1 : 0;
+	byte udma_100		= ((dev->device==PCI_DEVICE_ID_AMD_VIPER_7411)||
+				   (dev->device==PCI_DEVICE_ID_AMD_VIPER_7441)) ? 1 : 0;
 	byte speed		= 0x00;
 	int  rval;
 
-	if ((id->dma_ultra & 0x0020) && (udma_66)&& (udma_100)) {
+	if ((id->dma_ultra & 0x0020) && (udma_66) && (udma_100)) {
 		speed = XFER_UDMA_5;
 	} else if ((id->dma_ultra & 0x0010) && (udma_66)) {
 		speed = XFER_UDMA_4;
@@ -331,7 +330,7 @@
 
 	(void) amd74xx_tune_chipset(drive, speed);
 
-	rval = (int)(	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+	rval = (int)(	((id->dma_ultra >> 11) & 7) ? ide_dma_on :
 			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
 			((id->dma_mword >> 8) & 7) ? ide_dma_on :
 						     ide_dma_off_quietly);
@@ -352,7 +351,7 @@
 		}
 		dma_func = ide_dma_off_quietly;
 		if (id->field_valid & 4) {
-			if (id->dma_ultra & 0x002F) {
+			if (id->dma_ultra & 0x003F) {
 				/* Force if Capable UltraDMA */
 				dma_func = config_chipset_for_dma(drive);
 				if ((id->field_valid & 2) &&
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/cmd64x.c linux/drivers/ide/cmd64x.c
--- v2.5.0/linux/drivers/ide/cmd64x.c	Thu Jul 27 16:40:57 2000
+++ linux/drivers/ide/cmd64x.c	Tue Nov 27 09:23:27 2001
@@ -795,5 +795,7 @@
 		default:
 			break;
 	}
+
+	hwif->highmem = 1;
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/cs5530.c linux/drivers/ide/cs5530.c
--- v2.5.0/linux/drivers/ide/cs5530.c	Tue Jan  2 16:58:45 2001
+++ linux/drivers/ide/cs5530.c	Tue Nov 27 09:23:27 2001
@@ -352,9 +352,10 @@
 		unsigned int basereg, d0_timings;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
-		hwif->dmaproc  = &cs5530_dmaproc;
+	hwif->dmaproc  = &cs5530_dmaproc;
+	hwif->highmem = 1;
 #else
-		hwif->autodma = 0;
+	hwif->autodma = 0;
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 		hwif->tuneproc = &cs5530_tuneproc;
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/cy82c693.c linux/drivers/ide/cy82c693.c
--- v2.5.0/linux/drivers/ide/cy82c693.c	Sat May 19 17:43:06 2001
+++ linux/drivers/ide/cy82c693.c	Tue Nov 27 09:23:27 2001
@@ -441,6 +441,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
+		hwif->highmem = 1;
 		hwif->dmaproc = &cy82c693_dmaproc;
 		if (!noautodma)
 			hwif->autodma = 1;
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/hd.c linux/drivers/ide/hd.c
--- v2.5.0/linux/drivers/ide/hd.c	Mon Oct 15 13:27:42 2001
+++ linux/drivers/ide/hd.c	Tue Nov 27 09:23:27 2001
@@ -107,7 +107,6 @@
 static int hd_sizes[MAX_HD<<6];
 static int hd_blocksizes[MAX_HD<<6];
 static int hd_hardsectsizes[MAX_HD<<6];
-static int hd_maxsect[MAX_HD<<6];
 
 static struct timer_list device_timer;
 
@@ -560,19 +559,18 @@
 	dev = MINOR(CURRENT->rq_dev);
 	block = CURRENT->sector;
 	nsect = CURRENT->nr_sectors;
-	if (dev >= (NR_HD<<6) || block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) {
-#ifdef DEBUG
-		if (dev >= (NR_HD<<6))
+	if (dev >= (NR_HD<<6) || (dev & 0x3f) ||
+	    block >= hd[dev].nr_sects || ((block+nsect) > hd[dev].nr_sects)) {
+		if (dev >= (NR_HD<<6) || (dev & 0x3f))
 			printk("hd: bad minor number: device=%s\n",
 			       kdevname(CURRENT->rq_dev));
 		else
 			printk("hd%c: bad access: block=%d, count=%d\n",
 				(MINOR(CURRENT->rq_dev)>>6)+'a', block, nsect);
-#endif
 		end_request(0);
 		goto repeat;
 	}
-	block += hd[dev].start_sect;
+
 	dev >>= 6;
 	if (special_op[dev]) {
 		if (do_special_op(dev))
@@ -634,22 +632,17 @@
 			g.heads = hd_info[dev].head;
 			g.sectors = hd_info[dev].sect;
 			g.cylinders = hd_info[dev].cyl;
-			g.start = hd[MINOR(inode->i_rdev)].start_sect;
+			g.start = get_start_sect(inode->i_rdev);
 			return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
 		}
 
-         	case BLKGETSIZE:   /* Return device size */
-			return put_user(hd[MINOR(inode->i_rdev)].nr_sects, 
-					(unsigned long *) arg);
-         	case BLKGETSIZE64:
-			return put_user((u64)hd[MINOR(inode->i_rdev)].nr_sects << 9, 
-					(u64 *) arg);
-
 		case BLKRRPART: /* Re-read partition tables */
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
 			return revalidate_hddisk(inode->i_rdev, 1);
 
+         	case BLKGETSIZE:
+		case BLKGETSIZE64:
 		case BLKROSET:
 		case BLKROGET:
 		case BLKRASET:
@@ -733,11 +726,9 @@
 	for(drive=0; drive < (MAX_HD << 6); drive++) {
 		hd_blocksizes[drive] = 1024;
 		hd_hardsectsizes[drive] = 512;
-		hd_maxsect[drive]=255;
 	}
 	blksize_size[MAJOR_NR] = hd_blocksizes;
 	hardsect_size[MAJOR_NR] = hd_hardsectsizes;
-	max_sectors[MAJOR_NR] = hd_maxsect;
 
 #ifdef __i386__
 	if (!NR_HD) {
@@ -840,6 +831,7 @@
 		return -1;
 	}
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+	blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
 	read_ahead[MAJOR_NR] = 8;		/* 8 sector (4kB) read-ahead */
 	add_gendisk(&hd_gendisk);
 	init_timer(&device_timer);
@@ -868,9 +860,7 @@
 {
 	int target;
 	struct gendisk * gdev;
-	int max_p;
-	int start;
-	int i;
+	int res;
 	long flags;
 
 	target = DEVICE_NR(dev);
@@ -885,25 +875,20 @@
 	DEVICE_BUSY = 1;
 	restore_flags(flags);
 
-	max_p = gdev->max_p;
-	start = target << gdev->minor_shift;
-
-	for (i=max_p - 1; i >=0 ; i--) {
-		int minor = start + i;
-		invalidate_device(MKDEV(MAJOR_NR, minor), 1);
-		gdev->part[minor].start_sect = 0;
-		gdev->part[minor].nr_sects = 0;
-	}
+	res = wipe_partitions(dev);
+	if (res)
+		goto leave;
 
 #ifdef MAYBE_REINIT
 	MAYBE_REINIT;
 #endif
 
-	grok_partitions(gdev, target, 1<<6, CAPACITY);
+	grok_partitions(dev, CAPACITY);
 
+leave:
 	DEVICE_BUSY = 0;
 	wake_up(&busy_wait);
-	return 0;
+	return res;
 }
 
 static int parse_hd_setup (char *line) {
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/hpt34x.c linux/drivers/ide/hpt34x.c
--- v2.5.0/linux/drivers/ide/hpt34x.c	Sat May 19 17:43:06 2001
+++ linux/drivers/ide/hpt34x.c	Tue Nov 27 09:23:27 2001
@@ -425,6 +425,7 @@
 			hwif->autodma = 0;
 
 		hwif->dmaproc = &hpt34x_dmaproc;
+		hwif->highmem = 1;
 	} else {
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c
--- v2.5.0/linux/drivers/ide/hpt366.c	Tue Aug 14 20:01:07 2001
+++ linux/drivers/ide/hpt366.c	Tue Nov 27 09:23:27 2001
@@ -730,6 +730,7 @@
 			hwif->autodma = 1;
 		else
 			hwif->autodma = 0;
+		hwif->highmem = 1;
 	} else {
 		hwif->autodma = 0;
 		hwif->drives[0].autotune = 1;
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- v2.5.0/linux/drivers/ide/ide-cd.c	Wed Oct 24 23:53:51 2001
+++ linux/drivers/ide/ide-cd.c	Sat Dec  8 20:02:47 2001
@@ -533,8 +533,8 @@
 	/* stuff the sense request in front of our current request */
 	rq = &info->request_sense_request;
 	ide_init_drive_cmd(rq);
-	rq->cmd = REQUEST_SENSE_COMMAND;
-	rq->buffer = (char *) pc;
+	rq->flags = REQ_SENSE;
+	rq->special = (char *) pc;
 	rq->waiting = wait;
 	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
 }
@@ -544,17 +544,17 @@
 {
 	struct request *rq = HWGROUP(drive)->rq;
 
-	if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) {
-		struct packet_command *pc = (struct packet_command *) rq->buffer;
+	if ((rq->flags & REQ_SENSE) && uptodate) {
+		struct packet_command *pc = (struct packet_command *) rq->special;
 		cdrom_analyze_sense_data(drive,
 			(struct packet_command *) pc->sense,
 			(struct request_sense *) (pc->buffer - pc->c[4]));
 	}
-	if (rq->cmd == READ || rq->cmd == WRITE)
-		if (!rq->current_nr_sectors)
-			uptodate = 1;
 
-	ide_end_request (uptodate, HWGROUP(drive));
+	if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors)
+		uptodate = 1;
+
+	ide_end_request(uptodate, HWGROUP(drive));
 }
 
 
@@ -584,21 +584,20 @@
 		return 1;
 	}
 
-	if (rq->cmd == REQUEST_SENSE_COMMAND) {
+	if (rq->flags & REQ_SENSE) {
 		/* We got an error trying to get sense info
 		   from the drive (probably while trying
 		   to recover from a former error).  Just give up. */
 
-		pc = (struct packet_command *) rq->buffer;
+		pc = (struct packet_command *) rq->special;
 		pc->stat = 1;
 		cdrom_end_request (1, drive);
 		*startstop = ide_error (drive, "request sense failure", stat);
 		return 1;
-
-	} else if (rq->cmd == PACKET_COMMAND) {
+	} else if (rq->flags & REQ_PC) {
 		/* All other functions, except for READ. */
 		struct completion *wait = NULL;
-		pc = (struct packet_command *) rq->buffer;
+		pc = (struct packet_command *) rq->special;
 
 		/* Check for tray open. */
 		if (sense_key == NOT_READY) {
@@ -632,7 +631,7 @@
 
 		if ((stat & ERR_STAT) != 0)
 			cdrom_queue_request_sense(drive, wait, pc->sense, pc);
-	} else {
+	} else if (rq->flags & REQ_CMD) {
 		/* Handle errors from READ and WRITE requests. */
 
 		if (sense_key == NOT_READY) {
@@ -671,7 +670,8 @@
 		   queue a request sense command. */
 		if ((stat & ERR_STAT) != 0)
 			cdrom_queue_request_sense(drive, NULL, NULL, NULL);
-	}
+	} else
+		blk_dump_rq_flags(rq, "ide-cd bad flags");
 
 	/* Retry, or handle the next request. */
 	*startstop = ide_stopped;
@@ -681,7 +681,6 @@
 static int cdrom_timer_expiry(ide_drive_t *drive)
 {
 	struct request *rq = HWGROUP(drive)->rq;
-	struct packet_command *pc = (struct packet_command *) rq->buffer;
 	unsigned long wait = 0;
 
 	/*
@@ -690,7 +689,7 @@
 	 * this, but not all commands/drives support that. Let
 	 * ide_timer_expiry keep polling us for these.
 	 */
-	switch (pc->c[0]) {
+	switch (rq->cmd[0]) {
 		case GPCMD_BLANK:
 		case GPCMD_FORMAT_UNIT:
 		case GPCMD_RESERVE_RZONE_TRACK:
@@ -700,6 +699,7 @@
 			wait = 0;
 			break;
 	}
+
 	return wait;
 }
 
@@ -891,7 +891,7 @@
 	int stat;
 	int ireason, len, sectors_to_transfer, nskip;
 	struct cdrom_info *info = drive->driver_data;
-	int i, dma = info->dma, dma_error = 0;
+	int dma = info->dma, dma_error = 0;
 	ide_startstop_t startstop;
 
 	struct request *rq = HWGROUP(drive)->rq;
@@ -908,10 +908,7 @@
  
 	if (dma) {
 		if (!dma_error) {
-			for (i = rq->nr_sectors; i > 0;) {
-				i -= rq->current_nr_sectors;
-				ide_end_request(1, HWGROUP(drive));
-			}
+			__ide_end_request(HWGROUP(drive), 1, rq->nr_sectors);
 			return ide_stopped;
 		} else
 			return ide_error (drive, "dma error", stat);
@@ -926,7 +923,7 @@
 		/* If we're not done filling the current buffer, complain.
 		   Otherwise, complete the command normally. */
 		if (rq->current_nr_sectors > 0) {
-			printk ("%s: cdrom_read_intr: data underrun (%ld blocks)\n",
+			printk ("%s: cdrom_read_intr: data underrun (%u blocks)\n",
 				drive->name, rq->current_nr_sectors);
 			cdrom_end_request (0, drive);
 		} else
@@ -959,8 +956,7 @@
 
 	/* First, figure out if we need to bit-bucket
 	   any of the leading sectors. */
-	nskip = MIN ((int)(rq->current_nr_sectors - (rq->bh->b_size >> SECTOR_BITS)),
-		     sectors_to_transfer);
+	nskip = MIN(rq->current_nr_sectors - bio_sectors(rq->bio), sectors_to_transfer);
 
 	while (nskip > 0) {
 		/* We need to throw away a sector. */
@@ -1058,7 +1054,7 @@
 	   represent the number of sectors to skip at the start of a transfer
 	   will fail.  I think that this will never happen, but let's be
 	   paranoid and check. */
-	if (rq->current_nr_sectors < (rq->bh->b_size >> SECTOR_BITS) &&
+	if (rq->current_nr_sectors < bio_sectors(rq->bio) &&
 	    (rq->sector % SECTORS_PER_FRAME) != 0) {
 		printk ("%s: cdrom_read_from_buffer: buffer botch (%ld)\n",
 			drive->name, rq->sector);
@@ -1097,9 +1093,9 @@
 	nskip = (sector % SECTORS_PER_FRAME);
 	if (nskip > 0) {
 		/* Sanity check... */
-		if (rq->current_nr_sectors != (rq->bh->b_size >> SECTOR_BITS) &&
+		if (rq->current_nr_sectors != bio_sectors(rq->bio) &&
 			(rq->sector % CD_FRAMESIZE != 0)) {
-			printk ("%s: cdrom_start_read_continuation: buffer botch (%lu)\n",
+			printk ("%s: cdrom_start_read_continuation: buffer botch (%u)\n",
 				drive->name, rq->current_nr_sectors);
 			cdrom_end_request (0, drive);
 			return ide_stopped;
@@ -1120,11 +1116,7 @@
 		(65534 / CD_FRAMESIZE) : 65535);
 
 	/* Set up the command */
-	memset (&pc.c, 0, sizeof (pc.c));
-	pc.c[0] = GPCMD_READ_10;
-	pc.c[7] = (nframes >> 8);
-	pc.c[8] = (nframes & 0xff);
-	put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
+	memcpy(pc.c, rq->cmd, sizeof(pc.c));
 	pc.timeout = WAIT_CMD;
 
 	/* Send the command to the drive and return. */
@@ -1174,7 +1166,7 @@
 		sector -= nskip;
 	frame = sector / SECTORS_PER_FRAME;
 
-	memset (&pc.c, 0, sizeof (pc.c));
+	memset(rq->cmd, 0, sizeof(rq->cmd));
 	pc.c[0] = GPCMD_SEEK;
 	put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
 
@@ -1192,68 +1184,23 @@
 	return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation);
 }
 
-static inline int cdrom_merge_requests(struct request *rq, struct request *nxt)
-{
-	int ret = 1;
-
-	/*
-	 * partitions not really working, but better check anyway...
-	 */
-	if (rq->cmd == nxt->cmd && rq->rq_dev == nxt->rq_dev) {
-		rq->nr_sectors += nxt->nr_sectors;
-		rq->hard_nr_sectors += nxt->nr_sectors;
-		rq->bhtail->b_reqnext = nxt->bh;
-		rq->bhtail = nxt->bhtail;
-		list_del(&nxt->queue);
-		blkdev_release_request(nxt);
-		ret = 0;
-	}
-
-	return ret;
-}
-
 /*
- * the current request will always be the first one on the list
+ * Fix up a possibly partially-processed request so that we can
+ * start it over entirely -- remember to call prep_rq_fn again since we
+ * may have changed the layout
  */
-static void cdrom_attempt_remerge(ide_drive_t *drive, struct request *rq)
-{
-	struct list_head *entry;
-	struct request *nxt;
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_request_lock, flags);
-
-	while (1) {
-		entry = rq->queue.next;
-		if (entry == &drive->queue.queue_head)
-			break;
-
-		nxt = blkdev_entry_to_request(entry);
-		if (rq->sector + rq->nr_sectors != nxt->sector)
-			break;
-		else if (rq->nr_sectors + nxt->nr_sectors > SECTORS_MAX)
-			break;
-
-		if (cdrom_merge_requests(rq, nxt))
-			break;
-	}
-
-	spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-/* Fix up a possibly partially-processed request so that we can
-   start it over entirely, or even put it back on the request queue. */
 static void restore_request (struct request *rq)
 {
-	if (rq->buffer != rq->bh->b_data) {
-		int n = (rq->buffer - rq->bh->b_data) / SECTOR_SIZE;
-		rq->buffer = rq->bh->b_data;
+	if (rq->buffer != bio_data(rq->bio)) {
+		int n = (rq->buffer - (char *) bio_data(rq->bio)) / SECTOR_SIZE;
+		rq->buffer = bio_data(rq->bio);
 		rq->nr_sectors += n;
 		rq->sector -= n;
 	}
-	rq->current_nr_sectors = rq->bh->b_size >> SECTOR_BITS;
+	rq->hard_cur_sectors = rq->current_nr_sectors = bio_sectors(rq->bio);
 	rq->hard_nr_sectors = rq->nr_sectors;
 	rq->hard_sector = rq->sector;
+	rq->q->prep_rq_fn(rq->q, rq);
 }
 
 /*
@@ -1263,25 +1210,14 @@
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct request *rq = HWGROUP(drive)->rq;
-	int minor = MINOR (rq->rq_dev);
-
-	/* If the request is relative to a partition, fix it up to refer to the
-	   absolute address.  */
-	if (minor & PARTN_MASK) {
-		rq->sector = block;
-		minor &= ~PARTN_MASK;
-		rq->rq_dev = MKDEV(MAJOR(rq->rq_dev), minor);
-	}
 
-	/* We may be retrying this request after an error.  Fix up
-	   any weirdness which might be present in the request packet. */
 	restore_request(rq);
 
 	/* Satisfy whatever we can of this request from our cached sector. */
 	if (cdrom_read_from_buffer(drive))
 		return ide_stopped;
 
-	cdrom_attempt_remerge(drive, rq);
+	blk_attempt_remerge(&drive->queue, rq);
 
 	/* Clear the local sector buffer. */
 	info->nsectors_buffered = 0;
@@ -1311,7 +1247,7 @@
 {
 	int ireason, len, stat, thislen;
 	struct request *rq = HWGROUP(drive)->rq;
-	struct packet_command *pc = (struct packet_command *)rq->buffer;
+	struct packet_command *pc = (struct packet_command *) rq->special;
 	ide_startstop_t startstop;
 
 	/* Check for errors. */
@@ -1407,7 +1343,7 @@
 static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
 {
 	struct request *rq = HWGROUP(drive)->rq;
-	struct packet_command *pc = (struct packet_command *)rq->buffer;
+	struct packet_command *pc = (struct packet_command *) rq->special;
 
 	if (!pc->timeout)
 		pc->timeout = WAIT_CMD;
@@ -1421,7 +1357,7 @@
 {
 	int len;
 	struct request *rq = HWGROUP(drive)->rq;
-	struct packet_command *pc = (struct packet_command *)rq->buffer;
+	struct packet_command *pc = (struct packet_command *) rq->special;
 	struct cdrom_info *info = drive->driver_data;
 
 	info->dma = 0;
@@ -1460,8 +1396,8 @@
 	/* Start of retry loop. */
 	do {
 		ide_init_drive_cmd (&req);
-		req.cmd = PACKET_COMMAND;
-		req.buffer = (char *)pc;
+		req.flags = REQ_PC;
+		req.special = (char *) pc;
 		if (ide_do_drive_cmd (drive, &req, ide_wait)) {
 			printk("%s: do_drive_cmd returned stat=%02x,err=%02x\n",
 				drive->name, req.buffer[0], req.buffer[1]);
@@ -1532,7 +1468,7 @@
 {
 	int stat, ireason, len, sectors_to_transfer, uptodate;
 	struct cdrom_info *info = drive->driver_data;
-	int i, dma_error = 0, dma = info->dma;
+	int dma_error = 0, dma = info->dma;
 	ide_startstop_t startstop;
 
 	struct request *rq = HWGROUP(drive)->rq;
@@ -1559,10 +1495,7 @@
 			return ide_error(drive, "dma error", stat);
 
 		rq = HWGROUP(drive)->rq;
-		for (i = rq->nr_sectors; i > 0;) {
-			i -= rq->current_nr_sectors;
-			ide_end_request(1, HWGROUP(drive));
-		}
+		__ide_end_request(HWGROUP(drive), 1, rq->nr_sectors);
 		return ide_stopped;
 	}
 
@@ -1577,7 +1510,7 @@
 		 */
 		uptodate = 1;
 		if (rq->current_nr_sectors > 0) {
-			printk("%s: write_intr: data underrun (%ld blocks)\n",
+			printk("%s: write_intr: data underrun (%u blocks)\n",
 			drive->name, rq->current_nr_sectors);
 			uptodate = 0;
 		}
@@ -1639,18 +1572,10 @@
 	nframes = rq->nr_sectors >> 2;
 	frame = rq->sector >> 2;
 
-	memset(&pc.c, 0, sizeof(pc.c));
-	/*
-	 * we might as well use WRITE_12, but none of the device I have
-	 * support the streaming feature anyway, so who cares.
-	 */
-	pc.c[0] = GPCMD_WRITE_10;
+	memcpy(pc.c, rq->cmd, sizeof(pc.c));
 #if 0	/* the immediate bit */
 	pc.c[1] = 1 << 3;
 #endif
-	pc.c[7] = (nframes >> 8) & 0xff;
-	pc.c[8] = nframes & 0xff;
-	put_unaligned(cpu_to_be32(frame), (unsigned int *)&pc.c[2]);
 	pc.timeout = 2 * WAIT_CMD;
 
 	return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr);
@@ -1674,7 +1599,7 @@
 	 * remerge requests, often the plugging will not have had time
 	 * to do this properly
 	 */
-	cdrom_attempt_remerge(drive, rq);
+	blk_attempt_remerge(&drive->queue, rq);
 
 	info->nsectors_buffered = 0;
 
@@ -1687,6 +1612,28 @@
 	return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
 }
 
+/*
+ * just wrap this around cdrom_do_packet_command
+ */
+static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+{
+	struct packet_command pc;
+	ide_startstop_t startstop;
+
+	memset(&pc, 0, sizeof(pc));
+	memcpy(pc.c, rq->cmd, sizeof(pc.c));
+	pc.quiet = 1;
+	pc.timeout = 60 * HZ;
+	rq->special = (char *) &pc;
+
+	startstop = cdrom_do_packet_command(drive);
+	if (pc.stat)
+		rq->errors++;
+
+	return startstop;
+}
+
+
 /****************************************************************************
  * cdrom driver request routine.
  */
@@ -1696,50 +1643,45 @@
 	ide_startstop_t action;
 	struct cdrom_info *info = drive->driver_data;
 
-	switch (rq->cmd) {
-		case WRITE:
-		case READ: {
-			if (CDROM_CONFIG_FLAGS(drive)->seeking) {
-				unsigned long elpased = jiffies - info->start_seek;
-				int stat = GET_STAT();
-
-				if ((stat & SEEK_STAT) != SEEK_STAT) {
-					if (elpased < IDECD_SEEK_TIMEOUT) {
-						ide_stall_queue(drive, IDECD_SEEK_TIMER);
-						return ide_stopped;
-					}
-					printk ("%s: DSC timeout\n", drive->name);
+	if (rq->flags & REQ_CMD) {
+		if (CDROM_CONFIG_FLAGS(drive)->seeking) {
+			unsigned long elpased = jiffies - info->start_seek;
+			int stat = GET_STAT();
+
+			if ((stat & SEEK_STAT) != SEEK_STAT) {
+				if (elpased < IDECD_SEEK_TIMEOUT) {
+					ide_stall_queue(drive, IDECD_SEEK_TIMER);
+					return ide_stopped;
 				}
-				CDROM_CONFIG_FLAGS(drive)->seeking = 0;
+				printk ("%s: DSC timeout\n", drive->name);
 			}
-			if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
-				action = cdrom_start_seek (drive, block);
-			else {
-				if (rq->cmd == READ)
-					action = cdrom_start_read(drive, block);
-				else
-					action = cdrom_start_write(drive, rq);
-			}
-			info->last_block = block;
-			return action;
-		}
-
-		case PACKET_COMMAND:
-		case REQUEST_SENSE_COMMAND: {
-			return cdrom_do_packet_command(drive);
-		}
-
-		case RESET_DRIVE_COMMAND: {
-			cdrom_end_request(1, drive);
-			return ide_do_reset(drive);
+			CDROM_CONFIG_FLAGS(drive)->seeking = 0;
 		}
-
-		default: {
-			printk("ide-cd: bad cmd %d\n", rq->cmd);
-			cdrom_end_request(0, drive);
-			return ide_stopped;
+		if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap)
+			action = cdrom_start_seek (drive, block);
+		else {
+			if (rq_data_dir(rq) == READ)
+				action = cdrom_start_read(drive, block);
+			else
+				action = cdrom_start_write(drive, rq);
 		}
+		info->last_block = block;
+		return action;
+	} else if (rq->flags & (REQ_PC | REQ_SENSE)) {
+		return cdrom_do_packet_command(drive);
+	} else if (rq->flags & REQ_SPECIAL) {
+		/*
+		 * right now this can only be a reset...
+		 */
+		cdrom_end_request(1, drive);
+		return ide_do_reset(drive);
+	} else if (rq->flags & REQ_BLOCK_PC) {
+		return cdrom_do_block_pc(drive, rq);
 	}
+
+	blk_dump_rq_flags(rq, "ide-cd bad flags");
+	cdrom_end_request(0, drive);
+	return ide_stopped;
 }
 
 
@@ -2202,9 +2144,13 @@
 	pc.quiet = cgc->quiet;
 	pc.timeout = cgc->timeout;
 	pc.sense = cgc->sense;
-	return cgc->stat = cdrom_queue_packet_command(drive, &pc);
+	cgc->stat = cdrom_queue_packet_command(drive, &pc);
+	if (!cgc->stat)
+		cgc->buflen -= pc.buflen;
+	return cgc->stat;
 }
 
+
 static
 int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
 			 unsigned int cmd, unsigned long arg)
@@ -2338,7 +2284,7 @@
 	int ret;
 
 	ide_init_drive_cmd (&req);
-	req.cmd = RESET_DRIVE_COMMAND;
+	req.flags = REQ_SPECIAL;
 	ret = ide_do_drive_cmd(drive, &req, ide_wait);
 
 	/*
@@ -2711,7 +2657,6 @@
 
 	ide_add_setting(drive,	"breada_readahead",	SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
 	ide_add_setting(drive,	"file_readahead",	SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor],	NULL);
-	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
 	ide_add_setting(drive,	"dsc_overlap",		SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1,	1, &drive->dsc_overlap, NULL);
 }
 
@@ -2728,6 +2673,7 @@
 	 */
 	set_device_ro(MKDEV(HWIF(drive)->major, minor), 1);
 	set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE);
+	blk_queue_hardsect_size(&drive->queue, CD_FRAMESIZE);
 
 	drive->special.all	= 0;
 	drive->ready_stat	= 0;
@@ -2875,7 +2821,7 @@
 	MOD_INC_USE_COUNT;
 	if (info->buffer == NULL)
 		info->buffer = (char *) kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL);
-        if ((info->buffer == NULL) || (rc = cdrom_open(ip, fp))) {
+	if ((info->buffer == NULL) || (rc = cdrom_open(ip, fp))) {
 		drive->usage--;
 		MOD_DEC_USE_COUNT;
 	}
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-cd.h linux/drivers/ide/ide-cd.h
--- v2.5.0/linux/drivers/ide/ide-cd.h	Thu Nov 22 11:46:58 2001
+++ linux/drivers/ide/ide-cd.h	Tue Dec 11 09:52:26 2001
@@ -435,7 +435,7 @@
 
 	byte     curlba[3];
 	byte     nslots;
-	__u8 short slot_tablelen;
+	__u16 slot_tablelen;
 };
 
 
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-cs.c linux/drivers/ide/ide-cs.c
--- v2.5.0/linux/drivers/ide/ide-cs.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/ide/ide-cs.c	Sun Nov 25 09:48:08 2001
@@ -42,6 +42,7 @@
 #include <linux/ioport.h>
 #include <linux/hdreg.h>
 #include <linux/major.h>
+#include <linux/ide.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -226,6 +227,16 @@
 #define CFG_CHECK(fn, args...) \
 if (CardServices(fn, args) != 0) goto next_entry
 
+int idecs_register (int io_base, int ctl_base, int irq)
+{
+        hw_regs_t hw;
+        ide_init_hwif_ports(&hw, (ide_ioreg_t) io_base, (ide_ioreg_t) ctl_base, NULL);
+        hw.irq = irq;
+        hw.chipset = ide_pci; // this enables IRQ sharing w/ PCI irqs
+        return ide_register_hw(&hw, NULL);
+}
+
+
 void ide_config(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
@@ -327,12 +338,16 @@
     if (link->io.NumPorts2)
 	release_region(link->io.BasePort2, link->io.NumPorts2);
 
+    /* disable drive interrupts during IDE probe */
+    if(ctl_base)
+    	outb(0x02, ctl_base);
+
     /* retry registration in case device is still spinning up */
     for (i = 0; i < 10; i++) {
-	hd = ide_register(io_base, ctl_base, link->irq.AssignedIRQ);
+	hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
 	if (hd >= 0) break;
 	if (link->io.NumPorts1 == 0x20) {
-	    hd = ide_register(io_base+0x10, ctl_base+0x10,
+	    hd = idecs_register(io_base+0x10, ctl_base+0x10,
 			      link->irq.AssignedIRQ);
 	    if (hd >= 0) {
 		io_base += 0x10; ctl_base += 0x10;
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- v2.5.0/linux/drivers/ide/ide-disk.c	Tue Nov 20 21:35:28 2001
+++ linux/drivers/ide/ide-disk.c	Thu Dec  6 14:02:57 2001
@@ -27,6 +27,7 @@
  * Version 1.09		added increment of rq->sector in ide_multwrite
  *			added UDMA 3/4 reporting
  * Version 1.10		request queue changes, Ultra DMA 100
+ * Version 1.11		Highmem I/O support, Jens Axboe <axboe@suse.de>
  */
 
 #define IDEDISK_VERSION	"1.10"
@@ -139,7 +140,9 @@
 	byte stat;
 	int i;
 	unsigned int msect, nsect;
+	unsigned long flags;
 	struct request *rq;
+	char *to;
 
 	/* new way for dealing with premature shared PCI interrupts */
 	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
@@ -150,8 +153,8 @@
 		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
 		return ide_started;
 	}
+
 	msect = drive->mult_count;
-	
 read_next:
 	rq = HWGROUP(drive)->rq;
 	if (msect) {
@@ -160,14 +163,15 @@
 		msect -= nsect;
 	} else
 		nsect = 1;
-	idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
+	to = ide_map_buffer(rq, &flags);
+	idedisk_input_data(drive, to, nsect * SECTOR_WORDS);
 #ifdef DEBUG
 	printk("%s:  read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n",
 		drive->name, rq->sector, rq->sector+nsect-1,
 		(unsigned long) rq->buffer+(nsect<<9), rq->nr_sectors-nsect);
 #endif
+	ide_unmap_buffer(to, &flags);
 	rq->sector += nsect;
-	rq->buffer += nsect<<9;
 	rq->errors = 0;
 	i = (rq->nr_sectors -= nsect);
 	if (((long)(rq->current_nr_sectors -= nsect)) <= 0)
@@ -201,14 +205,16 @@
 #endif
 		if ((rq->nr_sectors == 1) ^ ((stat & DRQ_STAT) != 0)) {
 			rq->sector++;
-			rq->buffer += 512;
 			rq->errors = 0;
 			i = --rq->nr_sectors;
 			--rq->current_nr_sectors;
 			if (((long)rq->current_nr_sectors) <= 0)
 				ide_end_request(1, hwgroup);
 			if (i > 0) {
-				idedisk_output_data (drive, rq->buffer, SECTOR_WORDS);
+				unsigned long flags;
+				char *to = ide_map_buffer(rq, &flags);
+				idedisk_output_data (drive, to, SECTOR_WORDS);
+				ide_unmap_buffer(to, &flags);
 				ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
                                 return ide_started;
 			}
@@ -238,28 +244,28 @@
   	do {
   		char *buffer;
   		int nsect = rq->current_nr_sectors;
- 
+		unsigned long flags;
+
 		if (nsect > mcount)
 			nsect = mcount;
 		mcount -= nsect;
-		buffer = rq->buffer;
 
+		buffer = ide_map_buffer(rq, &flags);
 		rq->sector += nsect;
-		rq->buffer += nsect << 9;
 		rq->nr_sectors -= nsect;
 		rq->current_nr_sectors -= nsect;
 
 		/* Do we move to the next bh after this? */
 		if (!rq->current_nr_sectors) {
-			struct buffer_head *bh = rq->bh->b_reqnext;
+			struct bio *bio = rq->bio->bi_next;
 
 			/* end early early we ran out of requests */
-			if (!bh) {
+			if (!bio) {
 				mcount = 0;
 			} else {
-				rq->bh = bh;
-				rq->current_nr_sectors = bh->b_size >> 9;
-				rq->buffer             = bh->b_data;
+				rq->bio = bio;
+				rq->current_nr_sectors = bio_sectors(bio);
+				rq->hard_cur_sectors = rq->current_nr_sectors;
 			}
 		}
 
@@ -268,6 +274,7 @@
 		 * re-entering us on the last transfer.
 		 */
 		idedisk_output_data(drive, buffer, nsect<<7);
+		ide_unmap_buffer(buffer, &flags);
 	} while (mcount);
 
         return 0;
@@ -279,7 +286,6 @@
 static ide_startstop_t multwrite_intr (ide_drive_t *drive)
 {
 	byte stat;
-	int i;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	struct request *rq = &hwgroup->wrq;
 
@@ -302,10 +308,8 @@
 			 */
 			if (!rq->nr_sectors) {	/* all done? */
 				rq = hwgroup->rq;
-				for (i = rq->nr_sectors; i > 0;){
-					i -= rq->current_nr_sectors;
-					ide_end_request(1, hwgroup);
-				}
+
+				__ide_end_request(hwgroup, 1, rq->nr_sectors);
 				return ide_stopped;
 			}
 		}
@@ -367,6 +371,8 @@
  */
 static ide_startstop_t do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
 {
+	unsigned long flags;
+
 	if (IDE_CONTROL_REG)
 		OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
 	OUT_BYTE(0x00, IDE_FEATURE_REG);
@@ -378,7 +384,7 @@
 #endif /* CONFIG_BLK_DEV_PDC4030 */
 #ifdef DEBUG
 		printk("%s: %sing: LBAsect=%ld, sectors=%ld, buffer=0x%08lx\n",
-			drive->name, (rq->cmd==READ)?"read":"writ",
+			drive->name, (rq_data_dir(rq)==READ)?"read":"writ",
 			block, rq->nr_sectors, (unsigned long) rq->buffer);
 #endif
 		OUT_BYTE(block,IDE_SECTOR_REG);
@@ -397,7 +403,7 @@
 		OUT_BYTE(head|drive->select.all,IDE_SELECT_REG);
 #ifdef DEBUG
 		printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n",
-			drive->name, (rq->cmd==READ)?"read":"writ", cyl,
+			drive->name, (rq_data_dir(rq)==READ)?"read":"writ", cyl,
 			head, sect, rq->nr_sectors, (unsigned long) rq->buffer);
 #endif
 	}
@@ -407,7 +413,7 @@
 		return do_pdc4030_io (drive, rq);
 	}
 #endif /* CONFIG_BLK_DEV_PDC4030 */
-	if (rq->cmd == READ) {
+	if (rq_data_dir(rq) == READ) {
 #ifdef CONFIG_BLK_DEV_IDEDMA
 		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
 			return ide_started;
@@ -416,7 +422,7 @@
 		OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
 		return ide_started;
 	}
-	if (rq->cmd == WRITE) {
+	if (rq_data_dir(rq) == WRITE) {
 		ide_startstop_t startstop;
 #ifdef CONFIG_BLK_DEV_IDEDMA
 		if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
@@ -444,20 +450,21 @@
 			hwgroup->wrq = *rq; /* scratchpad */
 			ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
 			if (ide_multwrite(drive, drive->mult_count)) {
-				unsigned long flags;
-				spin_lock_irqsave(&io_request_lock, flags);
+				spin_lock_irqsave(&ide_lock, flags);
 				hwgroup->handler = NULL;
 				del_timer(&hwgroup->timer);
-				spin_unlock_irqrestore(&io_request_lock, flags);
+				spin_unlock_irqrestore(&ide_lock, flags);
 				return ide_stopped;
 			}
 		} else {
+			char *buffer = ide_map_buffer(rq, &flags);
 			ide_set_handler (drive, &write_intr, WAIT_CMD, NULL);
-			idedisk_output_data(drive, rq->buffer, SECTOR_WORDS);
+			idedisk_output_data(drive, buffer, SECTOR_WORDS);
+			ide_unmap_buffer(buffer, &flags);
 		}
 		return ide_started;
 	}
-	printk(KERN_ERR "%s: bad command: %d\n", drive->name, rq->cmd);
+	printk(KERN_ERR "%s: bad command: %lx\n", drive->name, rq->flags);
 	ide_end_request(0, HWGROUP(drive));
 	return ide_stopped;
 }
@@ -482,7 +489,8 @@
 {
 	if (drive->removable && !drive->usage) {
 		invalidate_bdev(inode->i_bdev, 0);
-		if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL))
+		if (drive->doorlocking &&
+		    ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL))
 			drive->doorlocking = 0;
 	}
 	MOD_DEC_USE_COUNT;
@@ -495,9 +503,7 @@
 
 static void idedisk_revalidate (ide_drive_t *drive)
 {
-	grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
-			1<<PARTN_BITS,
-			current_capacity(drive));
+	ide_revalidate_drive(drive);
 }
 
 /*
@@ -673,7 +679,7 @@
 		return -EBUSY;
 	drive->nowerr = arg;
 	drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
-	spin_unlock_irq(&io_request_lock);
+	spin_unlock_irq(&ide_lock);
 	return 0;
 }
 
@@ -691,7 +697,6 @@
 	ide_add_setting(drive,	"nowerr",		SETTING_RW,					HDIO_GET_NOWERR,	HDIO_SET_NOWERR,	TYPE_BYTE,	0,	1,				1,	1,	&drive->nowerr,			set_nowerr);
 	ide_add_setting(drive,	"breada_readahead",	SETTING_RW,					BLKRAGET,		BLKRASET,		TYPE_INT,	0,	255,				1,	2,	&read_ahead[major],		NULL);
 	ide_add_setting(drive,	"file_readahead",	SETTING_RW,					BLKFRAGET,		BLKFRASET,		TYPE_INTA,	0,	4096,			PAGE_SIZE,	1024,	&max_readahead[major][minor],	NULL);
-	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW,					BLKSECTGET,		BLKSECTSET,		TYPE_INTA,	1,	255,				1,	2,	&max_sectors[major][minor],	NULL);
 	ide_add_setting(drive,	"lun",			SETTING_RW,					-1,			-1,			TYPE_INT,	0,	7,				1,	1,	&drive->lun,			NULL);
 	ide_add_setting(drive,	"failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->failures,		NULL);
 	ide_add_setting(drive,	"max_failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->max_failures,		NULL);
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-dma.c linux/drivers/ide/ide-dma.c
--- v2.5.0/linux/drivers/ide/ide-dma.c	Sun Sep  9 10:43:02 2001
+++ linux/drivers/ide/ide-dma.c	Mon Dec 10 14:15:19 2001
@@ -203,30 +203,10 @@
 #endif /* CONFIG_IDEDMA_NEW_DRIVE_LISTINGS */
 
 /*
- * Our Physical Region Descriptor (PRD) table should be large enough
- * to handle the biggest I/O request we are likely to see.  Since requests
- * can have no more than 256 sectors, and since the typical blocksize is
- * two or more sectors, we could get by with a limit of 128 entries here for
- * the usual worst case.  Most requests seem to include some contiguous blocks,
- * further reducing the number of table entries required.
- *
- * The driver reverts to PIO mode for individual requests that exceed
- * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
- * 100% of all crazy scenarios here is not necessary.
- *
- * As it turns out though, we must allocate a full 4KB page for this,
- * so the two PRD tables (ide0 & ide1) will each get half of that,
- * allowing each to have about 256 entries (8 bytes each) from this.
- */
-#define PRD_BYTES	8
-#define PRD_ENTRIES	(PAGE_SIZE / (2 * PRD_BYTES))
-
-/*
  * dma_intr() is the handler for disk read/write DMA interrupts
  */
 ide_startstop_t ide_dma_intr (ide_drive_t *drive)
 {
-	int i;
 	byte stat, dma_stat;
 
 	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
@@ -234,11 +214,8 @@
 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
 		if (!dma_stat) {
 			struct request *rq = HWGROUP(drive)->rq;
-			rq = HWGROUP(drive)->rq;
-			for (i = rq->nr_sectors; i > 0;) {
-				i -= rq->current_nr_sectors;
-				ide_end_request(1, HWGROUP(drive));
-			}
+
+			__ide_end_request(HWGROUP(drive), 1, rq->nr_sectors);
 			return ide_stopped;
 		}
 		printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
@@ -249,35 +226,19 @@
 
 static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq)
 {
-	struct buffer_head *bh;
+	request_queue_t *q = &hwif->drives[DEVICE_NR(rq->rq_dev) & 1].queue;
 	struct scatterlist *sg = hwif->sg_table;
-	int nents = 0;
+	int nents;
+
+	nents = blk_rq_map_sg(q, rq, hwif->sg_table);
+
+	if (rq->q && nents > rq->nr_segments)
+		printk("ide-dma: received %d segments, build %d\n", rq->nr_segments, nents);
 
-	if (hwif->sg_dma_active)
-		BUG();
-		
-	if (rq->cmd == READ)
+	if (rq_data_dir(rq) == READ)
 		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
 	else
 		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-	bh = rq->bh;
-	do {
-		unsigned char *virt_addr = bh->b_data;
-		unsigned int size = bh->b_size;
-
-		if (nents >= PRD_ENTRIES)
-			return 0;
-
-		while ((bh = bh->b_reqnext) != NULL) {
-			if ((virt_addr + size) != (unsigned char *) bh->b_data)
-				break;
-			size += bh->b_size;
-		}
-		memset(&sg[nents], 0, sizeof(*sg));
-		sg[nents].address = virt_addr;
-		sg[nents].length = size;
-		nents++;
-	} while (bh != NULL);
 
 	return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
 }
@@ -289,9 +250,10 @@
  */
 int ide_build_dmatable (ide_drive_t *drive, ide_dma_action_t func)
 {
-	unsigned int *table = HWIF(drive)->dmatable_cpu;
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned int *table = hwif->dmatable_cpu;
 #ifdef CONFIG_BLK_DEV_TRM290
-	unsigned int is_trm290_chipset = (HWIF(drive)->chipset == ide_trm290);
+	unsigned int is_trm290_chipset = (hwif->chipset == ide_trm290);
 #else
 	const int is_trm290_chipset = 0;
 #endif
@@ -299,13 +261,12 @@
 	int i;
 	struct scatterlist *sg;
 
-	HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
-
+	hwif->sg_nents = i = ide_build_sglist(hwif, HWGROUP(drive)->rq);
 	if (!i)
 		return 0;
 
-	sg = HWIF(drive)->sg_table;
-	while (i && sg_dma_len(sg)) {
+	sg = hwif->sg_table;
+	while (i) {
 		u32 cur_addr;
 		u32 cur_len;
 
@@ -319,55 +280,53 @@
 		 */
 
 		while (cur_len) {
+			u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
+
 			if (count++ >= PRD_ENTRIES) {
-				printk("%s: DMA table too small\n", drive->name);
-				goto use_pio_instead;
-			} else {
-				u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
-
-				if (bcount > cur_len)
-					bcount = cur_len;
-				*table++ = cpu_to_le32(cur_addr);
-				xcount = bcount & 0xffff;
-				if (is_trm290_chipset)
-					xcount = ((xcount >> 2) - 1) << 16;
-				if (xcount == 0x0000) {
-					/* 
-					 * Most chipsets correctly interpret a length of 0x0000 as 64KB,
-					 * but at least one (e.g. CS5530) misinterprets it as zero (!).
-					 * So here we break the 64KB entry into two 32KB entries instead.
-					 */
-					if (count++ >= PRD_ENTRIES) {
-						printk("%s: DMA table too small\n", drive->name);
-						goto use_pio_instead;
-					}
-					*table++ = cpu_to_le32(0x8000);
-					*table++ = cpu_to_le32(cur_addr + 0x8000);
-					xcount = 0x8000;
+				printk("ide-dma: req %p\n", HWGROUP(drive)->rq);
+				printk("count %d, sg_nents %d, cur_len %d, cur_addr %u\n", count, hwif->sg_nents, cur_len, cur_addr);
+				BUG();
+			}
+
+			if (bcount > cur_len)
+				bcount = cur_len;
+			*table++ = cpu_to_le32(cur_addr);
+			xcount = bcount & 0xffff;
+			if (is_trm290_chipset)
+				xcount = ((xcount >> 2) - 1) << 16;
+			if (xcount == 0x0000) {
+		        /* 
+			 * Most chipsets correctly interpret a length of
+			 * 0x0000 as 64KB, but at least one (e.g. CS5530)
+			 * misinterprets it as zero (!). So here we break
+			 * the 64KB entry into two 32KB entries instead.
+			 */
+				if (count++ >= PRD_ENTRIES) {
+					pci_unmap_sg(hwif->pci_dev, sg,
+						     hwif->sg_nents,
+						     hwif->sg_dma_direction);
+					return 0;
 				}
-				*table++ = cpu_to_le32(xcount);
-				cur_addr += bcount;
-				cur_len -= bcount;
+
+				*table++ = cpu_to_le32(0x8000);
+				*table++ = cpu_to_le32(cur_addr + 0x8000);
+				xcount = 0x8000;
 			}
+			*table++ = cpu_to_le32(xcount);
+			cur_addr += bcount;
+			cur_len -= bcount;
 		}
 
 		sg++;
 		i--;
 	}
 
-	if (count) {
-		if (!is_trm290_chipset)
-			*--table |= cpu_to_le32(0x80000000);
-		return count;
-	}
-	printk("%s: empty DMA table?\n", drive->name);
-use_pio_instead:
-	pci_unmap_sg(HWIF(drive)->pci_dev,
-		     HWIF(drive)->sg_table,
-		     HWIF(drive)->sg_nents,
-		     HWIF(drive)->sg_dma_direction);
-	HWIF(drive)->sg_dma_active = 0;
-	return 0; /* revert to PIO for this request */
+	if (!count)
+		printk("%s: empty DMA table?\n", drive->name);
+	else if (!is_trm290_chipset)
+		*--table |= cpu_to_le32(0x80000000);
+
+	return count;
 }
 
 /* Teardown mappings after DMA has completed.  */
@@ -378,7 +337,6 @@
 	int nents = HWIF(drive)->sg_nents;
 
 	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
-	HWIF(drive)->sg_dma_active = 0;
 }
 
 /*
@@ -532,6 +490,20 @@
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */
 
+static void ide_toggle_bounce(ide_drive_t *drive, int on)
+{
+	dma64_addr_t addr = BLK_BOUNCE_HIGH;
+
+	if (on && drive->media == ide_disk && HWIF(drive)->highmem) {
+		if (!PCI_DMA_BUS_IS_PHYS)
+			addr = BLK_BOUNCE_ANY;
+		else
+			addr = HWIF(drive)->pci_dev->dma_mask;
+	}
+
+	blk_queue_bounce_limit(&drive->queue, addr);
+}
+
 /*
  * ide_dmaproc() initiates/aborts DMA read/write operations on a drive.
  *
@@ -550,19 +522,20 @@
  */
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-//	ide_hwgroup_t *hwgroup		= HWGROUP(drive);
-	ide_hwif_t *hwif		= HWIF(drive);
-	unsigned long dma_base		= hwif->dma_base;
-	byte unit			= (drive->select.b.unit & 0x01);
-	unsigned int count, reading	= 0;
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long dma_base = hwif->dma_base;
+	byte unit = (drive->select.b.unit & 0x01);
+	unsigned int count, reading = 0, set_high = 1;
 	byte dma_stat;
 
 	switch (func) {
 		case ide_dma_off:
 			printk("%s: DMA disabled\n", drive->name);
+			set_high = 0;
 		case ide_dma_off_quietly:
 			outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
 		case ide_dma_on:
+			ide_toggle_bounce(drive, set_high);
 			drive->using_dma = (func == ide_dma_on);
 			if (drive->using_dma)
 				outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c
--- v2.5.0/linux/drivers/ide/ide-floppy.c	Thu Oct 11 09:14:32 2001
+++ linux/drivers/ide/ide-floppy.c	Fri Nov 30 08:33:50 2001
@@ -707,24 +707,24 @@
 static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
 {
 	struct request *rq = pc->rq;
-	struct buffer_head *bh = rq->bh;
+	struct bio *bio = rq->bio;
 	int count;
 
 	while (bcount) {
-		if (pc->b_count == bh->b_size) {
+		if (pc->b_count == bio->bi_size) {
 			rq->sector += rq->current_nr_sectors;
 			rq->nr_sectors -= rq->current_nr_sectors;
 			idefloppy_end_request (1, HWGROUP(drive));
-			if ((bh = rq->bh) != NULL)
+			if ((bio = rq->bio) != NULL)
 				pc->b_count = 0;
 		}
-		if (bh == NULL) {
-			printk (KERN_ERR "%s: bh == NULL in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount);
+		if (bio == NULL) {
+			printk (KERN_ERR "%s: bio == NULL in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount);
 			idefloppy_discard_data (drive, bcount);
 			return;
 		}
-		count = IDEFLOPPY_MIN (bh->b_size - pc->b_count, bcount);
-		atapi_input_bytes (drive, bh->b_data + pc->b_count, count);
+		count = IDEFLOPPY_MIN (bio->bi_size - pc->b_count, bcount);
+		atapi_input_bytes (drive, bio_data(bio) + pc->b_count, count);
 		bcount -= count; pc->b_count += count;
 	}
 }
@@ -732,7 +732,7 @@
 static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
 {
 	struct request *rq = pc->rq;
-	struct buffer_head *bh = rq->bh;
+	struct bio *bio = rq->bio;
 	int count;
 	
 	while (bcount) {
@@ -740,13 +740,13 @@
 			rq->sector += rq->current_nr_sectors;
 			rq->nr_sectors -= rq->current_nr_sectors;
 			idefloppy_end_request (1, HWGROUP(drive));
-			if ((bh = rq->bh) != NULL) {
-				pc->b_data = bh->b_data;
-				pc->b_count = bh->b_size;
+			if ((bio = rq->bio) != NULL) {
+				pc->b_data = bio_data(bio);
+				pc->b_count = bio->bi_size;
 			}
 		}
-		if (bh == NULL) {
-			printk (KERN_ERR "%s: bh == NULL in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
+		if (bio == NULL) {
+			printk (KERN_ERR "%s: bio == NULL in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
 			idefloppy_write_zeros (drive, bcount);
 			return;
 		}
@@ -760,9 +760,9 @@
 static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
 {
 	struct request *rq = pc->rq;
-	struct buffer_head *bh = rq->bh;
+	struct bio *bio = rq->bio;
 
-	while ((bh = rq->bh) != NULL)
+	while ((bio = rq->bio) != NULL)
 		idefloppy_end_request (1, HWGROUP(drive));
 }
 #endif /* CONFIG_BLK_DEV_IDEDMA */
@@ -1210,7 +1210,7 @@
 	pc->callback = &idefloppy_rw_callback;
 	pc->rq = rq;
 	pc->b_data = rq->buffer;
-	pc->b_count = rq->cmd == READ ? 0 : rq->bh->b_size;
+	pc->b_count = rq->cmd == READ ? 0 : rq->bio->bi_size;
 	if (rq->cmd == WRITE)
 		set_bit (PC_WRITING, &pc->flags);
 	pc->buffer = NULL;
@@ -1778,9 +1778,7 @@
  */
 static void idefloppy_revalidate (ide_drive_t *drive)
 {
-	grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
-			1<<PARTN_BITS,
-			current_capacity(drive));
+	ide_revalidate_drive(drive);
 }
 
 /*
@@ -1920,7 +1918,6 @@
 	ide_add_setting(drive,	"bios_sect",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	63,				1,	1,	&drive->bios_sect,		NULL);
 	ide_add_setting(drive,	"breada_readahead",	SETTING_RW,					BLKRAGET,		BLKRASET,		TYPE_INT,	0,	255,				1,	2,	&read_ahead[major],		NULL);
 	ide_add_setting(drive,	"file_readahead",	SETTING_RW,					BLKFRAGET,		BLKFRASET,		TYPE_INTA,	0,	INT_MAX,			1,	1024,	&max_readahead[major][minor],	NULL);
-	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW,					BLKSECTGET,		BLKSECTSET,		TYPE_INTA,	1,	255,				1,	2,	&max_sectors[major][minor],	NULL);
 
 }
 
@@ -1930,8 +1927,7 @@
 static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
 {
 	struct idefloppy_id_gcw gcw;
-	int major = HWIF(drive)->major, i;
-	int minor = drive->select.b.unit << PARTN_BITS;
+	int i;
 
 	*((unsigned short *) &gcw) = drive->id->config;
 	drive->driver_data = floppy;
@@ -1953,34 +1949,17 @@
 	 */
 
 	if (strcmp(drive->id->model, "IOMEGA ZIP 100 ATAPI") == 0)
-	{
-		for (i = 0; i < 1 << PARTN_BITS; i++)
-			max_sectors[major][minor + i] = 64;
-	}
-  /*
-   *      Guess what?  The IOMEGA Clik! drive also needs the
-   *      above fix.  It makes nasty clicking noises without
-   *      it, so please don't remove this.
-   */
-  if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0)
-  {
-    for (i = 0; i < 1 << PARTN_BITS; i++)
-      max_sectors[major][minor + i] = 64;
-    set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
-  }
+		blk_queue_max_sectors(&drive->queue, 64);
 
 	/*
 	*      Guess what?  The IOMEGA Clik! drive also needs the
 	*      above fix.  It makes nasty clicking noises without
 	*      it, so please don't remove this.
 	*/
-	if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) 
-	{
-		for (i = 0; i < 1 << PARTN_BITS; i++)
-			max_sectors[major][minor + i] = 64;
+	if (strcmp(drive->id->model, "IOMEGA Clik! 40 CZ ATAPI") == 0) {
+		blk_queue_max_sectors(&drive->queue, 64);
 		set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
 	}
-
 
 	(void) idefloppy_get_capacity (drive);
 	idefloppy_add_settings(drive);
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c
--- v2.5.0/linux/drivers/ide/ide-pci.c	Thu Oct 25 13:53:47 2001
+++ linux/drivers/ide/ide-pci.c	Fri Nov 30 15:53:51 2001
@@ -30,14 +30,14 @@
 #define DEVID_MPIIX	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371MX})
 #define DEVID_PIIX3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371SB_1})
 #define DEVID_PIIX4	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371AB})
-#define DEVID_PIIX4E	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AB_1})
+#define DEVID_ICH0	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AB_1})
 #define DEVID_PIIX4E2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82443MX_1})
-#define DEVID_PIIX4U	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AA_1})
+#define DEVID_ICH	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AA_1})
 #define DEVID_PIIX4U2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82372FB_1})
 #define DEVID_PIIX4NX	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82451NX})
-#define DEVID_PIIX4U3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_9})
-#define DEVID_PIIX4U4	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_8})
-#define DEVID_PIIX4U5	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801CA_10})
+#define DEVID_ICH2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_9})
+#define DEVID_ICH2M	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801BA_8})
+#define DEVID_ICH3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801CA_10})
 #define DEVID_VIA_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C561})
 #define DEVID_MR_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C576_1})
 #define DEVID_VP_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C586_1})
@@ -79,6 +79,7 @@
 #define DEVID_AMD7401	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_COBRA_7401})
 #define DEVID_AMD7409	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7409})
 #define DEVID_AMD7411	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7411})
+#define DEVID_AMD7441	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7441})
 #define DEVID_PDCADMA	((ide_pci_devid_t){PCI_VENDOR_ID_PDC,     PCI_DEVICE_ID_PDC_1841})
 #define DEVID_SLC90E66	((ide_pci_devid_t){PCI_VENDOR_ID_EFAR,    PCI_DEVICE_ID_EFAR_SLC90E66_1})
 #define DEVID_OSB4	((ide_pci_devid_t){PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4IDE})
@@ -379,14 +380,14 @@
 	{DEVID_MPIIX,	"MPIIX",	NULL,		NULL,		INIT_PIIX,	NULL,		{{0x6D,0x80,0x80}, {0x6F,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX3,	"PIIX3",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
 	{DEVID_PIIX4,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
-	{DEVID_PIIX4E,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_ICH0,	"ICH0",		PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX4E2,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
-	{DEVID_PIIX4U,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_ICH,	"ICH",		PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX4U2,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX4NX,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
-	{DEVID_PIIX4U3,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
-	{DEVID_PIIX4U4, "PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
-	{DEVID_PIIX4U5, "PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_ICH2,	"ICH2",		PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_ICH2M,	"ICH2-M",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_ICH3,	"ICH3",		PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_VIA_IDE,	"VIA_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_MR_IDE,	"VP_IDE",	PCI_VIA82CXXX,	ATA66_VIA82CXXX,INIT_VIA82CXXX,	DMA_VIA82CXXX,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
 	{DEVID_VP_IDE,	"VP_IDE",	PCI_VIA82CXXX,	ATA66_VIA82CXXX,INIT_VIA82CXXX,	DMA_VIA82CXXX,	{{0x40,0x02,0x02}, {0x40,0x01,0x01}}, 	ON_BOARD,	0 },
@@ -437,6 +438,7 @@
 	{DEVID_AMD7401,	"AMD7401",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_AMD7409,	"AMD7409",	PCI_AMD74XX,	ATA66_AMD74XX,	INIT_AMD74XX,	DMA_AMD74XX,	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
 	{DEVID_AMD7411,	"AMD7411",	PCI_AMD74XX,	ATA66_AMD74XX,	INIT_AMD74XX,	DMA_AMD74XX,	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
+	{DEVID_AMD7441, "AMD7441",	PCI_AMD74XX,	ATA66_AMD74XX,	INIT_AMD74XX,	DMA_AMD74XX,	{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
 	{DEVID_PDCADMA,	"PDCADMA",	PCI_PDCADMA,	ATA66_PDCADMA,	INIT_PDCADMA,	DMA_PDCADMA,	{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	OFF_BOARD,	0 },
 	{DEVID_SLC90E66,"SLC90E66",	PCI_SLC90E66,	ATA66_SLC90E66,	INIT_SLC90E66,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
         {DEVID_OSB4,    "ServerWorks OSB4",		PCI_SVWKS,	ATA66_SVWKS,	INIT_SVWKS,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
@@ -840,7 +842,7 @@
 
 	switch(class_rev) {
 		case 4:
-		case 3:	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+		case 3:	printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
 			ide_setup_pci_device(dev, d);
 			return;
 		default:	break;
@@ -869,12 +871,12 @@
 			break;
 		}
 	}
-	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+	printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
 	ide_setup_pci_device(dev, d);
 	if (!dev2)
 		return;
 	d2 = d;
-	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn);
+	printk("%s: IDE controller on PCI slot %s\n", d2->name, dev2->slot_name);
 	ide_setup_pci_device(dev2, d2);
 }
 
@@ -904,10 +906,10 @@
 		hpt366_device_order_fixup(dev, d);
 	else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
 		if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL))
-			printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n",
-			       d->name, dev->bus->number, dev->devfn, devid.vid, devid.did);
+			printk("%s: unknown IDE controller on PCI slot %s, VID=%04x, DID=%04x\n",
+			       d->name, dev->slot_name, devid.vid, devid.did);
 		else
-			printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+			printk("%s: IDE controller on PCI slot %s\n", d->name, dev->slot_name);
 		ide_setup_pci_device(dev, d);
 	}
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c
--- v2.5.0/linux/drivers/ide/ide-probe.c	Thu Oct 11 09:14:32 2001
+++ linux/drivers/ide/ide-probe.c	Wed Nov 28 13:16:56 2001
@@ -594,9 +594,22 @@
 static void ide_init_queue(ide_drive_t *drive)
 {
 	request_queue_t *q = &drive->queue;
+	int max_sectors;
 
 	q->queuedata = HWGROUP(drive);
 	blk_init_queue(q, do_ide_request);
+	blk_queue_segment_boundary(q, 0xffff);
+
+	/* IDE can do up to 128K per request, pdc4030 needs smaller limit */
+#ifdef CONFIG_BLK_DEV_PDC4030
+	max_sectors = 127;
+#else
+	max_sectors = 255;
+#endif
+	blk_queue_max_sectors(q, max_sectors);
+
+	/* IDE DMA can do PRD_ENTRIES number of segments */
+	q->max_segments = PRD_ENTRIES;
 }
 
 /*
@@ -670,7 +683,7 @@
 		hwgroup->rq       = NULL;
 		hwgroup->handler  = NULL;
 		hwgroup->drive    = NULL;
-		hwgroup->busy     = 0;
+		hwgroup->flags	  = 0;
 		init_timer(&hwgroup->timer);
 		hwgroup->timer.function = &ide_timer_expiry;
 		hwgroup->timer.data = (unsigned long) hwgroup;
@@ -749,7 +762,7 @@
 {
 	struct gendisk *gd;
 	unsigned int unit, units, minors;
-	int *bs, *max_sect, *max_ra;
+	int *bs, *max_ra;
 	extern devfs_handle_t ide_devfs_handle;
 
 	/* figure out maximum drive number on the interface */
@@ -762,23 +775,15 @@
 	gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
 	gd->part  = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
 	bs        = kmalloc (minors*sizeof(int), GFP_KERNEL);
-	max_sect  = kmalloc (minors*sizeof(int), GFP_KERNEL);
 	max_ra    = kmalloc (minors*sizeof(int), GFP_KERNEL);
 
 	memset(gd->part, 0, minors * sizeof(struct hd_struct));
 
 	/* cdroms and msdos f/s are examples of non-1024 blocksizes */
 	blksize_size[hwif->major] = bs;
-	max_sectors[hwif->major] = max_sect;
 	max_readahead[hwif->major] = max_ra;
 	for (unit = 0; unit < minors; ++unit) {
 		*bs++ = BLOCK_SIZE;
-#ifdef CONFIG_BLK_DEV_PDC4030
-		*max_sect++ = ((hwif->chipset == ide_pdc4030) ? 127 : 255);
-#else
-		/* IDE can do up to 128K per request. */
-		*max_sect++ = 255;
-#endif
 		*max_ra++ = MAX_READAHEAD;
 	}
 
@@ -870,13 +875,6 @@
 	read_ahead[hwif->major] = 8;	/* (4kB) */
 	hwif->present = 1;	/* success */
 
-#if (DEBUG_SPINLOCK > 0)
-{
-	static int done = 0;
-	if (!done++)
-		printk("io_request_lock is %p\n", &io_request_lock);    /* FIXME */
-}
-#endif
 	return hwif->present;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-proc.c linux/drivers/ide/ide-proc.c
--- v2.5.0/linux/drivers/ide/ide-proc.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/ide/ide-proc.c	Tue Nov 27 09:23:27 2001
@@ -190,7 +190,7 @@
 			if (hwif->mate && hwif->mate->hwgroup)
 				mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
 			cli();	/* all CPUs; ensure all writes are done together */
-			while (mygroup->busy || (mategroup && mategroup->busy)) {
+			while (test_bit(IDE_BUSY, &mygroup->flags) || (mategroup && test_bit(IDE_BUSY, &mategroup->flags))) {
 				sti();	/* all CPUs */
 				if (0 < (signed long)(jiffies - timeout)) {
 					printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name);
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide-tape.c linux/drivers/ide/ide-tape.c
--- v2.5.0/linux/drivers/ide/ide-tape.c	Mon Aug 13 14:56:19 2001
+++ linux/drivers/ide/ide-tape.c	Mon Dec 10 14:15:19 2001
@@ -5488,7 +5488,6 @@
 	idetape_pc_t pc;
 	unsigned int minor=MINOR (inode->i_rdev);
 
-	lock_kernel();
 	tape = drive->driver_data;
 #if IDETAPE_DEBUG_LOG
 	if (tape->debug_level >= 3)
@@ -5519,7 +5518,6 @@
 		MOD_DEC_USE_COUNT;
 	}
 	clear_bit (IDETAPE_BUSY, &tape->flags);
-	unlock_kernel();
 	return 0;
 }
 
@@ -6182,6 +6180,7 @@
 };
 
 MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
+MODULE_LICENSE("GPL");
 
 static void __exit idetape_exit (void)
 {
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/ide.c linux/drivers/ide/ide.c
--- v2.5.0/linux/drivers/ide/ide.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/ide/ide.c	Mon Dec 10 14:15:19 2001
@@ -113,6 +113,8 @@
  * Version 6.31		Debug Share INTR's and request queue streaming
  *			Native ATA-100 support
  *			Prep for Cascades Project
+ * Version 6.32		4GB highmem support for DMA, and mapping of those for
+ * 			PIO transfer (Jens Axboe)
  *
  *  Some additional driver compile-time options are in ./include/linux/ide.h
  *
@@ -121,8 +123,8 @@
  *
  */
 
-#define	REVISION	"Revision: 6.31"
-#define	VERSION		"Id: ide.c 6.31 2000/06/09"
+#define	REVISION	"Revision: 6.32"
+#define	VERSION		"Id: ide.c 6.32 2001/05/24"
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
@@ -149,6 +151,7 @@
 #include <linux/ide.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/completion.h>
+#include <linux/cdrom.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -171,6 +174,14 @@
 static int	system_bus_speed; /* holds what we think is VESA/PCI bus speed */
 static int	initializing;     /* set while initializing built-in drivers */
 
+/*
+ * protects global structures etc, we want to split this into per-hwgroup
+ * instead.
+ *
+ * anti-deadlock ordering: ide_lock -> DRIVE_LOCK
+ */
+spinlock_t ide_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+
 #ifdef CONFIG_BLK_DEV_IDEPCI
 static int	ide_scan_direction;	/* THIS was formerly 2.2.x pci=reverse */
 #endif /* CONFIG_BLK_DEV_IDEPCI */
@@ -180,7 +191,7 @@
  * ide_lock is used by the Atari code to obtain access to the IDE interrupt,
  * which is shared between several drivers.
  */
-static int	ide_lock;
+static int	ide_intr_lock;
 #endif /* __mc68000__ || CONFIG_APUS */
 
 int noautodma = 0;
@@ -542,18 +553,25 @@
 	return 1;		/* drive ready: *might* be interrupting */
 }
 
-/*
- * This is our end_request replacement function.
- */
-void ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
+inline int __ide_end_request(ide_hwgroup_t *hwgroup, int uptodate, int nr_secs)
 {
+	ide_drive_t *drive = hwgroup->drive;
 	struct request *rq;
 	unsigned long flags;
-	ide_drive_t *drive = hwgroup->drive;
+	int ret = 1;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&ide_lock, flags);
 	rq = hwgroup->rq;
 
+	BUG_ON(!(rq->flags & REQ_STARTED));
+
+	/*
+	 * small hack to eliminate locking from ide_end_request to grab
+	 * the first segment number of sectors
+	 */
+	if (!nr_secs)
+		nr_secs = rq->hard_cur_sectors;
+
 	/*
 	 * decide whether to reenable DMA -- 3 is a random magic for now,
 	 * if we DMA timeout more than 3 times, just stay in PIO
@@ -563,13 +581,26 @@
 		hwgroup->hwif->dmaproc(ide_dma_on, drive);
 	}
 
-	if (!end_that_request_first(rq, uptodate, hwgroup->drive->name)) {
+	if (!end_that_request_first(rq, uptodate, nr_secs)) {
 		add_blkdev_randomness(MAJOR(rq->rq_dev));
+		spin_lock(DRIVE_LOCK(drive));
 		blkdev_dequeue_request(rq);
         	hwgroup->rq = NULL;
 		end_that_request_last(rq);
+		spin_unlock(DRIVE_LOCK(drive));
+		ret = 0;
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
+
+	spin_unlock_irqrestore(&ide_lock, flags);
+	return ret;
+}
+
+/*
+ * This is our end_request replacement function.
+ */
+int ide_end_request (byte uptodate, ide_hwgroup_t *hwgroup)
+{
+	return __ide_end_request(hwgroup, uptodate, 0);
 }
 
 /*
@@ -585,7 +616,7 @@
 	unsigned long flags;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&ide_lock, flags);
 	if (hwgroup->handler != NULL) {
 		printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
 			drive->name, hwgroup->handler, handler);
@@ -594,7 +625,7 @@
 	hwgroup->expiry		= expiry;
 	hwgroup->timer.expires	= jiffies + timeout;
 	add_timer(&hwgroup->timer);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
 /*
@@ -844,11 +875,10 @@
 	unsigned long flags;
 	struct request *rq;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&ide_lock, flags);
 	rq = HWGROUP(drive)->rq;
-	spin_unlock_irqrestore(&io_request_lock, flags);
 
-	if (rq->cmd == IDE_DRIVE_CMD) {
+	if (rq->flags & REQ_DRIVE_CMD) {
 		byte *args = (byte *) rq->buffer;
 		rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
 		if (args) {
@@ -856,7 +886,7 @@
 			args[1] = err;
 			args[2] = IN_BYTE(IDE_NSECTOR_REG);
 		}
-	} else if (rq->cmd == IDE_DRIVE_TASK) {
+	} else if (rq->flags & REQ_DRIVE_TASK) {
 		byte *args = (byte *) rq->buffer;
 		rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
 		if (args) {
@@ -869,11 +899,14 @@
 			args[6] = IN_BYTE(IDE_SELECT_REG);
 		}
 	}
-	spin_lock_irqsave(&io_request_lock, flags);
+
+	spin_lock(DRIVE_LOCK(drive));
 	blkdev_dequeue_request(rq);
 	HWGROUP(drive)->rq = NULL;
 	end_that_request_last(rq);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock(DRIVE_LOCK(drive));
+
+	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
 /*
@@ -975,7 +1008,7 @@
 	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
 		return ide_stopped;
 	/* retry only "normal" I/O: */
-	if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) {
+	if (!(rq->flags & REQ_CMD)) {
 		rq->errors = 1;
 		ide_end_drive_cmd(drive, stat, err);
 		return ide_stopped;
@@ -995,7 +1028,7 @@
 			else if (err & TRK0_ERR)	/* help it find track zero */
 				rq->errors |= ERROR_RECAL;
 		}
-		if ((stat & DRQ_STAT) && rq->cmd != WRITE)
+		if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ)
 			try_to_flush_leftover_data(drive);
 	}
 	if (GET_STAT() & (BUSY_STAT|DRQ_STAT))
@@ -1142,7 +1175,7 @@
 static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
 {
 	byte *args = rq->buffer;
-	if (args && rq->cmd == IDE_DRIVE_TASK) {
+	if (args && (rq->flags & REQ_DRIVE_TASK)) {
 		byte sel;
 #ifdef DEBUG
 		printk("%s: DRIVE_TASK_CMD data=x%02x cmd=0x%02x fr=0x%02x ns=0x%02x sc=0x%02x lcyl=0x%02x hcyl=0x%02x sel=0x%02x\n",
@@ -1192,17 +1225,19 @@
 /*
  * start_request() initiates handling of a new I/O request
  */
-static ide_startstop_t start_request (ide_drive_t *drive)
+static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
 {
 	ide_startstop_t startstop;
-	unsigned long block, blockend;
-	struct request *rq = blkdev_entry_next_request(&drive->queue.queue_head);
+	unsigned long block;
 	unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS;
 	ide_hwif_t *hwif = HWIF(drive);
 
+	BUG_ON(!(rq->flags & REQ_STARTED));
+
 #ifdef DEBUG
 	printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
 #endif
+
 	/* bail early if we've exceeded max_failures */
 	if (drive->max_failures && (drive->failures > drive->max_failures)) {
 		goto kill_rq;
@@ -1219,16 +1254,11 @@
 	}
 #endif
 	block    = rq->sector;
-	blockend = block + rq->nr_sectors;
 
-	if ((rq->cmd == READ || rq->cmd == WRITE) &&
+	/* Strange disk manager remap */
+	if ((rq->flags & REQ_CMD) && 
 	    (drive->media == ide_disk || drive->media == ide_floppy)) {
-		if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) {
-			printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name,
-			 (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors);
-			goto kill_rq;
-		}
-		block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0;
+		block += drive->sect0;
 	}
 	/* Yecch - this will shift the entire interval,
 	   possibly killing some innocent following sector */
@@ -1240,18 +1270,20 @@
 #endif
 
 	SELECT_DRIVE(hwif, drive);
-	if (ide_wait_stat(&startstop, drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
+	if (ide_wait_stat(&startstop, drive, drive->ready_stat,
+			  BUSY_STAT|DRQ_STAT, WAIT_READY)) {
 		printk("%s: drive not ready for command\n", drive->name);
 		return startstop;
 	}
 	if (!drive->special.all) {
-		if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) {
+		if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK))
 			return execute_drive_cmd(drive, rq);
-		}
+
 		if (drive->driver != NULL) {
 			return (DRIVER(drive)->do_request(drive, rq, block));
 		}
-		printk("%s: media type %d not supported\n", drive->name, drive->media);
+		printk("%s: media type %d not supported\n",
+		       drive->name, drive->media);
 		goto kill_rq;
 	}
 	return do_special(drive);
@@ -1267,13 +1299,15 @@
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	unsigned long flags;
+	struct request *rq;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&ide_lock, flags);
 	hwgroup->handler = NULL;
 	del_timer(&hwgroup->timer);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	rq = hwgroup->rq;
+	spin_unlock_irqrestore(&ide_lock, flags);
 
-	return start_request(drive);
+	return start_request(drive, rq);
 }
 
 /*
@@ -1305,7 +1339,7 @@
 			 || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
 			 || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
 			{
-				if( !drive->queue.plugged )
+				if (!blk_queue_plugged(&drive->queue))
 					best = drive;
 			}
 		}
@@ -1334,7 +1368,7 @@
 
 /*
  * Issue a new request to a drive from hwgroup
- * Caller must have already done spin_lock_irqsave(&io_request_lock, ..);
+ * Caller must have already done spin_lock_irqsave(DRIVE_LOCK(drive), ...)
  *
  * A hwgroup is a serialized group of IDE interfaces.  Usually there is
  * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
@@ -1346,39 +1380,34 @@
  * possibly along with many other devices.  This is especially common in
  * PCI-based systems with off-board IDE controller cards.
  *
- * The IDE driver uses the single global io_request_lock spinlock to protect
- * access to the request queues, and to protect the hwgroup->busy flag.
+ * The IDE driver uses the queue spinlock to protect access to the request
+ * queues.
  *
  * The first thread into the driver for a particular hwgroup sets the
- * hwgroup->busy flag to indicate that this hwgroup is now active,
+ * hwgroup->flags IDE_BUSY flag to indicate that this hwgroup is now active,
  * and then initiates processing of the top request from the request queue.
  *
  * Other threads attempting entry notice the busy setting, and will simply
- * queue their new requests and exit immediately.  Note that hwgroup->busy
- * remains set even when the driver is merely awaiting the next interrupt.
+ * queue their new requests and exit immediately.  Note that hwgroup->flags
+ * remains busy even when the driver is merely awaiting the next interrupt.
  * Thus, the meaning is "this hwgroup is busy processing a request".
  *
  * When processing of a request completes, the completing thread or IRQ-handler
  * will start the next request from the queue.  If no more work remains,
- * the driver will clear the hwgroup->busy flag and exit.
- *
- * The io_request_lock (spinlock) is used to protect all access to the
- * hwgroup->busy flag, but is otherwise not needed for most processing in
- * the driver.  This makes the driver much more friendlier to shared IRQs
- * than previous designs, while remaining 100% (?) SMP safe and capable.
+ * the driver will clear the hwgroup->flags IDE_BUSY flag and exit.
  */
 static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
 {
 	ide_drive_t	*drive;
 	ide_hwif_t	*hwif;
 	ide_startstop_t	startstop;
+	struct request	*rq;
 
-	ide_get_lock(&ide_lock, ide_intr, hwgroup);	/* for atari only: POSSIBLY BROKEN HERE(?) */
+	ide_get_lock(&ide_intr_lock, ide_intr, hwgroup);/* for atari only: POSSIBLY BROKEN HERE(?) */
 
 	__cli();	/* necessary paranoia: ensure IRQs are masked on local CPU */
 
-	while (!hwgroup->busy) {
-		hwgroup->busy = 1;
+	while (!test_and_set_bit(IDE_BUSY, &hwgroup->flags)) {
 		drive = choose_drive(hwgroup);
 		if (drive == NULL) {
 			unsigned long sleep = 0;
@@ -1401,13 +1430,13 @@
 				if (timer_pending(&hwgroup->timer))
 					printk("ide_set_handler: timer already active\n");
 #endif
-				hwgroup->sleeping = 1;	/* so that ide_timer_expiry knows what to do */
+				set_bit(IDE_SLEEP, &hwgroup->flags);
 				mod_timer(&hwgroup->timer, sleep);
-				/* we purposely leave hwgroup->busy==1 while sleeping */
+				/* we purposely leave hwgroup busy while sleeping */
 			} else {
 				/* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_disk? */
-				ide_release_lock(&ide_lock);	/* for atari only */
-				hwgroup->busy = 0;
+				ide_release_lock(&ide_intr_lock);/* for atari only */
+				clear_bit(IDE_BUSY, &hwgroup->flags);
 			}
 			return;		/* no more work for this hwgroup (for now) */
 		}
@@ -1421,9 +1450,16 @@
 		drive->sleep = 0;
 		drive->service_start = jiffies;
 
-		if ( drive->queue.plugged )	/* paranoia */
-			printk("%s: Huh? nuking plugged queue\n", drive->name);
-		hwgroup->rq = blkdev_entry_next_request(&drive->queue.queue_head);
+		if (blk_queue_plugged(&drive->queue))
+			BUG();
+
+		/*
+		 * just continuing an interrupted request maybe
+		 */
+		spin_lock(DRIVE_LOCK(drive));
+		rq = hwgroup->rq = elv_next_request(&drive->queue);
+		spin_unlock(DRIVE_LOCK(drive));
+
 		/*
 		 * Some systems have trouble with IDE IRQs arriving while
 		 * the driver is still setting things up.  So, here we disable
@@ -1434,14 +1470,14 @@
 		 */
 		if (masked_irq && hwif->irq != masked_irq)
 			disable_irq_nosync(hwif->irq);
-		spin_unlock(&io_request_lock);
+		spin_unlock(&ide_lock);
 		ide__sti();	/* allow other IRQs while we start this request */
-		startstop = start_request(drive);
-		spin_lock_irq(&io_request_lock);
+		startstop = start_request(drive, rq);
+		spin_lock_irq(&ide_lock);
 		if (masked_irq && hwif->irq != masked_irq)
 			enable_irq(hwif->irq);
 		if (startstop == ide_stopped)
-			hwgroup->busy = 0;
+			clear_bit(IDE_BUSY, &hwgroup->flags);
 	}
 }
 
@@ -1460,7 +1496,19 @@
  */
 void do_ide_request(request_queue_t *q)
 {
+	unsigned long flags;
+
+	/*
+	 * release queue lock, grab IDE global lock and restore when
+	 * we leave...
+	 */
+	spin_unlock(&q->queue_lock);
+
+	spin_lock_irqsave(&ide_lock, flags);
 	ide_do_request(q->queuedata, 0);
+	spin_unlock_irqrestore(&ide_lock, flags);
+
+	spin_lock(&q->queue_lock);
 }
 
 /*
@@ -1501,9 +1549,14 @@
 	HWGROUP(drive)->rq = NULL;
 
 	rq->errors = 0;
-	rq->sector = rq->bh->b_rsector;
-	rq->current_nr_sectors = rq->bh->b_size >> 9;
-	rq->buffer = rq->bh->b_data;
+	rq->sector = rq->bio->bi_sector;
+	rq->current_nr_sectors = bio_sectors(rq->bio);
+
+	/*
+	 * just to make sure...
+	 */
+	if (rq->bio)
+		rq->buffer = NULL;
 }
 
 /*
@@ -1519,7 +1572,11 @@
  	unsigned long	flags;
 	unsigned long	wait;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	/*
+	 * a global lock protects timers etc -- shouldn't get contention
+	 * worth mentioning
+	 */
+	spin_lock_irqsave(&ide_lock, flags);
 	del_timer(&hwgroup->timer);
 
 	if ((handler = hwgroup->handler) == NULL) {
@@ -1529,10 +1586,8 @@
 		 * or we were "sleeping" to give other devices a chance.
 		 * Either way, we don't really want to complain about anything.
 		 */
-		if (hwgroup->sleeping) {
-			hwgroup->sleeping = 0;
-			hwgroup->busy = 0;
-		}
+		if (test_and_clear_bit(IDE_SLEEP, &hwgroup->flags))
+			clear_bit(IDE_BUSY, &hwgroup->flags);
 	} else {
 		ide_drive_t *drive = hwgroup->drive;
 		if (!drive) {
@@ -1541,17 +1596,16 @@
 		} else {
 			ide_hwif_t *hwif;
 			ide_startstop_t startstop;
-			if (!hwgroup->busy) {
-				hwgroup->busy = 1;	/* paranoia */
-				printk("%s: ide_timer_expiry: hwgroup->busy was 0 ??\n", drive->name);
-			}
+			/* paranoia */
+			if (!test_and_set_bit(IDE_BUSY, &hwgroup->flags))
+				printk("%s: ide_timer_expiry: hwgroup was not busy??\n", drive->name);
 			if ((expiry = hwgroup->expiry) != NULL) {
 				/* continue */
 				if ((wait = expiry(drive)) != 0) {
 					/* reset timer */
 					hwgroup->timer.expires  = jiffies + wait;
 					add_timer(&hwgroup->timer);
-					spin_unlock_irqrestore(&io_request_lock, flags);
+					spin_unlock_irqrestore(&ide_lock, flags);
 					return;
 				}
 			}
@@ -1561,7 +1615,7 @@
 			 * the handler() function, which means we need to globally
 			 * mask the specific IRQ:
 			 */
-			spin_unlock(&io_request_lock);
+			spin_unlock(&ide_lock);
 			hwif  = HWIF(drive);
 #if DISABLE_IRQ_NOSYNC
 			disable_irq_nosync(hwif->irq);
@@ -1587,13 +1641,13 @@
 			set_recovery_timer(hwif);
 			drive->service_time = jiffies - drive->service_start;
 			enable_irq(hwif->irq);
-			spin_lock_irq(&io_request_lock);
+			spin_lock_irq(&ide_lock);
 			if (startstop == ide_stopped)
-				hwgroup->busy = 0;
+				clear_bit(IDE_BUSY, &hwgroup->flags);
 		}
 	}
 	ide_do_request(hwgroup, 0);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
 /*
@@ -1656,13 +1710,11 @@
 	ide_handler_t *handler;
 	ide_startstop_t startstop;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&ide_lock, flags);
 	hwif = hwgroup->hwif;
 
-	if (!ide_ack_intr(hwif)) {
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return;
-	}
+	if (!ide_ack_intr(hwif))
+		goto out_lock;
 
 	if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
 		/*
@@ -1694,16 +1746,14 @@
 			(void) IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
 #endif /* CONFIG_BLK_DEV_IDEPCI */
 		}
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return;
+		goto out_lock;
 	}
 	drive = hwgroup->drive;
 	if (!drive) {
 		/*
 		 * This should NEVER happen, and there isn't much we could do about it here.
 		 */
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return;
+		goto out_lock;
 	}
 	if (!drive_is_ready(drive)) {
 		/*
@@ -1712,21 +1762,19 @@
 		 * the IRQ before their status register is up to date.  Hopefully we have
 		 * enough advance overhead that the latter isn't a problem.
 		 */
-		spin_unlock_irqrestore(&io_request_lock, flags);
-		return;
-	}
-	if (!hwgroup->busy) {
-		hwgroup->busy = 1;	/* paranoia */
-		printk("%s: ide_intr: hwgroup->busy was 0 ??\n", drive->name);
+		goto out_lock;
 	}
+	/* paranoia */
+	if (!test_and_set_bit(IDE_BUSY, &hwgroup->flags))
+		printk("%s: ide_intr: hwgroup was not busy??\n", drive->name);
 	hwgroup->handler = NULL;
 	del_timer(&hwgroup->timer);
-	spin_unlock(&io_request_lock);
+	spin_unlock(&ide_lock);
 
 	if (drive->unmask)
 		ide__sti();	/* local CPU only */
 	startstop = handler(drive);		/* service this interrupt, may set handler for next interrupt */
-	spin_lock_irq(&io_request_lock);
+	spin_lock_irq(&ide_lock);
 
 	/*
 	 * Note that handler() may have set things up for another
@@ -1739,13 +1787,15 @@
 	drive->service_time = jiffies - drive->service_start;
 	if (startstop == ide_stopped) {
 		if (hwgroup->handler == NULL) {	/* paranoia */
-			hwgroup->busy = 0;
+			clear_bit(IDE_BUSY, &hwgroup->flags);
 			ide_do_request(hwgroup, hwif->irq);
 		} else {
 			printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name);
 		}
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
+
+out_lock:
+	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
 /*
@@ -1755,9 +1805,6 @@
 ide_drive_t *get_info_ptr (kdev_t i_rdev)
 {
 	int		major = MAJOR(i_rdev);
-#if 0
-	int		minor = MINOR(i_rdev) & PARTN_MASK;
-#endif
 	unsigned int	h;
 
 	for (h = 0; h < MAX_HWIFS; ++h) {
@@ -1766,11 +1813,7 @@
 			unsigned unit = DEVICE_NR(i_rdev);
 			if (unit < MAX_DRIVES) {
 				ide_drive_t *drive = &hwif->drives[unit];
-#if 0
-				if ((drive->present) && (drive->part[minor].nr_sects))
-#else
 				if (drive->present)
-#endif
 					return drive;
 			}
 			break;
@@ -1785,7 +1828,7 @@
 void ide_init_drive_cmd (struct request *rq)
 {
 	memset(rq, 0, sizeof(*rq));
-	rq->cmd = IDE_DRIVE_CMD;
+	rq->flags = REQ_DRIVE_CMD;
 }
 
 /*
@@ -1818,7 +1861,8 @@
 	unsigned long flags;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	unsigned int major = HWIF(drive)->major;
-	struct list_head *queue_head = &drive->queue.queue_head;
+	request_queue_t *q = &drive->queue;
+	struct list_head *queue_head = &q->queue_head;
 	DECLARE_COMPLETION(wait);
 
 #ifdef CONFIG_BLK_DEV_PDC4030
@@ -1830,8 +1874,9 @@
 	rq->rq_dev = MKDEV(major,(drive->select.b.unit)<<PARTN_BITS);
 	if (action == ide_wait)
 		rq->waiting = &wait;
-	spin_lock_irqsave(&io_request_lock, flags);
-	if (list_empty(queue_head) || action == ide_preempt) {
+	spin_lock_irqsave(&ide_lock, flags);
+	spin_lock(DRIVE_LOCK(drive));
+	if (blk_queue_empty(&drive->queue) || action == ide_preempt) {
 		if (action == ide_preempt)
 			hwgroup->rq = NULL;
 	} else {
@@ -1840,9 +1885,10 @@
 		} else
 			queue_head = queue_head->next;
 	}
-	list_add(&rq->queue, queue_head);
+	q->elevator.elevator_add_req_fn(q, rq, queue_head);
+	spin_unlock(DRIVE_LOCK(drive));
 	ide_do_request(hwgroup, 0);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&ide_lock, flags);
 	if (action == ide_wait) {
 		wait_for_completion(&wait);	/* wait for it to be serviced */
 		return rq->errors ? -EIO : 0;	/* return -EIO if errors */
@@ -1851,6 +1897,16 @@
 
 }
 
+/* Common for ide-floppy.c and ide-disk.c */
+void ide_revalidate_drive (ide_drive_t *drive)
+{
+        struct gendisk *g = HWIF(drive)->gd;
+        int minor = (drive->select.b.unit << g->minor_shift);
+        kdev_t dev = MKDEV(g->major, minor);
+
+        grok_partitions(dev, current_capacity(drive));
+}
+
 /*
  * This routine is called to flush all partitions and partition tables
  * for a changed disk, and then re-read the new partition table.
@@ -1863,40 +1919,33 @@
 {
 	ide_drive_t *drive;
 	ide_hwgroup_t *hwgroup;
-	unsigned int p, major, minor;
-	long flags;
+	unsigned long flags;
+	int res;
 
 	if ((drive = get_info_ptr(i_rdev)) == NULL)
 		return -ENODEV;
-	major = MAJOR(i_rdev);
-	minor = drive->select.b.unit << PARTN_BITS;
 	hwgroup = HWGROUP(drive);
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&ide_lock, flags);
 	if (drive->busy || (drive->usage > 1)) {
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&ide_lock, flags);
 		return -EBUSY;
-	};
+	}
 	drive->busy = 1;
 	MOD_INC_USE_COUNT;
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&ide_lock, flags);
 
-	for (p = 0; p < (1<<PARTN_BITS); ++p) {
-		if (drive->part[p].nr_sects > 0) {
-			kdev_t devp = MKDEV(major, minor+p);
-			invalidate_device(devp, 1);
-			set_blocksize(devp, 1024);
-		}
-		drive->part[p].start_sect = 0;
-		drive->part[p].nr_sects   = 0;
-	};
+	res = wipe_partitions(i_rdev);
+	if (res)
+		goto leave;
 
 	if (DRIVER(drive)->revalidate)
 		DRIVER(drive)->revalidate(drive);
 
+ leave:
 	drive->busy = 0;
 	wake_up(&drive->wqueue);
 	MOD_DEC_USE_COUNT;
-	return 0;
+	return res;
 }
 
 static void revalidate_drives (void)
@@ -2169,11 +2218,10 @@
 	 */
 	unregister_blkdev(hwif->major, hwif->name);
 	kfree(blksize_size[hwif->major]);
-	kfree(max_sectors[hwif->major]);
 	kfree(max_readahead[hwif->major]);
 	blk_dev[hwif->major].data = NULL;
 	blk_dev[hwif->major].queue = NULL;
-	blksize_size[hwif->major] = NULL;
+	blk_clear(hwif->major);
 	gd = hwif->gd;
 	if (gd) {
 		del_gendisk(gd);
@@ -2293,6 +2341,7 @@
 	memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
 	hwif->irq = hw->irq;
 	hwif->noprobe = 0;
+	hwif->chipset = hw->chipset;
 
 	if (!initializing) {
 		ide_probe_module();
@@ -2403,7 +2452,7 @@
 	unsigned long	flags;
 
 	if ((setting->rw & SETTING_READ)) {
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&ide_lock, flags);
 		switch(setting->data_type) {
 			case TYPE_BYTE:
 				val = *((u8 *) setting->data);
@@ -2416,7 +2465,7 @@
 				val = *((u32 *) setting->data);
 				break;
 		}
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&ide_lock, flags);
 	}
 	return val;
 }
@@ -2426,11 +2475,11 @@
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	unsigned long timeout = jiffies + (3 * HZ);
 
-	spin_lock_irq(&io_request_lock);
+	spin_lock_irq(&ide_lock);
 
-	while (hwgroup->busy) {
+	while (test_bit(IDE_BUSY, &hwgroup->flags)) {
 		unsigned long lflags;
-		spin_unlock_irq(&io_request_lock);
+		spin_unlock_irq(&ide_lock);
 		__save_flags(lflags);	/* local CPU only */
 		__sti();		/* local CPU only; needed for jiffies */
 		if (0 < (signed long)(jiffies - timeout)) {
@@ -2439,7 +2488,7 @@
 			return -EBUSY;
 		}
 		__restore_flags(lflags);	/* local CPU only */
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&ide_lock);
 	}
 	return 0;
 }
@@ -2480,7 +2529,7 @@
 				*p = val;
 			break;
 	}
-	spin_unlock_irq(&io_request_lock);
+	spin_unlock_irq(&ide_lock);
 	return 0;
 }
 
@@ -2560,7 +2609,7 @@
 	struct request rq;
 
 	ide_init_drive_cmd(&rq);
-	rq.cmd = IDE_DRIVE_TASK;
+	rq.flags = REQ_DRIVE_TASK;
 	rq.buffer = buf;
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
@@ -2633,6 +2682,7 @@
 		{
 			struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;
 			if (!loc || (drive->media != ide_disk && drive->media != ide_floppy)) return -EINVAL;
+
 			if (put_user(drive->bios_head, (byte *) &loc->heads)) return -EFAULT;
 			if (put_user(drive->bios_sect, (byte *) &loc->sectors)) return -EFAULT;
 			if (put_user(drive->bios_cyl, (unsigned int *) &loc->cylinders)) return -EFAULT;
@@ -2653,11 +2703,6 @@
 			return 0;
 		}
 
-	 	case BLKGETSIZE:   /* Return device size */
-			return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (unsigned long *) arg);
-	 	case BLKGETSIZE64:
-			return put_user((u64)drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects << 9, (u64 *) arg);
-
 		case BLKRRPART: /* Re-read partition tables */
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 			return ide_revalidate_disk(inode->i_rdev);
@@ -2775,6 +2820,8 @@
 			}
 			return 0;
 
+		case BLKGETSIZE:
+		case BLKGETSIZE64:
 		case BLKROSET:
 		case BLKROGET:
 		case BLKFLSBUF:
@@ -2786,6 +2833,13 @@
 		case BLKBSZSET:
 			return blk_ioctl(inode->i_rdev, cmd, arg);
 
+		/*
+		 * uniform packet command handling
+		 */
+		case CDROMEJECT:
+		case CDROMCLOSETRAY:
+			return block_ioctl(inode->i_rdev, cmd, arg);
+
 		case HDIO_GET_BUSSTATE:
 			if (!capable(CAP_SYS_ADMIN))
 				return -EACCES;
@@ -3409,7 +3463,7 @@
 #ifdef CONFIG_BLK_DEV_IDE
 #if defined(__mc68000__) || defined(CONFIG_APUS)
 	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
-		ide_get_lock(&ide_lock, NULL, NULL);	/* for atari only */
+		ide_get_lock(&ide_intr_lock, NULL, NULL);/* for atari only */
 		disable_irq(ide_hwifs[0].irq);	/* disable_irq_nosync ?? */
 //		disable_irq_nosync(ide_hwifs[0].irq);
 	}
@@ -3420,7 +3474,7 @@
 #if defined(__mc68000__) || defined(CONFIG_APUS)
 	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
 		enable_irq(ide_hwifs[0].irq);
-		ide_release_lock(&ide_lock);	/* for atari only */
+		ide_release_lock(&ide_intr_lock);/* for atari only */
 	}
 #endif /* __mc68000__ || CONFIG_APUS */
 #endif /* CONFIG_BLK_DEV_IDE */
@@ -3685,6 +3739,7 @@
 EXPORT_SYMBOL(ide_do_drive_cmd);
 EXPORT_SYMBOL(ide_end_drive_cmd);
 EXPORT_SYMBOL(ide_end_request);
+EXPORT_SYMBOL(__ide_end_request);
 EXPORT_SYMBOL(ide_revalidate_disk);
 EXPORT_SYMBOL(ide_cmd);
 EXPORT_SYMBOL(ide_wait_cmd);
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- v2.5.0/linux/drivers/ide/pdc202xx.c	Wed Nov 14 11:44:03 2001
+++ linux/drivers/ide/pdc202xx.c	Tue Nov 27 09:23:27 2001
@@ -893,6 +893,7 @@
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
 		hwif->dmaproc = &pdc202xx_dmaproc;
+		hwif->highmem = 1;
 		if (!noautodma)
 			hwif->autodma = 1;
 	} else {
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/piix.c linux/drivers/ide/piix.c
--- v2.5.0/linux/drivers/ide/piix.c	Thu Oct 25 13:53:47 2001
+++ linux/drivers/ide/piix.c	Fri Nov 30 15:53:51 2001
@@ -88,33 +88,9 @@
 	u8  c0 = 0, c1 = 0;
 	u8  reg44 = 0, reg48 = 0, reg4a = 0, reg4b = 0, reg54 = 0, reg55 = 0;
 
-	switch(bmide_dev->device) {
-		case PCI_DEVICE_ID_INTEL_82801BA_8:
-		case PCI_DEVICE_ID_INTEL_82801BA_9:
-	        case PCI_DEVICE_ID_INTEL_82801CA_10:
-			p += sprintf(p, "\n                                Intel PIIX4 Ultra 100 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_INTEL_82372FB_1:
-		case PCI_DEVICE_ID_INTEL_82801AA_1:
-			p += sprintf(p, "\n                                Intel PIIX4 Ultra 66 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_INTEL_82451NX:
-		case PCI_DEVICE_ID_INTEL_82801AB_1:
-		case PCI_DEVICE_ID_INTEL_82443MX_1:
-		case PCI_DEVICE_ID_INTEL_82371AB:
-			p += sprintf(p, "\n                                Intel PIIX4 Ultra 33 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_INTEL_82371SB_1:
-			p += sprintf(p, "\n                                Intel PIIX3 Chipset.\n");
-			break;
-		case PCI_DEVICE_ID_INTEL_82371MX:
-			p += sprintf(p, "\n                                Intel MPIIX Chipset.\n");
-			return p-buffer;	/* => must be less than 4k! */
-		case PCI_DEVICE_ID_INTEL_82371FB_1:
-		case PCI_DEVICE_ID_INTEL_82371FB_0:
-		default:
-			p += sprintf(p, "\n                                Intel PIIX Chipset.\n");
-			break;
+	if (bmide_dev->device == PCI_DEVICE_ID_INTEL_82371MX) {
+		p += sprintf(p, "\n                                Intel MPIIX Chipset.\n");
+		return p-buffer;	/* => must be less than 4k! */
 	}
 
 	pci_read_config_word(bmide_dev, 0x40, &reg40);
@@ -136,6 +112,7 @@
 	c0 = inb_p((unsigned short)bibma + 0x02);
 	c1 = inb_p((unsigned short)bibma + 0x0a);
 
+	p += sprintf(p, "\n                    %s Chipset.\n", bmide_dev->name);
 	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
 	p += sprintf(p, "                %sabled                         %sabled\n",
 			(c0&0x80) ? "dis" : " en",
@@ -523,6 +500,7 @@
 	if (!hwif->dma_base)
 		return;
 
+	hwif->highmem = 1;
 #ifndef CONFIG_BLK_DEV_IDEDMA
 	hwif->autodma = 0;
 #else /* CONFIG_BLK_DEV_IDEDMA */
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/serverworks.c linux/drivers/ide/serverworks.c
--- v2.5.0/linux/drivers/ide/serverworks.c	Sun Sep  9 10:43:02 2001
+++ linux/drivers/ide/serverworks.c	Tue Nov 27 09:23:27 2001
@@ -593,6 +593,7 @@
 		if (!noautodma)
 			hwif->autodma = 1;
 		hwif->dmaproc = &svwks_dmaproc;
+		hwif->highmem = 1;
 	} else {
 		hwif->autodma = 0;
 		hwif->drives[0].autotune = 1;
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/sis5513.c linux/drivers/ide/sis5513.c
--- v2.5.0/linux/drivers/ide/sis5513.c	Fri Sep  7 09:28:38 2001
+++ linux/drivers/ide/sis5513.c	Tue Nov 27 09:23:27 2001
@@ -671,6 +671,7 @@
 			case PCI_DEVICE_ID_SI_5591:
 				if (!noautodma)
 					hwif->autodma = 1;
+				hwif->highmem = 1;
 				hwif->dmaproc = &sis5513_dmaproc;
 				break;
 #endif /* CONFIG_BLK_DEV_IDEDMA */
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/slc90e66.c linux/drivers/ide/slc90e66.c
--- v2.5.0/linux/drivers/ide/slc90e66.c	Sun Jul 15 16:22:23 2001
+++ linux/drivers/ide/slc90e66.c	Tue Nov 27 09:23:27 2001
@@ -373,6 +373,7 @@
 		return;
 
 	hwif->autodma = 0;
+	hwif->highmem = 1;
 #ifdef CONFIG_BLK_DEV_IDEDMA 
 	if (!noautodma)
 		hwif->autodma = 1;
diff -u --recursive --new-file v2.5.0/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c
--- v2.5.0/linux/drivers/ide/via82cxxx.c	Tue Sep 11 08:40:36 2001
+++ linux/drivers/ide/via82cxxx.c	Tue Nov 27 09:23:27 2001
@@ -520,6 +520,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
+		hwif->highmem = 1;
 		hwif->dmaproc = &via82cxxx_dmaproc;
 #ifdef CONFIG_IDEDMA_AUTO
 		if (!noautodma)
diff -u --recursive --new-file v2.5.0/linux/drivers/ieee1394/raw1394.c linux/drivers/ieee1394/raw1394.c
--- v2.5.0/linux/drivers/ieee1394/raw1394.c	Mon Oct  1 21:24:24 2001
+++ linux/drivers/ieee1394/raw1394.c	Fri Nov 30 08:26:04 2001
@@ -949,7 +949,6 @@
         struct pending_request *req;
         int done = 0, i;
 
-        lock_kernel();
         for (i = 0; i < 64; i++) {
                 if (fi->listen_channels & (1ULL << i)) {
                         hpsb_unlisten_channel(hl_handle, fi->host, i);
@@ -990,7 +989,6 @@
         kfree(fi);
 
         V22_COMPAT_MOD_DEC_USE_COUNT;
-        unlock_kernel();
         return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/input/evdev.c linux/drivers/input/evdev.c
--- v2.5.0/linux/drivers/input/evdev.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/input/evdev.c	Fri Nov 30 08:26:04 2001
@@ -94,7 +94,6 @@
 	struct evdev_list *list = file->private_data;
 	struct evdev_list **listptr;
 
-	lock_kernel();
 	listptr = &list->evdev->list;
 	evdev_fasync(-1, file, 0);
 
@@ -113,7 +112,6 @@
 	}
 
 	kfree(list);
-	unlock_kernel();
 
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/input/input.c linux/drivers/input/input.c
--- v2.5.0/linux/drivers/input/input.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/input/input.c	Fri Nov 30 08:26:04 2001
@@ -387,9 +387,7 @@
 	old_fops = file->f_op;
 	file->f_op = new_fops;
 
-	lock_kernel();
 	err = new_fops->open(inode, file);
-	unlock_kernel();
 
 	if (err) {
 		fops_put(file->f_op);
diff -u --recursive --new-file v2.5.0/linux/drivers/input/joydev.c linux/drivers/input/joydev.c
--- v2.5.0/linux/drivers/input/joydev.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/input/joydev.c	Fri Nov 30 08:26:04 2001
@@ -164,8 +164,7 @@
 {
 	struct joydev_list *list = file->private_data;
 	struct joydev_list **listptr;
-
-	lock_kernel();
+	
 	listptr = &list->joydev->list;
 	joydev_fasync(-1, file, 0);
 
@@ -184,7 +183,6 @@
 	}
 
 	kfree(list);
-	unlock_kernel();
 
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/input/mousedev.c linux/drivers/input/mousedev.c
--- v2.5.0/linux/drivers/input/mousedev.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/input/mousedev.c	Fri Nov 30 08:26:04 2001
@@ -169,8 +169,7 @@
 {
 	struct mousedev_list *list = file->private_data;
 	struct mousedev_list **listptr;
-
-	lock_kernel();
+	
 	listptr = &list->mousedev->list;
 	mousedev_fasync(-1, file, 0);
 
@@ -208,7 +207,6 @@
 	}
 	
 	kfree(list);
-	unlock_kernel();
 
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/Config.in linux/drivers/isdn/Config.in
--- v2.5.0/linux/drivers/isdn/Config.in	Sun Sep  9 10:45:43 2001
+++ linux/drivers/isdn/Config.in	Fri Nov 30 09:48:32 2001
@@ -81,6 +81,7 @@
    dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA
    dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA
    dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
+   dep_tristate 'Fritz!PCIv2 support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
 fi
 endmenu
 
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.5.0/linux/drivers/isdn/avmb1/capi.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/avmb1/capi.c	Thu Dec  6 14:01:17 2001
@@ -87,10 +87,10 @@
 	struct capincci  *nccip;
 	unsigned int      minor;
 
-	__u16		 applid;
-	__u32		 ncci;
-	__u16		 datahandle;
-	__u16		 msgid;
+	u16  		 applid;
+	u32		 ncci;
+	u16		 datahandle;
+	u16		 msgid;
 
 	struct file      *file;
 	struct tty_struct *tty;
@@ -112,7 +112,7 @@
 	/* transmit path */
 	struct datahandle_queue {
 		    struct datahandle_queue *next;
-		    __u16                    datahandle;
+		    u16                      datahandle;
 	} *ackqueue;
 	int nack;
 
@@ -121,7 +121,7 @@
 
 struct capincci {
 	struct capincci *next;
-	__u32		 ncci;
+	u32		 ncci;
 	struct capidev	*cdev;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	struct capiminor *minorp;
@@ -131,8 +131,8 @@
 struct capidev {
 	struct capidev *next;
 	struct file    *file;
-	__u16		applid;
-	__u16		errcode;
+	u16		applid;
+	u16		errcode;
 	unsigned int    minor;
 	unsigned        userflags;
 
@@ -166,7 +166,7 @@
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 /* -------- datahandles --------------------------------------------- */
 
-int capincci_add_ack(struct capiminor *mp, __u16 datahandle)
+static int capincci_add_ack(struct capiminor *mp, u16 datahandle)
 {
 	struct datahandle_queue *n, **pp;
 
@@ -184,7 +184,7 @@
 	return 0;
 }
 
-int capiminor_del_ack(struct capiminor *mp, __u16 datahandle)
+static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
 {
 	struct datahandle_queue **pp, *p;
 
@@ -200,7 +200,7 @@
 	return -1;
 }
 
-void capiminor_del_all_ack(struct capiminor *mp)
+static void capiminor_del_all_ack(struct capiminor *mp)
 {
 	struct datahandle_queue **pp, *p;
 
@@ -216,7 +216,7 @@
 
 /* -------- struct capiminor ---------------------------------------- */
 
-struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci)
+static struct capiminor *capiminor_alloc(u16 applid, u32 ncci)
 {
 	struct capiminor *mp, **pp;
         unsigned int minor = 0;
@@ -257,7 +257,7 @@
 	return mp;
 }
 
-void capiminor_free(struct capiminor *mp)
+static void capiminor_free(struct capiminor *mp)
 {
 	struct capiminor **pp;
 
@@ -283,7 +283,7 @@
 	}
 }
 
-struct capiminor *capiminor_find(unsigned int minor)
+static struct capiminor *capiminor_find(unsigned int minor)
 {
 	struct capiminor *p;
 	for (p = minors; p && p->minor != minor; p = p->next)
@@ -294,7 +294,7 @@
 
 /* -------- struct capincci ----------------------------------------- */
 
-static struct capincci *capincci_alloc(struct capidev *cdev, __u32 ncci)
+static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
 {
 	struct capincci *np, **pp;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -331,7 +331,7 @@
         return np;
 }
 
-static void capincci_free(struct capidev *cdev, __u32 ncci)
+static void capincci_free(struct capidev *cdev, u32 ncci)
 {
 	struct capincci *np, **pp;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -375,7 +375,7 @@
 	}
 }
 
-struct capincci *capincci_find(struct capidev *cdev, __u32 ncci)
+static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
 {
 	struct capincci *p;
 
@@ -426,7 +426,7 @@
 	kmem_cache_free(capidev_cachep, cdev);
 }
 
-static struct capidev *capidev_find(__u16 applid)
+static struct capidev *capidev_find(u16 applid)
 {
 	struct capidev *p;
 	for (p=capidev_openlist; p; p = p->next) {
@@ -439,13 +439,13 @@
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 /* -------- handle data queue --------------------------------------- */
 
-struct sk_buff *
+static struct sk_buff *
 gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
 {
 	struct sk_buff *nskb;
 	nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC);
 	if (nskb) {
-		__u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
+		u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
 		unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
 		capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
 		capimsg_setu16(s, 2, mp->applid);
@@ -458,11 +458,11 @@
 	return nskb;
 }
 
-int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
+static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
 {
 	struct sk_buff *nskb;
 	unsigned int datalen;
-	__u16 errcode, datahandle;
+	u16 errcode, datahandle;
 
 	datalen = skb->len - CAPIMSG_LEN(skb->data);
 	if (mp->tty) {
@@ -538,7 +538,7 @@
 	return -1;
 }
 
-void handle_minor_recv(struct capiminor *mp)
+static void handle_minor_recv(struct capiminor *mp)
 {
 	struct sk_buff *skb;
 	while ((skb = skb_dequeue(&mp->inqueue)) != 0) {
@@ -552,13 +552,13 @@
 	}
 }
 
-int handle_minor_send(struct capiminor *mp)
+static int handle_minor_send(struct capiminor *mp)
 {
 	struct sk_buff *skb;
-	__u16 len;
+	u16 len;
 	int count = 0;
-	__u16 errcode;
-	__u16 datahandle;
+	u16 errcode;
+	u16 datahandle;
 
 	if (mp->tty && mp->ttyoutstop) {
 #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
@@ -569,7 +569,7 @@
 
 	while ((skb = skb_dequeue(&mp->outqueue)) != 0) {
 		datahandle = mp->datahandle;
-		len = (__u16)skb->len;
+		len = (u16)skb->len;
 		skb_push(skb, CAPI_DATA_B3_REQ_LEN);
 		memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
 		capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
@@ -578,7 +578,7 @@
 		capimsg_setu8 (skb->data, 5, CAPI_REQ);
 		capimsg_setu16(skb->data, 6, mp->msgid++);
 		capimsg_setu32(skb->data, 8, mp->ncci);	/* NCCI */
-		capimsg_setu32(skb->data, 12, (__u32) skb->data); /* Data32 */
+		capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
 		capimsg_setu16(skb->data, 16, len);	/* Data length */
 		capimsg_setu16(skb->data, 18, datahandle);
 		capimsg_setu16(skb->data, 20, 0);	/* Flags */
@@ -620,16 +620,16 @@
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 /* -------- function called by lower level -------------------------- */
 
-static void capi_signal(__u16 applid, void *param)
+static void capi_signal(u16 applid, void *param)
 {
 	struct capidev *cdev = (struct capidev *)param;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	struct capiminor *mp;
-	__u16 datahandle;
+	u16 datahandle;
 #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
 	struct capincci *np;
 	struct sk_buff *skb = 0;
-	__u32 ncci;
+	u32 ncci;
 
 	(void) (*capifuncs->capi_get_message) (applid, &skb);
 	if (!skb) {
@@ -758,7 +758,7 @@
 	struct capidev *cdev = (struct capidev *)file->private_data;
 	struct sk_buff *skb;
 	int retval;
-	__u16 mlen;
+	u16 mlen;
 
         if (ppos != &file->f_pos)
 		return -ESPIPE;
@@ -998,7 +998,7 @@
 						sizeof(ncci));
 			if (retval)
 				return -EFAULT;
-			nccip = capincci_find(cdev, (__u32) ncci);
+			nccip = capincci_find(cdev, (u32) ncci);
 			if (!nccip)
 				return 0;
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -1023,7 +1023,7 @@
 						sizeof(ncci));
 			if (retval)
 				return -EFAULT;
-			nccip = capincci_find(cdev, (__u32) ncci);
+			nccip = capincci_find(cdev, (u32) ncci);
 			if (!nccip || (mp = nccip->minorp) == 0)
 				return -ESRCH;
 			return mp->minor;
@@ -1055,7 +1055,6 @@
 {
 	struct capidev *cdev = (struct capidev *)file->private_data;
 
-	lock_kernel();
 	capincci_free(cdev, 0xffffffff);
 	capidev_free(cdev);
 	file->private_data = NULL;
@@ -1064,7 +1063,6 @@
 #ifdef _DEBUG_REFCOUNT
 	printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(THIS_MODULE));
 #endif
-	unlock_kernel();
 	return 0;
 }
 
@@ -1243,13 +1241,11 @@
 	struct capiminor *mp = (struct capiminor *)file->private_data;
 
 	if (mp) {
-		lock_kernel();
 		mp->file = 0;
 		if (mp->nccip == 0) {
 			capiminor_free(mp);
 			file->private_data = NULL;
 		}
-		unlock_kernel();
 	}
 
 #ifdef _DEBUG_REFCOUNT
@@ -1272,7 +1268,7 @@
 
 /* -------- tty_operations for capincci ----------------------------- */
 
-int capinc_tty_open(struct tty_struct * tty, struct file * file)
+static int capinc_tty_open(struct tty_struct * tty, struct file * file)
 {
 	struct capiminor *mp;
 
@@ -1300,7 +1296,7 @@
 	return 0;
 }
 
-void capinc_tty_close(struct tty_struct * tty, struct file * file)
+static void capinc_tty_close(struct tty_struct * tty, struct file * file)
 {
 	struct capiminor *mp;
 
@@ -1325,8 +1321,8 @@
 #endif
 }
 
-int capinc_tty_write(struct tty_struct * tty, int from_user,
-		      const unsigned char *buf, int count)
+static int capinc_tty_write(struct tty_struct * tty, int from_user,
+			    const unsigned char *buf, int count)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
@@ -1377,7 +1373,7 @@
 	return count;
 }
 
-void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
@@ -1414,7 +1410,7 @@
 	}
 }
 
-void capinc_tty_flush_chars(struct tty_struct *tty)
+static void capinc_tty_flush_chars(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	struct sk_buff *skb;
@@ -1440,7 +1436,7 @@
 	(void)handle_minor_recv(mp);
 }
 
-int capinc_tty_write_room(struct tty_struct *tty)
+static int capinc_tty_write_room(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	int room;
@@ -1458,7 +1454,7 @@
 	return room;
 }
 
-int capinc_tty_chars_in_buffer(struct tty_struct *tty)
+static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 	if (!mp || !mp->nccip) {
@@ -1476,7 +1472,7 @@
 	return mp->outbytes;
 }
 
-int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
+static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
 	int error = 0;
@@ -1488,14 +1484,14 @@
 	return error;
 }
 
-void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
+static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_set_termios\n");
 #endif
 }
 
-void capinc_tty_throttle(struct tty_struct * tty)
+static void capinc_tty_throttle(struct tty_struct * tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 #ifdef _DEBUG_TTYFUNCS
@@ -1505,7 +1501,7 @@
 		mp->ttyinstop = 1;
 }
 
-void capinc_tty_unthrottle(struct tty_struct * tty)
+static void capinc_tty_unthrottle(struct tty_struct * tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 #ifdef _DEBUG_TTYFUNCS
@@ -1517,7 +1513,7 @@
 	}
 }
 
-void capinc_tty_stop(struct tty_struct *tty)
+static void capinc_tty_stop(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 #ifdef _DEBUG_TTYFUNCS
@@ -1528,7 +1524,7 @@
 	}
 }
 
-void capinc_tty_start(struct tty_struct *tty)
+static void capinc_tty_start(struct tty_struct *tty)
 {
 	struct capiminor *mp = (struct capiminor *)tty->driver_data;
 #ifdef _DEBUG_TTYFUNCS
@@ -1540,49 +1536,43 @@
 	}
 }
 
-void capinc_tty_hangup(struct tty_struct *tty)
+static void capinc_tty_hangup(struct tty_struct *tty)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_hangup\n");
 #endif
 }
 
-void capinc_tty_break_ctl(struct tty_struct *tty, int state)
+static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
 #endif
 }
 
-void capinc_tty_flush_buffer(struct tty_struct *tty)
+static void capinc_tty_flush_buffer(struct tty_struct *tty)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_flush_buffer\n");
 #endif
 }
 
-void capinc_tty_set_ldisc(struct tty_struct *tty)
+static void capinc_tty_set_ldisc(struct tty_struct *tty)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_set_ldisc\n");
 #endif
 }
 
-void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
+static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
 {
 #ifdef _DEBUG_TTYFUNCS
 	printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);
 #endif
 }
 
-int capinc_tty_read_proc(char *page, char **start, off_t off,
-			  int count, int *eof, void *data)
-{
-	return 0;
-}
-
-int capinc_write_proc(struct file *file, const char *buffer,
-			  unsigned long count, void *data)
+static int capinc_tty_read_proc(char *page, char **start, off_t off,
+				int count, int *eof, void *data)
 {
 	return 0;
 }
@@ -1594,7 +1584,7 @@
 static struct termios *capinc_tty_termios[CAPINC_NR_PORTS];
 static struct termios *capinc_tty_termios_locked[CAPINC_NR_PORTS];
 
-int capinc_tty_init(void)
+static int capinc_tty_init(void)
 {
 	struct tty_driver *drv = &capinc_tty_driver;
 
@@ -1652,7 +1642,7 @@
 	return 0;
 }
 
-void capinc_tty_exit(void)
+static void capinc_tty_exit(void)
 {
 	struct tty_driver *drv = &capinc_tty_driver;
 	int retval;
@@ -1844,7 +1834,7 @@
 	return 0;
 }
 
-static void lower_callback(unsigned int cmd, __u32 contr, void *data)
+static void lower_callback(unsigned int cmd, u32 contr, void *data)
 {
 	struct capi_ncciinfo *np;
 	struct capidev *cdev;
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c
--- v2.5.0/linux/drivers/isdn/divert/divert_procfs.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/divert/divert_procfs.c	Thu Dec  6 14:01:17 2001
@@ -29,6 +29,7 @@
 ulong if_used = 0;		/* number of interface users */
 static struct divert_info *divert_info_head = NULL;	/* head of queue */
 static struct divert_info *divert_info_tail = NULL;	/* pointer to last entry */
+static spinlock_t divert_info_lock = SPIN_LOCK_UNLOCKED;/* lock for queue */
 static wait_queue_head_t rd_queue;
 
 /*********************************/
@@ -50,15 +51,13 @@
 		 return;	/* no memory */
 	strcpy(ib->info_start, cp);	/* set output string */
 	ib->next = NULL;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave( &divert_info_lock, flags );
 	ib->usage_cnt = if_used;
 	if (!divert_info_head)
 		divert_info_head = ib;	/* new head */
 	else
 		divert_info_tail->next = ib;	/* follows existing messages */
 	divert_info_tail = ib;	/* new tail */
-	restore_flags(flags);
 
 	/* delete old entrys */
 	while (divert_info_head->next) {
@@ -70,6 +69,7 @@
 		} else
 			break;
 	}			/* divert_info_head->next */
+	spin_unlock_irqrestore( &divert_info_lock, flags );
 	wake_up_interruptible(&(rd_queue));
 }				/* put_info_buffer */
 
@@ -135,17 +135,14 @@
 {
 	unsigned long flags;
 
-	lock_kernel();
-	save_flags(flags);
-	cli();
-	if_used++;
+	spin_lock_irqsave( &divert_info_lock, flags );
+ 	if_used++;
 	if (divert_info_head)
 		(struct divert_info **) filep->private_data = &(divert_info_tail->next);
 	else
 		(struct divert_info **) filep->private_data = &divert_info_head;
-	restore_flags(flags);
+	spin_unlock_irqrestore( &divert_info_lock, flags );
 	/*  start_divert(); */
-	unlock_kernel();
 	return (0);
 }				/* isdn_divert_open */
 
@@ -158,23 +155,20 @@
 	struct divert_info *inf;
 	unsigned long flags;
 
-	lock_kernel();
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave( &divert_info_lock, flags );
 	if_used--;
 	inf = *((struct divert_info **) filep->private_data);
 	while (inf) {
 		inf->usage_cnt--;
 		inf = inf->next;
 	}
-	restore_flags(flags);
 	if (if_used <= 0)
 		while (divert_info_head) {
 			inf = divert_info_head;
 			divert_info_head = divert_info_head->next;
 			kfree(inf);
 		}
-	unlock_kernel();
+	spin_unlock_irqrestore( &divert_info_lock, flags );
 	return (0);
 }				/* isdn_divert_close */
 
@@ -267,6 +261,7 @@
 #ifdef CONFIG_PROC_FS
 static struct file_operations isdn_fops =
 {
+	owner:          THIS_MODULE,
 	llseek:         no_llseek,
 	read:           isdn_divert_read,
 	write:          isdn_divert_write,
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/eicon/common.c linux/drivers/isdn/eicon/common.c
--- v2.5.0/linux/drivers/isdn/eicon/common.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/common.c	Thu Dec  6 14:01:17 2001
@@ -808,7 +808,9 @@
 	
 	while(i--)
 	{
-		DivaDoCardDpc(card++);
+            if (card->state == DIA_RUNNING)
+		DivaDoCardDpc(card);
+            card++;
 	}
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/eicon/eicon_mod.c linux/drivers/isdn/eicon/eicon_mod.c
--- v2.5.0/linux/drivers/isdn/eicon/eicon_mod.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/eicon/eicon_mod.c	Thu Dec  6 14:01:17 2001
@@ -1550,7 +1550,7 @@
             	};
 	};
 	/* all adapter flavors checked without match, finito with:            */
-        return ENODEV;
+        return -ENODEV;
 };
 
 
@@ -1597,14 +1597,14 @@
 				membase = cards_membase;
 			} else {
 				if (membase != cards_membase)
-					return ENODEV;
+					return -ENODEV;
 			};
 			cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
 			if (irq == -1) { 
 				irq = cards_irq;
 			} else {
 				if (irq != cards_irq)
-					return ENODEV;
+					return -ENODEV;
 			};
 			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
 			type = EICON_CTYPE_ISAPRI; 
@@ -1616,14 +1616,14 @@
 				membase = cards_membase;
 			} else {
 				if (membase != cards_membase)
-					return ENODEV;
+					return -ENODEV;
 			};
 			cards_irq=irq_array[((adf_pos0 & 0xC)>>2)];
 			if (irq == -1) { 
 				irq = cards_irq;
 			} else {
 				if (irq != cards_irq)
-					return ENODEV;
+					return -ENODEV;
 			};
 
 			cards_io= 0xC00 + ((adf_pos0>>4)*0x10);
@@ -1637,12 +1637,12 @@
 				irq = cards_irq;
 			} else {
 				if (irq != cards_irq)
-					return ENODEV;
+					return -ENODEV;
 			};
 			type = 0; 
 			break;
 		default:
-			return  ENODEV;
+			return -ENODEV;
 	};
 	/* matching membase & irq */
 	if ( 1 == eicon_addcard(type, membase, irq, id, 0)) { 
@@ -1661,7 +1661,7 @@
 			cards->mca_slot+1);
 		return  0 ; /* eicon_addcard added a card */
 	} else {
-		return ENODEV;
+		return -ENODEV;
 	};
 };
 #endif /* CONFIG_MCA */
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/Makefile linux/drivers/isdn/hisax/Makefile
--- v2.5.0/linux/drivers/isdn/hisax/Makefile	Sun Sep  9 10:45:43 2001
+++ linux/drivers/isdn/hisax/Makefile	Fri Nov 30 09:48:32 2001
@@ -6,7 +6,7 @@
 
 # Objects that export symbols.
 
-export-objs	  := config.o fsm.o
+export-objs	  := config.o fsm.o hisax_isac.o
 
 # Multipart objects.
 
@@ -58,6 +58,7 @@
 obj-$(CONFIG_HISAX_SEDLBAUER_CS)	+= sedlbauer_cs.o
 obj-$(CONFIG_HISAX_ELSA_CS)		+= elsa_cs.o
 obj-$(CONFIG_HISAX_ST5481)		+= hisax_st5481.o
+obj-$(CONFIG_HISAX_FRITZ_PCIPNP)        += hisax_isac.o hisax_fcpcipnp.o
 
 CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
 CFLAGS_cert.o := -DCERTIFICATION=$(CERT)
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- v2.5.0/linux/drivers/isdn/hisax/config.c	Sun Sep 30 12:26:05 2001
+++ linux/drivers/isdn/hisax/config.c	Fri Nov 30 09:48:32 2001
@@ -1505,15 +1505,9 @@
 	       nrcards, (nrcards > 1) ? "s" : "");
 
 	/* Install only, if at least one card found */
-	if (!HiSax_inithardware(NULL)) {
-		retval = -EIO;
-		goto out_isdnl1;
-	}
-
+	HiSax_inithardware(NULL);
 	return 0;
 
- out_isdnl1:
-	Isdnl1Free();
  out_tei:
 	TeiFree();
  out_isdnl2:
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/hisax_fcpcipnp.c linux/drivers/isdn/hisax/hisax_fcpcipnp.c
--- v2.5.0/linux/drivers/isdn/hisax/hisax_fcpcipnp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/hisax_fcpcipnp.c	Thu Dec  6 14:01:17 2001
@@ -0,0 +1,1001 @@
+/*
+ * Driver for AVM Fritz!PCI, Fritz!PCI v2, Fritz!PnP ISDN cards
+ *
+ * Author       Kai Germaschewski
+ * Copyright    2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
+ *              2001 by Karsten Keil       <keil@isdn4linux.de>
+ * 
+ * based upon Karsten Keil's original avm_pci.c driver
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * Thanks to Wizard Computersysteme GmbH, Bremervoerde and
+ *           SoHaNet Technology GmbH, Berlin
+ * for supporting the development of this driver
+ */
+
+
+/* TODO:
+ *
+ * o POWER PC
+ * o clean up debugging
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/isapnp.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include "hisax_fcpcipnp.h"
+
+// debugging cruft
+#define __debug_variable debug
+#include "hisax_debug.h"
+
+#ifdef CONFIG_HISAX_DEBUG
+static int debug = 0;
+MODULE_PARM(debug, "i");
+#endif
+
+MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
+MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
+
+static struct pci_device_id fcpci_ids[] __devinitdata = {
+	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1   , PCI_ANY_ID, PCI_ANY_ID,
+	  0, 0, (unsigned long) "Fritz!Card PCI" },
+	{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
+	  0, 0, (unsigned long) "Fritz!Card PCI v2" },
+	{ }
+};
+MODULE_DEVICE_TABLE(pci, fcpci_ids);
+
+static struct isapnp_device_id fcpnp_ids[] __devinitdata = {
+	{ ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900),
+	  ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), 
+	  (unsigned long) "Fritz!Card PnP" },
+	{ }
+};
+MODULE_DEVICE_TABLE(isapnp, fcpnp_ids);
+
+static int protocol = 2;       /* EURO-ISDN Default */
+MODULE_PARM(protocol, "i");
+
+// ----------------------------------------------------------------------
+
+#define  AVM_INDEX              0x04
+#define  AVM_DATA               0x10
+
+#define	 AVM_IDX_HDLC_1		0x00
+#define	 AVM_IDX_HDLC_2		0x01
+#define	 AVM_IDX_ISAC_FIFO	0x02
+#define	 AVM_IDX_ISAC_REG_LOW	0x04
+#define	 AVM_IDX_ISAC_REG_HIGH	0x06
+
+#define  AVM_STATUS0            0x02
+
+#define  AVM_STATUS0_IRQ_ISAC	0x01
+#define  AVM_STATUS0_IRQ_HDLC	0x02
+#define  AVM_STATUS0_IRQ_TIMER	0x04
+#define  AVM_STATUS0_IRQ_MASK	0x07
+
+#define  AVM_STATUS0_RESET	0x01
+#define  AVM_STATUS0_DIS_TIMER	0x02
+#define  AVM_STATUS0_RES_TIMER	0x04
+#define  AVM_STATUS0_ENA_IRQ	0x08
+#define  AVM_STATUS0_TESTBIT	0x10
+
+#define  AVM_STATUS1            0x03
+#define  AVM_STATUS1_ENA_IOM	0x80
+
+#define  HDLC_FIFO		0x0
+#define  HDLC_STATUS		0x4
+#define  HDLC_CTRL		0x4
+
+#define  HDLC_MODE_ITF_FLG	0x01
+#define  HDLC_MODE_TRANS	0x02
+#define  HDLC_MODE_CCR_7	0x04
+#define  HDLC_MODE_CCR_16	0x08
+#define  HDLC_MODE_TESTLOOP	0x80
+
+#define  HDLC_INT_XPR		0x80
+#define  HDLC_INT_XDU		0x40
+#define  HDLC_INT_RPR		0x20
+#define  HDLC_INT_MASK		0xE0
+
+#define  HDLC_STAT_RME		0x01
+#define  HDLC_STAT_RDO		0x10
+#define  HDLC_STAT_CRCVFRRAB	0x0E
+#define  HDLC_STAT_CRCVFR	0x06
+#define  HDLC_STAT_RML_MASK	0x3f00
+
+#define  HDLC_CMD_XRS		0x80
+#define  HDLC_CMD_XME		0x01
+#define  HDLC_CMD_RRS		0x20
+#define  HDLC_CMD_XML_MASK	0x3f00
+
+#define  AVM_HDLC_FIFO_1        0x10
+#define  AVM_HDLC_FIFO_2        0x18
+
+#define  AVM_HDLC_STATUS_1      0x14
+#define  AVM_HDLC_STATUS_2      0x1c
+
+#define  AVM_ISACSX_INDEX       0x04
+#define  AVM_ISACSX_DATA        0x08
+
+// ----------------------------------------------------------------------
+// Fritz!PCI
+
+static unsigned char fcpci_read_isac(struct isac *isac, unsigned char offset)
+{
+	struct fritz_adapter *adapter = isac->priv;
+	unsigned char idx = (offset > 0x2f) ? 
+		AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
+	unsigned char val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outb(idx, adapter->io + AVM_INDEX);
+	val = inb(adapter->io + AVM_DATA + (offset & 0xf));
+ 	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+	DBG(0x1000, " port %#x, value %#x",
+	    offset, val);
+	return val;
+}
+
+static void fcpci_write_isac(struct isac *isac, unsigned char offset,
+			     unsigned char value)
+{
+	struct fritz_adapter *adapter = isac->priv;
+	unsigned char idx = (offset > 0x2f) ? 
+		AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
+	unsigned long flags;
+
+	DBG(0x1000, " port %#x, value %#x",
+	    offset, value);
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outb(idx, adapter->io + AVM_INDEX);
+	outb(value, adapter->io + AVM_DATA + (offset & 0xf));
+ 	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+}
+
+static void fcpci_read_isac_fifo(struct isac *isac, unsigned char * data, 
+				 int size)
+{
+	struct fritz_adapter *adapter = isac->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
+	insb(adapter->io + AVM_DATA, data, size);
+ 	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+}
+
+static void fcpci_write_isac_fifo(struct isac *isac, unsigned char * data, 
+				  int size)
+{
+	struct fritz_adapter *adapter = isac->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
+	outsb(adapter->io + AVM_DATA, data, size);
+ 	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+}
+
+static u32 fcpci_read_hdlc_status(struct fritz_adapter *adapter, int nr)
+{
+	u32 val;
+	int idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outl(idx, adapter->io + AVM_INDEX);
+	val = inl(adapter->io + AVM_DATA + HDLC_STATUS);
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+	return val;
+}
+
+static void __fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	int idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
+
+	DBG(0x40, "hdlc %c wr%x ctrl %x",
+	    'A' + bcs->channel, which, bcs->ctrl.ctrl);
+
+	outl(idx, adapter->io + AVM_INDEX);
+	outl(bcs->ctrl.ctrl, adapter->io + AVM_DATA + HDLC_CTRL);
+}
+
+static void fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	__fcpci_write_ctrl(bcs, which);
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+}
+
+// ----------------------------------------------------------------------
+// Fritz!PCI v2
+
+static unsigned char fcpci2_read_isac(struct isac *isac, unsigned char offset)
+{
+	struct fritz_adapter *adapter = isac->priv;
+	unsigned char val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outl(offset, adapter->io + AVM_ISACSX_INDEX);
+	val = inl(adapter->io + AVM_ISACSX_DATA);
+ 	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+	DBG(0x1000, " port %#x, value %#x",
+	    offset, val);
+
+	return val;
+}
+
+static void fcpci2_write_isac(struct isac *isac, unsigned char offset, 
+			      unsigned char value)
+{
+	struct fritz_adapter *adapter = isac->priv;
+	unsigned long flags;
+
+	DBG(0x1000, " port %#x, value %#x",
+	    offset, value);
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outl(offset, adapter->io + AVM_ISACSX_INDEX);
+	outl(value, adapter->io + AVM_ISACSX_DATA);
+ 	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+}
+
+static void fcpci2_read_isac_fifo(struct isac *isac, unsigned char * data, 
+				  int size)
+{
+	struct fritz_adapter *adapter = isac->priv;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outl(0, adapter->io + AVM_ISACSX_INDEX);
+	for (i = 0; i < size; i++)
+		data[i] = inl(adapter->io + AVM_ISACSX_DATA);
+ 	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+}
+
+static void fcpci2_write_isac_fifo(struct isac *isac, unsigned char * data, 
+				   int size)
+{
+	struct fritz_adapter *adapter = isac->priv;
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outl(0, adapter->io + AVM_ISACSX_INDEX);
+	for (i = 0; i < size; i++)
+		outl(data[i], adapter->io + AVM_ISACSX_DATA);
+ 	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+}
+
+static u32 fcpci2_read_hdlc_status(struct fritz_adapter *adapter, int nr)
+{
+	int offset = nr ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
+
+	return inl(adapter->io + offset);
+}
+
+static void fcpci2_write_ctrl(struct fritz_bcs *bcs, int which)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	int offset = bcs->channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
+
+	DBG(0x40, "hdlc %c wr%x ctrl %x",
+	    'A' + bcs->channel, which, bcs->ctrl.ctrl);
+
+	outl(bcs->ctrl.ctrl, adapter->io + offset);
+}
+
+// ----------------------------------------------------------------------
+// Fritz!PnP (ISAC access as for Fritz!PCI)
+
+static u32 fcpnp_read_hdlc_status(struct fritz_adapter *adapter, int nr)
+{
+	unsigned char idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	outb(idx, adapter->io + AVM_INDEX);
+	val = inb(adapter->io + AVM_DATA + HDLC_STATUS);
+	if (val & HDLC_INT_RPR)
+		val |= inb(adapter->io + AVM_DATA + HDLC_STATUS + 1) << 8;
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+	return val;
+}
+
+static void __fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
+
+	DBG(0x40, "hdlc %c wr%x ctrl %x",
+	    'A' + bcs->channel, which, bcs->ctrl.ctrl);
+
+	outb(idx, adapter->io + AVM_INDEX);
+	if (which & 4)
+		outb(bcs->ctrl.sr.mode, 
+		     adapter->io + AVM_DATA + HDLC_STATUS + 2);
+	if (which & 2)
+		outb(bcs->ctrl.sr.xml, 
+		     adapter->io + AVM_DATA + HDLC_STATUS + 1);
+	if (which & 1)
+		outb(bcs->ctrl.sr.cmd,
+		     adapter->io + AVM_DATA + HDLC_STATUS + 0);
+}
+
+static void fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	unsigned long flags;
+
+	spin_lock_irqsave(&adapter->hw_lock, flags);
+	__fcpnp_write_ctrl(bcs, which);
+	spin_unlock_irqrestore(&adapter->hw_lock, flags);
+}
+
+// ----------------------------------------------------------------------
+
+static inline void B_L1L2(struct fritz_bcs *bcs, int pr, void *arg)
+{
+	struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;
+
+	DBG(2, "pr %#x", pr);
+	ifc->l1l2(ifc, pr, arg);
+}
+
+static void hdlc_fill_fifo(struct fritz_bcs *bcs)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	struct sk_buff *skb = bcs->tx_skb;
+	int count;
+	int fifo_size = 32;
+	unsigned long flags;
+	unsigned char *p;
+
+	DBG(0x40, "hdlc_fill_fifo");
+
+	if (!skb)
+		BUG();
+
+	if (skb->len == 0)
+		BUG();
+
+	bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME;
+	if (bcs->tx_skb->len > fifo_size) {
+		count = fifo_size;
+	} else {
+		count = bcs->tx_skb->len;
+		if (bcs->mode != L1_MODE_TRANS)
+			bcs->ctrl.sr.cmd |= HDLC_CMD_XME;
+	}
+	DBG(0x40, "hdlc_fill_fifo %d/%d", count, bcs->tx_skb->len);
+	p = bcs->tx_skb->data;
+	skb_pull(bcs->tx_skb, count);
+	bcs->tx_cnt += count;
+	bcs->ctrl.sr.xml = ((count == fifo_size) ? 0 : count);
+
+	switch (adapter->type) {
+	case AVM_FRITZ_PCI:
+		spin_lock_irqsave(&adapter->hw_lock, flags);
+		// sets the correct AVM_INDEX, too
+		__fcpci_write_ctrl(bcs, 3);
+		outsl(adapter->io + AVM_DATA + HDLC_FIFO,
+		      p, (count + 3) / 4);
+		spin_unlock_irqrestore(&adapter->hw_lock, flags);
+		break;
+	case AVM_FRITZ_PCIV2:
+		fcpci2_write_ctrl(bcs, 3);
+		outsl(adapter->io + 
+		      (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
+		      p, (count + 3) / 4);
+		break;
+	case AVM_FRITZ_PNP:
+		spin_lock_irqsave(&adapter->hw_lock, flags);
+		// sets the correct AVM_INDEX, too
+		__fcpnp_write_ctrl(bcs, 3);
+		outsb(adapter->io + AVM_DATA, p, count);
+		spin_unlock_irqrestore(&adapter->hw_lock, flags);
+		break;
+	}
+}
+
+static inline void hdlc_empty_fifo(struct fritz_bcs *bcs, int count)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	unsigned char *p;
+	unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
+
+	DBG(0x10, "hdlc_empty_fifo %d", count);
+	if (bcs->rcvidx + count > HSCX_BUFMAX) {
+		DBG(0x10, "hdlc_empty_fifo: incoming packet too large");
+		return;
+	}
+	p = bcs->rcvbuf + bcs->rcvidx;
+	bcs->rcvidx += count;
+	switch (adapter->type) {
+	case AVM_FRITZ_PCI:
+		spin_lock(&adapter->hw_lock);
+		outl(idx, adapter->io + AVM_INDEX);
+		insl(adapter->io + AVM_DATA + HDLC_FIFO, 
+		     p, (count + 3) / 4);
+		spin_unlock(&adapter->hw_lock);
+		break;
+	case AVM_FRITZ_PCIV2:
+		insl(adapter->io + 
+		     (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
+		     p, (count + 3) / 4);
+		break;
+	case AVM_FRITZ_PNP:
+		spin_lock(&adapter->hw_lock);
+		outb(idx, adapter->io + AVM_INDEX);
+		insb(adapter->io + AVM_DATA, p, count);
+		spin_unlock(&adapter->hw_lock);
+		break;
+	}
+}
+
+static inline void hdlc_rpr_irq(struct fritz_bcs *bcs, u32 stat)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	struct sk_buff *skb;
+	int len;
+
+	if (stat & HDLC_STAT_RDO) {
+		DBG(0x10, "RDO");
+		bcs->ctrl.sr.xml = 0;
+		bcs->ctrl.sr.cmd |= HDLC_CMD_RRS;
+		adapter->write_ctrl(bcs, 1);
+		bcs->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
+		adapter->write_ctrl(bcs, 1);
+		bcs->rcvidx = 0;
+		return;
+	}
+
+	len = (stat & HDLC_STAT_RML_MASK) >> 8;
+	if (len == 0)
+		len = 32;
+
+	hdlc_empty_fifo(bcs, len);
+
+	if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
+		if (((stat & HDLC_STAT_CRCVFRRAB)== HDLC_STAT_CRCVFR) ||
+		    (bcs->mode == L1_MODE_TRANS)) {
+			skb = dev_alloc_skb(bcs->rcvidx);
+			if (!skb) {
+				printk(KERN_WARNING "HDLC: receive out of memory\n");
+			} else {
+				memcpy(skb_put(skb, bcs->rcvidx), bcs->rcvbuf,
+				       bcs->rcvidx);
+				DBG_SKB(1, skb);
+				B_L1L2(bcs, PH_DATA | INDICATION, skb);
+			}
+			bcs->rcvidx = 0;
+		} else {
+			DBG(0x10, "ch%d invalid frame %#x",
+			    bcs->channel, stat);
+			bcs->rcvidx = 0;
+		}
+	}
+}
+
+static inline void hdlc_xdu_irq(struct fritz_bcs *bcs)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+
+	/* Here we lost an TX interrupt, so
+	 * restart transmitting the whole frame.
+	 */
+	bcs->ctrl.sr.xml = 0;
+	bcs->ctrl.sr.cmd |= HDLC_CMD_XRS;
+	adapter->write_ctrl(bcs, 1);
+	bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
+	adapter->write_ctrl(bcs, 1);
+
+	if (!bcs->tx_skb) {
+		DBG(0x10, "XDU without skb");
+		return;
+	}
+	skb_push(bcs->tx_skb, bcs->tx_cnt);
+	bcs->tx_cnt = 0;
+}
+
+static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
+{
+	struct sk_buff *skb;
+
+	skb = bcs->tx_skb;
+	if (!skb)
+		return;
+
+	if (skb->len) {
+		hdlc_fill_fifo(bcs);
+		return;
+	}
+	bcs->tx_cnt = 0;
+	bcs->tx_skb = NULL;
+	B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
+	dev_kfree_skb_irq(skb);
+}
+
+static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
+{
+	DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
+	if (stat & HDLC_INT_RPR) {
+		DBG(0x10, "RPR");
+		hdlc_rpr_irq(bcs, stat);
+	}
+	if (stat & HDLC_INT_XDU) {
+		DBG(0x10, "XDU");
+		hdlc_xdu_irq(bcs);
+	}
+	if (stat & HDLC_INT_XPR) {
+		DBG(0x10, "XPR");
+		hdlc_xpr_irq(bcs);
+	}
+}
+
+static inline void hdlc_irq(struct fritz_adapter *adapter)
+{
+	int nr;
+	u32 stat;
+
+	for (nr = 0; nr < 2; nr++) {
+		stat = adapter->read_hdlc_status(adapter, nr);
+		DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
+		if (stat & HDLC_INT_MASK)
+			hdlc_irq_one(&adapter->bcs[nr], stat);
+	}
+}
+
+static void modehdlc(struct fritz_bcs *bcs, int mode)
+{
+	struct fritz_adapter *adapter = bcs->adapter;
+	
+	DBG(0x40, "hdlc %c mode %d --> %d",
+	    'A' + bcs->channel, bcs->mode, mode);
+
+	if (bcs->mode == mode)
+		return;
+
+	bcs->ctrl.ctrl = 0;
+	bcs->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
+	switch (mode) {
+	case L1_MODE_NULL:
+		bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
+		adapter->write_ctrl(bcs, 5);
+		break;
+	case L1_MODE_TRANS:
+		bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
+		adapter->write_ctrl(bcs, 5);
+		bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
+		adapter->write_ctrl(bcs, 1);
+		bcs->ctrl.sr.cmd = 0;
+		break;
+	case L1_MODE_HDLC:
+		bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+		adapter->write_ctrl(bcs, 5);
+		bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
+		adapter->write_ctrl(bcs, 1);
+		bcs->ctrl.sr.cmd = 0;
+		break;
+	}
+	bcs->mode = mode;
+}
+
+static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
+{
+	struct fritz_bcs *bcs = ifc->priv;
+	struct sk_buff *skb = arg;
+	int mode;
+
+	DBG(0x10, "pr %#x", pr);
+
+	switch (pr) {
+	case PH_DATA | REQUEST:
+		if (bcs->tx_skb)
+			BUG();
+		
+		bcs->tx_skb = skb;
+		DBG_SKB(1, skb);
+		hdlc_fill_fifo(bcs);
+		break;
+	case PH_ACTIVATE | REQUEST:
+		mode = (int) arg;
+		DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
+		modehdlc(bcs, mode);
+		B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
+		break;
+	case PH_DEACTIVATE | REQUEST:
+		DBG(4,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
+		modehdlc(bcs, L1_MODE_NULL);
+		B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
+		break;
+	}
+}
+
+// ----------------------------------------------------------------------
+
+static void fcpci2_irq(int intno, void *dev, struct pt_regs *regs)
+{
+	struct fritz_adapter *adapter = dev;
+	unsigned char val;
+
+	val = inb(adapter->io + AVM_STATUS0);
+	if (!(val & AVM_STATUS0_IRQ_MASK))
+		/* hopefully a shared  IRQ reqest */
+		return;
+	DBG(2, "STATUS0 %#x", val);
+	if (val & AVM_STATUS0_IRQ_ISAC)
+		isacsx_irq(&adapter->isac);
+
+	if (val & AVM_STATUS0_IRQ_HDLC)
+		hdlc_irq(adapter);
+}
+
+static void fcpci_irq(int intno, void *dev, struct pt_regs *regs)
+{
+	struct fritz_adapter *adapter = dev;
+	unsigned char sval;
+
+	sval = inb(adapter->io + 2);
+	if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
+		/* possibly a shared  IRQ reqest */
+		return;
+	DBG(2, "sval %#x", sval);
+	if (!(sval & AVM_STATUS0_IRQ_ISAC))
+		isac_irq(&adapter->isac);
+
+	if (!(sval & AVM_STATUS0_IRQ_HDLC))
+		hdlc_irq(adapter);
+}
+
+// ----------------------------------------------------------------------
+
+static inline void fcpci2_init(struct fritz_adapter *adapter)
+{
+	outb(AVM_STATUS0_RES_TIMER, adapter->io + AVM_STATUS0);
+	outb(AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
+
+}
+
+static inline void fcpci_init(struct fritz_adapter *adapter)
+{
+	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | 
+	     AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
+
+	outb(AVM_STATUS1_ENA_IOM | adapter->irq, 
+	     adapter->io + AVM_STATUS1);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(50*HZ / 1000); /* Timeout 50ms */
+}
+
+// ----------------------------------------------------------------------
+
+static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter)
+{
+	u32 val = 0;
+	int retval;
+
+	DBG(1,"");
+
+	isac_init(&adapter->isac); // FIXME is this okay now
+
+	retval = -EBUSY;
+	if (!request_region(adapter->io, 32, "fcpcipnp"))
+		goto err;
+
+	switch (adapter->type) {
+	case AVM_FRITZ_PCIV2:
+		retval = request_irq(adapter->irq, fcpci2_irq, SA_SHIRQ, 
+				     "fcpcipnp", adapter);
+		break;
+	case AVM_FRITZ_PCI:
+		retval = request_irq(adapter->irq, fcpci_irq, SA_SHIRQ,
+				     "fcpcipnp", adapter);
+		break;
+	case AVM_FRITZ_PNP:
+		retval = request_irq(adapter->irq, fcpci_irq, 0,
+				     "fcpcipnp", adapter);
+		break;
+	}
+	if (retval)
+		goto err_region;
+
+	switch (adapter->type) {
+	case AVM_FRITZ_PCIV2:
+	case AVM_FRITZ_PCI:
+		val = inl(adapter->io);
+		break;
+	case AVM_FRITZ_PNP:
+		val = inb(adapter->io);
+		val |= inb(adapter->io + 1) << 8;
+		break;
+	}
+
+	DBG(1, "stat %#x Class %X Rev %d",
+	    val, val & 0xff, (val>>8) & 0xff);
+
+	spin_lock_init(&adapter->hw_lock);
+	adapter->isac.priv = adapter;
+	switch (adapter->type) {
+	case AVM_FRITZ_PCIV2:
+		adapter->isac.read_isac       = &fcpci2_read_isac;;
+		adapter->isac.write_isac      = &fcpci2_write_isac;
+		adapter->isac.read_isac_fifo  = &fcpci2_read_isac_fifo;
+		adapter->isac.write_isac_fifo = &fcpci2_write_isac_fifo;
+
+		adapter->read_hdlc_status     = &fcpci2_read_hdlc_status;
+		adapter->write_ctrl           = &fcpci2_write_ctrl;
+		break;
+	case AVM_FRITZ_PCI:
+		adapter->isac.read_isac       = &fcpci_read_isac;;
+		adapter->isac.write_isac      = &fcpci_write_isac;
+		adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
+		adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
+
+		adapter->read_hdlc_status     = &fcpci_read_hdlc_status;
+		adapter->write_ctrl           = &fcpci_write_ctrl;
+		break;
+	case AVM_FRITZ_PNP:
+		adapter->isac.read_isac       = &fcpci_read_isac;;
+		adapter->isac.write_isac      = &fcpci_write_isac;
+		adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
+		adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
+
+		adapter->read_hdlc_status     = &fcpnp_read_hdlc_status;
+		adapter->write_ctrl           = &fcpnp_write_ctrl;
+		break;
+	}
+
+	// Reset
+	outb(0, adapter->io + AVM_STATUS0);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(50 * HZ / 1000); // 50 msec
+	outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(50 * HZ / 1000); // 50 msec
+	outb(0, adapter->io + AVM_STATUS0);
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(10 * HZ / 1000); // 10 msec
+
+	switch (adapter->type) {
+	case AVM_FRITZ_PCIV2:
+		fcpci2_init(adapter);
+		isacsx_setup(&adapter->isac);
+		break;
+	case AVM_FRITZ_PCI:
+	case AVM_FRITZ_PNP:
+		fcpci_init(adapter);
+		isac_setup(&adapter->isac);
+		break;
+	}
+	val = adapter->read_hdlc_status(adapter, 0);
+	DBG(0x20, "HDLC A STA %x", val);
+	val = adapter->read_hdlc_status(adapter, 1);
+	DBG(0x20, "HDLC B STA %x", val);
+
+	adapter->bcs[0].mode = -1;
+	adapter->bcs[1].mode = -1;
+	modehdlc(&adapter->bcs[0], L1_MODE_NULL);
+	modehdlc(&adapter->bcs[1], L1_MODE_NULL);
+
+	return 0;
+
+ err_region:
+	release_region(adapter->io, 32);
+ err:
+	return retval;
+}
+
+static void __devexit fcpcipnp_release(struct fritz_adapter *adapter)
+{
+	DBG(1,"");
+
+	outb(0, adapter->io + AVM_STATUS0);
+	free_irq(adapter->irq, adapter);
+	release_region(adapter->io, 32);
+}
+
+// ----------------------------------------------------------------------
+
+static struct fritz_adapter * __devinit 
+new_adapter(struct pci_dev *pdev)
+{
+	struct fritz_adapter *adapter;
+	struct hisax_b_if *b_if[2];
+	int i;
+
+	adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
+	if (!adapter)
+		return NULL;
+
+	memset(adapter, 0, sizeof(struct fritz_adapter));
+
+	SET_MODULE_OWNER(&adapter->isac.hisax_d_if);
+	adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
+	adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
+	
+	for (i = 0; i < 2; i++) {
+		adapter->bcs[i].adapter = adapter;
+		adapter->bcs[i].channel = i;
+		adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
+		adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
+	}
+
+	pci_set_drvdata(pdev, adapter);
+
+	for (i = 0; i < 2; i++)
+		b_if[i] = &adapter->bcs[i].b_if;
+
+	hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp", protocol);
+
+	return adapter;
+}
+
+static void delete_adapter(struct fritz_adapter *adapter)
+{
+	hisax_unregister(&adapter->isac.hisax_d_if);
+	kfree(adapter);
+}
+
+static int __devinit fcpci_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *ent)
+{
+	struct fritz_adapter *adapter;
+	int retval;
+
+	retval = -ENOMEM;
+	adapter = new_adapter(pdev);
+	if (!adapter)
+		goto err;
+
+	if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2) 
+		adapter->type = AVM_FRITZ_PCIV2;
+	else
+		adapter->type = AVM_FRITZ_PCI;
+
+	retval = pci_enable_device(pdev);
+	if (retval)
+		goto err_free;
+
+	adapter->io = pci_resource_start(pdev, 1);
+	adapter->irq = pdev->irq;
+
+	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
+	       (char *) ent->driver_data, pdev->slot_name);
+
+	retval = fcpcipnp_setup(adapter);
+	if (retval)
+		goto err_free;
+
+	return 0;
+	
+ err_free:
+	delete_adapter(adapter);
+ err:
+	return retval;
+}
+
+static int __devinit fcpnp_probe(struct pci_dev *pdev,
+				 const struct isapnp_device_id *ent)
+{
+	struct fritz_adapter *adapter;
+	int retval;
+
+	retval = -ENOMEM;
+	adapter = new_adapter(pdev);
+	if (!adapter)
+		goto err;
+
+	adapter->type = AVM_FRITZ_PNP;
+
+	pdev->prepare(pdev);
+	pdev->deactivate(pdev); // why?
+	pdev->activate(pdev);
+	adapter->io = pdev->resource[0].start;
+	adapter->irq = pdev->irq_resource[0].start;
+
+	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
+	       (char *) ent->driver_data, adapter->io, adapter->irq);
+
+	retval = fcpcipnp_setup(adapter);
+	if (retval)
+		goto err_free;
+
+	return 0;
+	
+ err_free:
+	delete_adapter(adapter);
+ err:
+	return retval;
+}
+
+static void __devexit fcpci_remove(struct pci_dev *pdev)
+{
+	struct fritz_adapter *adapter = pci_get_drvdata(pdev);
+
+	fcpcipnp_release(adapter);
+	pci_disable_device(pdev);
+	delete_adapter(adapter);
+}
+
+static void __devexit fcpnp_remove(struct pci_dev *pdev)
+{
+	struct fritz_adapter *adapter = pci_get_drvdata(pdev);
+
+	fcpcipnp_release(adapter);
+	pdev->deactivate(pdev);
+	delete_adapter(adapter);
+}
+
+static struct pci_driver fcpci_driver = {
+	name:     "fcpci",
+	probe:    fcpci_probe,
+	remove:   fcpci_remove,
+	id_table: fcpci_ids,
+};
+
+static struct isapnp_driver fcpnp_driver = {
+	name:     "fcpnp",
+	probe:    fcpnp_probe,
+	remove:   fcpnp_remove,
+	id_table: fcpnp_ids,
+};
+
+static int __init hisax_fcpcipnp_init(void)
+{
+	int retval, pci_nr_found;
+
+	printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
+
+	retval = pci_register_driver(&fcpci_driver);
+	if (retval < 0)
+		goto out;
+	pci_nr_found = retval;
+
+	retval = isapnp_register_driver(&fcpnp_driver);
+	if (retval < 0)
+		goto out_unregister_pci;
+
+#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
+	if (pci_nr_found + retval == 0) {
+		retval = -ENODEV;
+		goto out_unregister_isapnp;
+	}
+#endif
+	return 0;
+
+#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
+ out_unregister_isapnp:
+	isapnp_unregister_driver(&fcpnp_driver);
+#endif
+ out_unregister_pci:
+	pci_unregister_driver(&fcpci_driver);
+ out:
+	return retval;
+}
+
+static void __exit hisax_fcpcipnp_exit(void)
+{
+	isapnp_unregister_driver(&fcpnp_driver);
+	pci_unregister_driver(&fcpci_driver);
+}
+
+module_init(hisax_fcpcipnp_init);
+module_exit(hisax_fcpcipnp_exit);
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/hisax_fcpcipnp.h linux/drivers/isdn/hisax/hisax_fcpcipnp.h
--- v2.5.0/linux/drivers/isdn/hisax/hisax_fcpcipnp.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/hisax_fcpcipnp.h	Fri Nov 30 09:48:32 2001
@@ -0,0 +1,57 @@
+#include "hisax_if.h"
+#include "hisax_isac.h"
+#include <linux/pci.h>
+
+#define HSCX_BUFMAX	4096
+
+enum {
+	AVM_FRITZ_PCI,
+	AVM_FRITZ_PNP,
+	AVM_FRITZ_PCIV2,
+};
+
+struct hdlc_stat_reg {
+#ifdef __BIG_ENDIAN
+	u_char fill __attribute__((packed));
+	u_char mode __attribute__((packed));
+	u_char xml  __attribute__((packed));
+	u_char cmd  __attribute__((packed));
+#else
+	u_char cmd  __attribute__((packed));
+	u_char xml  __attribute__((packed));
+	u_char mode __attribute__((packed));
+	u_char fill __attribute__((packed));
+#endif
+};
+
+struct fritz_bcs {
+	struct hisax_b_if b_if;
+	struct fritz_adapter *adapter;
+	int mode;
+	int channel;
+
+	union {
+		u_int ctrl;
+		struct hdlc_stat_reg sr;
+	} ctrl;
+	u_int stat;
+	int rcvidx;
+	u_char rcvbuf[HSCX_BUFMAX]; /* B-Channel receive Buffer */
+
+	int tx_cnt;		    /* B-Channel transmit counter */
+	struct sk_buff *tx_skb;     /* B-Channel transmit Buffer */
+};
+
+struct fritz_adapter {
+	int type;
+	spinlock_t hw_lock;
+	unsigned int io;
+	unsigned int irq;
+	struct isac isac;
+
+	struct fritz_bcs bcs[2];
+
+	u32  (*read_hdlc_status) (struct fritz_adapter *adapter, int nr);
+	void (*write_ctrl) (struct fritz_bcs *bcs, int which);
+};
+
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/hisax_isac.c linux/drivers/isdn/hisax/hisax_isac.c
--- v2.5.0/linux/drivers/isdn/hisax/hisax_isac.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/hisax_isac.c	Thu Dec  6 14:01:17 2001
@@ -0,0 +1,896 @@
+/*
+ * Driver for ISAC-S and ISAC-SX 
+ * ISDN Subscriber Access Controller for Terminals
+ *
+ * Author       Kai Germaschewski
+ * Copyright    2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
+ *              2001 by Karsten Keil       <keil@isdn4linux.de>
+ * 
+ * based upon Karsten Keil's original isac.c driver
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ *
+ * Thanks to Wizard Computersysteme GmbH, Bremervoerde and
+ *           SoHaNet Technology GmbH, Berlin
+ * for supporting the development of this driver
+ */
+
+/* TODO:
+ * specifically handle level vs edge triggered?
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include "hisax_isac.h"
+
+// debugging cruft
+
+#define __debug_variable debug
+#include "hisax_debug.h"
+
+#ifdef CONFIG_HISAX_DEBUG
+static int debug = 1;
+MODULE_PARM(debug, "i");
+
+static char *ISACVer[] = {
+  "2086/2186 V1.1", 
+  "2085 B1", 
+  "2085 B2",
+  "2085 V2.3"
+};
+#endif
+
+MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
+MODULE_DESCRIPTION("ISAC/ISAC-SX driver");
+
+#define DBG_WARN      0x0001
+#define DBG_IRQ       0x0002
+#define DBG_L1M       0x0004
+#define DBG_PR        0x0008
+#define DBG_RFIFO     0x0100
+#define DBG_RPACKET   0x0200
+#define DBG_XFIFO     0x1000
+#define DBG_XPACKET   0x2000
+
+// we need to distinguish ISAC-S and ISAC-SX
+#define TYPE_ISAC        0x00
+#define TYPE_ISACSX      0x01
+
+// registers etc.
+#define ISAC_MASK        0x20
+#define ISAC_ISTA        0x20
+#define ISAC_ISTA_EXI    0x01
+#define ISAC_ISTA_SIN    0x02
+#define ISAC_ISTA_CISQ   0x04
+#define ISAC_ISTA_XPR    0x10
+#define ISAC_ISTA_RSC    0x20
+#define ISAC_ISTA_RPF    0x40
+#define ISAC_ISTA_RME    0x80
+
+#define ISAC_STAR        0x21
+#define ISAC_CMDR        0x21
+#define ISAC_CMDR_XRES   0x01
+#define ISAC_CMDR_XME    0x02
+#define ISAC_CMDR_XTF    0x08
+#define ISAC_CMDR_RRES   0x40
+#define ISAC_CMDR_RMC    0x80
+
+#define ISAC_EXIR        0x24
+#define ISAC_EXIR_MOS    0x04
+#define ISAC_EXIR_XDU    0x40
+#define ISAC_EXIR_XMR    0x80
+
+#define ISAC_ADF2        0x39
+#define ISAC_SPCR        0x30
+#define ISAC_ADF1        0x38
+
+#define ISAC_CIR0        0x31
+#define ISAC_CIX0        0x31
+#define ISAC_CIR0_CIC0   0x02
+#define ISAC_CIR0_CIC1   0x01
+
+#define ISAC_CIR1        0x33
+#define ISAC_CIX1        0x33
+#define ISAC_STCR        0x37
+#define ISAC_MODE        0x22
+
+#define ISAC_RSTA        0x27
+#define ISAC_RSTA_RDO    0x40
+#define ISAC_RSTA_CRC    0x20
+#define ISAC_RSTA_RAB    0x10
+
+#define ISAC_RBCL 0x25
+#define ISAC_RBCH 0x2A
+#define ISAC_TIMR 0x23
+#define ISAC_SQXR 0x3b
+#define ISAC_MOSR 0x3a
+#define ISAC_MOCR 0x3a
+#define ISAC_MOR0 0x32
+#define ISAC_MOX0 0x32
+#define ISAC_MOR1 0x34
+#define ISAC_MOX1 0x34
+
+#define ISAC_RBCH_XAC 0x80
+
+#define ISAC_CMD_TIM    0x0
+#define ISAC_CMD_RES    0x1
+#define ISAC_CMD_SSP    0x2
+#define ISAC_CMD_SCP    0x3
+#define ISAC_CMD_AR8    0x8
+#define ISAC_CMD_AR10   0x9
+#define ISAC_CMD_ARL    0xa
+#define ISAC_CMD_DI     0xf
+
+#define ISACSX_MASK       0x60
+#define ISACSX_ISTA       0x60
+#define ISACSX_ISTA_ICD   0x01
+#define ISACSX_ISTA_CIC   0x10
+
+#define ISACSX_MASKD      0x20
+#define ISACSX_ISTAD      0x20
+#define ISACSX_ISTAD_XDU  0x04
+#define ISACSX_ISTAD_XMR  0x08
+#define ISACSX_ISTAD_XPR  0x10
+#define ISACSX_ISTAD_RFO  0x20
+#define ISACSX_ISTAD_RPF  0x40
+#define ISACSX_ISTAD_RME  0x80
+
+#define ISACSX_CMDRD      0x21
+#define ISACSX_CMDRD_XRES 0x01
+#define ISACSX_CMDRD_XME  0x02
+#define ISACSX_CMDRD_XTF  0x08
+#define ISACSX_CMDRD_RRES 0x40
+#define ISACSX_CMDRD_RMC  0x80
+
+#define ISACSX_MODED      0x22
+
+#define ISACSX_RBCLD      0x26
+
+#define ISACSX_RSTAD      0x28
+#define ISACSX_RSTAD_RAB  0x10
+#define ISACSX_RSTAD_CRC  0x20
+#define ISACSX_RSTAD_RDO  0x40
+#define ISACSX_RSTAD_VFR  0x80
+
+#define ISACSX_CIR0       0x2e
+#define ISACSX_CIR0_CIC0  0x08
+#define ISACSX_CIX0       0x2e
+
+#define ISACSX_TR_CONF0   0x30
+
+#define ISACSX_TR_CONF2   0x32
+
+static struct Fsm l1fsm;
+
+enum {
+	ST_L1_RESET,
+	ST_L1_F3_PDOWN,
+	ST_L1_F3_PUP,
+	ST_L1_F3_PEND_DEACT,
+	ST_L1_F4,
+	ST_L1_F5,
+	ST_L1_F6,
+	ST_L1_F7,
+	ST_L1_F8,
+};
+
+#define L1_STATE_COUNT (ST_L1_F8+1)
+
+static char *strL1State[] =
+{
+	"ST_L1_RESET",
+	"ST_L1_F3_PDOWN",
+	"ST_L1_F3_PUP",
+	"ST_L1_F3_PEND_DEACT",
+	"ST_L1_F4",
+	"ST_L1_F5",
+	"ST_L1_F6",
+	"ST_L1_F7",
+	"ST_L1_F8",
+};
+
+enum {
+	EV_PH_DR,           // 0000
+	EV_PH_RES,          // 0001
+	EV_PH_TMA,          // 0010
+	EV_PH_SLD,          // 0011
+	EV_PH_RSY,          // 0100
+	EV_PH_DR6,          // 0101
+	EV_PH_EI,           // 0110
+	EV_PH_PU,           // 0111
+	EV_PH_AR,           // 1000
+	EV_PH_9,            // 1001
+	EV_PH_ARL,          // 1010
+	EV_PH_CVR,          // 1011
+	EV_PH_AI8,          // 1100
+	EV_PH_AI10,         // 1101
+	EV_PH_AIL,          // 1110
+	EV_PH_DC,           // 1111
+	EV_PH_ACTIVATE_REQ,
+	EV_PH_DEACTIVATE_REQ,
+	EV_TIMER3,
+};
+
+#define L1_EVENT_COUNT (EV_TIMER3 + 1)
+
+static char *strL1Event[] =
+{
+	"EV_PH_DR",           // 0000
+	"EV_PH_RES",          // 0001
+	"EV_PH_TMA",          // 0010
+	"EV_PH_SLD",          // 0011
+	"EV_PH_RSY",          // 0100
+	"EV_PH_DR6",          // 0101
+	"EV_PH_EI",           // 0110
+	"EV_PH_PU",           // 0111
+	"EV_PH_AR",           // 1000
+	"EV_PH_9",            // 1001
+	"EV_PH_ARL",          // 1010
+	"EV_PH_CVR",          // 1011
+	"EV_PH_AI8",          // 1100
+	"EV_PH_AI10",         // 1101
+	"EV_PH_AIL",          // 1110
+	"EV_PH_DC",           // 1111
+	"EV_PH_ACTIVATE_REQ",
+	"EV_PH_DEACTIVATE_REQ",
+	"EV_TIMER3",
+};
+
+static inline void D_L1L2(struct isac *isac, int pr, void *arg)
+{
+	struct hisax_if *ifc = (struct hisax_if *) &isac->hisax_d_if;
+
+	DBG(DBG_PR, "pr %#x", pr);
+	ifc->l1l2(ifc, pr, arg);
+}
+
+static void ph_command(struct isac *isac, unsigned int command)
+{
+	DBG(DBG_L1M, "ph_command %#x", command);
+	switch (isac->type) {
+	case TYPE_ISAC:
+		isac->write_isac(isac, ISAC_CIX0, (command << 2) | 3);
+		break;
+	case TYPE_ISACSX:
+		isac->write_isac(isac, ISACSX_CIX0, (command << 4) | (7 << 1));
+		break;
+	}
+}
+
+// ----------------------------------------------------------------------
+
+static void l1_di(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_RESET);
+	ph_command(isac, ISAC_CMD_DI);
+}
+
+static void l1_di_deact_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_RESET);
+	D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
+	ph_command(isac, ISAC_CMD_DI);
+}
+
+static void l1_go_f3pdown(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F3_PDOWN);
+}
+
+static void l1_go_f3pend_deact_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_F3_PEND_DEACT);
+	D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
+	ph_command(isac, ISAC_CMD_DI);
+}
+
+static void l1_go_f3pend(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_F3_PEND_DEACT);
+	ph_command(isac, ISAC_CMD_DI);
+}
+
+static void l1_go_f4(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F4);
+}
+
+static void l1_go_f5(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F5);
+}
+
+static void l1_go_f6(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F6);
+}
+
+static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_F6);
+	D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
+}
+
+static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	FsmDelTimer(&isac->timer, 0);
+	FsmChangeState(fi, ST_L1_F7);
+	ph_command(isac, ISAC_CMD_AR8);
+	D_L1L2(isac, PH_ACTIVATE | INDICATION, NULL);
+}
+
+static void l1_go_f8(struct FsmInst *fi, int event, void *arg)
+{
+	FsmChangeState(fi, ST_L1_F8);
+}
+
+static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	FsmChangeState(fi, ST_L1_F8);
+	D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
+}
+
+static void l1_ar8(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	FsmRestartTimer(&isac->timer, TIMER3_VALUE, EV_TIMER3, NULL, 2);
+	ph_command(isac, ISAC_CMD_AR8);
+}
+
+static void l1_timer3(struct FsmInst *fi, int event, void *arg)
+{
+	struct isac *isac = fi->userdata;
+
+	ph_command(isac, ISAC_CMD_DI);
+	D_L1L2(isac, PH_DEACTIVATE | INDICATION, NULL);
+}
+
+// state machines according to data sheet PSB 2186 / 3186
+
+static struct FsmNode L1FnList[] __initdata =
+{
+	{ST_L1_RESET,         EV_PH_RES,            l1_di},
+	{ST_L1_RESET,         EV_PH_EI,             l1_di},
+	{ST_L1_RESET,         EV_PH_DC,             l1_go_f3pdown},
+	{ST_L1_RESET,         EV_PH_AR,             l1_go_f6},
+	{ST_L1_RESET,         EV_PH_AI8,            l1_go_f7_act_ind},
+
+	{ST_L1_F3_PDOWN,      EV_PH_RES,            l1_di},
+	{ST_L1_F3_PDOWN,      EV_PH_EI,             l1_di},
+	{ST_L1_F3_PDOWN,      EV_PH_AR,             l1_go_f6},
+	{ST_L1_F3_PDOWN,      EV_PH_RSY,            l1_go_f5},
+	{ST_L1_F3_PDOWN,      EV_PH_PU,             l1_go_f4},
+	{ST_L1_F3_PDOWN,      EV_PH_AI8,            l1_go_f7_act_ind},
+	{ST_L1_F3_PDOWN,      EV_PH_ACTIVATE_REQ,   l1_ar8},
+	{ST_L1_F3_PDOWN,      EV_TIMER3,            l1_timer3},
+	
+	{ST_L1_F3_PEND_DEACT, EV_PH_RES,            l1_di},
+	{ST_L1_F3_PEND_DEACT, EV_PH_EI,             l1_di},
+	{ST_L1_F3_PEND_DEACT, EV_PH_DC,             l1_go_f3pdown},
+	{ST_L1_F3_PEND_DEACT, EV_PH_RSY,            l1_go_f5},
+	{ST_L1_F3_PEND_DEACT, EV_PH_AR,             l1_go_f6},
+	{ST_L1_F3_PEND_DEACT, EV_PH_AI8,            l1_go_f7_act_ind},
+
+	{ST_L1_F4,            EV_PH_RES,            l1_di},
+	{ST_L1_F4,            EV_PH_EI,             l1_di},
+	{ST_L1_F4,            EV_PH_RSY,            l1_go_f5},
+	{ST_L1_F4,            EV_PH_AI8,            l1_go_f7_act_ind},
+	{ST_L1_F4,            EV_TIMER3,            l1_timer3},
+	{ST_L1_F4,            EV_PH_DC,             l1_go_f3pdown},
+
+	{ST_L1_F5,            EV_PH_RES,            l1_di},
+	{ST_L1_F5,            EV_PH_EI,             l1_di},
+	{ST_L1_F5,            EV_PH_AR,             l1_go_f6},
+	{ST_L1_F5,            EV_PH_AI8,            l1_go_f7_act_ind},
+	{ST_L1_F5,            EV_TIMER3,            l1_timer3},
+	{ST_L1_F5,            EV_PH_DR,             l1_go_f3pend},
+	{ST_L1_F5,            EV_PH_DC,             l1_go_f3pdown},
+
+	{ST_L1_F6,            EV_PH_RES,            l1_di},
+	{ST_L1_F6,            EV_PH_EI,             l1_di},
+	{ST_L1_F6,            EV_PH_RSY,            l1_go_f8},
+	{ST_L1_F6,            EV_PH_AI8,            l1_go_f7_act_ind},
+	{ST_L1_F6,            EV_PH_DR6,            l1_go_f3pend},
+	{ST_L1_F6,            EV_TIMER3,            l1_timer3},
+	{ST_L1_F6,            EV_PH_DC,             l1_go_f3pdown},
+
+	{ST_L1_F7,            EV_PH_RES,            l1_di_deact_ind},
+	{ST_L1_F7,            EV_PH_EI,             l1_di_deact_ind},
+	{ST_L1_F7,            EV_PH_AR,             l1_go_f6_deact_ind},
+	{ST_L1_F7,            EV_PH_RSY,            l1_go_f8_deact_ind},
+	{ST_L1_F7,            EV_PH_DR,             l1_go_f3pend_deact_ind},
+
+	{ST_L1_F8,            EV_PH_RES,            l1_di},
+	{ST_L1_F8,            EV_PH_EI,             l1_di},
+	{ST_L1_F8,            EV_PH_AR,             l1_go_f6},
+	{ST_L1_F8,            EV_PH_DR,             l1_go_f3pend},
+	{ST_L1_F8,            EV_PH_AI8,            l1_go_f7_act_ind},
+	{ST_L1_F8,            EV_TIMER3,            l1_timer3},
+	{ST_L1_F8,            EV_PH_DC,             l1_go_f3pdown},
+};
+
+static void l1m_debug(struct FsmInst *fi, char *fmt, ...)
+{
+	va_list args;
+	char buf[256];
+	
+	va_start(args, fmt);
+	vsprintf(buf, fmt, args);
+	DBG(DBG_L1M, "%s", buf);
+	va_end(args);
+}
+
+static void isac_version(struct isac *cs)
+{
+	int val;
+
+	val = cs->read_isac(cs, ISAC_RBCH);
+	DBG(1, "ISAC version (%x): %s", val, ISACVer[(val >> 5) & 3]);
+}
+
+static void isac_empty_fifo(struct isac *isac, int count)
+{
+	// this also works for isacsx, since
+	// CMDR(D) register works the same
+	u_char *ptr;
+
+	DBG(DBG_IRQ, "count %d", count);
+
+	if ((isac->rcvidx + count) >= MAX_DFRAME_LEN_L1) {
+		DBG(DBG_WARN, "overrun %d", isac->rcvidx + count);
+		isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
+		isac->rcvidx = 0;
+		return;
+	}
+	ptr = isac->rcvbuf + isac->rcvidx;
+	isac->rcvidx += count;
+	isac->read_isac_fifo(isac, ptr, count);
+	isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
+	DBG_PACKET(DBG_RFIFO, ptr, count);
+}
+
+static void isac_fill_fifo(struct isac *isac)
+{
+	// this also works for isacsx, since
+	// CMDR(D) register works the same
+
+	int count;
+	unsigned char cmd;
+	u_char *ptr;
+
+	if (!isac->tx_skb)
+		BUG();
+
+	count = isac->tx_skb->len;
+	if (count <= 0)
+		BUG();
+
+	DBG(DBG_IRQ, "count %d", count);
+
+	if (count > 0x20) {
+		count = 0x20;
+		cmd = ISAC_CMDR_XTF;
+	} else {
+		cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME;
+	}
+
+	ptr = isac->tx_skb->data;
+	skb_pull(isac->tx_skb, count);
+	isac->tx_cnt += count;
+	DBG_PACKET(DBG_XFIFO, ptr, count);
+	isac->write_isac_fifo(isac, ptr, count);
+	isac->write_isac(isac, ISAC_CMDR, cmd);
+}
+
+static void isac_retransmit(struct isac *isac)
+{
+	if (!isac->tx_skb) {
+		DBG(DBG_WARN, "no skb");
+		return;
+	}
+	skb_push(isac->tx_skb, isac->tx_cnt);
+	isac->tx_cnt = 0;
+}
+
+
+static inline void isac_cisq_interrupt(struct isac *isac)
+{
+	unsigned char val;
+
+	val = isac->read_isac(isac, ISAC_CIR0);
+	DBG(DBG_IRQ, "CIR0 %#x", val);
+	if (val & ISAC_CIR0_CIC0) {
+		DBG(DBG_IRQ, "CODR0 %#x", (val >> 2) & 0xf);
+		FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);
+	}
+	if (val & ISAC_CIR0_CIC1) {
+		val = isac->read_isac(isac, ISAC_CIR1);
+		DBG(DBG_WARN, "ISAC CIR1 %#x", val );
+	}
+}
+
+static inline void isac_rme_interrupt(struct isac *isac)
+{
+	unsigned char val;
+	int count;
+	struct sk_buff *skb;
+	
+	val = isac->read_isac(isac, ISAC_RSTA);
+	if ((val & (ISAC_RSTA_RDO | ISAC_RSTA_CRC | ISAC_RSTA_RAB) )
+	     != ISAC_RSTA_CRC) {
+		DBG(DBG_WARN, "RSTA %#x, dropped", val);
+		isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_RMC);
+		goto out;
+	}
+
+	count = isac->read_isac(isac, ISAC_RBCL) & 0x1f;
+	DBG(DBG_IRQ, "RBCL %#x", count);
+	if (count == 0)
+		count = 0x20;
+
+	isac_empty_fifo(isac, count);
+	count = isac->rcvidx;
+	if (count < 1) {
+		DBG(DBG_WARN, "count %d < 1", count);
+		goto out;
+	}
+
+	skb = alloc_skb(count, GFP_ATOMIC);
+	if (!skb) {
+		DBG(DBG_WARN, "no memory, dropping\n");
+		goto out;
+	}
+	memcpy(skb_put(skb, count), isac->rcvbuf, count);
+	DBG_SKB(DBG_RPACKET, skb);
+	D_L1L2(isac, PH_DATA | INDICATION, skb);
+ out:
+	isac->rcvidx = 0;
+}
+
+static inline void isac_xpr_interrupt(struct isac *isac)
+{
+	if (!isac->tx_skb)
+		return;
+
+	if (isac->tx_skb->len > 0) {
+		isac_fill_fifo(isac);
+		return;
+	}
+	dev_kfree_skb_irq(isac->tx_skb);
+	isac->tx_cnt = 0;
+	isac->tx_skb = NULL;
+	D_L1L2(isac, PH_DATA | CONFIRM, NULL);
+}
+
+static inline void isac_exi_interrupt(struct isac *isac)
+{
+	unsigned char val;
+
+	val = isac->read_isac(isac, ISAC_EXIR);
+	DBG(2, "EXIR %#x", val);
+
+	if (val & ISAC_EXIR_XMR) {
+		DBG(DBG_WARN, "ISAC XMR");
+		isac_retransmit(isac);
+	}
+	if (val & ISAC_EXIR_XDU) {
+		DBG(DBG_WARN, "ISAC XDU");
+		isac_retransmit(isac);
+	}
+	if (val & ISAC_EXIR_MOS) {  /* MOS */
+		DBG(DBG_WARN, "MOS");
+		val = isac->read_isac(isac, ISAC_MOSR);
+		DBG(2, "ISAC MOSR %#x", val);
+	}
+}
+
+void isac_irq(struct isac *isac)
+{
+	unsigned char val;
+
+	val = isac->read_isac(isac, ISAC_ISTA);
+	DBG(DBG_IRQ, "ISTA %#x", val);
+
+	if (val & ISAC_ISTA_EXI) {
+		DBG(DBG_IRQ, "EXI");
+		isac_exi_interrupt(isac);
+	}
+	if (val & ISAC_ISTA_XPR) {
+		DBG(DBG_IRQ, "XPR");
+		isac_xpr_interrupt(isac);
+	}
+	if (val & ISAC_ISTA_RME) {
+		DBG(DBG_IRQ, "RME");
+		isac_rme_interrupt(isac);
+	}
+	if (val & ISAC_ISTA_RPF) {
+		DBG(DBG_IRQ, "RPF");
+		isac_empty_fifo(isac, 0x20);
+	}
+	if (val & ISAC_ISTA_CISQ) {
+		DBG(DBG_IRQ, "CISQ");
+		isac_cisq_interrupt(isac);
+	}
+	if (val & ISAC_ISTA_RSC) {
+		DBG(DBG_WARN, "RSC");
+	}
+	if (val & ISAC_ISTA_SIN) {
+		DBG(DBG_WARN, "SIN");
+	}
+	isac->write_isac(isac, ISAC_MASK, 0xff);
+	isac->write_isac(isac, ISAC_MASK, 0x00);
+}
+
+// ======================================================================
+
+static inline void isacsx_cic_interrupt(struct isac *isac)
+{
+	unsigned char val;
+
+	val = isac->read_isac(isac, ISACSX_CIR0);
+	DBG(DBG_IRQ, "CIR0 %#x", val);
+	if (val & ISACSX_CIR0_CIC0) {
+		DBG(DBG_IRQ, "CODR0 %#x", val >> 4);
+		FsmEvent(&isac->l1m, val >> 4, NULL);
+	}
+}
+
+static inline void isacsx_rme_interrupt(struct isac *isac)
+{
+	int count;
+	struct sk_buff *skb;
+	unsigned char val;
+
+	val = isac->read_isac(isac, ISACSX_RSTAD);
+	if ((val & (ISACSX_RSTAD_VFR | 
+		    ISACSX_RSTAD_RDO | 
+		    ISACSX_RSTAD_CRC | 
+		    ISACSX_RSTAD_RAB)) 
+	    != (ISACSX_RSTAD_VFR | ISACSX_RSTAD_CRC)) {
+		DBG(DBG_WARN, "RSTAD %#x, dropped", val);
+		isac->write_isac(isac, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
+		goto out;
+	}
+
+	count = isac->read_isac(isac, ISACSX_RBCLD) & 0x1f;
+	DBG(DBG_IRQ, "RBCLD %#x", count);
+	if (count == 0)
+		count = 0x20;
+
+	isac_empty_fifo(isac, count);
+	// strip trailing status byte
+	count = isac->rcvidx - 1;
+	if (count < 1) {
+		DBG(DBG_WARN, "count %d < 1", count);
+		goto out;
+	}
+
+	skb = dev_alloc_skb(count);
+	if (!skb) {
+		DBG(DBG_WARN, "no memory, dropping");
+		goto out;
+	}
+	memcpy(skb_put(skb, count), isac->rcvbuf, count);
+	DBG_SKB(DBG_RPACKET, skb);
+	D_L1L2(isac, PH_DATA | INDICATION, skb);
+ out:
+	isac->rcvidx = 0;
+}
+
+static inline void isacsx_xpr_interrupt(struct isac *isac)
+{
+	if (!isac->tx_skb)
+		return;
+
+	if (isac->tx_skb->len > 0) {
+		isac_fill_fifo(isac);
+		return;
+	}
+	dev_kfree_skb_irq(isac->tx_skb);
+	isac->tx_skb = NULL;
+	isac->tx_cnt = 0;
+	D_L1L2(isac, PH_DATA | CONFIRM, NULL);
+}
+
+static inline void isacsx_icd_interrupt(struct isac *isac)
+{
+	unsigned char val;
+
+	val = isac->read_isac(isac, ISACSX_ISTAD);
+	DBG(DBG_IRQ, "ISTAD %#x", val);
+	if (val & ISACSX_ISTAD_XDU) {
+		DBG(DBG_WARN, "ISTAD XDU");
+		isac_retransmit(isac);
+	}
+	if (val & ISACSX_ISTAD_XMR) {
+		DBG(DBG_WARN, "ISTAD XMR");
+		isac_retransmit(isac);
+	}
+	if (val & ISACSX_ISTAD_XPR) {
+		DBG(DBG_IRQ, "ISTAD XPR");
+		isacsx_xpr_interrupt(isac);
+	}
+	if (val & ISACSX_ISTAD_RFO) {
+		DBG(DBG_WARN, "ISTAD RFO");
+		isac->write_isac(isac, ISACSX_CMDRD, ISACSX_CMDRD_RMC);
+	}
+	if (val & ISACSX_ISTAD_RME) {
+		DBG(DBG_IRQ, "ISTAD RME");
+		isacsx_rme_interrupt(isac);
+	}
+	if (val & ISACSX_ISTAD_RPF) {
+		DBG(DBG_IRQ, "ISTAD RPF");
+		isac_empty_fifo(isac, 0x20);
+	}
+}
+
+void isacsx_irq(struct isac *isac)
+{
+	unsigned char val;
+
+	val = isac->read_isac(isac, ISACSX_ISTA);
+	DBG(DBG_IRQ, "ISTA %#x", val);
+
+	if (val & ISACSX_ISTA_ICD)
+		isacsx_icd_interrupt(isac);
+	if (val & ISACSX_ISTA_CIC)
+		isacsx_cic_interrupt(isac);
+}
+
+void isac_init(struct isac *isac)
+{
+	isac->tx_skb = NULL;
+	isac->l1m.fsm = &l1fsm;
+	isac->l1m.state = ST_L1_RESET;
+#ifdef CONFIG_HISAX_DEBUG
+	isac->l1m.debug = 1;
+#else
+	isac->l1m.debug = 0;
+#endif
+	isac->l1m.userdata = isac;
+	isac->l1m.printdebug = l1m_debug;
+	FsmInitTimer(&isac->l1m, &isac->timer);
+}
+
+void isac_setup(struct isac *isac)
+{
+	int val, eval;
+
+	isac->type = TYPE_ISAC;
+	isac_version(isac);
+
+	ph_command(isac, ISAC_CMD_RES);
+
+  	isac->write_isac(isac, ISAC_MASK, 0xff);
+  	isac->mocr = 0xaa;
+	if (test_bit(ISAC_IOM1, &isac->flags)) {
+		/* IOM 1 Mode */
+		isac->write_isac(isac, ISAC_ADF2, 0x0);
+		isac->write_isac(isac, ISAC_SPCR, 0xa);
+		isac->write_isac(isac, ISAC_ADF1, 0x2);
+		isac->write_isac(isac, ISAC_STCR, 0x70);
+		isac->write_isac(isac, ISAC_MODE, 0xc9);
+	} else {
+		/* IOM 2 Mode */
+		if (!isac->adf2)
+			isac->adf2 = 0x80;
+		isac->write_isac(isac, ISAC_ADF2, isac->adf2);
+		isac->write_isac(isac, ISAC_SQXR, 0x2f);
+		isac->write_isac(isac, ISAC_SPCR, 0x00);
+		isac->write_isac(isac, ISAC_STCR, 0x70);
+		isac->write_isac(isac, ISAC_MODE, 0xc9);
+		isac->write_isac(isac, ISAC_TIMR, 0x00);
+		isac->write_isac(isac, ISAC_ADF1, 0x00);
+	}
+	val = isac->read_isac(isac, ISAC_STAR);
+	DBG(2, "ISAC STAR %x", val);
+	val = isac->read_isac(isac, ISAC_MODE);
+	DBG(2, "ISAC MODE %x", val);
+	val = isac->read_isac(isac, ISAC_ADF2);
+	DBG(2, "ISAC ADF2 %x", val);
+	val = isac->read_isac(isac, ISAC_ISTA);
+	DBG(2, "ISAC ISTA %x", val);
+	if (val & 0x01) {
+		eval = isac->read_isac(isac, ISAC_EXIR);
+		DBG(2, "ISAC EXIR %x", eval);
+	}
+	val = isac->read_isac(isac, ISAC_CIR0);
+	DBG(2, "ISAC CIR0 %x", val);
+	FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);
+
+	isac->write_isac(isac, ISAC_MASK, 0x0);
+	// RESET Receiver and Transmitter
+	isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_XRES | ISAC_CMDR_RRES);
+}
+
+void isacsx_setup(struct isac *isac)
+{
+	isac->type = TYPE_ISACSX;
+	// clear LDD
+	isac->write_isac(isac, ISACSX_TR_CONF0, 0x00);
+	// enable transmitter
+	isac->write_isac(isac, ISACSX_TR_CONF2, 0x00);
+	// transparent mode 0, RAC, stop/go
+	isac->write_isac(isac, ISACSX_MODED,    0xc9);
+	// all HDLC IRQ unmasked
+	isac->write_isac(isac, ISACSX_MASKD,    0x03);
+	// unmask ICD, CID IRQs
+	isac->write_isac(isac, ISACSX_MASK,            
+			 ~(ISACSX_ISTA_ICD | ISACSX_ISTA_CIC));
+}
+
+void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg)
+{
+	struct isac *isac = hisax_d_if->priv;
+	struct sk_buff *skb = arg;
+
+	DBG(DBG_PR, "pr %#x", pr);
+
+	switch (pr) {
+	case PH_ACTIVATE | REQUEST:
+		FsmEvent(&isac->l1m, EV_PH_ACTIVATE_REQ, NULL);
+		break;
+	case PH_DEACTIVATE | REQUEST:
+		FsmEvent(&isac->l1m, EV_PH_DEACTIVATE_REQ, NULL);
+		break;
+	case PH_DATA | REQUEST:
+		DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len);
+		DBG_SKB(DBG_XPACKET, skb);
+		if (isac->l1m.state != ST_L1_F7) {
+			DBG(1, "L1 wrong state %d\n", isac->l1m.state);
+			dev_kfree_skb(skb);
+			break;
+		}
+		if (isac->tx_skb)
+			BUG();
+
+		isac->tx_skb = skb;
+		isac_fill_fifo(isac);
+		break;
+	}
+}
+
+static int __init hisax_isac_init(void)
+{
+	printk(KERN_INFO "hisax_isac: ISAC-S/ISAC-SX ISDN driver v0.1.0\n");
+
+	l1fsm.state_count = L1_STATE_COUNT;
+	l1fsm.event_count = L1_EVENT_COUNT;
+	l1fsm.strState = strL1State;
+	l1fsm.strEvent = strL1Event;
+	return FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList));
+}
+
+static void __exit hisax_isac_exit(void)
+{
+	FsmFree(&l1fsm);
+}
+
+EXPORT_SYMBOL(isac_init);
+EXPORT_SYMBOL(isac_d_l2l1);
+
+EXPORT_SYMBOL(isacsx_setup);
+EXPORT_SYMBOL(isacsx_irq);
+
+EXPORT_SYMBOL(isac_setup);
+EXPORT_SYMBOL(isac_irq);
+
+module_init(hisax_isac_init);
+module_exit(hisax_isac_exit);
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/hisax_isac.h linux/drivers/isdn/hisax/hisax_isac.h
--- v2.5.0/linux/drivers/isdn/hisax/hisax_isac.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/hisax/hisax_isac.h	Thu Dec  6 14:01:17 2001
@@ -0,0 +1,45 @@
+#ifndef __HISAX_ISAC_H__
+#define __HISAX_ISAC_H__
+
+#include <linux/kernel.h>
+#include "fsm.h"
+#include "hisax_if.h"
+
+#define TIMER3_VALUE 7000
+#define MAX_DFRAME_LEN_L1 300
+
+#define ISAC_IOM1	0
+
+struct isac {
+	void *priv;
+
+	u_long flags;
+	struct hisax_d_if hisax_d_if;
+	struct FsmInst l1m;
+	struct FsmTimer timer;
+	u_char mocr;
+	u_char adf2;
+	int    type;
+
+	u_char rcvbuf[MAX_DFRAME_LEN_L1];
+	int rcvidx;
+
+	struct sk_buff *tx_skb;
+	int tx_cnt;
+
+	u_char (*read_isac)      (struct isac *, u_char);
+	void   (*write_isac)     (struct isac *, u_char, u_char);
+	void   (*read_isac_fifo) (struct isac *, u_char *, int);
+	void   (*write_isac_fifo)(struct isac *, u_char *, int);
+};
+
+void isac_init(struct isac *isac);
+void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
+
+void isac_setup(struct isac *isac);
+void isac_irq(struct isac *isac);
+
+void isacsx_setup(struct isac *isac);
+void isacsx_irq(struct isac *isac);
+
+#endif
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/st5481_b.c linux/drivers/isdn/hisax/st5481_b.c
--- v2.5.0/linux/drivers/isdn/hisax/st5481_b.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/isdn/hisax/st5481_b.c	Sat Dec  8 20:28:45 2001
@@ -168,7 +168,7 @@
 	test_and_clear_bit(buf_nr, &b_out->busy);
 
 	if (urb->status < 0) {
-		if (urb->status != USB_ST_URB_KILLED) {
+		if (urb->status != -ENOENT) {
 			WARN("urb status %d",urb->status);
 			if (b_out->busy == 0) {
 				st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2 | USB_DIR_OUT, NULL, NULL);
@@ -275,7 +275,7 @@
 				      usb_b_out_complete, bcs);
 }
 
-static void __devexit st5481_release_b_out(struct st5481_bcs *bcs)
+static void st5481_release_b_out(struct st5481_bcs *bcs)
 {
 	struct st5481_b_out *b_out = &bcs->b_out;
 
@@ -316,7 +316,7 @@
 /*
  * Release buffers and URBs for the B channels
  */
-void __devexit st5481_release_b(struct st5481_bcs *bcs)
+void st5481_release_b(struct st5481_bcs *bcs)
 {
 	DBG(4,"");
 
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/st5481_d.c linux/drivers/isdn/hisax/st5481_d.c
--- v2.5.0/linux/drivers/isdn/hisax/st5481_d.c	Wed Oct 24 15:34:51 2001
+++ linux/drivers/isdn/hisax/st5481_d.c	Sat Dec  8 20:28:45 2001
@@ -382,7 +382,7 @@
 	test_and_clear_bit(buf_nr, &d_out->busy);
 
 	if (urb->status < 0) {
-		if (urb->status != USB_ST_URB_KILLED) {
+		if (urb->status != -ENOENT) {
 			WARN("urb status %d",urb->status);
 			if (d_out->busy == 0) {
 				st5481_usb_pipe_reset(adapter, EP_D_OUT | USB_DIR_OUT, fifo_reseted, adapter);
@@ -673,7 +673,7 @@
 				      usb_d_out_complete, adapter);
 }
 
-static void __devexit st5481_release_d_out(struct st5481_adapter *adapter)
+static void st5481_release_d_out(struct st5481_adapter *adapter)
 {
 	struct st5481_d_out *d_out = &adapter->d_out;
 
@@ -723,7 +723,7 @@
 	return retval;
 }
 
-void __devexit st5481_release_d(struct st5481_adapter *adapter)
+void st5481_release_d(struct st5481_adapter *adapter)
 {
 	DBG(2,"");
 
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hisax/st5481_usb.c linux/drivers/isdn/hisax/st5481_usb.c
--- v2.5.0/linux/drivers/isdn/hisax/st5481_usb.c	Wed Oct 24 15:34:51 2001
+++ linux/drivers/isdn/hisax/st5481_usb.c	Sat Dec  8 20:28:45 2001
@@ -130,7 +130,7 @@
 	struct ctrl_msg *ctrl_msg;
 	
 	if (urb->status < 0) {
-		if (urb->status != USB_ST_URB_KILLED) {
+		if (urb->status != -ENOENT) {
 			WARN("urb status %d",urb->status);
 		} else {
 			DBG(1,"urb killed");
@@ -184,7 +184,7 @@
 	int j;
 
 	if (urb->status < 0) {
-		if (urb->status != USB_ST_URB_KILLED) {
+		if (urb->status != -ENOENT) {
 			WARN("urb status %d",urb->status);
 			urb->actual_length = 0;
 		} else {
@@ -307,7 +307,7 @@
  * Release buffers and URBs for the interrupt and control
  * endpoint.
  */
-void __devexit st5481_release_usb(struct st5481_adapter *adapter)
+void st5481_release_usb(struct st5481_adapter *adapter)
 {
 	struct st5481_intr *intr = &adapter->intr;
 	struct st5481_ctrl *ctrl = &adapter->ctrl;
@@ -443,7 +443,7 @@
 	return retval;
 }
 
-void __devexit st5481_release_isocpipes(struct urb* urb[2])
+void st5481_release_isocpipes(struct urb* urb[2])
 {
 	int j;
 
@@ -470,7 +470,7 @@
 	int len, count, status;
 
 	if (urb->status < 0) {
-		if (urb->status != USB_ST_URB_KILLED) {
+		if (urb->status != -ENOENT) {
 			WARN("urb status %d",urb->status);
 		} else {
 			DBG(1,"urb killed");
@@ -547,7 +547,7 @@
 	return retval;
 }
 
-void __devexit st5481_release_in(struct st5481_in *in)
+void st5481_release_in(struct st5481_in *in)
 {
 	DBG(2,"");
 
diff -u --recursive --new-file v2.5.0/linux/drivers/isdn/hysdn/hysdn_procfs.c linux/drivers/isdn/hysdn/hysdn_procfs.c
--- v2.5.0/linux/drivers/isdn/hysdn/hysdn_procfs.c	Sun Aug 12 10:38:48 2001
+++ linux/drivers/isdn/hysdn/hysdn_procfs.c	Wed Dec 31 16:00:00 1969
@@ -1,471 +0,0 @@
-/* $Id: hysdn_procfs.c,v 1.1 2000/02/10 19:45:18 werner Exp $
-
- * Linux driver for HYSDN cards, /proc/net filesystem log functions.
- * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
- *
- * Copyright 1999  by Werner Cornelius (werner@titro.de)
- *
- * 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, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Log: hysdn_procfs.c,v $
- * Revision 1.1  2000/02/10 19:45:18  werner
- *
- * Initial release
- *
- *
- */
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/poll.h>
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include <linux/smp_lock.h>
-
-#include "hysdn_defs.h"
-
-static char *hysdn_procfs_revision = "$Revision: 1.1 $";
-
-#define INFO_OUT_LEN 80		/* length of info line including lf */
-
-/*************************************************/
-/* structure keeping ascii log for device output */
-/*************************************************/
-struct log_data {
-	struct log_data *next;
-	ulong usage_cnt;	/* number of files still to work */
-	void *proc_ctrl;	/* pointer to own control procdata structure */
-	char log_start[2];	/* log string start (final len aligned by size) */
-};
-
-/**********************************************/
-/* structure holding proc entrys for one card */
-/**********************************************/
-struct procdata {
-	struct proc_dir_entry *log;	/* log entry */
-	char log_name[15];	/* log filename */
-	struct log_data *log_head, *log_tail;	/* head and tail for queue */
-	int if_used;		/* open count for interface */
-	wait_queue_head_t rd_queue;
-};
-
-/********************************************/
-/* put an log buffer into the log queue.    */
-/* This buffer will be kept until all files */
-/* opened for read got the contents.        */
-/* Flushes buffers not longer in use.       */
-/********************************************/
-void
-put_log_buffer(hysdn_card * card, char *cp)
-{
-	struct log_data *ib;
-	struct procdata *pd = card->procfs;
-	int flags;
-
-	if (!pd)
-		return;
-	if (!cp)
-		return;
-	if (!*cp)
-		return;
-	if (pd->if_used <= 0)
-		return;		/* no open file for read */
-
-	if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC)))
-		 return;	/* no memory */
-	strcpy(ib->log_start, cp);	/* set output string */
-	ib->next = NULL;
-	ib->proc_ctrl = pd;	/* point to own control structure */
-	save_flags(flags);
-	cli();
-	ib->usage_cnt = pd->if_used;
-	if (!pd->log_head)
-		pd->log_head = ib;	/* new head */
-	else
-		pd->log_tail->next = ib;	/* follows existing messages */
-	pd->log_tail = ib;	/* new tail */
-	restore_flags(flags);
-
-	/* delete old entrys */
-	while (pd->log_head->next) {
-		if ((pd->log_head->usage_cnt <= 0) &&
-		    (pd->log_head->next->usage_cnt <= 0)) {
-			ib = pd->log_head;
-			pd->log_head = pd->log_head->next;
-			kfree(ib);
-		} else
-			break;
-	}			/* pd->log_head->next */
-	wake_up_interruptible(&(pd->rd_queue));		/* announce new entry */
-}				/* put_log_buffer */
-
-
-/**********************************/
-/* log file operations and tables */
-/**********************************/
-
-/****************************************/
-/* write log file -> set log level bits */
-/****************************************/
-static ssize_t
-hysdn_log_write(struct file *file, const char *buf, size_t count, loff_t * off)
-{
-	int retval;
-	hysdn_card *card = (hysdn_card *) file->private_data;
-
-	if (&file->f_pos != off)	/* fs error check */
-		return (-ESPIPE);
-
-	if ((retval = pof_boot_write(card, buf, count)) < 0)
-		retval = -EFAULT;	/* an error occurred */
-
-	return (retval);
-}				/* hysdn_log_write */
-
-/******************/
-/* read log file */
-/******************/
-static ssize_t
-hysdn_log_read(struct file *file, char *buf, size_t count, loff_t * off)
-{
-	struct log_data *inf;
-	int len;
-	word ino;
-	struct procdata *pd;
-	hysdn_card *card;
-
-	if (!*((struct log_data **) file->private_data)) {
-		if (file->f_flags & O_NONBLOCK)
-			return (-EAGAIN);
-
-		/* sorry, but we need to search the card */
-		ino = file->f_dentry->d_inode->i_ino & 0xFFFF;	/* low-ino */
-		card = card_root;
-		while (card) {
-			pd = card->procfs;
-			if (pd->log->low_ino == ino)
-				break;
-			card = card->next;	/* search next entry */
-		}
-		if (card)
-			interruptible_sleep_on(&(pd->rd_queue));
-		else
-			return (-EAGAIN);
-
-	}
-	if (!(inf = *((struct log_data **) file->private_data)))
-		return (0);
-
-	inf->usage_cnt--;	/* new usage count */
-	(struct log_data **) file->private_data = &inf->next;	/* next structure */
-	if ((len = strlen(inf->log_start)) <= count) {
-		if (copy_to_user(buf, inf->log_start, len))
-			return -EFAULT;
-		file->f_pos += len;
-		return (len);
-	}
-	return (0);
-}				/* hysdn_log_read */
-
-/******************/
-/* open log file */
-/******************/
-static int
-hysdn_log_open(struct inode *ino, struct file *filep)
-{
-	hysdn_card *card;
-	struct procdata *pd;
-	ulong flags;
-
-	lock_kernel();
-	card = card_root;
-	while (card) {
-		pd = card->procfs;
-		if (pd->log->low_ino == (ino->i_ino & 0xFFFF))
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card) {
-		unlock_kernel();
-		return (-ENODEV);	/* device is unknown/invalid */
-	}
-	filep->private_data = card;	/* remember our own card */
-
-	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
-		/* write only access -> boot pof data */
-		if (pof_boot_open(card)) {
-			unlock_kernel();
-			return (-EPERM);	/* no permission this time */
-		}
-	} else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
-
-		/* read access -> log/debug read */
-		save_flags(flags);
-		cli();
-		pd->if_used++;
-		if (pd->log_head)
-			(struct log_data **) filep->private_data = &(pd->log_tail->next);
-		else
-			(struct log_data **) filep->private_data = &(pd->log_head);
-		restore_flags(flags);
-
-	} else {		/* simultaneous read/write access forbidden ! */
-		unlock_kernel();
-		return (-EPERM);	/* no permission this time */
-	}
-	unlock_kernel();
-	return (0);
-}				/* hysdn_log_open */
-
-/*******************************************************************************/
-/* close a cardlog file. If the file has been opened for exclusive write it is */
-/* assumed as pof data input and the pof loader is noticed about.              */
-/* Otherwise file is handled as log output. In this case the interface usage   */
-/* count is decremented and all buffers are noticed of closing. If this file   */
-/* was the last one to be closed, all buffers are freed.                       */
-/*******************************************************************************/
-static int
-hysdn_log_close(struct inode *ino, struct file *filep)
-{
-	struct log_data *inf;
-	struct procdata *pd;
-	hysdn_card *card;
-	int flags, retval = 0;
-
-	lock_kernel();
-	if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
-		/* write only access -> write debug completely written */
-		retval = 0;	/* success */
-	} else {
-		/* read access -> log/debug read, mark one further file as closed */
-
-		pd = NULL;
-		save_flags(flags);
-		cli();
-		inf = *((struct log_data **) filep->private_data);	/* get first log entry */
-		if (inf)
-			pd = (struct procdata *) inf->proc_ctrl;	/* still entries there */
-		else {
-			/* no info available -> search card */
-			card = card_root;
-			while (card) {
-				pd = card->procfs;
-				if (pd->log->low_ino == (ino->i_ino & 0xFFFF))
-					break;
-				card = card->next;	/* search next entry */
-			}
-			if (card)
-				pd = card->procfs;	/* pointer to procfs ctrl */
-		}
-		if (pd)
-			pd->if_used--;	/* decrement interface usage count by one */
-
-		while (inf) {
-			inf->usage_cnt--;	/* decrement usage count for buffers */
-			inf = inf->next;
-		}
-		restore_flags(flags);
-
-		if (pd)
-			if (pd->if_used <= 0)	/* delete buffers if last file closed */
-				while (pd->log_head) {
-					inf = pd->log_head;
-					pd->log_head = pd->log_head->next;
-					kfree(inf);
-				}
-	}			/* read access */
-
-	unlock_kernel();
-	return (retval);
-}				/* hysdn_log_close */
-
-/*************************************************/
-/* select/poll routine to be able using select() */
-/*************************************************/
-static unsigned int
-hysdn_log_poll(struct file *file, poll_table * wait)
-{
-	unsigned int mask = 0;
-	word ino;
-	hysdn_card *card;
-	struct procdata *pd;
-
-	if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE)
-		return (mask);	/* no polling for write supported */
-
-	/* we need to search the card */
-	ino = file->f_dentry->d_inode->i_ino & 0xFFFF;	/* low-ino */
-	card = card_root;
-	while (card) {
-		pd = card->procfs;
-		if (pd->log->low_ino == ino)
-			break;
-		card = card->next;	/* search next entry */
-	}
-	if (!card)
-		return (mask);	/* card not found */
-
-	poll_wait(file, &(pd->rd_queue), wait);
-
-	if (*((struct log_data **) file->private_data))
-		mask |= POLLIN | POLLRDNORM;
-
-	return mask;
-}				/* hysdn_log_poll */
-
-/**************************************************/
-/* table for log filesystem functions defined above. */
-/**************************************************/
-static struct file_operations log_fops =
-{
-	llseek:		no_llseek,
-	read:		hysdn_log_read,
-	write:		hysdn_log_write,
-	poll:		hysdn_log_poll,
-	open:		hysdn_log_open,
-	release:	hysdn_log_close,
-};
-
-/*****************************************/
-/* Output info data to the cardinfo file */
-/*****************************************/
-static int
-info_read(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
-{
-	char tmp[INFO_OUT_LEN * 11 + 2];
-	int i;
-	char *cp;
-	hysdn_card *card;
-
-	sprintf(tmp, "id bus slot type irq iobase plx-mem    dp-mem     boot device");
-	cp = tmp;		/* start of string */
-	while (*cp)
-		cp++;
-	while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
-		*cp++ = ' ';
-	*cp++ = '\n';
-
-	card = card_root;	/* start of list */
-	while (card) {
-		sprintf(cp, "%d  %3d %4d %4d %3d 0x%04x 0x%08x 0x%08x",
-			card->myid,
-			card->bus,
-			PCI_SLOT(card->devfn),
-			card->brdtype,
-			card->irq,
-			card->iobase,
-			card->plxbase,
-			card->membase);
-		card = card->next;
-		while (*cp)
-			cp++;
-		while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN)
-			*cp++ = ' ';
-		*cp++ = '\n';
-	}
-
-	i = cp - tmp;
-	*start = buffer;
-	if (offset + length > i) {
-		length = i - offset;
-		*eof = 1;
-	} else if (offset > i) {
-		length = 0;
-		*eof = 1;
-	}
-	cp = tmp + offset;
-
-	if (length > 0) {
-		/*   start_bh_atomic(); */
-		memcpy(buffer, cp, length);
-		/* end_bh_atomic(); */
-		return length;
-	}
-	return 0;
-}				/* info_read */
-
-/*****************************/
-/* hysdn subdir in /proc/net */
-/*****************************/
-static struct proc_dir_entry *hysdn_proc_entry = NULL;
-static struct proc_dir_entry *hysdn_info_entry = NULL;
-
-/***************************************************************************************/
-/* hysdn_procfs_init is called when the module is loaded and after the cards have been */
-/* detected. The needed proc dir and card entries are created.                         */
-/***************************************************************************************/
-int
-hysdn_procfs_init(void)
-{
-	struct procdata *pd;
-	hysdn_card *card;
-
-	hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
-	if (!hysdn_proc_entry) {
-		printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n");
-		return (-1);
-	}
-	hysdn_info_entry = create_proc_entry("cardinfo", 0, hysdn_proc_entry);
-	if (hysdn_info_entry)
-		hysdn_info_entry->read_proc = info_read;	/* read info function */
-
-	/* create all cardlog proc entries */
-
-	card = card_root;	/* start with first card */
-	while (card) {
-		if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
-			memset(pd, 0, sizeof(struct procdata));
-
-			sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
-			if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
-				pd->log->proc_fops = &log_fops;	/* set new operations table */
-				pd->log->owner = THIS_MODULE;
-			}
-
-			init_waitqueue_head(&(pd->rd_queue));
-
-			card->procfs = (void *) pd;	/* remember procfs structure */
-		}
-		card = card->next;	/* point to next card */
-	}
-
-	printk(KERN_NOTICE "HYSDN: procfs Rev. %s initialised\n", hysdn_getrev(hysdn_procfs_revision));
-	return (0);
-}				/* hysdn_procfs_init */
-
-/***************************************************************************************/
-/* hysdn_procfs_release is called when the module is unloaded and before the cards     */
-/* resources are released. The module counter is assumed to be 0 !                     */
-/***************************************************************************************/
-void
-hysdn_procfs_release(void)
-{
-	struct procdata *pd;
-	hysdn_card *card;
-
-	card = card_root;	/* start with first card */
-	while (card) {
-		if ((pd = (struct procdata *) card->procfs) != NULL) {
-			if (pd->log)
-				remove_proc_entry(pd->log_name, hysdn_proc_entry);
-			kfree(pd);	/* release memory */
-		}
-		card = card->next;	/* point to next card */
-	}
-
-	remove_proc_entry("cardinfo", hysdn_proc_entry);
-	remove_proc_entry(PROC_SUBDIR_NAME, proc_net);
-}				/* hysdn_procfs_release */
diff -u --recursive --new-file v2.5.0/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.5.0/linux/drivers/macintosh/adb.c	Tue Sep 18 14:23:14 2001
+++ linux/drivers/macintosh/adb.c	Fri Nov 30 08:26:04 2001
@@ -672,7 +672,6 @@
 	struct adbdev_state *state = file->private_data;
 	unsigned long flags;
 
-	lock_kernel();
 	if (state) {
 		file->private_data = NULL;
 		spin_lock_irqsave(&state->lock, flags);
@@ -685,7 +684,6 @@
 			spin_unlock_irqrestore(&state->lock, flags);
 		}
 	}
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.5.0/linux/drivers/macintosh/via-pmu.c	Sat Sep  8 12:38:42 2001
+++ linux/drivers/macintosh/via-pmu.c	Fri Nov 30 08:26:04 2001
@@ -1983,7 +1983,6 @@
 	struct pmu_private *pp = file->private_data;
 	unsigned long flags;
 
-	lock_kernel();
 	if (pp != 0) {
 		file->private_data = 0;
 		spin_lock_irqsave(&all_pvt_lock, flags);
@@ -1991,7 +1990,6 @@
 		spin_unlock_irqrestore(&all_pvt_lock, flags);
 		kfree(pp);
 	}
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/md/linear.c linux/drivers/md/linear.c
--- v2.5.0/linux/drivers/md/linear.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/md/linear.c	Fri Nov 30 12:33:24 2001
@@ -119,22 +119,21 @@
 	return 0;
 }
 
-static int linear_make_request (mddev_t *mddev,
-			int rw, struct buffer_head * bh)
+static int linear_make_request (mddev_t *mddev, int rw, struct bio *bio)
 {
         linear_conf_t *conf = mddev_to_conf(mddev);
         struct linear_hash *hash;
         dev_info_t *tmp_dev;
         long block;
 
-	block = bh->b_rsector >> 1;
+	block = bio->bi_sector >> 1;
 	hash = conf->hash_table + (block / conf->smallest->size);
   
 	if (block >= (hash->dev0->size + hash->dev0->offset)) {
 		if (!hash->dev1) {
 			printk ("linear_make_request : hash->dev1==NULL for block %ld\n",
 						block);
-			buffer_IO_error(bh);
+			bio_io_error(bio);
 			return 0;
 		}
 		tmp_dev = hash->dev1;
@@ -144,11 +143,11 @@
 	if (block >= (tmp_dev->size + tmp_dev->offset)
 				|| block < tmp_dev->offset) {
 		printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset);
-		buffer_IO_error(bh);
+		bio_io_error(bio);
 		return 0;
 	}
-	bh->b_rdev = tmp_dev->dev;
-	bh->b_rsector = bh->b_rsector - (tmp_dev->offset << 1);
+	bio->bi_dev = tmp_dev->dev;
+	bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1);
 
 	return 1;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/md/lvm-snap.c linux/drivers/md/lvm-snap.c
--- v2.5.0/linux/drivers/md/lvm-snap.c	Mon Nov 12 09:34:20 2001
+++ linux/drivers/md/lvm-snap.c	Tue Nov 27 09:23:27 2001
@@ -351,7 +351,7 @@
 	blksize_snap = lvm_get_blksize(snap_phys_dev);
 	max_blksize = max(blksize_org, blksize_snap);
 	min_blksize = min(blksize_org, blksize_snap);
-	max_sectors = KIO_MAX_SECTORS * (min_blksize>>9);
+	max_sectors = LVM_MAX_SECTORS * (min_blksize>>9);
 
 	if (chunk_size % (max_blksize>>9))
 		goto fail_blksize;
@@ -363,20 +363,20 @@
 
 		iobuf->length = nr_sectors << 9;
 
-		if(!lvm_snapshot_prepare_blocks(iobuf->blocks, org_start,
+		if(!lvm_snapshot_prepare_blocks(lv_snap->blocks, org_start,
 						nr_sectors, blksize_org))
 			goto fail_prepare;
 
 		if (brw_kiovec(READ, 1, &iobuf, org_phys_dev,
-			       iobuf->blocks, blksize_org) != (nr_sectors<<9))
+			       lv_snap->blocks, blksize_org) != (nr_sectors<<9))
 			goto fail_raw_read;
 
-		if(!lvm_snapshot_prepare_blocks(iobuf->blocks, snap_start,
+		if(!lvm_snapshot_prepare_blocks(lv_snap->blocks, snap_start,
 						nr_sectors, blksize_snap))
 			goto fail_prepare;
 
 		if (brw_kiovec(WRITE, 1, &iobuf, snap_phys_dev,
-			       iobuf->blocks, blksize_snap) != (nr_sectors<<9))
+			       lv_snap->blocks, blksize_snap) !=(nr_sectors<<9))
 			goto fail_raw_write;
 	}
 
@@ -505,7 +505,7 @@
 	ret = alloc_kiovec(1, &lv_snap->lv_iobuf);
 	if (ret) goto out;
 
-	max_sectors = KIO_MAX_SECTORS << (PAGE_SHIFT-9);
+	max_sectors = LVM_MAX_SECTORS << (PAGE_SHIFT-9);
 
 	ret = lvm_snapshot_alloc_iobuf_pages(lv_snap->lv_iobuf, max_sectors);
 	if (ret) goto out_free_kiovec;
@@ -542,8 +542,6 @@
 
 void lvm_snapshot_release(lv_t * lv)
 {
-	int 	nbhs = KIO_MAX_SECTORS;
-
 	if (lv->lv_block_exception)
 	{
 		vfree(lv->lv_block_exception);
diff -u --recursive --new-file v2.5.0/linux/drivers/md/lvm.c linux/drivers/md/lvm.c
--- v2.5.0/linux/drivers/md/lvm.c	Mon Nov 19 09:56:04 2001
+++ linux/drivers/md/lvm.c	Thu Nov 29 07:48:43 2001
@@ -236,7 +236,7 @@
 /*
  * External function prototypes
  */
-static int lvm_make_request_fn(request_queue_t*, int, struct buffer_head*);
+static int lvm_make_request_fn(request_queue_t*, struct bio *);
 
 static int lvm_blk_ioctl(struct inode *, struct file *, uint, ulong);
 static int lvm_blk_open(struct inode *, struct file *);
@@ -262,7 +262,7 @@
 #ifdef LVM_HD_NAME
 extern void (*lvm_hd_name_ptr) (char *, int);
 #endif
-static int lvm_map(struct buffer_head *, int);
+static int lvm_map(struct bio *);
 static int lvm_do_lock_lvm(void);
 static int lvm_do_le_remap(vg_t *, void *);
 
@@ -291,9 +291,9 @@
 static void __update_hardsectsize(lv_t *lv);
 
 
-static void _queue_io(struct buffer_head *bh, int rw);
-static struct buffer_head *_dequeue_io(void);
-static void _flush_io(struct buffer_head *bh);
+static void _queue_io(struct bio *bh, int rw);
+static struct bio *_dequeue_io(void);
+static void _flush_io(struct bio *bh);
 
 static int _open_pv(pv_t *pv);
 static void _close_pv(pv_t *pv);
@@ -346,7 +346,7 @@
 static spinlock_t lvm_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t lvm_snapshot_lock = SPIN_LOCK_UNLOCKED;
 
-static struct buffer_head *_pe_requests;
+static struct bio *_pe_requests;
 static DECLARE_RWSEM(_pe_lock);
 
 
@@ -369,7 +369,6 @@
 /* gendisk structures */
 static struct hd_struct lvm_hd_struct[MAX_LV];
 static int lvm_blocksizes[MAX_LV];
-static int lvm_hardsectsizes[MAX_LV];
 static int lvm_size[MAX_LV];
 
 static struct gendisk lvm_gendisk =
@@ -451,9 +450,7 @@
 
 	del_gendisk(&lvm_gendisk);
 
-	blk_size[MAJOR_NR] = NULL;
-	blksize_size[MAJOR_NR] = NULL;
-	hardsect_size[MAJOR_NR] = NULL;
+	blk_clear(MAJOR_NR);
 
 #ifdef LVM_HD_NAME
 	/* reference from linux/drivers/block/genhd.c */
@@ -1037,25 +1034,25 @@
 
 static int lvm_user_bmap(struct inode *inode, struct lv_bmap *user_result)
 {
-	struct buffer_head bh;
+	struct bio bio;
 	unsigned long block;
 	int err;
 
 	if (get_user(block, &user_result->lv_block))
 		return -EFAULT;
 
-	memset(&bh,0,sizeof bh);
-	bh.b_blocknr = block;
-	bh.b_dev = bh.b_rdev = inode->i_rdev;
-	bh.b_size = lvm_get_blksize(bh.b_dev);
- 	bh.b_rsector = block * (bh.b_size >> 9);
-	if ((err=lvm_map(&bh, READ)) < 0)  {
+	memset(&bio,0,sizeof(bio));
+	bio.bi_dev = inode->i_rdev;
+	bio.bi_io_vec.bv_len = lvm_get_blksize(bio.bi_dev);
+ 	bio.bi_sector = block * bio_sectors(&bio);
+	bio.bi_rw = READ;
+	if ((err=lvm_map(&bio)) < 0)  {
 		printk("lvm map failed: %d\n", err);
 		return -EINVAL;
 	}
 
-	return put_user(kdev_t_to_nr(bh.b_rdev), &user_result->lv_dev) ||
-	       put_user(bh.b_rsector/(bh.b_size>>9), &user_result->lv_block) ?
+	return put_user(kdev_t_to_nr(bio.bi_dev), &user_result->lv_dev) ||
+	       put_user(bio.bi_sector/bio_sectors(&bio), &user_result->lv_block) ?
 	       -EFAULT : 0;
 }
 
@@ -1104,7 +1101,7 @@
 		(sector < (pe_lock_req.data.pv_offset + pe_size)));
 }
 
-static inline int _defer_extent(struct buffer_head *bh, int rw,
+static inline int _defer_extent(struct bio *bh, int rw,
 				kdev_t pv, ulong sector, uint32_t pe_size)
 {
 	if (pe_lock_req.lock == LOCK_PE) {
@@ -1122,17 +1119,18 @@
 	return 0;
 }
 
-static int lvm_map(struct buffer_head *bh, int rw)
+static int lvm_map(struct bio *bh)
 {
-	int minor = MINOR(bh->b_rdev);
+	int minor = MINOR(bh->bi_dev);
 	ulong index;
 	ulong pe_start;
-	ulong size = bh->b_size >> 9;
-	ulong rsector_org = bh->b_rsector;
+	ulong size = bio_sectors(bh);
+	ulong rsector_org = bh->bi_sector;
 	ulong rsector_map;
 	kdev_t rdev_map;
 	vg_t *vg_this = vg[VG_BLK(minor)];
 	lv_t *lv = vg_this->lv[LV_BLK(minor)];
+	int rw = bio_data_dir(bh);
 
 
 	down_read(&lv->lv_lock);
@@ -1153,7 +1151,7 @@
 
 	P_MAP("%s - lvm_map minor: %d  *rdev: %s  *rsector: %lu  size:%lu\n",
 	      lvm_name, minor,
-	      kdevname(bh->b_rdev),
+	      kdevname(bh->bi_dev),
 	      rsector_org, size);
 
 	if (rsector_org + size > lv->lv_size) {
@@ -1248,13 +1246,13 @@
  	}
 
  out:
-	bh->b_rdev = rdev_map;
-	bh->b_rsector = rsector_map;
+	bh->bi_dev = rdev_map;
+	bh->bi_sector = rsector_map;
 	up_read(&lv->lv_lock);
 	return 1;
 
  bad:
-	buffer_IO_error(bh);
+	bio_io_error(bh);
 	up_read(&lv->lv_lock);
 	return -1;
 } /* lvm_map() */
@@ -1287,10 +1285,9 @@
 /*
  * make request function
  */
-static int lvm_make_request_fn(request_queue_t *q,
-			       int rw,
-			       struct buffer_head *bh) {
-	return (lvm_map(bh, rw) <= 0) ? 0 : 1;
+static int lvm_make_request_fn(request_queue_t *q, struct bio *bio)
+{
+	return (lvm_map(bio) <= 0) ? 0 : 1;
 }
 
 
@@ -1331,7 +1328,7 @@
 static int lvm_do_pe_lock_unlock(vg_t *vg_ptr, void *arg)
 {
 	pe_lock_req_t new_lock;
-	struct buffer_head *bh;
+	struct bio *bh;
 	uint p;
 
 	if (vg_ptr == NULL) return -ENXIO;
@@ -1820,8 +1817,6 @@
 				max_hardsectsize = hardsectsize;
 		}
 	}
-
-	lvm_hardsectsizes[MINOR(lv->lv_dev)] = max_hardsectsize;
 }
 
 /*
@@ -2665,7 +2660,6 @@
 
 	blk_size[MAJOR_NR] = lvm_size;
 	blksize_size[MAJOR_NR] = lvm_blocksizes;
-	hardsect_size[MAJOR_NR] = lvm_hardsectsizes;
 
 	return;
 } /* lvm_gen_init() */
@@ -2673,16 +2667,16 @@
 
 
 /* Must have down_write(_pe_lock) when we enqueue buffers */
-static void _queue_io(struct buffer_head *bh, int rw) {
-	if (bh->b_reqnext) BUG();
-	bh->b_reqnext = _pe_requests;
+static void _queue_io(struct bio *bh, int rw) {
+	if (bh->bi_next) BUG();
+	bh->bi_next = _pe_requests;
 	_pe_requests = bh;
 }
 
 /* Must have down_write(_pe_lock) when we dequeue buffers */
-static struct buffer_head *_dequeue_io(void)
+static struct bio *_dequeue_io(void)
 {
-	struct buffer_head *bh = _pe_requests;
+	struct bio *bh = _pe_requests;
 	_pe_requests = NULL;
 	return bh;
 }
@@ -2697,13 +2691,14 @@
  * If, for some reason, the same PE is locked again before all of these writes
  * have finished, then these buffers will just be re-queued (i.e. no danger).
  */
-static void _flush_io(struct buffer_head *bh)
+static void _flush_io(struct bio *bh)
 {
 	while (bh) {
-		struct buffer_head *next = bh->b_reqnext;
-		bh->b_reqnext = NULL;
+		struct bio *next = bh->bi_next;
+		bh->bi_next = NULL;
 		/* resubmit this buffer head */
-		generic_make_request(WRITE, bh);
+		bh->bi_rw = WRITE; /* needed? */
+		generic_make_request(bh);
 		bh = next;
 	}
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/md/md.c linux/drivers/md/md.c
--- v2.5.0/linux/drivers/md/md.c	Thu Oct 25 13:58:34 2001
+++ linux/drivers/md/md.c	Tue Nov 27 09:23:27 2001
@@ -105,7 +105,6 @@
  */
 struct hd_struct md_hd_struct[MAX_MD_DEVS];
 static int md_blocksizes[MAX_MD_DEVS];
-static int md_hardsect_sizes[MAX_MD_DEVS];
 static int md_maxreadahead[MAX_MD_DEVS];
 static mdk_thread_t *md_recovery_thread;
 
@@ -172,14 +171,14 @@
 	mddev_map[minor].data = NULL;
 }
 
-static int md_make_request(request_queue_t *q, int rw, struct buffer_head * bh)
+static int md_make_request (request_queue_t *q, struct bio *bio)
 {
-	mddev_t *mddev = kdev_to_mddev(bh->b_rdev);
+	mddev_t *mddev = kdev_to_mddev(bio->bi_dev);
 
 	if (mddev && mddev->pers)
-		return mddev->pers->make_request(mddev, rw, bh);
+		return mddev->pers->make_request(mddev, bio_rw(bio), bio);
 	else {
-		buffer_IO_error(bh);
+		bio_io_error(bio);
 		return 0;
 	}
 }
@@ -1701,19 +1700,14 @@
 	 * device.
 	 * Also find largest hardsector size
 	 */
-	md_hardsect_sizes[mdidx(mddev)] = 512;
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		if (rdev->faulty)
 			continue;
 		invalidate_device(rdev->dev, 1);
-		if (get_hardsect_size(rdev->dev)
-			> md_hardsect_sizes[mdidx(mddev)])
-			md_hardsect_sizes[mdidx(mddev)] =
-				get_hardsect_size(rdev->dev);
-	}
-	md_blocksizes[mdidx(mddev)] = 1024;
-	if (md_blocksizes[mdidx(mddev)] < md_hardsect_sizes[mdidx(mddev)])
-		md_blocksizes[mdidx(mddev)] = md_hardsect_sizes[mdidx(mddev)];
+		md_blocksizes[mdidx(mddev)] = 1024;
+		if (get_hardsect_size(rdev->dev) > md_blocksizes[mdidx(mddev)])
+			md_blocksizes[mdidx(mddev)] = get_hardsect_size(rdev->dev);
+	}
 	mddev->pers = pers[pnum];
 
 	err = mddev->pers->run(mddev);
@@ -2769,7 +2763,7 @@
 						(short *) &loc->cylinders);
 			if (err)
 				goto abort_unlock;
-			err = md_put_user (md_hd_struct[minor].start_sect,
+			err = md_put_user (get_start_sect(dev),
 						(long *) &loc->start);
 			goto done_unlock;
 	}
@@ -3621,13 +3615,11 @@
 	for(i = 0; i < MAX_MD_DEVS; i++) {
 		md_blocksizes[i] = 1024;
 		md_size[i] = 0;
-		md_hardsect_sizes[i] = 512;
 		md_maxreadahead[i] = MD_READAHEAD;
 	}
 	blksize_size[MAJOR_NR] = md_blocksizes;
 	blk_size[MAJOR_NR] = md_size;
 	max_readahead[MAJOR_NR] = md_maxreadahead;
-	hardsect_size[MAJOR_NR] = md_hardsect_sizes;
 
 	dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
 
@@ -3670,7 +3662,8 @@
 
 	md_recovery_thread = md_register_thread(md_do_recovery, NULL, name);
 	if (!md_recovery_thread)
-		printk(KERN_ALERT "md: bug: couldn't allocate md_recovery_thread\n");
+		printk(KERN_ALERT
+		       "md: bug: couldn't allocate md_recovery_thread\n");
 
 	md_register_reboot_notifier(&md_notifier);
 	raid_table_header = register_sysctl_table(raid_root_table, 1);
@@ -4008,15 +4001,10 @@
 #endif
 
 	del_gendisk(&md_gendisk);
-
 	blk_dev[MAJOR_NR].queue = NULL;
-	blksize_size[MAJOR_NR] = NULL;
-	blk_size[MAJOR_NR] = NULL;
-	max_readahead[MAJOR_NR] = NULL;
-	hardsect_size[MAJOR_NR] = NULL;
-
+	blk_clear(MAJOR_NR);
+	
 	free_device_names();
-
 }
 #endif
 
diff -u --recursive --new-file v2.5.0/linux/drivers/md/raid0.c linux/drivers/md/raid0.c
--- v2.5.0/linux/drivers/md/raid0.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/md/raid0.c	Fri Nov 30 12:33:24 2001
@@ -223,8 +223,7 @@
  * Of course, those facts may not be valid anymore (and surely won't...)
  * Hey guys, there's some work out there ;-)
  */
-static int raid0_make_request (mddev_t *mddev,
-			       int rw, struct buffer_head * bh)
+static int raid0_make_request (mddev_t *mddev, int rw, struct bio *bio)
 {
 	unsigned int sect_in_chunk, chunksize_bits,  chunk_size;
 	raid0_conf_t *conf = mddev_to_conf(mddev);
@@ -235,11 +234,11 @@
 
 	chunk_size = mddev->param.chunk_size >> 10;
 	chunksize_bits = ffz(~chunk_size);
-	block = bh->b_rsector >> 1;
+	block = bio->bi_sector >> 1;
 	hash = conf->hash_table + block / conf->smallest->size;
 
 	/* Sanity check */
-	if (chunk_size < (block % chunk_size) + (bh->b_size >> 10))
+	if (chunk_size < (block % chunk_size) + (bio->bi_size >> 10))
 		goto bad_map;
  
 	if (!hash)
@@ -255,7 +254,7 @@
 	} else
 		zone = hash->zone0;
     
-	sect_in_chunk = bh->b_rsector & ((chunk_size<<1) -1);
+	sect_in_chunk = bio->bi_sector & ((chunk_size<<1) -1);
 	chunk = (block - zone->zone_offset) / (zone->nb_dev << chunksize_bits);
 	tmp_dev = zone->dev[(block >> chunksize_bits) % zone->nb_dev];
 	rsect = (((chunk << chunksize_bits) + zone->dev_offset)<<1)
@@ -265,8 +264,8 @@
 	 * The new BH_Lock semantics in ll_rw_blk.c guarantee that this
 	 * is the only IO operation happening on this bh.
 	 */
-	bh->b_rdev = tmp_dev->dev;
-	bh->b_rsector = rsect;
+	bio->bi_dev = tmp_dev->dev;
+	bio->bi_sector = rsect;
 
 	/*
 	 * Let the main block layer submit the IO and resolve recursion:
@@ -274,7 +273,7 @@
 	return 1;
 
 bad_map:
-	printk ("raid0_make_request bug: can't convert block across chunks or bigger than %dk %ld %d\n", chunk_size, bh->b_rsector, bh->b_size >> 10);
+	printk ("raid0_make_request bug: can't convert block across chunks or bigger than %dk %ld %d\n", chunk_size, bio->bi_sector, bio->bi_size >> 10);
 	goto outerr;
 bad_hash:
 	printk("raid0_make_request bug: hash==NULL for block %ld\n", block);
@@ -285,7 +284,7 @@
 bad_zone1:
 	printk ("raid0_make_request bug: hash->zone1==NULL for block %ld\n", block);
  outerr:
-	buffer_IO_error(bh);
+	bio_io_error(bio);
 	return 0;
 }
 			   
diff -u --recursive --new-file v2.5.0/linux/drivers/media/video/Makefile linux/drivers/media/video/Makefile
--- v2.5.0/linux/drivers/media/video/Makefile	Fri Nov  9 14:01:22 2001
+++ linux/drivers/media/video/Makefile	Tue Dec 11 10:06:03 2001
@@ -44,11 +44,10 @@
 obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
 obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
 obj-$(CONFIG_VIDEO_W9966) += w9966.o
-obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o i2c-old.o
 obj-$(CONFIG_VIDEO_ZORAN_BUZ) += saa7111.o saa7185.o
 obj-$(CONFIG_VIDEO_ZORAN_DC10) += saa7110.o adv7175.o
 obj-$(CONFIG_VIDEO_ZORAN_LML33) += bt819.o bt856.o
-obj-$(CONFIG_VIDEO_LML33) += bt856.o bt819.o
+obj-$(CONFIG_VIDEO_ZORAN) += zr36067.o i2c-old.o
 obj-$(CONFIG_VIDEO_PMS) += pms.o
 obj-$(CONFIG_VIDEO_PLANB) += planb.o
 obj-$(CONFIG_VIDEO_VINO) += vino.o
diff -u --recursive --new-file v2.5.0/linux/drivers/media/video/saa7146.h linux/drivers/media/video/saa7146.h
--- v2.5.0/linux/drivers/media/video/saa7146.h	Mon Dec 11 13:15:51 2000
+++ linux/drivers/media/video/saa7146.h	Thu Dec  6 14:07:57 2001
@@ -74,7 +74,6 @@
         unsigned int nr;
 	unsigned long irq;          /* IRQ used by SAA7146 card */
 	unsigned short id;
-	struct i2c_bus i2c;
 	struct pci_dev *dev;
 	unsigned char revision;
 	unsigned char boardcfg[64];	/* 64 bytes of config from eeprom */
diff -u --recursive --new-file v2.5.0/linux/drivers/media/video/stradis.c linux/drivers/media/video/stradis.c
--- v2.5.0/linux/drivers/media/video/stradis.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/video/stradis.c	Thu Dec  6 14:07:57 2001
@@ -45,7 +45,6 @@
 #include <asm/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/videodev.h>
-#include <linux/i2c-old.h>
 
 #include "saa7146.h"
 #include "saa7146reg.h"
@@ -142,14 +141,13 @@
 	     !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++)
 		schedule();
 }
+
 /* read I2C */
-static int I2CRead(struct i2c_bus *bus, unsigned char addr,
+static int I2CRead(struct saa7146 *saa, unsigned char addr,
 		   unsigned char subaddr, int dosub)
 {
-	struct saa7146 *saa = (struct saa7146 *) bus->data;
 	int i;
 
-
 	if (saaread(SAA7146_I2C_STATUS) & 0x3c)
 		I2CWipe(saa);
 	for (i = 0; i < 1000 &&
@@ -194,17 +192,12 @@
 		printk("i2c read timeout\n");
 	return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff);
 }
-static int I2CReadOld(struct i2c_bus *bus, unsigned char addr)
-{
-	return I2CRead(bus, addr, 0, 0);
-}
 
 /* set both to write both bytes, reset it to write only b1 */
 
-static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1,
+static int I2CWrite(struct saa7146 *saa, unsigned char addr, unsigned char b1,
 		    unsigned char b2, int both)
 {
-	struct saa7146 *saa = (struct saa7146 *) bus->data;
 	int i;
 	u32 data;
 
@@ -226,15 +219,14 @@
 	return 0;
 }
 
-static void attach_inform(struct i2c_bus *bus, int id)
+static void attach_inform(struct saa7146 *saa, int id)
 {
-	struct saa7146 *saa = (struct saa7146 *) bus->data;
 	int i;
 
 	DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, id));
 	if (id == 0xa0)	{ /* we have rev2 or later board, fill in info */
 		for (i = 0; i < 64; i++)
-			saa->boardcfg[i] = I2CRead(bus, 0xa0, i, 1);
+			saa->boardcfg[i] = I2CRead(saa, 0xa0, i, 1);
 #ifdef USE_RESCUE_EEPROM_SDM275
 		if (saa->boardcfg[0] != 0) {
 			printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE BEEN IGNORED\n", saa->nr);
@@ -250,35 +242,20 @@
 	}
 }
 
-static void detach_inform(struct i2c_bus *bus, int id)
+static void detach_inform(struct saa7146 *saa, int id)
 {
-	struct saa7146 *saa = (struct saa7146 *) bus->data;
 	int i;
 	i = saa->nr;
 }
 
-static void I2CBusScan(struct i2c_bus *bus)
+static void I2CBusScan(struct saa7146 *saa)
 {
 	int i;
 	for (i = 0; i < 0xff; i += 2)
-		if ((I2CRead(bus, i, 0, 0)) >= 0)
-			attach_inform(bus, i);
+		if ((I2CRead(saa, i, 0, 0)) >= 0)
+			attach_inform(saa, i);
 }
 
-static struct i2c_bus saa7146_i2c_bus_template =
-{
-	"saa7146",
-	I2C_BUSID_BT848,
-	NULL,
-	SPIN_LOCK_UNLOCKED,
-	attach_inform,
-	detach_inform,
-	NULL,
-	NULL,
-	I2CReadOld,
-	I2CWrite,
-};
-
 static int debiwait_maxwait = 0;
 
 static int wait_for_debi_done(struct saa7146 *saa)
@@ -664,10 +641,8 @@
 
 static void cs4341_setlevel(struct saa7146 *saa, int left, int right)
 {
-	I2CWrite(&(saa->i2c), 0x22, 0x03,
-		 left > 94 ? 94 : left, 2);
-	I2CWrite(&(saa->i2c), 0x22, 0x04,
-		 right > 94 ? 94 : right, 2);
+	I2CWrite(saa, 0x22, 0x03, left > 94 ? 94 : left, 2);
+	I2CWrite(saa, 0x22, 0x04, right > 94 ? 94 : right, 2);
 }
 
 static void initialize_cs4341(struct saa7146 *saa)
@@ -676,15 +651,15 @@
 	for (i = 0; i < 200; i++) {
 		/* auto mute off, power on, no de-emphasis */
 		/* I2S data up to 24-bit 64xFs internal SCLK */
-		I2CWrite(&(saa->i2c), 0x22, 0x01, 0x11, 2);
+		I2CWrite(saa, 0x22, 0x01, 0x11, 2);
 		/* ATAPI mixer settings */
-		I2CWrite(&(saa->i2c), 0x22, 0x02, 0x49, 2);
+		I2CWrite(saa, 0x22, 0x02, 0x49, 2);
 		/* attenuation left 3db */
-		I2CWrite(&(saa->i2c), 0x22, 0x03, 0x00, 2);
+		I2CWrite(saa, 0x22, 0x03, 0x00, 2);
 		/* attenuation right 3db */
-		I2CWrite(&(saa->i2c), 0x22, 0x04, 0x00, 2);
-		I2CWrite(&(saa->i2c), 0x22, 0x01, 0x10, 2);
-		if (I2CRead(&(saa->i2c), 0x22, 0x02, 1) == 0x49)
+		I2CWrite(saa, 0x22, 0x04, 0x00, 2);
+		I2CWrite(saa, 0x22, 0x01, 0x10, 2);
+		if (I2CRead(saa, 0x22, 0x02, 1) == 0x49)
 			break;
 		schedule();
 	}
@@ -701,10 +676,10 @@
 	else
 		sequence = mode8420con;
 	for (i = 0; i < INIT8420LEN; i++)
-		I2CWrite(&(saa->i2c), 0x20, init8420[i * 2],
+		I2CWrite(saa, 0x20, init8420[i * 2],
 			 init8420[i * 2 + 1], 2);
 	for (i = 0; i < MODE8420LEN; i++)
-		I2CWrite(&(saa->i2c), 0x20, sequence[i * 2],
+		I2CWrite(saa, 0x20, sequence[i * 2],
 			 sequence[i * 2 + 1], 2);
 	printk("stradis%d: CS8420 initialized\n", saa->nr);
 }
@@ -722,39 +697,39 @@
 	for (i = 0; i < INIT7121LEN; i++) {
 		if (NewCard) {	/* handle new card encoder differences */
 			if (sequence[i*2] == 0x3a)
-				I2CWrite(&(saa->i2c), 0x88, 0x3a, 0x13, 2);
+				I2CWrite(saa, 0x88, 0x3a, 0x13, 2);
 			else if (sequence[i*2] == 0x6b)
-				I2CWrite(&(saa->i2c), 0x88, 0x6b, 0x20, 2);
+				I2CWrite(saa, 0x88, 0x6b, 0x20, 2);
 			else if (sequence[i*2] == 0x6c)
-				I2CWrite(&(saa->i2c), 0x88, 0x6c,
+				I2CWrite(saa, 0x88, 0x6c,
 					 dopal ? 0x09 : 0xf5, 2);
 			else if (sequence[i*2] == 0x6d)
-				I2CWrite(&(saa->i2c), 0x88, 0x6d,
+				I2CWrite(saa, 0x88, 0x6d,
 					 dopal ? 0x20 : 0x00, 2);
 			else if (sequence[i*2] == 0x7a)
-				I2CWrite(&(saa->i2c), 0x88, 0x7a,
+				I2CWrite(saa, 0x88, 0x7a,
 					 dopal ? (PALFirstActive - 1) :
 					 (NTSCFirstActive - 4), 2);
 			else if (sequence[i*2] == 0x7b)
-				I2CWrite(&(saa->i2c), 0x88, 0x7b,
+				I2CWrite(saa, 0x88, 0x7b,
 					 dopal ? PALLastActive :
 					 NTSCLastActive, 2);
-			else I2CWrite(&(saa->i2c), 0x88, sequence[i * 2],
+			else I2CWrite(saa, 0x88, sequence[i * 2],
 				 sequence[i * 2 + 1], 2);
 		} else {
 			if (sequence[i*2] == 0x6b && mod)
-				I2CWrite(&(saa->i2c), 0x88, 0x6b, 
+				I2CWrite(saa, 0x88, 0x6b, 
 					(sequence[i * 2 + 1] ^ 0x09), 2);
 			else if (sequence[i*2] == 0x7a)
-				I2CWrite(&(saa->i2c), 0x88, 0x7a,
+				I2CWrite(saa, 0x88, 0x7a,
 					 dopal ? (PALFirstActive - 1) :
 					 (NTSCFirstActive - 4), 2);
 			else if (sequence[i*2] == 0x7b)
-				I2CWrite(&(saa->i2c), 0x88, 0x7b,
+				I2CWrite(saa, 0x88, 0x7b,
 					 dopal ? PALLastActive :
 					 NTSCLastActive, 2);
 			else
-				I2CWrite(&(saa->i2c), 0x88, sequence[i * 2],
+				I2CWrite(saa, 0x88, sequence[i * 2],
 					 sequence[i * 2 + 1], 2);
 		}
 	}
@@ -2060,10 +2035,7 @@
 	if (!saa->saa7146_mem)
 		return -EIO;
 
-	memcpy(&(saa->i2c), &saa7146_i2c_bus_template, sizeof(struct i2c_bus));
 	memcpy(&saa->video_dev, &saa_template, sizeof(saa_template));
-	sprintf(saa->i2c.name, "stradis%d", num);
-	saa->i2c.data = saa;
 	saawrite(0, SAA7146_IER);	/* turn off all interrupts */
 	result = request_irq(saa->irq, saa7146_irq,
 		       SA_SHIRQ | SA_INTERRUPT, "stradis", (void *) saa);
@@ -2082,10 +2054,6 @@
 		iounmap(saa->saa7146_mem);
 		return -1;
 	}
-#if 0
-	/* i2c generic interface is currently BROKEN */
-	i2c_register_bus(&saa->i2c);
-#endif
 	return 0;
 }
 
@@ -2176,7 +2144,7 @@
 	saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */
 	saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2,
 		 SAA7146_MC2);
-	I2CBusScan(&(saa->i2c));
+	I2CBusScan(saa);
 	return 0;
 }
 
@@ -2194,10 +2162,6 @@
 		saawrite(0, SAA7146_MC2);
 		saawrite(0, SAA7146_IER);
 		saawrite(0xffffffffUL, SAA7146_ISR);
-#if 0
-		/* unregister i2c_bus */
-		i2c_unregister_bus((&saa->i2c));
-#endif
 
 		/* disable PCI bus-mastering */
 		pci_read_config_byte(saa->dev, PCI_COMMAND, &command);
diff -u --recursive --new-file v2.5.0/linux/drivers/message/fusion/mptscsih.h linux/drivers/message/fusion/mptscsih.h
--- v2.5.0/linux/drivers/message/fusion/mptscsih.h	Fri Jul  6 17:03:11 2001
+++ linux/drivers/message/fusion/mptscsih.h	Wed Nov 28 10:22:27 2001
@@ -198,7 +198,6 @@
 	cmd_per_lun:			MPT_SCSI_CMD_PER_LUN,	\
 	unchecked_isa_dma:		0,			\
 	use_clustering:			ENABLE_CLUSTERING,	\
-	use_new_eh_code:		1			\
 }
 
 #else
diff -u --recursive --new-file v2.5.0/linux/drivers/message/i2o/i2o_block.c linux/drivers/message/i2o/i2o_block.c
--- v2.5.0/linux/drivers/message/i2o/i2o_block.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/message/i2o/i2o_block.c	Sat Dec  8 20:02:47 2001
@@ -114,15 +114,16 @@
 #define I2O_BSA_DSC_VOLUME_CHANGED      0x000D
 #define I2O_BSA_DSC_TIMEOUT             0x000E
 
+#define I2O_UNIT(dev)	(i2ob_dev[MINOR((dev)) & 0xf0])
+#define I2O_LOCK(unit)	(i2ob_dev[(unit)].req_queue->queue_lock)
+
 /*
  *	Some of these can be made smaller later
  */
 
 static int i2ob_blksizes[MAX_I2OB<<4];
-static int i2ob_hardsizes[MAX_I2OB<<4];
 static int i2ob_sizes[MAX_I2OB<<4];
 static int i2ob_media_change_flag[MAX_I2OB];
-static u32 i2ob_max_sectors[MAX_I2OB<<4];
 
 static int i2ob_context;
 
@@ -252,9 +253,9 @@
 	unsigned long mptr;
 	u64 offset;
 	struct request *req = ireq->req;
-	struct buffer_head *bh = req->bh;
+	struct bio *bio = req->bio;
 	int count = req->nr_sectors<<9;
-	char *last = NULL;
+	unsigned long last = ~0UL;
 	unsigned short size = 0;
 
 	// printk(KERN_INFO "i2ob_send called\n");
@@ -283,30 +284,30 @@
 	if(req->cmd == READ)
 	{
 		__raw_writel(I2O_CMD_BLOCK_READ<<24|HOST_TID<<12|tid, msg+4);
-		while(bh!=NULL)
+		while(bio)
 		{
-			if(bh->b_data == last) {
-				size += bh->b_size;
-				last += bh->b_size;
-				if(bh->b_reqnext)
+			if (bio_to_phys(bio) == last) {
+				size += bio->bi_size;
+				last += bio->bi_size;
+				if(bio->bi_next)
 					__raw_writel(0x14000000|(size), mptr-8);
 				else
 					__raw_writel(0xD4000000|(size), mptr-8);
 			}
 			else
 			{
-				if(bh->b_reqnext)
-					__raw_writel(0x10000000|(bh->b_size), mptr);
+				if(bio->bi_next)
+					__raw_writel(0x10000000|bio->bi_size, mptr);
 				else
-					__raw_writel(0xD0000000|(bh->b_size), mptr);
-				__raw_writel(virt_to_bus(bh->b_data), mptr+4);
+					__raw_writel(0xD0000000|bio->bi_size, mptr);
+				__raw_writel(bio_to_phys(bio), mptr+4);
 				mptr += 8;	
-				size = bh->b_size;
-				last = bh->b_data + size;
+				size = bio->bi_size;
+				last = bio_to_phys(bio) + bio->bi_size;
 			}
 
-			count -= bh->b_size;
-			bh = bh->b_reqnext;
+			count -= bio->bi_size;
+			bio = bio->bi_next;
 		}
 		/*
 		 *	Heuristic for now since the block layer doesnt give
@@ -322,30 +323,30 @@
 	else if(req->cmd == WRITE)
 	{
 		__raw_writel(I2O_CMD_BLOCK_WRITE<<24|HOST_TID<<12|tid, msg+4);
-		while(bh!=NULL)
+		while(bio)
 		{
-			if(bh->b_data == last) {
-				size += bh->b_size;
-				last += bh->b_size;
-				if(bh->b_reqnext)
+			if (bio_to_phys(bio) == last) {
+				size += bio->bi_size;
+				last += bio->bi_size;
+				if(bio->bi_next)
 					__raw_writel(0x14000000|(size), mptr-8);
 				else
 					__raw_writel(0xD4000000|(size), mptr-8);
 			}
 			else
 			{
-				if(bh->b_reqnext)
-					__raw_writel(0x14000000|(bh->b_size), mptr);
+				if(bio->bi_next)
+					__raw_writel(0x14000000|bio->bi_size, mptr);
 				else
-					__raw_writel(0xD4000000|(bh->b_size), mptr);
-				__raw_writel(virt_to_bus(bh->b_data), mptr+4);
+					__raw_writel(0xD4000000|bio->bi_size, mptr);
+				__raw_writel(bio_to_phys(bio), mptr+4);
 				mptr += 8;	
-				size = bh->b_size;
-				last = bh->b_data + size;
+				size = bio->bi_size;
+				last = bio_to_phys(bio) + bio->bi_size;
 			}
 
-			count -= bh->b_size;
-			bh = bh->b_reqnext;
+			count -= bio->bi_size;
+			bio = bio->bi_next;
 		}
 
 		if(c->battery)
@@ -409,7 +410,8 @@
 	 * unlocked.
 	 */
 
-	while (end_that_request_first( req, !req->errors, "i2o block" ));
+	while (end_that_request_first(req, !req->errors, req->hard_cur_sectors))
+		;
 
 	/*
 	 * It is now ok to complete the request.
@@ -417,61 +419,6 @@
 	end_that_request_last( req );
 }
 
-/*
- * Request merging functions
- */
-static inline int i2ob_new_segment(request_queue_t *q, struct request *req,
-				  int __max_segments)
-{
-	int max_segments = i2ob_dev[MINOR(req->rq_dev)].max_segments;
-
-	if (__max_segments < max_segments)
-		max_segments = __max_segments;
-
-	if (req->nr_segments < max_segments) {
-		req->nr_segments++;
-		return 1;
-	}
-	return 0;
-}
-
-static int i2ob_back_merge(request_queue_t *q, struct request *req, 
-			     struct buffer_head *bh, int __max_segments)
-{
-	if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data)
-		return 1;
-	return i2ob_new_segment(q, req, __max_segments);
-}
-
-static int i2ob_front_merge(request_queue_t *q, struct request *req, 
-			      struct buffer_head *bh, int __max_segments)
-{
-	if (bh->b_data + bh->b_size == req->bh->b_data)
-		return 1;
-	return i2ob_new_segment(q, req, __max_segments);
-}
-
-static int i2ob_merge_requests(request_queue_t *q,
-				struct request *req,
-				struct request *next,
-				int __max_segments)
-{
-	int max_segments = i2ob_dev[MINOR(req->rq_dev)].max_segments;
-	int total_segments = req->nr_segments + next->nr_segments;
-
-	if (__max_segments < max_segments)
-		max_segments = __max_segments;
-
-	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
-		total_segments--;
-    
-	if (total_segments > max_segments)
-		return 0;
-
-	req->nr_segments = total_segments;
-	return 1;
-}
-
 static int i2ob_flush(struct i2o_controller *c, struct i2ob_device *d, int unit)
 {
 	unsigned long msg;
@@ -512,12 +459,6 @@
 	struct i2ob_device *dev = &i2ob_dev[(unit&0xF0)];
 
 	/*
-	 *	Pull the lock over ready
-	 */	
-	 
-	spin_lock_prefetch(&io_request_lock);
-		
-	/*
 	 * FAILed message
 	 */
 	if(m[0] & (1<<13))
@@ -535,10 +476,10 @@
 		ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
 		ireq->req->errors++;
 
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&I2O_LOCK(c->unit), flags);
 		i2ob_unhook_request(ireq, c->unit);
 		i2ob_end_request(ireq->req);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&I2O_LOCK(c->unit), flags);
 	
 		/* Now flush the message by making it a NOP */
 		m[0]&=0x00FFFFFF;
@@ -559,12 +500,12 @@
 
 	if(msg->function == I2O_CMD_BLOCK_CFLUSH)
 	{
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&I2O_LOCK(c->unit), flags);
 		dev->constipated=0;
 		DEBUG(("unconstipated\n"));
 		if(i2ob_backlog_request(c, dev)==0)
 			i2ob_request(dev->req_queue);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&I2O_LOCK(c->unit), flags);
 		return;
 	}
 
@@ -580,10 +521,10 @@
 		ireq=&i2ob_queues[c->unit]->request_queue[m[3]];
 		ireq->req->errors++;
 		printk(KERN_WARNING "I2O Block: Data transfer to deleted device!\n");
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&I2O_LOCK(c->unit), flags);
 		i2ob_unhook_request(ireq, c->unit);
 		i2ob_end_request(ireq->req);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&I2O_LOCK(c->unit), flags);
 		return;
 	}	
 
@@ -629,7 +570,7 @@
 		 */
 		 
 		
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&I2O_LOCK(c->unit), flags);
 		if(err==4)
 		{
 			/*
@@ -674,7 +615,7 @@
 			 */
 			 
 			i2ob_request(dev->req_queue);
-			spin_unlock_irqrestore(&io_request_lock, flags);
+			spin_unlock_irqrestore(&I2O_LOCK(c->unit), flags);
 			
 			/*
 			 *	and out
@@ -682,7 +623,7 @@
 			 
 			return;	
 		}
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&I2O_LOCK(c->unit), flags);
 		printk(KERN_ERR "\n/dev/%s error: %s", dev->i2odev->dev_name, 
 			bsa_errors[m[4]&0XFFFF]);
 		if(m[4]&0x00FF0000)
@@ -697,8 +638,8 @@
 	 *	Dequeue the request. We use irqsave locks as one day we
 	 *	may be running polled controllers from a BH...
 	 */
-	
-	spin_lock_irqsave(&io_request_lock, flags);
+
+	spin_lock_irqsave(&I2O_LOCK(c->unit), flags);
 	i2ob_unhook_request(ireq, c->unit);
 	i2ob_end_request(ireq->req);
 	atomic_dec(&i2ob_queues[c->unit]->queue_depth);
@@ -710,7 +651,7 @@
 	if(i2ob_backlog_request(c, dev)==0)
 		i2ob_request(dev->req_queue);
 
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&I2O_LOCK(c->unit), flags);
 }
 
 /* 
@@ -789,8 +730,7 @@
 				for(i = unit; i <= unit+15; i++)
 				{
 					i2ob_sizes[i] = 0;
-					i2ob_hardsizes[i] = 0;
-					i2ob_max_sectors[i] = 0;
+					blk_queue_max_sectors(i2ob_dev[i].req_queue, 0);
 					i2ob[i].nr_sects = 0;
 					i2ob_gendisk.part[i].nr_sects = 0;
 				}
@@ -824,11 +764,11 @@
 	  			if(i2ob_query_device(&i2ob_dev[unit], 0x0004, 0, &size, 8) !=0 )
 					i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8);
 
-				spin_lock_irqsave(&io_request_lock, flags);	
+				spin_lock_irqsave(&I2O_LOCK(unit), flags);	
 				i2ob_sizes[unit] = (int)(size>>10);
 				i2ob_gendisk.part[unit].nr_sects = size>>9;
 				i2ob[unit].nr_sects = (int)(size>>9);
-				spin_unlock_irqrestore(&io_request_lock, flags);	
+				spin_unlock_irqrestore(&I2O_LOCK(unit), flags);	
 				break;
 			}
 
@@ -881,13 +821,14 @@
 
 static void i2ob_timer_handler(unsigned long q)
 {
+	request_queue_t *req_queue = (request_queue_t *) q;
 	unsigned long flags;
 
 	/*
 	 * We cannot touch the request queue or the timer
-         * flag without holding the io_request_lock.
+         * flag without holding the queue_lock
 	 */
-	spin_lock_irqsave(&io_request_lock,flags);
+	spin_lock_irqsave(&req_queue->queue_lock,flags);
 
 	/* 
 	 * Clear the timer started flag so that 
@@ -898,12 +839,12 @@
 	/* 
 	 * Restart any requests.
 	 */
-	i2ob_request((request_queue_t*)q);
+	i2ob_request(req_queue);
 
 	/* 
 	 * Free the lock.
 	 */
-	spin_unlock_irqrestore(&io_request_lock,flags);
+	spin_unlock_irqrestore(&req_queue->queue_lock,flags);
 }
 
 static int i2ob_backlog_request(struct i2o_controller *c, struct i2ob_device *dev)
@@ -1132,34 +1073,23 @@
 static int i2ob_ioctl(struct inode *inode, struct file *file,
 		     unsigned int cmd, unsigned long arg)
 {
-	struct i2ob_device *dev;
-	int minor;
-
 	/* Anyone capable of this syscall can do *real bad* things */
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
-	if (!inode)
+	if (!inode || !inode->i_rdev)
 		return -EINVAL;
-	minor = MINOR(inode->i_rdev);
-	if (minor >= (MAX_I2OB<<4))
-		return -ENODEV;
 
-	dev = &i2ob_dev[minor];
 	switch (cmd) {
-		case BLKGETSIZE:
-			return put_user(i2ob[minor].nr_sects, (long *) arg);
-		case BLKGETSIZE64:
-			return put_user((u64)i2ob[minor].nr_sects << 9, (u64 *)arg);
-
 		case HDIO_GETGEO:
 		{
 			struct hd_geometry g;
-			int u=minor&0xF0;
+			int u = MINOR(inode->i_rdev) & 0xF0;
 			i2o_block_biosparam(i2ob_sizes[u]<<1, 
 				&g.cylinders, &g.heads, &g.sectors);
-			g.start = i2ob[minor].start_sect;
-			return copy_to_user((void *)arg,&g, sizeof(g))?-EFAULT:0;
+			g.start = get_start_sect(inode->i_rdev);
+			return copy_to_user((void *)arg, &g, sizeof(g))
+				? -EFAULT : 0;
 		}
 	
 		case BLKRRPART:
@@ -1167,6 +1097,8 @@
 				return -EACCES;
 			return do_i2ob_revalidate(inode->i_rdev,1);
 			
+		case BLKGETSIZE:
+		case BLKGETSIZE64:
 		case BLKFLSBUF:
 		case BLKROSET:
 		case BLKROGET:
@@ -1354,8 +1286,6 @@
 	i2ob_query_device(dev, 0x0000, 5, &flags, 4);
 	i2ob_query_device(dev, 0x0000, 6, &status, 4);
 	i2ob_sizes[unit] = (int)(size>>10);
-	for(i=unit; i <= unit+15 ; i++)
-		i2ob_hardsizes[i] = blocksize;
 	i2ob_gendisk.part[unit].nr_sects = size>>9;
 	i2ob[unit].nr_sects = (int)(size>>9);
 
@@ -1366,26 +1296,27 @@
 	/*
 	 * Max number of Scatter-Gather Elements
 	 */	
-
 	for(i=unit;i<=unit+15;i++)
 	{
-		i2ob_max_sectors[i] = 256;
-		i2ob_dev[i].max_segments = (d->controller->status_block->inbound_frame_size - 8)/2;
+		request_queue_t *q = i2ob_dev[unit].req_queue;
+
+		blk_queue_max_sectors(q, 256);
+		blk_queue_max_segments(q, (d->controller->status_block->inbound_frame_size - 8)/2);
 
 		if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.queue_buggy == 2)
 			i2ob_dev[i].depth = 32;
 
 		if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.queue_buggy == 1)
 		{
-			i2ob_max_sectors[i] = 32;
-			i2ob_dev[i].max_segments = 8;
+			blk_queue_max_sectors(q, 32);
+			blk_queue_max_segments(q, 8);
 			i2ob_dev[i].depth = 4;
 		}
 
 		if(d->controller->type == I2O_TYPE_PCI && d->controller->bus.pci.short_req)
 		{
-			i2ob_max_sectors[i] = 8;
-			i2ob_dev[i].max_segments = 8;
+			blk_queue_max_sectors(q, 8);
+			blk_queue_max_segments(q, 8);
 		}
 	}
 
@@ -1430,7 +1361,7 @@
 	}
 	printk(".\n");
 	printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", 
-		d->dev_name, i2ob_max_sectors[unit]);
+		d->dev_name, i2ob_dev[unit].req_queue->max_sectors);
 
 	/* 
 	 * If this is the first I2O block device found on this IOP,
@@ -1450,7 +1381,7 @@
 	 */
 	dev->req_queue = &i2ob_queues[c->unit]->req_queue;
 
-	grok_partitions(&i2ob_gendisk, unit>>4, 1<<4, (long)(size>>9));
+	grok_partitions(MKDEV(MAJOR_NR, unit), (long)(size>>9));
 
 	/*
 	 * Register for the events we're interested in and that the
@@ -1492,10 +1423,6 @@
 	atomic_set(&i2ob_queues[unit]->queue_depth, 0);
 
 	blk_init_queue(&i2ob_queues[unit]->req_queue, i2ob_request);
-	blk_queue_headactive(&i2ob_queues[unit]->req_queue, 0);
-	i2ob_queues[unit]->req_queue.back_merge_fn = i2ob_back_merge;
-	i2ob_queues[unit]->req_queue.front_merge_fn = i2ob_front_merge;
-	i2ob_queues[unit]->req_queue.merge_requests_fn = i2ob_merge_requests;
 	i2ob_queues[unit]->req_queue.queuedata = &i2ob_queues[unit];
 
 	return 0;
@@ -1506,11 +1433,11 @@
  */	
 static request_queue_t* i2ob_get_queue(kdev_t dev)
 {
-	int unit = MINOR(dev)&0xF0;
-
-	return i2ob_dev[unit].req_queue;
+	return I2O_UNIT(dev).req_queue;
 }
 
+
+
 /*
  * Probe the I2O subsytem for block class devices
  */
@@ -1708,7 +1635,7 @@
 	int i = 0;
 	unsigned long flags;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&I2O_LOCK(c->unit), flags);
 
 	/*
 	 * Need to do this...we somtimes get two events from the IRTOS
@@ -1730,7 +1657,7 @@
 	if(unit >= MAX_I2OB<<4)
 	{
 		printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&I2O_LOCK(c->unit), flags);
 		return;
 	}
 
@@ -1743,12 +1670,11 @@
 	{
 		i2ob_dev[i].i2odev = NULL;
 		i2ob_sizes[i] = 0;
-		i2ob_hardsizes[i] = 0;
-		i2ob_max_sectors[i] = 0;
+		blk_queue_max_sectors(i2ob_dev[i].req_queue, 0);
 		i2ob[i].nr_sects = 0;
 		i2ob_gendisk.part[i].nr_sects = 0;
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&I2O_LOCK(c->unit), flags);
 
 	/*
 	 * Decrease usage count for module
@@ -1891,13 +1817,10 @@
 	 */
 	 
 	blksize_size[MAJOR_NR] = i2ob_blksizes;
-	hardsect_size[MAJOR_NR] = i2ob_hardsizes;
 	blk_size[MAJOR_NR] = i2ob_sizes;
-	max_sectors[MAJOR_NR] = i2ob_max_sectors;
 	blk_dev[MAJOR_NR].queue = i2ob_get_queue;
 	
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), i2ob_request);
-	blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
 
 	for (i = 0; i < MAX_I2OB << 4; i++) {
 		i2ob_dev[i].refcnt = 0;
@@ -1909,7 +1832,6 @@
 		i2ob_dev[i].tail = NULL;
 		i2ob_dev[i].depth = MAX_I2OB_DEPTH;
 		i2ob_blksizes[i] = 1024;
-		i2ob_max_sectors[i] = 2;
 	}
 	
 	/*
@@ -1977,7 +1899,6 @@
 MODULE_AUTHOR("Red Hat Software");
 MODULE_DESCRIPTION("I2O Block Device OSM");
 MODULE_LICENSE("GPL");
-
 
 void cleanup_module(void)
 {
diff -u --recursive --new-file v2.5.0/linux/drivers/message/i2o/i2o_config.c linux/drivers/message/i2o/i2o_config.c
--- v2.5.0/linux/drivers/message/i2o/i2o_config.c	Mon Oct 22 08:39:56 2001
+++ linux/drivers/message/i2o/i2o_config.c	Fri Nov 30 08:26:04 2001
@@ -847,7 +847,6 @@
 	struct i2o_cfg_info *p1, *p2;
 	unsigned long flags;
 
-	lock_kernel();
 	p1 = p2 = NULL;
 
 	spin_lock_irqsave(&i2o_config_lock, flags);
@@ -870,7 +869,6 @@
 		p1 = p1->next;
 	}
 	spin_unlock_irqrestore(&i2o_config_lock, flags);
-	unlock_kernel();
 
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/message/i2o/i2o_core.c linux/drivers/message/i2o/i2o_core.c
--- v2.5.0/linux/drivers/message/i2o/i2o_core.c	Mon Oct 22 08:39:56 2001
+++ linux/drivers/message/i2o/i2o_core.c	Tue Nov 27 09:23:27 2001
@@ -125,6 +125,7 @@
  * Function table to send to bus specific layers
  * See <include/linux/i2o.h> for explanation of this
  */
+#ifdef CONFIG_I2O_PCI_MODULE
 static struct i2o_core_func_table i2o_core_functions =
 {
 	i2o_install_controller,
@@ -135,7 +136,6 @@
 	i2o_delete_controller
 };
 
-#ifdef CONFIG_I2O_PCI_MODULE
 extern int i2o_pci_core_attach(struct i2o_core_func_table *);
 extern void i2o_pci_core_detach(void);
 #endif /* CONFIG_I2O_PCI_MODULE */
diff -u --recursive --new-file v2.5.0/linux/drivers/message/i2o/i2o_scsi.c linux/drivers/message/i2o/i2o_scsi.c
--- v2.5.0/linux/drivers/message/i2o/i2o_scsi.c	Mon Oct 22 08:39:56 2001
+++ linux/drivers/message/i2o/i2o_scsi.c	Wed Nov 28 08:49:22 2001
@@ -151,11 +151,10 @@
 static void i2o_scsi_reply(struct i2o_handler *h, struct i2o_controller *c, struct i2o_message *msg)
 {
 	Scsi_Cmnd *current_command;
+	spinlock_t *lock;
 	u32 *m = (u32 *)msg;
 	u8 as,ds,st;
 
-	spin_lock_prefetch(&io_request_lock);		
-
 	if(m[0] & (1<<13))
 	{
 		printk("IOP fail.\n");
@@ -190,12 +189,13 @@
 		{
 			/* Create a scsi error for this */
 			current_command = (Scsi_Cmnd *)m[3];
+			lock = &current_command->host->host_lock;
 			printk("Aborted %ld\n", current_command->serial_number);
 
-			spin_lock_irq(&io_request_lock);			
+			spin_lock_irq(lock);
 			current_command->result = DID_ERROR << 16;
 			current_command->scsi_done(current_command);
-			spin_unlock_irq(&io_request_lock);			
+			spin_unlock_irq(lock);
 			
 			/* Now flush the message by making it a NOP */
 			m[0]&=0x00FFFFFF;
@@ -284,9 +284,10 @@
 		 *	It worked maybe ?
 		 */		
 		current_command->result = DID_OK << 16 | ds;
-	spin_lock(&io_request_lock);
+	lock = &current_command->host->host_lock;
+	spin_lock(lock);
 	current_command->scsi_done(current_command);
-	spin_unlock(&io_request_lock);
+	spin_unlock(lock);
 	return;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c
--- v2.5.0/linux/drivers/mtd/ftl.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/mtd/ftl.c	Tue Nov 27 09:23:27 2001
@@ -1166,7 +1166,7 @@
 	put_user(1, (char *)&geo->heads);
 	put_user(8, (char *)&geo->sectors);
 	put_user((sect>>3), (short *)&geo->cylinders);
-	put_user(ftl_hd[minor].start_sect, (u_long *)&geo->start);
+	put_user(get_start_sect(inode->i_rdev), (u_long *)&geo->start);
 	break;
     case BLKGETSIZE:
 	ret = put_user(ftl_hd[minor].nr_sects, (unsigned long *)arg);
@@ -1206,42 +1206,27 @@
 
 ======================================================================*/
 
-static int ftl_reread_partitions(int minor)
+static int ftl_reread_partitions(kdev_t dev)
 {
+    int minor = MINOR(dev);
     partition_t *part = myparts[minor >> 4];
-    int i, whole;
+    int res;
 
     DEBUG(0, "ftl_cs: ftl_reread_partition(%d)\n", minor);
     if ((atomic_read(&part->open) > 1)) {
 	    return -EBUSY;
     }
-    whole = minor & ~(MAX_PART-1);
 
-    i = MAX_PART - 1;
-    while (i-- > 0) {
-	if (ftl_hd[whole+i].nr_sects > 0) {
-	    kdev_t rdev = MKDEV(FTL_MAJOR, whole+i);
-
-	    invalidate_device(rdev, 1);
-	}
-	ftl_hd[whole+i].start_sect = 0;
-	ftl_hd[whole+i].nr_sects = 0;
-    }
+    res = wipe_partitions(dev);
+    if (res)
+	goto leave;
 
     scan_header(part);
 
     register_disk(&ftl_gendisk, whole >> PART_BITS, MAX_PART,
 		  &ftl_blk_fops, le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE);
 
-#ifdef PCMCIA_DEBUG
-    for (i = 0; i < MAX_PART; i++) {
-	if (ftl_hd[whole+i].nr_sects > 0)
-	    printk(KERN_INFO "  %d: start %ld size %ld\n", i,
-		   ftl_hd[whole+i].start_sect,
-		   ftl_hd[whole+i].nr_sects);
-    }
-#endif
-    return 0;
+    return res;
 }
 
 /*======================================================================
@@ -1431,7 +1416,7 @@
 
     unregister_blkdev(FTL_MAJOR, "ftl");
     blk_cleanup_queue(BLK_DEFAULT_QUEUE(FTL_MAJOR));
-    blksize_size[FTL_MAJOR] = NULL;
+    bklk_clear(FTL_MAJOR);
 
     del_gendisk(&ftl_gendisk);
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/mtd/mtdblock.c linux/drivers/mtd/mtdblock.c
--- v2.5.0/linux/drivers/mtd/mtdblock.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/mtd/mtdblock.c	Tue Nov 27 09:23:27 2001
@@ -29,7 +29,7 @@
 #if LINUX_VERSION_CODE < 0x20300
 #define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync)
 #else
-#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged)
+#define QUEUE_PLUGGED (blk_queue_plugged(QUEUE))
 #endif
 
 #ifdef CONFIG_DEVFS_FS
@@ -402,7 +402,7 @@
 
 /* 
  * This is a special request_fn because it is executed in a process context 
- * to be able to sleep independently of the caller.  The io_request_lock 
+ * to be able to sleep independently of the caller.  The queue_lock 
  * is held upon entry and exit.
  * The head of our request queue is considered active so there is no need 
  * to dequeue requests before we are done.
@@ -416,7 +416,7 @@
 	for (;;) {
 		INIT_REQUEST;
 		req = CURRENT;
-		spin_unlock_irq(&io_request_lock);
+		spin_unlock_irq(&QUEUE->queue_lock);
 		mtdblk = mtdblks[MINOR(req->rq_dev)];
 		res = 0;
 
@@ -458,7 +458,7 @@
 		}
 
 end_req:
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&QUEUE->queue_lock);
 		end_request(res);
 	}
 }
@@ -490,16 +490,16 @@
 	while (!leaving) {
 		add_wait_queue(&thr_wq, &wait);
 		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&QUEUE->queue_lock);
 		if (QUEUE_EMPTY || QUEUE_PLUGGED) {
-			spin_unlock_irq(&io_request_lock);
+			spin_unlock_irq(&QUEUE->queue_lock);
 			schedule();
 			remove_wait_queue(&thr_wq, &wait); 
 		} else {
 			remove_wait_queue(&thr_wq, &wait); 
 			set_current_state(TASK_RUNNING);
 			handle_mtdblock_request();
-			spin_unlock_irq(&io_request_lock);
+			spin_unlock_irq(&QUEUE->queue_lock);
 		}
 	}
 
diff -u --recursive --new-file v2.5.0/linux/drivers/mtd/nftlcore.c linux/drivers/mtd/nftlcore.c
--- v2.5.0/linux/drivers/mtd/nftlcore.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/mtd/nftlcore.c	Tue Nov 27 09:23:27 2001
@@ -59,11 +59,6 @@
 /* .. for the Linux partition table handling. */
 struct hd_struct part_table[256];
 
-#if LINUX_VERSION_CODE < 0x20328
-static void dummy_init (struct gendisk *crap)
-{}
-#endif
-
 static struct gendisk nftl_gendisk = {
 	major:		MAJOR_NR,
 	major_name:	"nftl",
@@ -166,7 +161,8 @@
 #if LINUX_VERSION_CODE < 0x20328
 	resetup_one_dev(&nftl_gendisk, firstfree);
 #else
-	grok_partitions(&nftl_gendisk, firstfree, 1<<NFTL_PARTN_BITS, nftl->nr_sects);
+	grok_partitions(MKDEV(MAJOR_NR,firstfree<<NFTL_PARTN_BITS),
+			nftl->nr_sects);
 #endif
 }
 
@@ -786,7 +782,7 @@
 static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg)
 {
 	struct NFTLrecord *nftl;
-	int p;
+	int res;
 
 	nftl = NFTLs[MINOR(inode->i_rdev) >> NFTL_PARTN_BITS];
 
@@ -799,16 +795,9 @@
 		g.heads = nftl->heads;
 		g.sectors = nftl->sectors;
 		g.cylinders = nftl->cylinders;
-		g.start = part_table[MINOR(inode->i_rdev)].start_sect;
+		g.start = get_start_sect(inode->i_rdev);
 		return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;
 	}
-	case BLKGETSIZE:   /* Return device size */
-		return put_user(part_table[MINOR(inode->i_rdev)].nr_sects,
-                                (unsigned long *) arg);
-	case BLKGETSIZE64:
-		return put_user((u64)part_table[MINOR(inode->i_rdev)].nr_sects << 9,
-                                (u64 *)arg);
-
 	case BLKFLSBUF:
 		if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 		fsync_dev(inode->i_rdev);
@@ -825,27 +814,17 @@
 		 * or we won't be able to re-use the partitions,
 		 * if there was a change and we don't want to reboot
 		 */
-		p = (1<<NFTL_PARTN_BITS) - 1;
-		while (p-- > 0) {
-			kdev_t devp = MKDEV(MAJOR(inode->i_dev), MINOR(inode->i_dev)+p);
-			if (part_table[p].nr_sects > 0)
-				invalidate_device (devp, 1);
+		res = wipe_partitions(inode->i_rdev);
+		if (!res)
+			grok_partitions(inode->i_rdev, nftl->nr_sects);
 
-			part_table[MINOR(inode->i_dev)+p].start_sect = 0;
-			part_table[MINOR(inode->i_dev)+p].nr_sects = 0;
-		}
-		
-#if LINUX_VERSION_CODE < 0x20328
-		resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS);
-#else
-		grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) >> NFTL_PARTN_BITS,
-				1<<NFTL_PARTN_BITS, nftl->nr_sects);
-#endif
-		return 0;
+		return res;
 
 #if (LINUX_VERSION_CODE < 0x20303)		
 	RO_IOCTLS(inode->i_rdev, arg);  /* ref. linux/blk.h */
 #else
+	case BLKGETSIZE:
+	case BLKGETSIZE64:
 	case BLKROSET:
 	case BLKROGET:
 	case BLKSSZGET:
@@ -859,7 +838,7 @@
 
 void nftl_request(RQFUNC_ARG)
 {
-	unsigned int dev, block, nsect;
+	unsigned int dev, unit, block, nsect;
 	struct NFTLrecord *nftl;
 	char *buffer;
 	struct request *req;
@@ -871,10 +850,11 @@
 		
 		/* We can do this because the generic code knows not to
 		   touch the request at the head of the queue */
-		spin_unlock_irq(&io_request_lock);
+		spin_unlock_irq(&QUEUE->queue_lock);
 
 		DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n");
-		DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n",
+		DEBUG(MTD_DEBUG_LEVEL3,
+		      "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n",
 		      (req->cmd == READ) ? "Read " : "Write",
 		      req->sector, req->current_nr_sectors);
 
@@ -884,8 +864,8 @@
 		buffer = req->buffer;
 		res = 1; /* succeed */
 
-		if (dev >= MAX_NFTLS * (1<<NFTL_PARTN_BITS)) {
-			/* there is no such partition */
+		unit = dev >> NFTL_PARTN_BITS;
+		if (unit >= MAX_NFTLS || dev != (unit << NFTL_PARTN_BITS)) {
 			printk("nftl: bad minor number: device = %s\n",
 			       kdevname(req->rq_dev));
 			res = 0; /* fail */
@@ -906,8 +886,6 @@
 			goto repeat;
 		}
 		
-		block += part_table[dev].start_sect;
-		
 		if (req->cmd == READ) {
 			DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x "
 			      "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors);
@@ -953,7 +931,7 @@
 		}
 	repeat: 
 		DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res);
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&QUEUE->queue_lock);
 		end_request(res);
 	}
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.5.0/linux/drivers/net/3c509.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/3c509.c	Sun Nov 25 09:43:42 2001
@@ -175,7 +175,7 @@
 };
 #endif /* CONFIG_MCA */
 
-#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
+#ifdef __ISAPNP__
 static struct isapnp_device_id el3_isapnp_adapters[] __initdata = {
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090),
@@ -206,7 +206,7 @@
 
 
 static u16 el3_isapnp_phys_addr[8][3];
-#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
+#endif /* __ISAPNP__ */
 static int nopnp;
 
 int __init el3_probe(struct net_device *dev)
@@ -217,9 +217,9 @@
 	u16 phys_addr[3];
 	static int current_tag;
 	int mca_slot = -1;
-#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
+#ifdef __ISAPNP__
 	static int pnp_cards;
-#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
+#endif /* __ISAPNP__ */
 
 	if (dev) SET_MODULE_OWNER(dev);
 
@@ -323,7 +323,7 @@
 	}
 #endif /* CONFIG_MCA */
 
-#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
+#ifdef __ISAPNP__
 	if (nopnp == 1)
 		goto no_pnp;
 
@@ -359,7 +359,7 @@
 		}
 	}
 no_pnp:
-#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
+#endif /* __ISAPNP__ */
 
 	/* Select an open I/O location at 0x1*0 to do contention select. */
 	for ( ; id_port < 0x200; id_port += 0x10) {
@@ -405,7 +405,7 @@
 		phys_addr[i] = htons(id_read_eeprom(i));
 	}
 
-#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
+#ifdef __ISAPNP__
 	if (nopnp == 0) {
 		/* The ISA PnP 3c509 cards respond to the ID sequence.
 		   This check is needed in order not to register them twice. */
@@ -425,7 +425,7 @@
 			}
 		}
 	}
-#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
+#endif /* __ISAPNP__ */
 
 	{
 		unsigned int iobase = id_read_eeprom(8);
@@ -1017,10 +1017,10 @@
 MODULE_PARM_DESC(irq, "EtherLink III IRQ number(s) (assigned)");
 MODULE_PARM_DESC(xcvr,"EtherLink III tranceiver(s) (0=internal, 1=external)");
 MODULE_PARM_DESC(max_interrupt_work, "EtherLink III maximum events handled per interrupt");
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
 MODULE_PARM(nopnp, "i");
 MODULE_PARM_DESC(nopnp, "EtherLink III disable ISA PnP support (0-1)");
-#endif	/* CONFIG_ISAPNP */
+#endif	/* __ISAPNP__ */
 
 int
 init_module(void)
diff -u --recursive --new-file v2.5.0/linux/drivers/net/3c515.c linux/drivers/net/3c515.c
--- v2.5.0/linux/drivers/net/3c515.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/net/3c515.c	Sun Nov 25 09:43:42 2001
@@ -359,7 +359,7 @@
 	{ "Default", 0, 0xFF, XCVR_10baseT, 10000},
 };
 
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
 static struct isapnp_device_id corkscrew_isapnp_adapters[] = {
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 		ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5051),
@@ -372,7 +372,7 @@
 static int corkscrew_isapnp_phys_addr[3];
 
 static int nopnp;
-#endif /* CONFIG_ISAPNP */
+#endif /* __ISAPNP__ */
 
 static int corkscrew_scan(struct net_device *dev);
 static struct net_device *corkscrew_found_device(struct net_device *dev,
@@ -450,12 +450,12 @@
 {
 	int cards_found = 0;
 	static int ioaddr;
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
 	short i;
 	static int pnp_cards;
 #endif
 
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
 	if(nopnp == 1)
 		goto no_pnp;
 	for(i=0; corkscrew_isapnp_adapters[i].vendor != 0; i++) {
@@ -513,17 +513,17 @@
 		}
 	}
 no_pnp:
-#endif /* CONFIG_ISAPNP */
+#endif /* __ISAPNP__ */
 
 	/* Check all locations on the ISA bus -- evil! */
 	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20) {
 		int irq;
-#ifdef CONFIG_ISAPNP
+#ifdef __ISAPNP__
 		/* Make sure this was not already picked up by isapnp */
 		if(ioaddr == corkscrew_isapnp_phys_addr[0]) continue;
 		if(ioaddr == corkscrew_isapnp_phys_addr[1]) continue;
 		if(ioaddr == corkscrew_isapnp_phys_addr[2]) continue;
-#endif /* CONFIG_ISAPNP */
+#endif /* __ISAPNP__ */
 		if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE))
 			continue;
 		/* Check the resource configuration for a matching ioaddr. */
diff -u --recursive --new-file v2.5.0/linux/drivers/net/8139too.c linux/drivers/net/8139too.c
--- v2.5.0/linux/drivers/net/8139too.c	Fri Nov  9 13:45:35 2001
+++ linux/drivers/net/8139too.c	Sat Nov 24 11:26:37 2001
@@ -1270,6 +1270,7 @@
 	tp->full_duplex = tp->duplex_lock;
 	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
 	tp->twistie = 1;
+	tp->time_to_die = 0;
 
 	rtl8139_init_ring (dev);
 	rtl8139_hw_start (dev);
diff -u --recursive --new-file v2.5.0/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.5.0/linux/drivers/net/Config.in	Mon Nov 19 15:19:42 2001
+++ linux/drivers/net/Config.in	Mon Dec 10 11:17:40 2001
@@ -159,7 +159,8 @@
 
       dep_tristate '    Apricot Xen-II on board Ethernet' CONFIG_APRICOT $CONFIG_ISA
       dep_tristate '    CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA
-      dep_tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI
+      dep_tristate '    Early DECchip Tulip (dc2104x) PCI support (EXPERIMENTAL)' CONFIG_DE2104X $CONFIG_PCI $CONFIG_EXPERIMENTAL
+      dep_tristate '    DECchip Tulip (dc2114x) PCI support' CONFIG_TULIP $CONFIG_PCI
       if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then
          dep_bool '      New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL
          bool '      Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO
diff -u --recursive --new-file v2.5.0/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.5.0/linux/drivers/net/Makefile	Fri Oct 19 08:32:28 2001
+++ linux/drivers/net/Makefile	Mon Dec 10 11:17:40 2001
@@ -174,6 +174,7 @@
 obj-$(CONFIG_EWRK3) += ewrk3.o
 obj-$(CONFIG_ATP) += atp.o
 obj-$(CONFIG_DE4X5) += de4x5.o
+obj-$(CONFIG_DE2104X) += de2104x.o
 obj-$(CONFIG_NI5010) += ni5010.o
 obj-$(CONFIG_NI52) += ni52.o
 obj-$(CONFIG_NI65) += ni65.o
diff -u --recursive --new-file v2.5.0/linux/drivers/net/de2104x.c linux/drivers/net/de2104x.c
--- v2.5.0/linux/drivers/net/de2104x.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/de2104x.c	Mon Dec 10 11:17:40 2001
@@ -0,0 +1,2141 @@
+/* de2104x.c: A Linux PCI Ethernet driver for Intel/Digital 21040/1 chips. */
+/*
+	Copyright 2001 Jeff Garzik <jgarzik@mandrakesoft.com>
+
+	Copyright 1994, 1995 Digital Equipment Corporation.	    [de4x5.c]
+	Written/copyright 1994-2001 by Donald Becker.		    [tulip.c]
+
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
+
+	See the file COPYING in this distribution for more information.
+
+	TODO, in rough priority order:
+	* Support forcing media type with a module parameter,
+	  like dl2k.c/sundance.c
+	* Constants (module parms?) for Rx work limit
+	* Complete reset on PciErr
+	* Jumbo frames / dev->change_mtu
+	* Adjust Rx FIFO threshold and Max Rx DMA burst on Rx FIFO error
+	* Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error
+	* Implement Tx software interrupt mitigation via
+	  Tx descriptor bit
+
+ */
+
+#define DRV_NAME		"de2104x"
+#define DRV_VERSION		"0.5.1"
+#define DRV_RELDATE		"Nov 20, 2001"
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
+#include <linux/compiler.h>
+#include <linux/sched.h>
+#include <linux/rtnetlink.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+/* These identify the driver base version and may not be removed. */
+static char version[] __initdata =
+KERN_INFO DRV_NAME " PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
+
+MODULE_AUTHOR("Jeff Garzik <jgarzik@mandrakesoft.com>");
+MODULE_DESCRIPTION("Intel/Digital 21040/1 series PCI Ethernet driver");
+MODULE_LICENSE("GPL");
+
+static int debug = -1;
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "de2104x bitmapped message enable number");
+
+/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
+#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
+        || defined(__sparc_) || defined(__ia64__) \
+        || defined(__sh__) || defined(__mips__)
+static int rx_copybreak = 1518;
+#else
+static int rx_copybreak = 100;
+#endif
+MODULE_PARM (rx_copybreak, "i");
+MODULE_PARM_DESC (rx_copybreak, "de2104x Breakpoint at which Rx packets are copied");
+
+#define PFX			DRV_NAME ": "
+
+#define DE_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
+				 NETIF_MSG_PROBE 	| \
+				 NETIF_MSG_LINK		| \
+				 NETIF_MSG_TIMER	| \
+				 NETIF_MSG_IFDOWN	| \
+				 NETIF_MSG_IFUP		| \
+				 NETIF_MSG_RX_ERR	| \
+				 NETIF_MSG_TX_ERR)
+
+#define DE_RX_RING_SIZE		64
+#define DE_TX_RING_SIZE		64
+#define DE_RING_BYTES		\
+		((sizeof(struct de_desc) * DE_RX_RING_SIZE) +	\
+		(sizeof(struct de_desc) * DE_TX_RING_SIZE))
+#define NEXT_TX(N)		(((N) + 1) & (DE_TX_RING_SIZE - 1))
+#define NEXT_RX(N)		(((N) + 1) & (DE_RX_RING_SIZE - 1))
+#define TX_BUFFS_AVAIL(CP)					\
+	(((CP)->tx_tail <= (CP)->tx_head) ?			\
+	  (CP)->tx_tail + (DE_TX_RING_SIZE - 1) - (CP)->tx_head :	\
+	  (CP)->tx_tail - (CP)->tx_head - 1)
+
+#define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer.*/
+#define RX_OFFSET		2
+
+#define DE_SETUP_SKB		((struct sk_buff *) 1)
+#define DE_DUMMY_SKB		((struct sk_buff *) 2)
+#define DE_SETUP_FRAME_WORDS	96
+#define DE_EEPROM_WORDS		256
+#define DE_MAX_MEDIA		5
+
+#define DE_MEDIA_TP_AUTO	0
+#define DE_MEDIA_BNC		1
+#define DE_MEDIA_AUI		2
+#define DE_MEDIA_TP		3
+#define DE_MEDIA_TP_FD		4
+#define DE_MEDIA_INVALID	DE_MAX_MEDIA
+#define DE_MEDIA_FIRST		0
+#define DE_MEDIA_LAST		(DE_MAX_MEDIA - 1)
+#define DE_TIMER_LINK		(60 * HZ)
+#define DE_TIMER_NO_LINK	(5 * HZ)
+
+#define DE_NUM_REGS		16
+#define DE_REGS_SIZE		(DE_NUM_REGS * sizeof(u32))
+#define DE_REGS_VER		1
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (6*HZ)
+
+/* This is a mysterious value that can be written to CSR11 in the 21040 (only)
+   to support a pre-NWay full-duplex signaling mechanism using short frames.
+   No one knows what it should be, but if left at its default value some
+   10base2(!) packets trigger a full-duplex-request interrupt. */
+#define FULL_DUPLEX_MAGIC	0x6969
+
+enum {
+	/* NIC registers */
+	BusMode			= 0x00,
+	TxPoll			= 0x08,
+	RxPoll			= 0x10,
+	RxRingAddr		= 0x18,
+	TxRingAddr		= 0x20,
+	MacStatus		= 0x28,
+	MacMode			= 0x30,
+	IntrMask		= 0x38,
+	RxMissed		= 0x40,
+	ROMCmd			= 0x48,
+	CSR11			= 0x58,
+	SIAStatus		= 0x60,
+	CSR13			= 0x68,
+	CSR14			= 0x70,
+	CSR15			= 0x78,
+	PCIPM			= 0x40,
+
+	/* BusMode bits */
+	CmdReset		= (1 << 0),
+	CacheAlign16		= 0x00008000,
+	BurstLen4		= 0x00000400,
+
+	/* Rx/TxPoll bits */
+	NormalTxPoll		= (1 << 0),
+	NormalRxPoll		= (1 << 0),
+
+	/* Tx/Rx descriptor status bits */
+	DescOwn			= (1 << 31),
+	RxError			= (1 << 15),
+	RxErrLong		= (1 << 7),
+	RxErrCRC		= (1 << 1),
+	RxErrFIFO		= (1 << 0),
+	RxErrRunt		= (1 << 11),
+	RxErrFrame		= (1 << 14),
+	RingEnd			= (1 << 25),
+	FirstFrag		= (1 << 29),
+	LastFrag		= (1 << 30),
+	TxError			= (1 << 15),
+	TxFIFOUnder		= (1 << 1),
+	TxLinkFail		= (1 << 2) | (1 << 10) | (1 << 11),
+	TxMaxCol		= (1 << 8),
+	TxOWC			= (1 << 9),
+	TxJabber		= (1 << 14),
+	SetupFrame		= (1 << 27),
+	TxSwInt			= (1 << 31),
+
+	/* MacStatus bits */
+	IntrOK			= (1 << 16),
+	IntrErr			= (1 << 15),
+	RxIntr			= (1 << 6),
+	RxEmpty			= (1 << 7),
+	TxIntr			= (1 << 0),
+	TxEmpty			= (1 << 2),
+	PciErr			= (1 << 13),
+	TxState			= (1 << 22) | (1 << 21) | (1 << 20),
+	RxState			= (1 << 19) | (1 << 18) | (1 << 17),
+	LinkFail		= (1 << 12),
+	LinkPass		= (1 << 4),
+	RxStopped		= (1 << 8),
+	TxStopped		= (1 << 1),
+
+	/* MacMode bits */
+	TxEnable		= (1 << 13),
+	RxEnable		= (1 << 1),
+	RxTx			= TxEnable | RxEnable,
+	FullDuplex		= (1 << 9),
+	AcceptAllMulticast	= (1 << 7),
+	AcceptAllPhys		= (1 << 6),
+	BOCnt			= (1 << 5),
+	MacModeClear		= (1<<12) | (1<<11) | (1<<10) | (1<<8) | (1<<3) |
+				  RxTx | BOCnt | AcceptAllPhys | AcceptAllMulticast,
+
+	/* ROMCmd bits */
+	EE_SHIFT_CLK		= 0x02,	/* EEPROM shift clock. */
+	EE_CS			= 0x01,	/* EEPROM chip select. */
+	EE_DATA_WRITE		= 0x04,	/* Data from the Tulip to EEPROM. */
+	EE_WRITE_0		= 0x01,
+	EE_WRITE_1		= 0x05,
+	EE_DATA_READ		= 0x08,	/* Data from the EEPROM chip. */
+	EE_ENB			= (0x4800 | EE_CS),
+
+	/* The EEPROM commands include the alway-set leading bit. */
+	EE_READ_CMD		= 6,
+
+	/* RxMissed bits */
+	RxMissedOver		= (1 << 16),
+	RxMissedMask		= 0xffff,
+
+	/* SROM-related bits */
+	SROMC0InfoLeaf		= 27,
+	MediaBlockMask		= 0x3f,
+	MediaCustomCSRs		= (1 << 6),
+	
+	/* PCIPM bits */
+	PM_Sleep		= (1 << 31),
+	PM_Snooze		= (1 << 30),
+	PM_Mask			= PM_Sleep | PM_Snooze,
+	
+	/* SIAStatus bits */
+	NWayState		= (1 << 14) | (1 << 13) | (1 << 12),
+	NWayRestart		= (1 << 12),
+	NonselPortActive	= (1 << 9),
+	LinkFailStatus		= (1 << 2),
+	NetCxnErr		= (1 << 1),
+};
+
+static const u32 de_intr_mask =
+	IntrOK | IntrErr | RxIntr | RxEmpty | TxIntr | TxEmpty |
+	LinkPass | LinkFail | PciErr;
+
+/*
+ * Set the programmable burst length to 4 longwords for all:
+ * DMA errors result without these values. Cache align 16 long.
+ */
+static const u32 de_bus_mode = CacheAlign16 | BurstLen4;
+
+struct de_srom_media_block {
+	u8			opts;
+	u16			csr13;
+	u16			csr14;
+	u16			csr15;
+} __attribute__((packed));
+
+struct de_srom_info_leaf {
+	u16			default_media;
+	u8			n_blocks;
+	u8			unused;
+	struct de_srom_media_block	media[0];
+} __attribute__((packed));
+
+struct de_desc {
+	u32			opts1;
+	u32			opts2;
+	u32			addr1;
+	u32			addr2;
+};
+
+struct media_info {
+	u16			type;	/* DE_MEDIA_xxx */
+	u16			csr13;
+	u16			csr14;
+	u16			csr15;
+};
+
+struct ring_info {
+	struct sk_buff		*skb;
+	dma_addr_t		mapping;
+};
+
+struct de_private {
+	unsigned		tx_head;
+	unsigned		tx_tail;
+	unsigned		rx_tail;
+
+	void			*regs;
+	struct net_device	*dev;
+	spinlock_t		lock;
+
+	struct de_desc		*rx_ring;
+	struct de_desc		*tx_ring;
+	struct ring_info	tx_skb[DE_TX_RING_SIZE];
+	struct ring_info	rx_skb[DE_RX_RING_SIZE];
+	unsigned		rx_buf_sz;
+	dma_addr_t		ring_dma;
+
+	u32			msg_enable;
+
+	struct net_device_stats net_stats;
+
+	struct pci_dev		*pdev;
+	u32			macmode;
+
+	u16			setup_frame[DE_SETUP_FRAME_WORDS];
+
+	u32			media_type;
+	u32			media_supported;
+	u32			media_advertise;
+	struct media_info	media[DE_MAX_MEDIA];
+	struct timer_list	media_timer;
+
+	unsigned		board_idx;
+	unsigned		de21040 : 1;
+	unsigned		media_lock : 1;
+};
+
+
+static void de_set_rx_mode (struct net_device *dev);
+static void de_tx (struct de_private *de);
+static void de_clean_rings (struct de_private *de);
+static void de_media_interrupt (struct de_private *de, u32 status);
+static void de21040_media_timer (unsigned long data);
+static void de21041_media_timer (unsigned long data);
+
+
+static struct pci_device_id de_pci_tbl[] __initdata = {
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_PLUS,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, de_pci_tbl);
+
+static const char * const media_name[DE_MAX_MEDIA] = {
+	"10baseT auto",
+	"BNC",
+	"AUI",
+	"10baseT-HD",
+	"10baseT-FD"
+};
+
+/* 21040 transceiver register settings:
+ * TP AUTO(unused), BNC(unused), AUI, TP, TP FD*/
+static u16 t21040_csr13[] = { 0, 0, 0x8F09, 0x8F01, 0x8F01, };
+static u16 t21040_csr14[] = { 0, 0, 0x0705, 0xFFFF, 0xFFFD, };
+static u16 t21040_csr15[] = { 0, 0, 0x0006, 0x0000, 0x0000, };
+
+/* 21041 transceiver register settings: TP AUTO, BNC, AUI, TP, TP FD*/
+static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, };
+static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x6F3F, 0x6F3D, };
+static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, };
+
+
+static inline unsigned long
+msec_to_jiffies(unsigned long ms)
+{
+	return (((ms)*HZ+999)/1000);
+}
+
+
+#define dr32(reg)		readl(de->regs + (reg))
+#define dw32(reg,val)		writel((val), de->regs + (reg))
+
+
+static void de_rx_err_acct (struct de_private *de, unsigned rx_tail,
+			    u32 status, u32 len)
+{
+	if (netif_msg_rx_err (de))
+		printk (KERN_DEBUG
+			"%s: rx err, slot %d status 0x%x len %d\n",
+			de->dev->name, rx_tail, status, len);
+
+	if ((status & 0x38000300) != 0x0300) {
+		/* Ingore earlier buffers. */
+		if ((status & 0xffff) != 0x7fff) {
+			if (netif_msg_rx_err(de))
+				printk(KERN_WARNING "%s: Oversized Ethernet frame "
+					   "spanned multiple buffers, status %8.8x!\n",
+					   de->dev->name, status);
+			de->net_stats.rx_length_errors++;
+		}
+	} else if (status & RxError) {
+		/* There was a fatal error. */
+		de->net_stats.rx_errors++; /* end of a packet.*/
+		if (status & 0x0890) de->net_stats.rx_length_errors++;
+		if (status & RxErrCRC) de->net_stats.rx_crc_errors++;
+		if (status & RxErrFIFO) de->net_stats.rx_fifo_errors++;
+	}
+}
+
+static void de_rx (struct de_private *de)
+{
+	unsigned rx_tail = de->rx_tail;
+	unsigned rx_work = DE_RX_RING_SIZE;
+	unsigned drop = 0;
+	int rc;
+
+	while (rx_work--) {
+		u32 status, len;
+		dma_addr_t mapping;
+		struct sk_buff *skb, *copy_skb;
+		unsigned copying_skb, buflen;
+
+		skb = de->rx_skb[rx_tail].skb;
+		if (!skb)
+			BUG();
+		rmb();
+		status = le32_to_cpu(de->rx_ring[rx_tail].opts1);
+		if (status & DescOwn)
+			break;
+
+		len = ((status >> 16) & 0x7ff) - 4;
+		mapping = de->rx_skb[rx_tail].mapping;
+
+		if (unlikely(drop)) {
+			de->net_stats.rx_dropped++;
+			goto rx_next;
+		}
+
+		if (unlikely((status & 0x38008300) != 0x0300)) {
+			de_rx_err_acct(de, rx_tail, status, len);
+			goto rx_next;
+		}
+
+		copying_skb = (len <= rx_copybreak);
+
+		if (unlikely(netif_msg_rx_status(de)))
+			printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d copying? %d\n",
+			       de->dev->name, rx_tail, status, len,
+			       copying_skb);
+
+		buflen = copying_skb ? (len + RX_OFFSET) : de->rx_buf_sz;
+		copy_skb = dev_alloc_skb (buflen);
+		if (unlikely(!copy_skb)) {
+			de->net_stats.rx_dropped++;
+			drop = 1;
+			rx_work = 100;
+			goto rx_next;
+		}
+		copy_skb->dev = de->dev;
+
+		if (!copying_skb) {
+			pci_unmap_single(de->pdev, mapping,
+					 buflen, PCI_DMA_FROMDEVICE);
+			skb_put(skb, len);
+
+			mapping =
+			de->rx_skb[rx_tail].mapping =
+				pci_map_single(de->pdev, copy_skb->tail,
+					       buflen, PCI_DMA_FROMDEVICE);
+			de->rx_skb[rx_tail].skb = copy_skb;
+		} else {
+			pci_dma_sync_single(de->pdev, mapping, len, PCI_DMA_FROMDEVICE);
+			skb_reserve(copy_skb, RX_OFFSET);
+			memcpy(skb_put(copy_skb, len), skb->tail, len);
+
+			/* We'll reuse the original ring buffer. */
+			skb = copy_skb;
+		}
+
+		skb->protocol = eth_type_trans (skb, de->dev);
+
+		de->net_stats.rx_packets++;
+		de->net_stats.rx_bytes += skb->len;
+		de->dev->last_rx = jiffies;
+		rc = netif_rx (skb);
+		if (rc == NET_RX_DROP)
+			drop = 1;
+
+rx_next:
+		de->rx_ring[rx_tail].opts1 = cpu_to_le32(DescOwn);
+		if (rx_tail == (DE_RX_RING_SIZE - 1))
+			de->rx_ring[rx_tail].opts2 =
+				cpu_to_le32(RingEnd | de->rx_buf_sz);
+		else
+			de->rx_ring[rx_tail].opts2 = cpu_to_le32(de->rx_buf_sz);
+		de->rx_ring[rx_tail].addr1 = cpu_to_le32(mapping);
+		rx_tail = NEXT_RX(rx_tail);
+	}
+
+	if (!rx_work)
+		printk(KERN_WARNING "%s: rx work limit reached\n", de->dev->name);
+
+	de->rx_tail = rx_tail;
+}
+
+static void de_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_instance;
+	struct de_private *de = dev->priv;
+	u32 status;
+
+	status = dr32(MacStatus);
+	if ((!(status & (IntrOK|IntrErr))) || (status == 0xFFFF))
+		return;
+
+	if (netif_msg_intr(de))
+		printk(KERN_DEBUG "%s: intr, status %08x mode %08x desc %u/%u/%u\n",
+		        dev->name, status, dr32(MacMode), de->rx_tail, de->tx_head, de->tx_tail);
+
+	dw32(MacStatus, status);
+
+	if (status & (RxIntr | RxEmpty)) {
+		de_rx(de);
+		if (status & RxEmpty)
+			dw32(RxPoll, NormalRxPoll);
+	}
+
+	spin_lock(&de->lock);
+
+	if (status & (TxIntr | TxEmpty))
+		de_tx(de);
+
+	if (status & (LinkPass | LinkFail))
+		de_media_interrupt(de, status);
+
+	spin_unlock(&de->lock);
+
+	if (status & PciErr) {
+		u16 pci_status;
+
+		pci_read_config_word(de->pdev, PCI_STATUS, &pci_status);
+		pci_write_config_word(de->pdev, PCI_STATUS, pci_status);
+		printk(KERN_ERR "%s: PCI bus error, status=%08x, PCI status=%04x\n",
+		       dev->name, status, pci_status);
+	}
+}
+
+static void de_tx (struct de_private *de)
+{
+	unsigned tx_head = de->tx_head;
+	unsigned tx_tail = de->tx_tail;
+
+	while (tx_tail != tx_head) {
+		struct sk_buff *skb;
+		u32 status;
+
+		rmb();
+		status = le32_to_cpu(de->tx_ring[tx_tail].opts1);
+		if (status & DescOwn)
+			break;
+
+		skb = de->tx_skb[tx_tail].skb;
+		if (!skb)
+			BUG();
+		if (unlikely(skb == DE_DUMMY_SKB))
+			goto next;
+
+		if (unlikely(skb == DE_SETUP_SKB)) {
+			pci_unmap_single(de->pdev, de->tx_skb[tx_tail].mapping,
+					 sizeof(de->setup_frame), PCI_DMA_TODEVICE);
+			goto next;
+		}
+
+		pci_unmap_single(de->pdev, de->tx_skb[tx_tail].mapping,
+				 skb->len, PCI_DMA_TODEVICE);
+
+		if (status & LastFrag) {
+			if (status & TxError) {
+				if (netif_msg_tx_err(de))
+					printk(KERN_DEBUG "%s: tx err, status 0x%x\n",
+					       de->dev->name, status);
+				de->net_stats.tx_errors++;
+				if (status & TxOWC)
+					de->net_stats.tx_window_errors++;
+				if (status & TxMaxCol)
+					de->net_stats.tx_aborted_errors++;
+				if (status & TxLinkFail)
+					de->net_stats.tx_carrier_errors++;
+				if (status & TxFIFOUnder)
+					de->net_stats.tx_fifo_errors++;
+			} else {
+				de->net_stats.tx_packets++;
+				de->net_stats.tx_bytes += skb->len;
+				if (netif_msg_tx_done(de))
+					printk(KERN_DEBUG "%s: tx done, slot %d\n", de->dev->name, tx_tail);
+			}
+			dev_kfree_skb_irq(skb);
+		}
+
+next:
+		de->tx_skb[tx_tail].skb = NULL;
+
+		tx_tail = NEXT_TX(tx_tail);
+	}
+
+	de->tx_tail = tx_tail;
+
+	if (netif_queue_stopped(de->dev) && (TX_BUFFS_AVAIL(de) > (DE_TX_RING_SIZE / 4)))
+		netif_wake_queue(de->dev);
+}
+
+static int de_start_xmit (struct sk_buff *skb, struct net_device *dev)
+{
+	struct de_private *de = dev->priv;
+	unsigned int entry, tx_free;
+	u32 mapping, len, flags = FirstFrag | LastFrag;
+	struct de_desc *txd;
+
+	spin_lock_irq(&de->lock);
+
+	tx_free = TX_BUFFS_AVAIL(de);
+	if (tx_free == 0) {
+		netif_stop_queue(dev);
+		spin_unlock_irq(&de->lock);
+		return 1;
+	}
+	tx_free--;
+
+	entry = de->tx_head;
+
+	txd = &de->tx_ring[entry];
+
+	len = skb->len;
+	mapping = pci_map_single(de->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	if (entry == (DE_TX_RING_SIZE - 1))
+		flags |= RingEnd;
+	if (!tx_free || (tx_free == (DE_TX_RING_SIZE / 2)))
+		flags |= TxSwInt;
+	flags |= len;
+	txd->opts2 = cpu_to_le32(flags);
+	txd->addr1 = cpu_to_le32(mapping);
+
+	de->tx_skb[entry].skb = skb;
+	de->tx_skb[entry].mapping = mapping;
+	wmb();
+
+	txd->opts1 = cpu_to_le32(DescOwn);
+	wmb();
+
+	de->tx_head = NEXT_TX(entry);
+	if (netif_msg_tx_queued(de))
+		printk(KERN_DEBUG "%s: tx queued, slot %d, skblen %d\n",
+		       dev->name, entry, skb->len);
+
+	if (tx_free == 0)
+		netif_stop_queue(dev);
+
+	spin_unlock_irq(&de->lock);
+
+	/* Trigger an immediate transmit demand. */
+	dw32(TxPoll, NormalTxPoll);
+	dev->trans_start = jiffies;
+
+	return 0;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+   Note that we only use exclusion around actually queueing the
+   new frame, not around filling de->setup_frame.  This is non-deterministic
+   when re-entered but still correct. */
+
+/* The little-endian AUTODIN32 ethernet CRC calculation.
+   N.B. Do not use for bulk data, use a table-based routine instead.
+   This is common code and should be moved to net/core/crc.c */
+static unsigned const ethernet_polynomial_le = 0xedb88320U;
+static inline u32 ether_crc_le(int length, unsigned char *data)
+{
+	u32 crc = 0xffffffff;	/* Initial value. */
+	while(--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 8; --bit >= 0; current_octet >>= 1) {
+			if ((crc ^ current_octet) & 1) {
+				crc >>= 1;
+				crc ^= ethernet_polynomial_le;
+			} else
+				crc >>= 1;
+		}
+	}
+	return crc;
+}
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+    int crc = -1;
+
+    while(--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+			crc = (crc << 1) ^
+				((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
+    }
+    return crc;
+}
+
+#undef set_bit_le
+#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0)
+
+static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
+{
+	struct de_private *de = dev->priv;
+	u16 hash_table[32];
+	struct dev_mc_list *mclist;
+	int i;
+	u16 *eaddrs;
+
+	memset(hash_table, 0, sizeof(hash_table));
+	set_bit_le(255, hash_table); 			/* Broadcast entry */
+	/* This should work on big-endian machines as well. */
+	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+	     i++, mclist = mclist->next) {
+		int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff;
+
+		set_bit_le(index, hash_table);
+
+		for (i = 0; i < 32; i++) {
+			*setup_frm++ = hash_table[i];
+			*setup_frm++ = hash_table[i];
+		}
+		setup_frm = &de->setup_frame[13*6];
+	}
+
+	/* Fill the final entry with our physical address. */
+	eaddrs = (u16 *)dev->dev_addr;
+	*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+	*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+	*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+}
+
+static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev)
+{
+	struct de_private *de = dev->priv;
+	struct dev_mc_list *mclist;
+	int i;
+	u16 *eaddrs;
+
+	/* We have <= 14 addresses so we can use the wonderful
+	   16 address perfect filtering of the Tulip. */
+	for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
+	     i++, mclist = mclist->next) {
+		eaddrs = (u16 *)mclist->dmi_addr;
+		*setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;
+		*setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;
+		*setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++;
+	}
+	/* Fill the unused entries with the broadcast address. */
+	memset(setup_frm, 0xff, (15-i)*12);
+	setup_frm = &de->setup_frame[15*6];
+
+	/* Fill the final entry with our physical address. */
+	eaddrs = (u16 *)dev->dev_addr;
+	*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
+	*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
+	*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];
+}
+
+
+static void __de_set_rx_mode (struct net_device *dev)
+{
+	struct de_private *de = dev->priv;
+	u32 macmode;
+	unsigned int entry;
+	u32 mapping;
+	struct de_desc *txd;
+	struct de_desc *dummy_txd = NULL;
+
+	macmode = de->macmode & ~(AcceptAllMulticast | AcceptAllPhys);
+
+	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
+		macmode |= AcceptAllMulticast | AcceptAllPhys;
+		goto out;
+	}
+
+	if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to filter well -- accept all multicasts. */
+		macmode |= AcceptAllMulticast;
+		goto out;
+	}
+
+	/* Note that only the low-address shortword of setup_frame is valid!
+	   The values are doubled for big-endian architectures. */
+	if (dev->mc_count > 14)	/* Must use a multicast hash table. */
+		build_setup_frame_hash (de->setup_frame, dev);
+	else
+		build_setup_frame_perfect (de->setup_frame, dev);
+
+	/*
+	 * Now add this frame to the Tx list.
+	 */
+
+	entry = de->tx_head;
+
+	/* Avoid a chip errata by prefixing a dummy entry. */
+	if (entry != 0) {
+		de->tx_skb[entry].skb = DE_DUMMY_SKB;
+
+		dummy_txd = &de->tx_ring[entry];
+		dummy_txd->opts2 = (entry == (DE_TX_RING_SIZE - 1)) ?
+				   cpu_to_le32(RingEnd) : 0;
+		dummy_txd->addr1 = 0;
+
+		/* Must set DescOwned later to avoid race with chip */
+
+		entry = NEXT_TX(entry);
+	}
+
+	de->tx_skb[entry].skb = DE_SETUP_SKB;
+	de->tx_skb[entry].mapping = mapping =
+	    pci_map_single (de->pdev, de->setup_frame,
+			    sizeof (de->setup_frame), PCI_DMA_TODEVICE);
+
+	/* Put the setup frame on the Tx list. */
+	txd = &de->tx_ring[entry];
+	if (entry == (DE_TX_RING_SIZE - 1))
+		txd->opts2 = cpu_to_le32(SetupFrame | RingEnd | sizeof (de->setup_frame));
+	else
+		txd->opts2 = cpu_to_le32(SetupFrame | sizeof (de->setup_frame));
+	txd->addr1 = cpu_to_le32(mapping);
+	wmb();
+
+	txd->opts1 = cpu_to_le32(DescOwn);
+	wmb();
+
+	if (dummy_txd) {
+		dummy_txd->opts1 = cpu_to_le32(DescOwn);
+		wmb();
+	}
+
+	de->tx_head = NEXT_TX(entry);
+
+	if (TX_BUFFS_AVAIL(de) < 0)
+		BUG();
+	if (TX_BUFFS_AVAIL(de) == 0)
+		netif_stop_queue(dev);
+
+	/* Trigger an immediate transmit demand. */
+	dw32(TxPoll, NormalTxPoll);
+
+out:
+	if (macmode != de->macmode) {
+		dw32 (MacMode, macmode);
+		de->macmode = macmode;
+	}
+}
+
+static void de_set_rx_mode (struct net_device *dev)
+{
+	unsigned long flags;
+	struct de_private *de = dev->priv;
+
+	spin_lock_irqsave (&de->lock, flags);
+	__de_set_rx_mode(dev);
+	spin_unlock_irqrestore (&de->lock, flags);
+}
+
+static inline void de_rx_missed(struct de_private *de, u32 rx_missed)
+{
+	if (unlikely(rx_missed & RxMissedOver))
+		de->net_stats.rx_missed_errors += RxMissedMask;
+	else
+		de->net_stats.rx_missed_errors += (rx_missed & RxMissedMask);
+}
+
+static void __de_get_stats(struct de_private *de)
+{
+	u32 tmp = dr32(RxMissed); /* self-clearing */
+
+	de_rx_missed(de, tmp);
+}
+
+static struct net_device_stats *de_get_stats(struct net_device *dev)
+{
+	struct de_private *de = dev->priv;
+
+	/* The chip only need report frame silently dropped. */
+	spin_lock_irq(&de->lock);
+ 	if (netif_running(dev) && netif_device_present(dev))
+ 		__de_get_stats(de);
+	spin_unlock_irq(&de->lock);
+
+	return &de->net_stats;
+}
+
+static inline int de_is_running (struct de_private *de)
+{
+	return (dr32(MacStatus) & (RxState | TxState)) ? 1 : 0;
+}
+
+static void de_stop_rxtx (struct de_private *de)
+{
+	u32 macmode;
+	unsigned int work = 1000;
+
+	macmode = dr32(MacMode);
+	if (macmode & RxTx) {
+		dw32(MacMode, macmode & ~RxTx);
+		dr32(MacMode);
+	}
+
+	while (--work > 0) {
+		if (!de_is_running(de))
+			return;
+		cpu_relax();
+	}
+	
+	printk(KERN_WARNING "%s: timeout expired stopping DMA\n", de->dev->name);
+}
+
+static inline void de_start_rxtx (struct de_private *de)
+{
+	u32 macmode;
+
+	macmode = dr32(MacMode);
+	if ((macmode & RxTx) != RxTx) {
+		dw32(MacMode, macmode | RxTx);
+		dr32(MacMode);
+	}
+}
+
+static void de_stop_hw (struct de_private *de)
+{
+
+	udelay(5);
+	dw32(IntrMask, 0);
+
+	de_stop_rxtx(de);
+
+	dw32(MacStatus, dr32(MacStatus));
+
+	synchronize_irq();
+	udelay(10);
+
+	de->rx_tail = 0;
+	de->tx_head = de->tx_tail = 0;
+}
+
+static void de_link_up(struct de_private *de)
+{
+	if (!netif_carrier_ok(de->dev)) {
+		netif_carrier_on(de->dev);
+		if (netif_msg_link(de))
+			printk(KERN_INFO "%s: link up, media %s\n",
+			       de->dev->name, media_name[de->media_type]);
+	}
+}
+
+static void de_link_down(struct de_private *de)
+{
+	if (netif_carrier_ok(de->dev)) {
+		netif_carrier_off(de->dev);
+		if (netif_msg_link(de))
+			printk(KERN_INFO "%s: link down\n", de->dev->name);
+	}
+}
+
+static void de_set_media (struct de_private *de)
+{
+	unsigned media = de->media_type;
+
+	if (de_is_running(de))
+		BUG();
+
+	if (de->de21040)
+		dw32(CSR11, FULL_DUPLEX_MAGIC);
+	dw32(CSR13, 0); /* Reset phy */
+	dw32(CSR14, de->media[media].csr14);
+	dw32(CSR15, de->media[media].csr15);
+	dw32(CSR13, de->media[media].csr13);
+
+	/* must delay 10ms before writing to other registers,
+	 * especially CSR6
+	 */
+	mdelay(10);
+
+	if (media == DE_MEDIA_TP_FD)
+		de->macmode |= FullDuplex;
+	else
+		de->macmode &= ~FullDuplex;
+	
+	if (netif_msg_link(de))
+		printk(KERN_INFO "%s: set link %s, mode %x, sia %x,%x,%x,%x\n"
+		       KERN_INFO "                 set mode %x, set sia %x,%x,%x\n",
+		       de->dev->name, media_name[media],
+		       dr32(MacMode), dr32(SIAStatus), dr32(CSR13),
+		       dr32(CSR14), dr32(CSR15), de->macmode,
+			de->media[media].csr13,
+			de->media[media].csr14,
+			de->media[media].csr15);
+}
+
+static void de21040_media_timer (unsigned long data)
+{
+	struct de_private *de = (struct de_private *) data;
+	struct net_device *dev = de->dev;
+	u32 status = dr32(SIAStatus);
+	unsigned int carrier;
+	
+	carrier = (status & NetCxnErr) ? 0 : 1;
+		
+	if (carrier) {
+		if (de->media_type != DE_MEDIA_AUI && (status & LinkFailStatus))
+			goto no_link_yet;
+
+		de->media_timer.expires = jiffies + DE_TIMER_LINK;
+		add_timer(&de->media_timer);
+		if (!netif_carrier_ok(dev))
+			de_link_up(de);
+		else
+			if (netif_msg_timer(de))
+				printk(KERN_INFO "%s: %s link ok, status %x\n",
+				       dev->name, media_name[de->media_type],
+				       status);
+		return;
+	}
+
+	de_link_down(de);	
+
+	if (de->media_lock)
+		return;
+
+	if (de->media_type == DE_MEDIA_AUI)
+		de->media_type = DE_MEDIA_TP;
+	else
+		de->media_type = DE_MEDIA_AUI;
+
+	de_stop_rxtx(de);
+	de_set_media(de);
+	de_start_rxtx(de);
+
+no_link_yet:
+	de->media_timer.expires = jiffies + DE_TIMER_NO_LINK;
+	add_timer(&de->media_timer);
+
+	if (netif_msg_timer(de))
+		printk(KERN_INFO "%s: no link, trying media %s, status %x\n",
+		       dev->name, media_name[de->media_type], status);
+}
+
+static unsigned int de_ok_to_advertise (struct de_private *de, u32 new_media)
+{
+	switch (new_media) {
+	case DE_MEDIA_TP_AUTO:
+		if (!(de->media_advertise & ADVERTISED_Autoneg))
+			return 0;
+		if (!(de->media_advertise & (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full)))
+			return 0;
+		break;
+	case DE_MEDIA_BNC:
+		if (!(de->media_advertise & ADVERTISED_BNC))
+			return 0;
+		break;
+	case DE_MEDIA_AUI:
+		if (!(de->media_advertise & ADVERTISED_AUI))
+			return 0;
+		break;
+	case DE_MEDIA_TP:
+		if (!(de->media_advertise & ADVERTISED_10baseT_Half))
+			return 0;
+		break;
+	case DE_MEDIA_TP_FD:
+		if (!(de->media_advertise & ADVERTISED_10baseT_Full))
+			return 0;
+		break;
+	}
+	
+	return 1;
+}
+
+static void de21041_media_timer (unsigned long data)
+{
+	struct de_private *de = (struct de_private *) data;
+	struct net_device *dev = de->dev;
+	u32 status = dr32(SIAStatus), new_media;
+	unsigned int carrier;
+	
+	carrier = (status & NetCxnErr) ? 0 : 1;
+		
+	if (carrier) {
+		if ((de->media_type == DE_MEDIA_TP_AUTO ||
+		     de->media_type == DE_MEDIA_TP ||
+		     de->media_type == DE_MEDIA_TP_FD) &&
+		    (status & LinkFailStatus))
+			goto no_link_yet;
+
+		de->media_timer.expires = jiffies + DE_TIMER_LINK;
+		add_timer(&de->media_timer);
+		if (!netif_carrier_ok(dev))
+			de_link_up(de);
+		else
+			if (netif_msg_timer(de))
+				printk(KERN_INFO "%s: %s link ok, mode %x status %x\n",
+				       dev->name, media_name[de->media_type],
+				       dr32(MacMode), status);
+		return;
+	}
+
+	de_link_down(de);	
+
+	/* if media type locked, don't switch media */
+	if (de->media_lock)
+		goto set_media;
+
+	/* if activity detected, use that as hint for new media type */
+	if (status & NonselPortActive) {
+		if (de->media_type == DE_MEDIA_AUI)
+			de->media_type = DE_MEDIA_TP;
+		else
+			de->media_type = DE_MEDIA_AUI;
+		goto set_media;
+	}
+
+	/* move to next advertised media */
+	new_media = de->media_type;
+	do {
+		if (new_media == DE_MEDIA_LAST)
+			new_media = DE_MEDIA_FIRST;
+		else
+			new_media++;
+	} while ((!de_ok_to_advertise(de, new_media)) &&
+	         (new_media != de->media_type));
+
+	de->media_type = new_media;
+	
+set_media:
+	de_stop_rxtx(de);
+	de_set_media(de);
+	de_start_rxtx(de);
+
+no_link_yet:
+	de->media_timer.expires = jiffies + DE_TIMER_NO_LINK;
+	add_timer(&de->media_timer);
+
+	if (netif_msg_timer(de))
+		printk(KERN_INFO "%s: no link, trying media %s, status %x\n",
+		       dev->name, media_name[de->media_type], status);
+}
+
+static void de_media_interrupt (struct de_private *de, u32 status)
+{
+	if (status & LinkPass) {
+		de_link_up(de);
+		mod_timer(&de->media_timer, jiffies + DE_TIMER_LINK);
+		return;
+	}
+	
+	if (!(status & LinkFail))
+		BUG();
+
+	if (netif_carrier_ok(de->dev)) {
+		de_link_down(de);
+		mod_timer(&de->media_timer, jiffies + DE_TIMER_NO_LINK);
+	}
+}
+
+static int de_reset_mac (struct de_private *de)
+{
+	unsigned tmp;
+	u32 status;
+
+	/*
+	 * Reset MAC.  Copied from de4x5.c.
+	 */
+
+	dr32 (BusMode);
+	mdelay (1);
+
+	dw32 (BusMode, de_bus_mode | CmdReset);
+	mdelay (1);
+
+	dw32 (BusMode, de_bus_mode);
+	mdelay (1);
+
+	for (tmp = 0; tmp < 5; tmp++) {
+		dr32 (BusMode);
+		mdelay (1);
+	}
+
+	mdelay (1);
+
+	status = dr32(MacStatus);
+	if (status & (RxState | TxState))
+		return -EBUSY;
+	if (status == 0xffffffff)
+		return -ENODEV;
+	return 0;
+}
+
+static void de_adapter_wake (struct de_private *de)
+{
+	u32 pmctl;
+
+	if (de->de21040)
+		return;
+
+	pci_read_config_dword(de->pdev, PCIPM, &pmctl);
+	if (pmctl & PM_Mask) {
+		pmctl &= ~PM_Mask;
+		pci_write_config_dword(de->pdev, PCIPM, pmctl);
+
+		/* de4x5.c delays, so we do too */
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(msec_to_jiffies(10));
+	}
+}
+
+static void de_adapter_sleep (struct de_private *de)
+{
+	u32 pmctl;
+
+	if (de->de21040)
+		return;
+
+	pci_read_config_dword(de->pdev, PCIPM, &pmctl);
+	pmctl |= PM_Sleep;
+	pci_write_config_dword(de->pdev, PCIPM, pmctl);
+}
+
+static int de_init_hw (struct de_private *de)
+{
+	struct net_device *dev = de->dev;
+	int rc;
+
+	de_adapter_wake(de);
+	
+	de->macmode = dr32(MacMode) & ~MacModeClear;
+
+	rc = de_reset_mac(de);
+	if (rc)
+		return rc;
+
+	de_set_media(de); /* reset phy */
+
+	dw32(RxRingAddr, de->ring_dma);
+	dw32(TxRingAddr, de->ring_dma + (sizeof(struct de_desc) * DE_RX_RING_SIZE));
+
+	dw32(MacMode, RxTx | de->macmode);
+
+	dr32(RxMissed); /* self-clearing */
+
+	dw32(IntrMask, de_intr_mask);
+
+	de_set_rx_mode(dev);
+
+	return 0;
+}
+
+static int de_refill_rx (struct de_private *de)
+{
+	unsigned i;
+
+	for (i = 0; i < DE_RX_RING_SIZE; i++) {
+		struct sk_buff *skb;
+
+		skb = dev_alloc_skb(de->rx_buf_sz);
+		if (!skb)
+			goto err_out;
+
+		skb->dev = de->dev;
+
+		de->rx_skb[i].mapping = pci_map_single(de->pdev,
+			skb->tail, de->rx_buf_sz, PCI_DMA_FROMDEVICE);
+		de->rx_skb[i].skb = skb;
+
+		de->rx_ring[i].opts1 = cpu_to_le32(DescOwn);
+		if (i == (DE_RX_RING_SIZE - 1))
+			de->rx_ring[i].opts2 =
+				cpu_to_le32(RingEnd | de->rx_buf_sz);
+		else
+			de->rx_ring[i].opts2 = cpu_to_le32(de->rx_buf_sz);
+		de->rx_ring[i].addr1 = cpu_to_le32(de->rx_skb[i].mapping);
+		de->rx_ring[i].addr2 = 0;
+	}
+
+	return 0;
+
+err_out:
+	de_clean_rings(de);
+	return -ENOMEM;
+}
+
+static int de_init_rings (struct de_private *de)
+{
+	memset(de->tx_ring, 0, sizeof(struct de_desc) * DE_TX_RING_SIZE);
+	de->tx_ring[DE_TX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd);
+
+	de->rx_tail = 0;
+	de->tx_head = de->tx_tail = 0;
+
+	return de_refill_rx (de);
+}
+
+static int de_alloc_rings (struct de_private *de)
+{
+	de->rx_ring = pci_alloc_consistent(de->pdev, DE_RING_BYTES, &de->ring_dma);
+	if (!de->rx_ring)
+		return -ENOMEM;
+	de->tx_ring = &de->rx_ring[DE_RX_RING_SIZE];
+	return de_init_rings(de);
+}
+
+static void de_clean_rings (struct de_private *de)
+{
+	unsigned i;
+
+	memset(de->rx_ring, 0, sizeof(struct de_desc) * DE_RX_RING_SIZE);
+	de->rx_ring[DE_RX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd);
+	wmb();
+	memset(de->tx_ring, 0, sizeof(struct de_desc) * DE_TX_RING_SIZE);
+	de->tx_ring[DE_TX_RING_SIZE - 1].opts2 = cpu_to_le32(RingEnd);
+	wmb();
+
+	for (i = 0; i < DE_RX_RING_SIZE; i++) {
+		if (de->rx_skb[i].skb) {
+			pci_unmap_single(de->pdev, de->rx_skb[i].mapping,
+					 de->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			dev_kfree_skb(de->rx_skb[i].skb);
+		}
+	}
+
+	for (i = 0; i < DE_TX_RING_SIZE; i++) {
+		if (de->tx_skb[i].skb) {
+			struct sk_buff *skb = de->tx_skb[i].skb;
+			pci_unmap_single(de->pdev, de->tx_skb[i].mapping,
+					 skb->len, PCI_DMA_TODEVICE);
+			dev_kfree_skb(skb);
+			de->net_stats.tx_dropped++;
+		}
+	}
+
+	memset(&de->rx_skb, 0, sizeof(struct ring_info) * DE_RX_RING_SIZE);
+	memset(&de->tx_skb, 0, sizeof(struct ring_info) * DE_TX_RING_SIZE);
+}
+
+static void de_free_rings (struct de_private *de)
+{
+	de_clean_rings(de);
+	pci_free_consistent(de->pdev, DE_RING_BYTES, de->rx_ring, de->ring_dma);
+	de->rx_ring = NULL;
+	de->tx_ring = NULL;
+}
+
+static int de_open (struct net_device *dev)
+{
+	struct de_private *de = dev->priv;
+	int rc;
+
+	if (netif_msg_ifup(de))
+		printk(KERN_DEBUG "%s: enabling interface\n", dev->name);
+
+	de->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
+
+	rc = de_alloc_rings(de);
+	if (rc) {
+		printk(KERN_ERR "%s: ring allocation failure, err=%d\n",
+		       dev->name, rc);
+		return rc;
+	}
+
+	rc = de_init_hw(de);
+	if (rc) {
+		printk(KERN_ERR "%s: h/w init failure, err=%d\n",
+		       dev->name, rc);
+		goto err_out_free;
+	}
+
+	rc = request_irq(dev->irq, de_interrupt, SA_SHIRQ, dev->name, dev);
+	if (rc) {
+		printk(KERN_ERR "%s: IRQ %d request failure, err=%d\n",
+		       dev->name, dev->irq, rc);
+		goto err_out_hw;
+	}
+
+	netif_start_queue(dev);
+
+	return 0;
+
+err_out_hw:
+	de_stop_hw(de);
+err_out_free:
+	de_free_rings(de);
+	return rc;
+}
+
+static int de_close (struct net_device *dev)
+{
+	struct de_private *de = dev->priv;
+
+	if (netif_msg_ifdown(de))
+		printk(KERN_DEBUG "%s: disabling interface\n", dev->name);
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+	del_timer_sync(&de->media_timer);
+	de_stop_hw(de);
+	free_irq(dev->irq, dev);
+	de_free_rings(de);
+	de_adapter_sleep(de);
+	pci_disable_device(de->pdev);
+	return 0;
+}
+
+static void de_tx_timeout (struct net_device *dev)
+{
+	struct de_private *de = dev->priv;
+
+	printk(KERN_DEBUG "%s: NIC status %08x mode %08x sia %08x desc %u/%u/%u\n",
+	       dev->name, dr32(MacStatus), dr32(MacMode), dr32(SIAStatus),
+	       de->rx_tail, de->tx_head, de->tx_tail);
+
+	del_timer_sync(&de->media_timer);
+
+	disable_irq(dev->irq);
+	spin_lock_irq(&de->lock);
+
+	de_stop_hw(de);
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	spin_unlock_irq(&de->lock);
+	enable_irq(dev->irq);
+		
+	/* Update the error counts. */
+	__de_get_stats(de);
+
+	synchronize_irq();
+	de_clean_rings(de);
+
+	de_init_hw(de);
+	
+	netif_wake_queue(dev);
+}
+
+static int de_get_regs(struct de_private *de, u8 *buf)
+{
+	int i;
+	u32 *rbuf = (u32 *)buf;
+	
+	/* read all CSRs */
+	for (i = 0; i < DE_NUM_REGS; i++)
+		rbuf[i] = dr32(i * 8);
+
+	/* handle self-clearing RxMissed counter, CSR8 */
+	de_rx_missed(de, rbuf[8]);
+
+	return 0;
+}
+
+static int de_ethtool_gset(struct de_private *de, struct ethtool_cmd *ecmd)
+{
+	ecmd->supported = de->media_supported;
+	ecmd->transceiver = XCVR_INTERNAL;
+	ecmd->phy_address = 0;
+	ecmd->advertising = de->media_advertise;
+	
+	switch (de->media_type) {
+	case DE_MEDIA_AUI:
+		ecmd->port = PORT_AUI;
+		ecmd->speed = 5;
+		break;
+	case DE_MEDIA_BNC:
+		ecmd->port = PORT_BNC;
+		ecmd->speed = 2;
+		break;
+	default:
+		ecmd->port = PORT_TP;
+		ecmd->speed = SPEED_10;
+		break;
+	}
+	
+	if (de->macmode & FullDuplex)
+		ecmd->duplex = DUPLEX_FULL;
+	else
+		ecmd->duplex = DUPLEX_HALF;
+
+	if (de->media_lock)
+		ecmd->autoneg = AUTONEG_DISABLE;
+	else
+		ecmd->autoneg = AUTONEG_ENABLE;
+
+	/* ignore maxtxpkt, maxrxpkt for now */
+
+	return 0;
+}
+
+static int de_ethtool_sset(struct de_private *de, struct ethtool_cmd *ecmd)
+{
+	u32 new_media;
+	unsigned int media_lock;
+
+	if (ecmd->speed != SPEED_10 && ecmd->speed != 5 && ecmd->speed != 2)
+		return -EINVAL;
+	if (de->de21040 && ecmd->speed == 2)
+		return -EINVAL;
+	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
+		return -EINVAL;
+	if (ecmd->port != PORT_TP && ecmd->port != PORT_AUI && ecmd->port != PORT_BNC)
+		return -EINVAL;
+	if (de->de21040 && ecmd->port == PORT_BNC)
+		return -EINVAL;
+	if (ecmd->transceiver != XCVR_INTERNAL)
+		return -EINVAL;
+	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
+		return -EINVAL;
+	if (ecmd->advertising & ~de->media_supported)
+		return -EINVAL;
+	if (ecmd->autoneg == AUTONEG_ENABLE &&
+	    (!(ecmd->advertising & ADVERTISED_Autoneg)))
+		return -EINVAL;
+	
+	switch (ecmd->port) {
+	case PORT_AUI:
+		new_media = DE_MEDIA_AUI;
+		if (!(ecmd->advertising & ADVERTISED_AUI))
+			return -EINVAL;
+		break;
+	case PORT_BNC:
+		new_media = DE_MEDIA_BNC;
+		if (!(ecmd->advertising & ADVERTISED_BNC))
+			return -EINVAL;
+		break;
+	default:
+		if (ecmd->autoneg == AUTONEG_ENABLE)
+			new_media = DE_MEDIA_TP_AUTO;
+		else if (ecmd->duplex == DUPLEX_FULL)
+			new_media = DE_MEDIA_TP_FD;
+		else
+			new_media = DE_MEDIA_TP;
+		if (!(ecmd->advertising & ADVERTISED_TP))
+			return -EINVAL;
+		if (!(ecmd->advertising & (ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half)))
+			return -EINVAL;
+		break;
+	}
+	
+	media_lock = (ecmd->autoneg == AUTONEG_ENABLE) ? 0 : 1;
+	
+	if ((new_media == de->media_type) &&
+	    (media_lock == de->media_lock) &&
+	    (ecmd->advertising == de->media_advertise))
+		return 0; /* nothing to change */
+	    
+	de_link_down(de);
+	de_stop_rxtx(de);
+	
+	de->media_type = new_media;
+	de->media_lock = media_lock;
+	de->media_advertise = ecmd->advertising;
+	de_set_media(de);
+	
+	return 0;
+}
+
+static int de_ethtool_ioctl (struct de_private *de, void *useraddr)
+{
+	u32 ethcmd;
+
+	/* dev_ioctl() in ../../net/core/dev.c has already checked
+	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, de->pdev->slot_name);
+		info.regdump_len = DE_REGS_SIZE;
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&de->lock);
+		de_ethtool_gset(de, &ecmd);
+		spin_unlock_irq(&de->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		struct ethtool_cmd ecmd;
+		int r;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&de->lock);
+		r = de_ethtool_sset(de, &ecmd);
+		spin_unlock_irq(&de->lock);
+		return r;
+	}
+
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		u32 status;
+
+		if (de->media_type != DE_MEDIA_TP_AUTO)
+			return -EINVAL;
+		if (netif_carrier_ok(de->dev))
+			de_link_down(de);
+
+		status = dr32(SIAStatus);
+		dw32(SIAStatus, (status & ~NWayState) | NWayRestart);
+		if (netif_msg_link(de))
+			printk(KERN_INFO "%s: link nway restart, status %x,%x\n",
+			       de->dev->name, status, dr32(SIAStatus));
+		return 0;
+	}
+
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = (netif_carrier_ok(de->dev)) ? 1 : 0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = de->msg_enable;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		de->msg_enable = edata.data;
+		return 0;
+	}
+
+	/* get registers */
+	case ETHTOOL_GREGS: {
+		struct ethtool_regs regs;
+		u8 regbuf[DE_REGS_SIZE];
+		int r;
+
+		if (copy_from_user(&regs, useraddr, sizeof(regs)))
+			return -EFAULT;
+		
+		if (regs.len > DE_REGS_SIZE) {
+			regs.len = DE_REGS_SIZE;
+		}
+		regs.version = (DE_REGS_VER << 2) | de->de21040;
+		if (copy_to_user(useraddr, &regs, sizeof(regs)))
+			return -EFAULT;
+
+		useraddr += offsetof(struct ethtool_regs, data);
+
+		spin_lock_irq(&de->lock);
+		r = de_get_regs(de, regbuf);
+		spin_unlock_irq(&de->lock);
+
+		if (r)
+			return r;
+		if (copy_to_user(useraddr, regbuf, regs.len))
+			return -EFAULT;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+
+static int de_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct de_private *de = dev->priv;
+	int rc = 0;
+
+	if (!netif_running(dev))
+		return -EINVAL;
+		
+	switch (cmd) {
+	case SIOCETHTOOL:
+		return de_ethtool_ioctl(de, (void *) rq->ifr_data);
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	return rc;
+}
+
+static void __init de21040_get_mac_address (struct de_private *de)
+{
+	unsigned i;
+
+	dw32 (ROMCmd, 0);	/* Reset the pointer with a dummy write. */
+
+	for (i = 0; i < 6; i++) {
+		int value, boguscnt = 100000;
+		do
+			value = dr32(ROMCmd);
+		while (value < 0 && --boguscnt > 0);
+		de->dev->dev_addr[i] = value;
+		if (boguscnt <= 0)
+			printk(KERN_WARNING PFX "timeout reading 21040 MAC address byte %u\n", i);
+	}
+}
+
+/* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
+
+/* Note: this routine returns extra data bits for size detection. */
+static unsigned __init tulip_read_eeprom(void *regs, int location, int addr_len)
+{
+	int i;
+	unsigned retval = 0;
+	void *ee_addr = regs + ROMCmd;
+	int read_cmd = location | (EE_READ_CMD << addr_len);
+
+	writel(EE_ENB & ~EE_CS, ee_addr);
+	writel(EE_ENB, ee_addr);
+
+	/* Shift the read command bits out. */
+	for (i = 4 + addr_len; i >= 0; i--) {
+		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+		writel(EE_ENB | dataval, ee_addr);
+		readl(ee_addr);
+		writel(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+		readl(ee_addr);
+		retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+	}
+	writel(EE_ENB, ee_addr);
+	readl(ee_addr);
+
+	for (i = 16; i > 0; i--) {
+		writel(EE_ENB | EE_SHIFT_CLK, ee_addr);
+		readl(ee_addr);
+		retval = (retval << 1) | ((readl(ee_addr) & EE_DATA_READ) ? 1 : 0);
+		writel(EE_ENB, ee_addr);
+		readl(ee_addr);
+	}
+
+	/* Terminate the EEPROM access. */
+	writel(EE_ENB & ~EE_CS, ee_addr);
+	return retval;
+}
+
+static void __init tulip_get_srom_info (struct de_private *de)
+{
+	unsigned i, sa_offset = 0, ofs;
+	u8 ee_data[DE_EEPROM_WORDS * sizeof(u16)];
+	unsigned ee_addr_size = tulip_read_eeprom(de->regs, 0xff, 8) & 0x40000 ? 8 : 6;
+	struct de_srom_info_leaf *il;
+
+	/* download entire eeprom */
+	for (i = 0; i < sizeof(ee_data)/2; i++)
+		((u16 *)ee_data)[i] =
+			le16_to_cpu(tulip_read_eeprom(de->regs, i, ee_addr_size));
+
+	/* DEC now has a specification but early board makers
+	   just put the address in the first EEPROM locations. */
+	/* This does  memcmp(eedata, eedata+16, 8) */
+	for (i = 0; i < 8; i ++)
+		if (ee_data[i] != ee_data[16+i])
+			sa_offset = 20;
+
+	/* store MAC address */
+	for (i = 0; i < 6; i ++)
+		de->dev->dev_addr[i] = ee_data[i + sa_offset];
+
+	/* get offset of controller 0 info leaf.  ignore 2nd byte. */
+	ofs = ee_data[SROMC0InfoLeaf];
+	if (ofs >= (sizeof(ee_data) - sizeof(struct de_srom_info_leaf) - sizeof(struct de_srom_media_block)))
+		goto bad_srom;
+
+	/* get pointer to info leaf */
+	il = (struct de_srom_info_leaf *) &ee_data[ofs];
+
+	/* paranoia checks */
+	if (il->n_blocks == 0)
+		goto bad_srom;
+	if ((sizeof(ee_data) - ofs) <
+	    (sizeof(struct de_srom_info_leaf) + (sizeof(struct de_srom_media_block) * il->n_blocks)))
+		goto bad_srom;
+
+	/* get default media type */
+	switch (il->default_media) {
+	case 0x0001:  de->media_type = DE_MEDIA_BNC; break;
+	case 0x0002:  de->media_type = DE_MEDIA_AUI; break;
+	case 0x0204:  de->media_type = DE_MEDIA_TP_FD; break;
+	default: de->media_type = DE_MEDIA_TP_AUTO; break;
+	}
+	
+	/* init SIA register values to defaults */
+	for (i = 0; i < DE_MAX_MEDIA; i++) {
+		de->media[i].type = DE_MEDIA_INVALID;
+		de->media[i].csr13 = 0xffff;
+		de->media[i].csr14 = 0xffff;
+		de->media[i].csr15 = 0xffff;
+	}
+
+	/* parse media blocks to see what medias are supported,
+	 * and if any custom CSR values are provided
+	 */
+	for (i = 0; i < il->n_blocks; i++) {
+		struct de_srom_media_block *ib = &il[i].media[0];
+		unsigned idx;
+
+		/* index based on media type in media block */
+		switch(ib->opts & MediaBlockMask) {
+		case 0: /* 10baseT */
+			de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half
+					  | SUPPORTED_Autoneg;
+			idx = DE_MEDIA_TP;
+			de->media[DE_MEDIA_TP_AUTO].type = DE_MEDIA_TP_AUTO;
+			break;
+		case 1: /* BNC */
+			de->media_supported |= SUPPORTED_BNC;
+			idx = DE_MEDIA_BNC;
+			break;
+		case 2: /* AUI */
+			de->media_supported |= SUPPORTED_AUI;
+			idx = DE_MEDIA_AUI;
+			break;
+		case 4: /* 10baseT-FD */
+			de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full
+					  | SUPPORTED_Autoneg;
+			idx = DE_MEDIA_TP_FD;
+			de->media[DE_MEDIA_TP_AUTO].type = DE_MEDIA_TP_AUTO;
+			break;
+		default:
+			goto bad_srom;
+		}
+
+		if (ib->opts & MediaCustomCSRs) {
+			de->media[idx].csr13 = ib->csr13;
+			de->media[idx].csr14 = ib->csr14;
+			de->media[idx].csr15 = ib->csr15;
+		}
+
+		de->media[idx].type = idx;
+		de->media_advertise |= de->media_supported;
+	}
+
+fill_defaults:
+	/* fill in defaults, for cases where custom CSRs not used */
+	for (i = 0; i < DE_MAX_MEDIA; i++) {
+		if (de->media[i].csr13 == 0xffff)
+			de->media[i].csr13 = t21041_csr13[i];
+		if (de->media[i].csr14 == 0xffff)
+			de->media[i].csr14 = t21041_csr14[i];
+		if (de->media[i].csr15 == 0xffff)
+			de->media[i].csr15 = t21041_csr15[i];
+	}
+
+	if (netif_msg_link(de))
+		printk(KERN_INFO "de%d: SROM-listed ports: %s%s%s\n",
+		       de->board_idx,
+		       de->media_supported & SUPPORTED_TP ? "TP " : "",
+		       de->media_supported & SUPPORTED_BNC ? "BNC " : "",
+		       de->media_supported & SUPPORTED_AUI ? "AUI" : "");
+
+	return;
+
+bad_srom:
+	/* for error cases, it's ok to assume we support all these */
+	for (i = 0; i < DE_MAX_MEDIA; i++)
+		de->media[i].type = i;
+	de->media_supported =
+		SUPPORTED_10baseT_Half |
+		SUPPORTED_10baseT_Full |
+		SUPPORTED_Autoneg |
+		SUPPORTED_TP |
+		SUPPORTED_AUI |
+		SUPPORTED_BNC;
+	goto fill_defaults;
+}
+
+static int __init de_init_one (struct pci_dev *pdev,
+				  const struct pci_device_id *ent)
+{
+	struct net_device *dev;
+	struct de_private *de;
+	int rc;
+	void *regs;
+	long pciaddr;
+	static int board_idx = -1;
+
+	board_idx++;
+
+#ifndef MODULE
+	if (board_idx == 0)
+		printk("%s", version);
+#endif
+
+	/* allocate a new ethernet device structure, and fill in defaults */
+	dev = alloc_etherdev(sizeof(struct de_private));
+	if (!dev)
+		return -ENOMEM;
+
+	SET_MODULE_OWNER(dev);
+	dev->open = de_open;
+	dev->stop = de_close;
+	dev->set_multicast_list = de_set_rx_mode;
+	dev->hard_start_xmit = de_start_xmit;
+	dev->get_stats = de_get_stats;
+	dev->do_ioctl = de_ioctl;
+	dev->tx_timeout = de_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	dev->irq = pdev->irq;
+
+	de = dev->priv;
+	de->de21040 = ent->driver_data == 0 ? 1 : 0;
+	de->pdev = pdev;
+	de->dev = dev;
+	de->msg_enable = (debug < 0 ? DE_DEF_MSG_ENABLE : debug);
+	de->board_idx = board_idx;
+	spin_lock_init (&de->lock);
+	init_timer(&de->media_timer);
+	if (de->de21040)
+		de->media_timer.function = de21040_media_timer;
+	else
+		de->media_timer.function = de21041_media_timer;
+	de->media_timer.data = (unsigned long) de;
+
+	netif_carrier_off(dev);
+	netif_stop_queue(dev);
+
+	/* wake up device, assign resources */
+	rc = pci_enable_device(pdev);
+	if (rc)
+		goto err_out_free;
+
+	/* reserve PCI resources to ensure driver atomicity */
+	rc = pci_request_regions(pdev, DRV_NAME);
+	if (rc)
+		goto err_out_disable;
+
+	/* check for invalid IRQ value */
+	if (pdev->irq < 2) {
+		rc = -EIO;
+		printk(KERN_ERR PFX "invalid irq (%d) for pci dev %s\n",
+		       pdev->irq, pdev->slot_name);
+		goto err_out_res;
+	}
+
+	/* obtain and check validity of PCI I/O address */
+	pciaddr = pci_resource_start(pdev, 1);
+	if (!pciaddr) {
+		rc = -EIO;
+		printk(KERN_ERR PFX "no MMIO resource for pci dev %s\n",
+		       pdev->slot_name);
+		goto err_out_res;
+	}
+	if (pci_resource_len(pdev, 1) < DE_REGS_SIZE) {
+		rc = -EIO;
+		printk(KERN_ERR PFX "MMIO resource (%lx) too small on pci dev %s\n",
+		       pci_resource_len(pdev, 1), pdev->slot_name);
+		goto err_out_res;
+	}
+
+	/* remap CSR registers */
+	regs = ioremap_nocache(pciaddr, DE_REGS_SIZE);
+	if (!regs) {
+		rc = -EIO;
+		printk(KERN_ERR PFX "Cannot map PCI MMIO (%lx@%lx) on pci dev %s\n",
+		       pci_resource_len(pdev, 1), pciaddr, pdev->slot_name);
+		goto err_out_res;
+	}
+	dev->base_addr = (unsigned long) regs;
+	de->regs = regs;
+
+	de_adapter_wake(de);
+
+	/* make sure hardware is not running */
+	de_stop_hw(de);
+
+	/* get MAC address, and some register values related to media types */
+	if (de->de21040) {
+		unsigned i;
+		
+		de21040_get_mac_address(de);
+
+		de->media_type = DE_MEDIA_TP;
+		de->media_supported |= SUPPORTED_TP | SUPPORTED_10baseT_Full |
+				  SUPPORTED_10baseT_Half | SUPPORTED_AUI;
+		de->media_advertise = de->media_supported;
+		for (i = 0; i < DE_MAX_MEDIA; i++) {
+			switch (i) {
+			case DE_MEDIA_AUI:
+			case DE_MEDIA_TP:
+			case DE_MEDIA_TP_FD:
+				de->media[i].type = i;
+				de->media[i].csr13 = t21040_csr13[i];
+				de->media[i].csr14 = t21040_csr14[i];
+				de->media[i].csr15 = t21040_csr15[i];
+				break;
+			default:
+				de->media[i].type = DE_MEDIA_INVALID;
+				break;
+			}
+		}
+	} else {
+		tulip_get_srom_info(de);
+	}
+
+	/* register new network interface with kernel */
+	rc = register_netdev(dev);
+	if (rc)
+		goto err_out_iomap;
+
+	/* print info about board and interface just registered */
+	printk (KERN_INFO "%s: %s at 0x%lx, "
+		"%02x:%02x:%02x:%02x:%02x:%02x, "
+		"IRQ %d\n",
+		dev->name,
+		de->de21040 ? "21040" : "21041",
+		dev->base_addr,
+		dev->dev_addr[0], dev->dev_addr[1],
+		dev->dev_addr[2], dev->dev_addr[3],
+		dev->dev_addr[4], dev->dev_addr[5],
+		dev->irq);
+
+	pci_set_drvdata(pdev, dev);
+
+	/* enable busmastering */
+	pci_set_master(pdev);
+
+	/* put adapter to sleep */
+	de_adapter_sleep(de);
+
+	return 0;
+
+err_out_iomap:
+	iounmap(regs);
+err_out_res:
+	pci_release_regions(pdev);
+err_out_disable:
+	pci_disable_device(pdev);
+err_out_free:
+	kfree(dev);
+	return rc;
+}
+
+static void __exit de_remove_one (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct de_private *de = dev->priv;
+
+	if (!dev)
+		BUG();
+	unregister_netdev(dev);
+	iounmap(de->regs);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+	kfree(dev);
+}
+
+#ifdef CONFIG_PM
+
+static int de_suspend (struct pci_dev *pdev, u32 state)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	struct de_private *de = dev->priv;
+
+	rtnl_lock();
+	if (netif_running (dev)) {
+		del_timer_sync(&de->media_timer);
+
+		disable_irq(dev->irq);
+		spin_lock_irq(&de->lock);
+
+		de_stop_hw(de);
+		netif_stop_queue(dev);
+		netif_device_detach(dev);
+		netif_carrier_off(dev);
+
+		spin_unlock_irq(&de->lock);
+		enable_irq(dev->irq);
+		
+		/* Update the error counts. */
+		__de_get_stats(de);
+
+		synchronize_irq();
+		de_clean_rings(de);
+
+		de_adapter_sleep(de);
+		pci_disable_device(pdev);
+	} else {
+		netif_device_detach(dev);
+	}
+	rtnl_unlock();
+	return 0;
+}
+
+static int de_resume (struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata (pdev);
+	struct de_private *de = dev->priv;
+
+	rtnl_lock();
+	if (netif_device_present(dev))
+		goto out;
+	if (netif_running(dev)) {
+		pci_enable_device(pdev);
+		de_init_hw(de);
+		netif_device_attach(dev);
+	} else {
+		netif_device_attach(dev);
+	}
+out:
+	rtnl_unlock();
+	return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct pci_driver de_driver = {
+	name:		DRV_NAME,
+	id_table:	de_pci_tbl,
+	probe:		de_init_one,
+	remove:		de_remove_one,
+#ifdef CONFIG_PM
+	suspend:	de_suspend,
+	resume:		de_resume,
+#endif
+};
+
+static int __init de_init (void)
+{
+#ifdef MODULE
+	printk("%s", version);
+#endif
+	return pci_module_init (&de_driver);
+}
+
+static void __exit de_exit (void)
+{
+	pci_unregister_driver (&de_driver);
+}
+
+module_init(de_init);
+module_exit(de_exit);
diff -u --recursive --new-file v2.5.0/linux/drivers/net/fc/iph5526.c linux/drivers/net/fc/iph5526.c
--- v2.5.0/linux/drivers/net/fc/iph5526.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/net/fc/iph5526.c	Wed Nov 28 10:22:27 2001
@@ -3802,7 +3802,6 @@
 		fi->host = host;
 		//host->max_id = MAX_SCSI_TARGETS;
 		host->max_id = 5;
-		host->hostt->use_new_eh_code = 1;
 		host->this_id = tmpt->this_id;
 
 		pci_maddr = pci_resource_start(pdev, 0);
diff -u --recursive --new-file v2.5.0/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c
--- v2.5.0/linux/drivers/net/hamradio/baycom_epp.c	Mon Sep 10 09:04:53 2001
+++ linux/drivers/net/hamradio/baycom_epp.c	Sun Nov 25 09:48:47 2001
@@ -807,10 +807,11 @@
 /* --------------------------------------------------------------------- */
 
 #ifdef __i386__
+#include <asm/msr.h>
 #define GETTICK(x)                                                \
 ({                                                                \
 	if (cpu_has_tsc)                                          \
-		__asm__ __volatile__("rdtsc" : "=a" (x) : : "dx");\
+		rdtscl(x);                                        \
 })
 #else /* __i386__ */
 #define GETTICK(x)
diff -u --recursive --new-file v2.5.0/linux/drivers/net/irda/irda-usb.c linux/drivers/net/irda/irda-usb.c
--- v2.5.0/linux/drivers/net/irda/irda-usb.c	Fri Nov  9 14:22:17 2001
+++ linux/drivers/net/irda/irda-usb.c	Sat Dec  8 20:28:45 2001
@@ -256,7 +256,7 @@
 
 	/* Grab the speed URB */
 	purb = &self->speed_urb;
-	if (purb->status != USB_ST_NOERROR) {
+	if (purb->status != 0) {
 		WARNING(__FUNCTION__ "(), URB still in use!\n");
 		return;
 	}
@@ -301,7 +301,7 @@
 	}
 
 	/* Check for timeout and other USB nasties */
-	if(purb->status != USB_ST_NOERROR) {
+	if (purb->status != 0) {
 		/* I get a lot of -ECONNABORTED = -103 here - Jean II */
 		IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
 
@@ -314,7 +314,7 @@
 	}
 
 	/* urb is now available */
-	purb->status = USB_ST_NOERROR;
+	purb->status = 0;
 
 	/* If it was the speed URB, allow the stack to send more packets */
 	if(purb == &self->speed_urb) {
@@ -372,7 +372,7 @@
 		}
 	}
 
-	if (purb->status != USB_ST_NOERROR) {
+	if (purb->status != 0) {
 		WARNING(__FUNCTION__ "(), URB still in use!\n");
 		dev_kfree_skb(skb);
 		return 0;
@@ -490,7 +490,7 @@
 	purb->context = NULL;
 
 	/* Check for timeout and other USB nasties */
-	if(purb->status != USB_ST_NOERROR) {
+	if (purb->status != 0) {
 		/* I get a lot of -ECONNABORTED = -103 here - Jean II */
 		IRDA_DEBUG(0, __FUNCTION__ "(), URB complete status %d, transfer_flags 0x%04X\n", purb->status, purb->transfer_flags);
 
@@ -504,7 +504,7 @@
 	}
 
 	/* urb is now available */
-	purb->status = USB_ST_NOERROR;
+	purb->status = 0;
 
 	/* If the network is closed, stop everything */
 	if ((!self->netopen) || (!self->present)) {
@@ -547,11 +547,11 @@
 
 	/* Check speed URB */
 	purb = &(self->speed_urb);
-	if (purb->status != USB_ST_NOERROR) {
+	if (purb->status != 0) {
 		IRDA_DEBUG(0, "%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
 
 		switch (purb->status) {
-		case USB_ST_URB_PENDING:	/* -EINPROGRESS == -115 */
+		case -EINPROGRESS:
 			usb_unlink_urb(purb);
 			/* Note : above will  *NOT* call netif_wake_queue()
 			 * in completion handler, we will come back here.
@@ -563,7 +563,7 @@
 		case -ETIMEDOUT:		/* -110 */
 		case -ENOENT:			/* -2 (urb unlinked by us)  */
 		default:			/* ??? - Play safe */
-			purb->status = USB_ST_NOERROR;
+			purb->status = 0;
 			netif_wake_queue(self->netdev);
 			done = 1;
 			break;
@@ -572,7 +572,7 @@
 
 	/* Check Tx URB */
 	purb = &(self->tx_urb);
-	if (purb->status != USB_ST_NOERROR) {
+	if (purb->status != 0) {
 		struct sk_buff *skb = purb->context;
 
 		IRDA_DEBUG(0, "%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, purb->status, purb->transfer_flags);
@@ -590,7 +590,7 @@
 #endif /* IU_BUG_KICK_TIMEOUT */
 
 		switch (purb->status) {
-		case USB_ST_URB_PENDING:	/* -EINPROGRESS == -115 */
+		case -EINPROGRESS:
 			usb_unlink_urb(purb);
 			/* Note : above will  *NOT* call netif_wake_queue()
 			 * in completion handler, because purb->status will
@@ -610,7 +610,7 @@
 				dev_kfree_skb_any(skb);
 				purb->context = NULL;
 			}
-			purb->status = USB_ST_NOERROR;
+			purb->status = 0;
 			netif_wake_queue(self->netdev);
 			done = 1;
 			break;
@@ -727,7 +727,7 @@
 	purb->transfer_flags = USB_QUEUE_BULK;
 	/* Note : unlink *must* be synchronous because of the code in 
 	 * irda_usb_net_close() -> free the skb - Jean II */
-	purb->status = USB_ST_NOERROR;
+	purb->status = 0;
 	purb->next = NULL;	/* Don't auto resubmit URBs */
 	
 	ret = usb_submit_urb(purb);
@@ -768,9 +768,9 @@
 	}
 	
 	/* Check the status */
-	if(purb->status != USB_ST_NOERROR) {
+	if (purb->status != 0) {
 		switch (purb->status) {
-		case USB_ST_CRC:		/* -EILSEQ */
+		case -EILSEQ:
 			self->stats.rx_errors++;
 			self->stats.rx_crc_errors++;	
 			break;
@@ -1442,9 +1442,9 @@
 	ret = usb_set_interface(dev, ifnum, 0);
 	IRDA_DEBUG(1, "usb-irda: set interface %d result %d\n", ifnum, ret);
 	switch (ret) {
-		case USB_ST_NOERROR:		/* 0 */
+		case 0:
 			break;
-		case USB_ST_STALL:		/* -EPIPE = -32 */
+		case -EPIPE:		/* -EPIPE = -32 */
 			usb_clear_halt(dev, usb_sndctrlpipe(dev, 0));
 			IRDA_DEBUG(0, __FUNCTION__ "(), Clearing stall on control interface\n" );
 			break;
diff -u --recursive --new-file v2.5.0/linux/drivers/net/irda/vlsi_ir.c linux/drivers/net/irda/vlsi_ir.c
--- v2.5.0/linux/drivers/net/irda/vlsi_ir.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/net/irda/vlsi_ir.c	Fri Nov 30 13:25:10 2001
@@ -2,7 +2,7 @@
  *
  *	vlsi_ir.c:	VLSI82C147 PCI IrDA controller driver for Linux
  *
- *	Version:	0.3, Sep 30, 2001
+ *	Version:	0.3a, Nov 10, 2001
  *
  *	Copyright (c) 2001 Martin Diehl
  *
@@ -490,7 +490,7 @@
 	if (mode == IFF_FIR)
 		config ^= IRENABLE_FIR_ON;
 	else if (mode == IFF_MIR)
-		config ^= (IRENABLE_FIR_ON|IRENABLE_CRC16_ON);
+		config ^= (IRENABLE_MIR_ON|IRENABLE_CRC16_ON);
 	else
 		config ^= IRENABLE_SIR_ON;
 
@@ -877,6 +877,7 @@
 	idev->irlap = irlap_open(ndev,&idev->qos,hwname);
 
 	netif_start_queue(ndev);
+	outw(0, ndev->base_addr+VLSI_PIO_PROMPT);	/* kick hw state machine */
 
 	printk(KERN_INFO "%s: device %s operational using (%d,%d) tx,rx-ring\n",
 		__FUNCTION__, ndev->name, ringsize[0], ringsize[1]);
@@ -1200,7 +1201,6 @@
 	int			alloc_size;
 
 
-	vlsi_reg_debug(0x3000, "vlsi initial state");
 	if (pci_enable_device(pdev))
 		goto out;
 
diff -u --recursive --new-file v2.5.0/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c
--- v2.5.0/linux/drivers/net/ppp_generic.c	Thu Oct 11 09:18:31 2001
+++ linux/drivers/net/ppp_generic.c	Fri Nov 30 08:26:04 2001
@@ -325,7 +325,6 @@
 {
 	struct ppp_file *pf = (struct ppp_file *) file->private_data;
 
-	lock_kernel();
 	if (pf != 0) {
 		file->private_data = 0;
 		if (atomic_dec_and_test(&pf->refcnt)) {
@@ -339,7 +338,6 @@
 			}
 		}
 	}
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.5.0/linux/drivers/net/smc-ultra.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/smc-ultra.c	Sun Nov 25 09:43:42 2001
@@ -80,7 +80,7 @@
 int ultra_probe(struct net_device *dev);
 static int ultra_probe1(struct net_device *dev, int ioaddr);
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 static int ultra_probe_isapnp(struct net_device *dev);
 #endif
 
@@ -100,7 +100,7 @@
 							 const unsigned char *buf, const int start_page);
 static int ultra_close_card(struct net_device *dev);
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 static struct isapnp_device_id ultra_device_ids[] __initdata = {
         {       ISAPNP_VENDOR('S','M','C'), ISAPNP_FUNCTION(0x8416),
                 ISAPNP_VENDOR('S','M','C'), ISAPNP_FUNCTION(0x8416),
@@ -140,7 +140,7 @@
 	else if (base_addr != 0)	/* Don't probe at all. */
 		return -ENXIO;
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	/* Look for any installed ISAPnP cards */
 	if (isapnp_present() && (ultra_probe_isapnp(dev) == 0))
 		return 0;
@@ -279,7 +279,7 @@
 	return retval;
 }
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 static int __init ultra_probe_isapnp(struct net_device *dev)
 {
         int i;
@@ -544,7 +544,7 @@
 			/* NB: ultra_close_card() does free_irq */
 			int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 			struct pci_dev *idev = (struct pci_dev *)ei_status.priv;
 			if (idev)
 				idev->deactivate(idev);
diff -u --recursive --new-file v2.5.0/linux/drivers/net/tlan.c linux/drivers/net/tlan.c
--- v2.5.0/linux/drivers/net/tlan.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/net/tlan.c	Tue Nov 27 09:23:27 2001
@@ -2265,8 +2265,8 @@
 				printk("TLAN: Partner capability: ");
 					for (i = 5; i <= 10; i++)
 						if (partner & (1<<i))
-							printk("%s", media[i-5]);
-							printk("\n");
+							printk("%s",media[i-5]);
+				printk("\n");
 			}
 
 			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
diff -u --recursive --new-file v2.5.0/linux/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c
--- v2.5.0/linux/drivers/net/wan/cosa.c	Thu Sep 13 16:04:43 2001
+++ linux/drivers/net/wan/cosa.c	Fri Nov 30 08:26:04 2001
@@ -974,13 +974,11 @@
 	struct cosa_data *cosa;
 	unsigned long flags;
 
-	lock_kernel();
 	cosa = channel->cosa;
 	spin_lock_irqsave(&cosa->lock, flags);
 	cosa->usage--;
 	channel->usage--;
 	spin_unlock_irqrestore(&cosa->lock, flags);
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c
--- v2.5.0/linux/drivers/pci/setup-res.c	Thu Oct  4 18:47:08 2001
+++ linux/drivers/pci/setup-res.c	Mon Nov 26 14:23:58 2001
@@ -219,9 +219,8 @@
 		cmd |= PCI_COMMAND_IO;
 	}
 
-	/* ??? Always turn on bus mastering.  If the device doesn't support
-	   it, the bit will go into the bucket. */
-	cmd |= PCI_COMMAND_MASTER;
+	/* Do not enable bus mastering.  A device could corrupt
+	 * system memory by DMAing before a driver is ready for it. */
 
 	/* Set the cache line and default latency (32).  */
 	pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
diff -u --recursive --new-file v2.5.0/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- v2.5.0/linux/drivers/pcmcia/ds.c	Mon Nov 12 09:39:01 2001
+++ linux/drivers/pcmcia/ds.c	Fri Nov 30 08:26:04 2001
@@ -597,7 +597,6 @@
     DEBUG(0, "ds_release(socket %d)\n", i);
     if ((i >= sockets) || (sockets == 0))
 	return 0;
-    lock_kernel();
     s = &socket_table[i];
     user = file->private_data;
     if (CHECK_USER(user))
@@ -615,7 +614,6 @@
     user->user_magic = 0;
     kfree(user);
 out:
-    unlock_kernel();
     return 0;
 } /* ds_release */
 
diff -u --recursive --new-file v2.5.0/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- v2.5.0/linux/drivers/pcmcia/i82365.c	Mon Nov 12 09:39:01 2001
+++ linux/drivers/pcmcia/i82365.c	Sun Nov 25 09:43:42 2001
@@ -813,11 +813,7 @@
 
 #ifdef CONFIG_ISA
 
-#if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
-#define I82365_ISAPNP
-#endif
-
-#ifdef I82365_ISAPNP
+#ifdef __ISAPNP__
 static struct isapnp_device_id id_table[] __initdata = {
 	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
 		ISAPNP_FUNCTION(0x0e00), (unsigned long) "Intel 82365-Compatible" },
@@ -836,7 +832,7 @@
 {
     int i, j, sock, k, ns, id;
     ioaddr_t port;
-#ifdef I82365_ISAPNP
+#ifdef __ISAPNP__
     struct isapnp_device_id *devid;
     struct pci_dev *dev;
 
@@ -1647,7 +1643,7 @@
 	i365_set(i, I365_CSCINT, 0);
 	release_region(socket[i].ioaddr, 2);
     }
-#if defined(CONFIG_ISA) && defined(I82365_ISAPNP)
+#if defined(CONFIG_ISA) && defined(__ISAPNP__)
     if (i82365_pnpdev && i82365_pnpdev->deactivate)
 		i82365_pnpdev->deactivate(i82365_pnpdev);
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c
--- v2.5.0/linux/drivers/pnp/isapnp_proc.c	Wed Jan 17 13:29:14 2001
+++ linux/drivers/pnp/isapnp_proc.c	Fri Nov 30 08:26:04 2001
@@ -170,12 +170,10 @@
 		kfree(buffer);
 		return -ENOMEM;
 	}
-	lock_kernel();
 	buffer->curr = buffer->buffer;
 	file->private_data = buffer;
 	if (mode == O_RDONLY)
 		isapnp_info_read(buffer);
-	unlock_kernel();
 	return 0;
 }
 
@@ -187,12 +185,10 @@
 	if ((buffer = (isapnp_info_buffer_t *) file->private_data) == NULL)
 		return -EINVAL;
 	mode = file->f_flags & O_ACCMODE;
-	lock_kernel();
 	if (mode == O_WRONLY)
 		isapnp_info_write(buffer);
 	vfree(buffer->buffer);
 	kfree(buffer);
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c
--- v2.5.0/linux/drivers/s390/block/dasd.c	Fri Nov  9 14:05:02 2001
+++ linux/drivers/s390/block/dasd.c	Sat Dec  8 20:02:47 2001
@@ -730,13 +730,6 @@
 		goto out_hardsect_size;
 	memset (hardsect_size[major], 0, (1 << MINORBITS) * sizeof (int));
 
-        /* init max_sectors */
-	max_sectors[major] =
-	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);
-	if (!max_sectors[major])
-		goto out_max_sectors;
-	memset (max_sectors[major], 0, (1 << MINORBITS) * sizeof (int));
-
 	/* finally do the gendisk stuff */
 	major_info->gendisk.part = kmalloc ((1 << MINORBITS) *
 					    sizeof (struct hd_struct),
@@ -755,10 +748,6 @@
 
         /* error handling - free the prior allocated memory */  
       out_gendisk:
-	kfree (max_sectors[major]);
-	max_sectors[major] = NULL;
-
-      out_max_sectors:
 	kfree (hardsect_size[major]);
 	hardsect_size[major] = NULL;
 
@@ -825,12 +814,8 @@
 	kfree (blk_size[major]);
 	kfree (blksize_size[major]);
 	kfree (hardsect_size[major]);
-	kfree (max_sectors[major]);
 
-	blk_size[major]      = NULL;
-	blksize_size[major]  = NULL;
-	hardsect_size[major] = NULL;
-	max_sectors[major]   = NULL;
+	blk_clear(major);
 
 	rc = devfs_unregister_blkdev (major, DASD_NAME);
 	if (rc < 0) {
@@ -1704,10 +1689,6 @@
                                 dasd_end_request (req, 0);
                                 dasd_dequeue_request (queue,req);
                         } else {
-                            /* relocate request according to partition table */
-                            req->sector +=
-                                device->major_info->gendisk.
-                                part[MINOR (req->rq_dev)].start_sect;
                             cqr = device->discipline->build_cp_from_req (device, req);
                             if (cqr == NULL) {
 
@@ -1716,10 +1697,7 @@
                                                              "on request %p\n",
                                                              device->devinfo.devno,
                                                              req);
-                                    /* revert relocation of request */
-                                    req->sector -=
-                                        device->major_info->gendisk.
-                                        part[MINOR (req->rq_dev)].start_sect;
+
                                     break;	/* terminate request queue loop */
                                     
                             }
@@ -1769,10 +1747,10 @@
 dasd_run_bh (dasd_device_t * device)
 {
 	long flags;
-	spin_lock_irqsave (&io_request_lock, flags);
+	spin_lock_irqsave (&device->request_queue.queue_lock, flags);
 	atomic_set (&device->bh_scheduled, 0);
 	dasd_process_queues (device);
-	spin_unlock_irqrestore (&io_request_lock, flags);
+	spin_unlock_irqrestore (&device->request_queue.queue_lock, flags);
 }
 
 /*
@@ -2468,14 +2446,12 @@
 			dasd_info.chanq_len = 0;
 			if (device->request_queue->request_fn) {
 				struct list_head *l;
+				request_queue_t *q = drive->request_queue;
 				ccw_req_t *cqr = device->queue.head;
-				spin_lock_irqsave (&io_request_lock, flags);
-				list_for_each (l,
-					       &device->request_queue->
-					       queue_head) {
+				spin_lock_irqsave (&q->queue_lock, flags);
+				list_for_each (l, q->queue_head, queue_head)
 					dasd_info.req_queue_len++;
-				}
-				spin_unlock_irqrestore (&io_request_lock,
+				spin_unlock_irqrestore (&q->queue_lock,
 							flags);
 				s390irq_spin_lock_irqsave (device->devinfo.irq,
 							   flags);
@@ -2668,7 +2644,7 @@
 
 /* SECTION: Management of device list */
 int
-dasd_fillgeo(int kdev,struct hd_geometry *geo)
+dasd_fillgeo(kdev_t kdev,struct hd_geometry *geo)
 {
 	dasd_device_t *device = dasd_device_from_kdev (kdev);
 
@@ -2679,8 +2655,7 @@
 		return -EINVAL;
 
 	device->discipline->fill_geometry (device, geo);
-	geo->start = device->major_info->gendisk.part[MINOR(kdev)].start_sect 
-		     >> device->sizes.s2b_shift;;
+	geo->start = get_start_sect(kdev);
         return 0;
 } 
 
@@ -3365,6 +3340,11 @@
         int major = MAJOR(device->kdev);
         int minor = MINOR(device->kdev);
 
+        device->request_queue = kmalloc(sizeof(request_queue_t),GFP_KERNEL);
+        device->request_queue->queuedata = device;
+        blk_init_queue (device->request_queue, do_dasd_request);
+        elevator_init (&(device->request_queue->elevator),ELEVATOR_NOOP);
+
         for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
                 if (i == 0)
                         device->major_info->gendisk.sizes[minor] =
@@ -3374,17 +3354,11 @@
                         device->major_info->gendisk.sizes[minor + i] = 0;
                 hardsect_size[major][minor + i] = device->sizes.bp_block;
                 blksize_size[major][minor + i] = device->sizes.bp_block;
-                max_sectors[major][minor + i] =
-                        device->discipline->max_blocks << 
-                        device->sizes.s2b_shift;
+		blk_queue_max_sectors(device->request_queue,
+		 device->discipline->max_blocks << device->sizes.s2b_shift);
 		device->major_info->gendisk.part[minor+i].start_sect = 0;
 		device->major_info->gendisk.part[minor+i].nr_sects = 0;
         }
-        device->request_queue = kmalloc(sizeof(request_queue_t),GFP_KERNEL);
-        device->request_queue->queuedata = device;
-        blk_init_queue (device->request_queue, do_dasd_request);
-        blk_queue_headactive (device->request_queue, 0);
-        elevator_init (&(device->request_queue->elevator),ELEVATOR_NOOP);
         return rc;
 }
 
@@ -3411,7 +3385,6 @@
                 device->major_info->gendisk.sizes[minor + i] = 0;
                 hardsect_size[major][minor + i] = 0;
                 blksize_size[major][minor + i] = 0;
-                max_sectors[major][minor + i] = 0;
         }
         if (device->request_queue) {
             blk_cleanup_queue (device->request_queue);
diff -u --recursive --new-file v2.5.0/linux/drivers/s390/block/xpram.c linux/drivers/s390/block/xpram.c
--- v2.5.0/linux/drivers/s390/block/xpram.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/s390/block/xpram.c	Sat Dec  8 20:02:47 2001
@@ -1041,7 +1041,6 @@
 #elif (XPRAM_VERSION == 24)
 	q = BLK_DEFAULT_QUEUE (major);
 	blk_init_queue (q, xpram_request);
-	blk_queue_headactive (BLK_DEFAULT_QUEUE (major), 0);
 #endif /* V22/V24 */
 	read_ahead[major] = xpram_rahead;
 
@@ -1213,8 +1212,7 @@
 {
 	int i;
 
-				/* first of all, flush it all and reset all the data structures */
-
+	/* first of all, flush it all and reset all the data structures */
 
 	for (i=0; i<xpram_devs; i++)
 		fsync_dev(MKDEV(xpram_major, i)); /* flush the devices */
@@ -1222,13 +1220,10 @@
 #if (XPRAM_VERSION == 22)
 	blk_dev[major].request_fn = NULL;
 #endif /* V22 */
-	read_ahead[major] = 0;
-	blk_size[major] = NULL;
 	kfree(blksize_size[major]);
-	blksize_size[major] = NULL;
 	kfree(hardsect_size[major]);
-	hardsect_size[major] = NULL;
 	kfree(xpram_offsets);
+	blk_clear(major);
 
 				/* finally, the usual cleanup */
 #if (XPRAM_VERSION == 22)
diff -u --recursive --new-file v2.5.0/linux/drivers/s390/char/tapeblock.c linux/drivers/s390/char/tapeblock.c
--- v2.5.0/linux/drivers/s390/char/tapeblock.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/s390/char/tapeblock.c	Sat Dec  8 20:02:47 2001
@@ -77,7 +77,6 @@
     blksize_size[tapeblock_major][ti->blk_minor]=2048; // blocks are 2k by default.
     hardsect_size[tapeblock_major][ti->blk_minor]=512;
     blk_init_queue (&ti->request_queue, tape_request_fn); 
-    blk_queue_headactive (&ti->request_queue, 0); 
 #ifdef CONFIG_DEVFS_FS
     tapeblock_mkdevfstree(ti);
 #endif
@@ -366,12 +365,14 @@
 static void
 run_tapeblock_exec_IO (tape_info_t* ti) {
     long flags_390irq,flags_ior;
-    spin_lock_irqsave (&io_request_lock, flags_ior);
+    request_queue_t *q = &tape->request_queue;
+
+    spin_lock_irqsave (&q->queue_lock, flags_ior);
     s390irq_spin_lock_irqsave(ti->devinfo.irq,flags_390irq);
     atomic_set(&ti->bh_scheduled,0);
     tapeblock_exec_IO(ti);
     s390irq_spin_unlock_irqrestore(ti->devinfo.irq,flags_390irq);
-    spin_unlock_irqrestore (&io_request_lock, flags_ior);
+    spin_unlock_irqrestore (&q->queue_lock, flags_ior);
 }
 
 void
diff -u --recursive --new-file v2.5.0/linux/drivers/sbus/char/jsflash.c linux/drivers/sbus/char/jsflash.c
--- v2.5.0/linux/drivers/sbus/char/jsflash.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/sbus/char/jsflash.c	Sat Dec  8 20:02:47 2001
@@ -662,7 +662,6 @@
 	blk_size[JSFD_MAJOR] = jsfd_sizes;
 
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
-	/* blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0); */
 	for (i = 0; i < JSF_MAX; i++) {
 		if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
 		jsf = &jsf0;	/* actually, &jsfv[i >> JSF_PART_BITS] */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/3w-xxxx.h linux/drivers/scsi/3w-xxxx.h
--- v2.5.0/linux/drivers/scsi/3w-xxxx.h	Fri Nov  9 14:05:02 2001
+++ linux/drivers/scsi/3w-xxxx.h	Wed Nov 28 10:22:27 2001
@@ -461,7 +461,6 @@
 	present : 0,					\
 	unchecked_isa_dma : 0,				\
 	use_clustering : ENABLE_CLUSTERING,		\
- 	use_new_eh_code : 1,				\
 	emulated : 1					\
 }
 #endif /* _3W_XXXX_H */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v2.5.0/linux/drivers/scsi/53c7,8xx.c	Thu Oct 25 13:53:48 2001
+++ linux/drivers/scsi/53c7,8xx.c	Mon Nov 26 14:23:58 2001
@@ -1427,13 +1427,14 @@
 	return -1;
     }
 
-#ifdef __powerpc__
     if ( ! (command & PCI_COMMAND_MASTER)) {
-      printk("SCSI: PCI Master Bit has not been set. Setting...\n");
+      printk(KERN_INFO "SCSI: PCI Master Bit has not been set. Setting...\n");
       command |= PCI_COMMAND_MASTER|PCI_COMMAND_IO;
       pci_write_config_word(pdev, PCI_COMMAND, command);
+    }
 
-      if (io_port >= 0x10000000 && is_prep ) {
+#ifdef __powerpc__
+    if (io_port >= 0x10000000 && is_prep ) {
 	      /* Mapping on PowerPC can't handle this! */
 	      unsigned long new_io_port;
 	      new_io_port = (io_port & 0x00FFFFFF) | 0x01000000;
@@ -1441,7 +1442,6 @@
 	      io_port = new_io_port;
 	      pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, io_port);
 	      pdev->base_address[0] = io_port;
-      }
     }
 #endif
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/53c700.c linux/drivers/scsi/53c700.c
--- v2.5.0/linux/drivers/scsi/53c700.c	Thu Oct 11 09:43:29 2001
+++ linux/drivers/scsi/53c700.c	Wed Nov 28 10:22:27 2001
@@ -267,7 +267,6 @@
 	tpnt->sg_tablesize = NCR_700_SG_SEGMENTS;
 	tpnt->cmd_per_lun = NCR_700_MAX_TAGS;
 	tpnt->use_clustering = DISABLE_CLUSTERING;
-	tpnt->use_new_eh_code = 1;
 	tpnt->proc_info = NCR_700_proc_directory_info;
 	
 	if(tpnt->name == NULL)
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.5.0/linux/drivers/scsi/Config.in	Fri Nov  9 15:22:54 2001
+++ linux/drivers/scsi/Config.in	Tue Nov 27 09:23:27 2001
@@ -20,10 +20,6 @@
 
 comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
 
-#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   bool '  Enable extra checks in new queueing code' CONFIG_SCSI_DEBUG_QUEUES
-#fi
-
 bool '  Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
   
 bool '  Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.5.0/linux/drivers/scsi/Makefile	Wed Nov 21 09:59:11 2001
+++ linux/drivers/scsi/Makefile	Wed Nov 28 10:22:27 2001
@@ -133,11 +133,9 @@
 obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
 
 list-multi	:= scsi_mod.o sd_mod.o sr_mod.o initio.o a100u2w.o cpqfc.o
-scsi_mod-objs	:= scsi.o hosts.o scsi_ioctl.o constants.o \
-			scsicam.o scsi_proc.o scsi_error.o \
-			scsi_obsolete.o scsi_queue.o scsi_lib.o \
-			scsi_merge.o scsi_dma.o scsi_scan.o \
-			scsi_syms.o
+scsi_mod-objs	:= scsi.o hosts.o scsi_ioctl.o constants.o scsicam.o \
+			scsi_proc.o scsi_error.o scsi_queue.o scsi_lib.o \
+			scsi_merge.o scsi_dma.o scsi_scan.o scsi_syms.o
 sd_mod-objs	:= sd.o
 sr_mod-objs	:= sr.o sr_ioctl.o sr_vendor.o
 initio-objs	:= ini9100u.o i91uscsi.o
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/advansys.h linux/drivers/scsi/advansys.h
--- v2.5.0/linux/drivers/scsi/advansys.h	Thu Jul 19 21:07:47 2001
+++ linux/drivers/scsi/advansys.h	Wed Nov 28 10:22:27 2001
@@ -77,7 +77,6 @@
     release:                    advansys_release, \
     info:                       advansys_info, \
     queuecommand:               advansys_queuecommand, \
-    use_new_eh_code:		1, \
     eh_bus_reset_handler:	advansys_reset, \
     bios_param:                 advansys_biosparam, \
     /* \
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/aha152x.h linux/drivers/scsi/aha152x.h
--- v2.5.0/linux/drivers/scsi/aha152x.h	Thu Jul 19 21:08:07 2001
+++ linux/drivers/scsi/aha152x.h	Thu Nov 29 13:58:14 2001
@@ -49,8 +49,7 @@
                   cmd_per_lun:			1,			\
                   present:			0,			\
                   unchecked_isa_dma:		0,			\
-                  use_clustering:		DISABLE_CLUSTERING,	\
-		  use_new_eh_code:		1 }
+                  use_clustering:		DISABLE_CLUSTERING }
 #endif
 
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/aha1542.h linux/drivers/scsi/aha1542.h
--- v2.5.0/linux/drivers/scsi/aha1542.h	Thu Jul 19 21:08:11 2001
+++ linux/drivers/scsi/aha1542.h	Wed Nov 28 10:22:27 2001
@@ -166,7 +166,6 @@
 		     sg_tablesize:		AHA1542_SCATTER, 	\
 		     cmd_per_lun:		AHA1542_CMDLUN, 	\
 		     unchecked_isa_dma:		1, 			\
-		     use_clustering:		ENABLE_CLUSTERING,	\
-		     use_new_eh_code:		1}
-
+		     use_clustering:		ENABLE_CLUSTERING	\
+}
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c linux/drivers/scsi/aic7xxx/aic7xxx_linux.c
--- v2.5.0/linux/drivers/scsi/aic7xxx/aic7xxx_linux.c	Wed Nov 21 14:05:29 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux.c	Tue Nov 27 09:23:27 2001
@@ -1123,9 +1123,9 @@
 	if (host == NULL)
 		return (ENOMEM);
 
-	ahc_lock(ahc, &s);
 	*((struct ahc_softc **)host->hostdata) = ahc;
 	ahc->platform_data->host = host;
+	ahc_lock(ahc, &s);
 	host->can_queue = AHC_MAX_QUEUE;
 	host->cmd_per_lun = 2;
 	host->sg_tablesize = AHC_NSEG;
@@ -1272,7 +1272,9 @@
 	TAILQ_INIT(&ahc->platform_data->completeq);
 	TAILQ_INIT(&ahc->platform_data->device_runq);
 	ahc->platform_data->hw_dma_mask = 0xFFFFFFFF;
-	ahc_lockinit(ahc);
+	/*
+	 * ahc_lockinit done by scsi_register, as we don't own that lock
+	 */
 	ahc_done_lockinit(ahc);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
 	init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
@@ -1530,22 +1532,17 @@
 int
 ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
 {
-	struct	 ahc_softc *ahc;
+	struct	 ahc_softc *ahc = *(struct ahc_softc **)cmd->host->hostdata;
 	struct	 ahc_linux_device *dev;
-	u_long	 flags;
-
-	ahc = *(struct ahc_softc **)cmd->host->hostdata;
 
 	/*
 	 * Save the callback on completion function.
 	 */
 	cmd->scsi_done = scsi_done;
 
-	ahc_lock(ahc, &flags);
 	dev = ahc_linux_get_device(ahc, cmd->channel, cmd->target,
 				   cmd->lun, /*alloc*/TRUE);
 	if (dev == NULL) {
-		ahc_unlock(ahc, &flags);
 		printf("aic7xxx_linux_queue: Unable to allocate device!\n");
 		return (-ENOMEM);
 	}
@@ -1556,7 +1553,6 @@
 		dev->flags |= AHC_DEV_ON_RUN_LIST;
 		ahc_linux_run_device_queues(ahc);
 	}
-	ahc_unlock(ahc, &flags);
 	return (0);
 }
 
@@ -2408,12 +2404,10 @@
 	       flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");
 
 	/*
-	 * It is a bug that the upper layer takes
-	 * this lock just prior to calling us.
+	 * we used to drop io_request_lock and lock ahc from here, but
+	 * now that the global lock is gone the upper layer have already
+	 * done what ahc_lock would do /jens
 	 */
-	spin_unlock_irq(&io_request_lock);
-
-	ahc_lock(ahc, &s);
 
 	/*
 	 * First determine if we currently own this command.
@@ -2661,7 +2655,7 @@
 	ahc_unlock(ahc, &s);
 	if (acmd != NULL)
 		ahc_linux_run_complete_queue(ahc, acmd);
-	spin_lock_irq(&io_request_lock);
+	ahc_lock(ahc, &s);
 	return (retval);
 }
 
@@ -2704,14 +2698,7 @@
 	u_long s;
 	int    found;
 
-	/*
-	 * It is a bug that the upper layer takes
-	 * this lock just prior to calling us.
-	 */
-	spin_unlock_irq(&io_request_lock);
-
 	ahc = *(struct ahc_softc **)cmd->host->hostdata;
-	ahc_lock(ahc, &s);
 	found = ahc_reset_channel(ahc, cmd->channel + 'A',
 				  /*initiate reset*/TRUE);
 	acmd = TAILQ_FIRST(&ahc->platform_data->completeq);
@@ -2724,7 +2711,7 @@
 	if (acmd != NULL)
 		ahc_linux_run_complete_queue(ahc, acmd);
 
-	spin_lock_irq(&io_request_lock);
+	ahc_lock(ahc, &s);
 	return SUCCESS;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h
--- v2.5.0/linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h	Thu Oct 25 13:53:49 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h	Wed Nov 28 10:22:27 2001
@@ -89,7 +89,7 @@
 	present: 0,		/* number of 7xxx's present   */\
 	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
 	use_clustering: ENABLE_CLUSTERING,			\
-	use_new_eh_code: 1					\
+	highmem_io: 1						\
 }
 
 #endif /* _AIC7XXX_LINUX_HOST_H_ */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h linux/drivers/scsi/aic7xxx/aic7xxx_osm.h
--- v2.5.0/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h	Thu Oct 25 13:53:49 2001
+++ linux/drivers/scsi/aic7xxx/aic7xxx_osm.h	Tue Nov 27 09:23:27 2001
@@ -575,9 +575,6 @@
 	TAILQ_HEAD(, ahc_linux_device) device_runq;
 	struct ahc_completeq	 completeq;
 
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
-	spinlock_t		 spin_lock;
-#endif
 	u_int			 qfrozen;
 	struct timer_list	 reset_timer;
 	struct semaphore	 eh_sem;
@@ -716,20 +713,20 @@
 static __inline void
 ahc_lockinit(struct ahc_softc *ahc)
 {
-	spin_lock_init(&ahc->platform_data->spin_lock);
+	spin_lock_init(&ahc->platform_data->host->host_lock);
 }
 
 static __inline void
 ahc_lock(struct ahc_softc *ahc, unsigned long *flags)
 {
 	*flags = 0;
-	spin_lock_irqsave(&ahc->platform_data->spin_lock, *flags);
+	spin_lock_irqsave(&ahc->platform_data->host->host_lock, *flags);
 }
 
 static __inline void
 ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
 {
-	spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags);
+	spin_unlock_irqrestore(&ahc->platform_data->host->host_lock, *flags);
 }
 
 static __inline void
@@ -741,14 +738,18 @@
 static __inline void
 ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags)
 {
+	struct Scsi_Host *host = ahc->platform_data->host;
+
 	*flags = 0;
-	spin_lock_irqsave(&io_request_lock, *flags);
+	spin_lock_irqsave(&host->host_lock, *flags);
 }
 
 static __inline void
 ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags)
 {
-	spin_unlock_irqrestore(&io_request_lock, *flags);
+	struct Scsi_Host *host = ahc->platform_data->host;
+
+	spin_unlock_irqrestore(&host->host_lock, *flags);
 }
 
 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/aic7xxx_old/aic7xxx.h linux/drivers/scsi/aic7xxx_old/aic7xxx.h
--- v2.5.0/linux/drivers/scsi/aic7xxx_old/aic7xxx.h	Sun Mar  4 14:30:18 2001
+++ linux/drivers/scsi/aic7xxx_old/aic7xxx.h	Wed Nov 28 10:22:27 2001
@@ -55,7 +55,6 @@
 	present: 0,		/* number of 7xxx's present   */\
 	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
 	use_clustering: ENABLE_CLUSTERING,			\
-	use_new_eh_code: 0					\
 }
 
 extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/aic7xxx_old.c linux/drivers/scsi/aic7xxx_old.c
--- v2.5.0/linux/drivers/scsi/aic7xxx_old.c	Wed Nov 21 14:05:29 2001
+++ linux/drivers/scsi/aic7xxx_old.c	Tue Nov 27 09:23:27 2001
@@ -4127,7 +4127,7 @@
   unsigned long cpu_flags = 0;
   struct aic7xxx_scb *scb;
 
-  spin_lock_irqsave(&io_request_lock, cpu_flags);
+  spin_lock_irqsave(&p->host->host_lock, cpu_flags);
   p->dev_timer_active &= ~(0x01 << MAX_TARGETS);
   if ( (p->dev_timer_active & (0x01 << p->scsi_id)) &&
        time_after_eq(jiffies, p->dev_expires[p->scsi_id]) )
@@ -4184,7 +4184,7 @@
   }
 
   aic7xxx_run_waiting_queues(p);
-  spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+  spin_unlock_irqrestore(&p->host->host_lock, cpu_flags);
 }
 
 /*+F*************************************************************************
@@ -7011,7 +7011,7 @@
   p = (struct aic7xxx_host *)dev_id;
   if(!p)
     return;
-  spin_lock_irqsave(&io_request_lock, cpu_flags);
+  spin_lock_irqsave(&p->host->host_lock, cpu_flags);
   p->flags |= AHC_IN_ISR;
   do
   {
@@ -7020,7 +7020,7 @@
   aic7xxx_done_cmds_complete(p);
   aic7xxx_run_waiting_queues(p);
   p->flags &= ~AHC_IN_ISR;
-  spin_unlock_irqrestore(&io_request_lock, cpu_flags);
+  spin_unlock_irqrestore(&p->host->host_lock, cpu_flags);
 }
 
 /*+F*************************************************************************
@@ -11148,7 +11148,7 @@
   disable_irq(p->irq);
   aic7xxx_print_card(p);
   aic7xxx_print_scratch_ram(p);
-  spin_unlock_irq(&io_request_lock);
+  spin_unlock_irq(&p->host->host_lock);
   for(;;) barrier();
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/atp870u.h linux/drivers/scsi/atp870u.h
--- v2.5.0/linux/drivers/scsi/atp870u.h	Thu Jul 19 21:08:56 2001
+++ linux/drivers/scsi/atp870u.h	Wed Nov 28 10:22:27 2001
@@ -65,7 +65,6 @@
 	present: 0,		/* number of 7xxx's present   */\
 	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
 	use_clustering: ENABLE_CLUSTERING,			\
-	use_new_eh_code: 0					\
 }
 
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/cpqfc.Readme linux/drivers/scsi/cpqfc.Readme
--- v2.5.0/linux/drivers/scsi/cpqfc.Readme	Thu Oct 25 13:53:50 2001
+++ linux/drivers/scsi/cpqfc.Readme	Mon Dec 10 14:18:02 2001
@@ -7,6 +7,11 @@
 SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc() 
 	max of 128k bytes contiguous.
 
+Ver 2.5.0  Nov 29, 2001
+   * eliminated io_request_lock.  This change makes the driver specific
+     to the 2.5.x kernels.
+   * silenced excessively noisy printks.
+
 Ver 2.1.1  Oct 18, 2001
    * reinitialize Cmnd->SCp.sent_command (used to identify commands as
      passthrus) on calling scsi_done, since the scsi mid layer does not
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/cpqfcTS.h linux/drivers/scsi/cpqfcTS.h
--- v2.5.0/linux/drivers/scsi/cpqfcTS.h	Sun Aug  5 13:12:41 2001
+++ linux/drivers/scsi/cpqfcTS.h	Wed Nov 28 10:22:27 2001
@@ -38,7 +38,6 @@
  present:                0,                      \
  unchecked_isa_dma:      0,                      \
  use_clustering:         ENABLE_CLUSTERING,      \
- use_new_eh_code:        1			 \
 }
 
 #endif /* CPQFCTS_H */ 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/cpqfcTScontrol.c linux/drivers/scsi/cpqfcTScontrol.c
--- v2.5.0/linux/drivers/scsi/cpqfcTScontrol.c	Thu Oct 25 13:53:50 2001
+++ linux/drivers/scsi/cpqfcTScontrol.c	Mon Dec 10 14:19:02 2001
@@ -97,11 +97,11 @@
   fcChip->Exchanges = NULL;
   cpqfcHBAdata->fcLQ = NULL;
   
-  printk("Allocating %u for %u Exchanges ", 
-	  (ULONG)sizeof(FC_EXCHANGES), TACH_MAX_XID);
+  /* printk("Allocating %u for %u Exchanges ", 
+	  (ULONG)sizeof(FC_EXCHANGES), TACH_MAX_XID); */
   fcChip->Exchanges = pci_alloc_consistent(cpqfcHBAdata->PciDev, 
 			sizeof(FC_EXCHANGES), &fcChip->exch_dma_handle);
-  printk("@ %p\n", fcChip->Exchanges);
+  /* printk("@ %p\n", fcChip->Exchanges); */
 
   if( fcChip->Exchanges == NULL ) // fatal error!!
   {
@@ -112,10 +112,10 @@
   memset( fcChip->Exchanges, 0, sizeof( FC_EXCHANGES));  
 
 
-  printk("Allocating %u for LinkQ ", (ULONG)sizeof(FC_LINK_QUE));
+  /* printk("Allocating %u for LinkQ ", (ULONG)sizeof(FC_LINK_QUE)); */
   cpqfcHBAdata->fcLQ = pci_alloc_consistent(cpqfcHBAdata->PciDev,
 				 sizeof( FC_LINK_QUE), &cpqfcHBAdata->fcLQ_dma_handle);
-  printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH);
+  /* printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH); */
   memset( cpqfcHBAdata->fcLQ, 0, sizeof( FC_LINK_QUE));
 
   if( cpqfcHBAdata->fcLQ == NULL ) // fatal error!!
@@ -222,8 +222,8 @@
   // power-of-2 boundary
   // LIVE DANGEROUSLY!  Assume the boundary for SEST mem will
   // be on physical page (e.g. 4k) boundary.
-  printk("Allocating %u for TachSEST for %u Exchanges\n", 
-		 (ULONG)sizeof(TachSEST), TACH_SEST_LEN);
+  /* printk("Allocating %u for TachSEST for %u Exchanges\n", 
+		 (ULONG)sizeof(TachSEST), TACH_SEST_LEN); */
   fcChip->SEST = fcMemManager( cpqfcHBAdata->PciDev,
 		  &cpqfcHBAdata->dynamic_mem[0],
 		  sizeof(TachSEST),  4, 0L, &SESTdma );
@@ -289,7 +289,7 @@
 
   // set the Host's pointer for Tachyon to access
 
-  printk("  cpqfcTS: writing IMQ BASE %Xh  ", fcChip->IMQ->base );
+  /* printk("  cpqfcTS: writing IMQ BASE %Xh  ", fcChip->IMQ->base ); */
   writel( fcChip->IMQ->base, 
     (fcChip->Registers.ReMapMemBase + IMQ_BASE));
 
@@ -315,9 +315,9 @@
     return -1;  // failed
   }
 #endif
-//#if DBG
+#if DBG
   printk("  PI %Xh\n", (ULONG)ulAddr );
-//#endif
+#endif
   writel( (ULONG)ulAddr, 
     (fcChip->Registers.ReMapMemBase + IMQ_PRODUCER_INDEX));
 
@@ -337,9 +337,9 @@
   writel( fcChip->SEST->base,
     (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE));
 
-  printk("  cpqfcTS: SEST %p(virt): Wrote base %Xh @ %p\n",
+  /* printk("  cpqfcTS: SEST %p(virt): Wrote base %Xh @ %p\n",
     fcChip->SEST, fcChip->SEST->base, 
-    fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE);
+    fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE); */
 
   writel( fcChip->SEST->length,
     (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_LENGTH));
@@ -1723,7 +1723,7 @@
 	UCHAR Minor = (UCHAR)(RevId & 0x3);
 	UCHAR Major = (UCHAR)((RevId & 0x1C) >>2);
   
-        printk("  HBA Tachyon RevId %d.%d\n", Major, Minor);
+	/* printk("  HBA Tachyon RevId %d.%d\n", Major, Minor); */
   	if( (Major == 1) && (Minor == 2) )
         {
 	  sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE66_TS12);
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/cpqfcTSinit.c linux/drivers/scsi/cpqfcTSinit.c
--- v2.5.0/linux/drivers/scsi/cpqfcTSinit.c	Thu Oct 25 13:53:50 2001
+++ linux/drivers/scsi/cpqfcTSinit.c	Mon Dec 10 14:22:21 2001
@@ -188,7 +188,7 @@
   DEBUG_PCI(printk("    IOBaseU = %x\n", 
     cpqfcHBAdata->fcChip.Registers.IOBaseU));
   
-  printk(" ioremap'd Membase: %p\n", cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
+  /* printk(" ioremap'd Membase: %p\n", cpqfcHBAdata->fcChip.Registers.ReMapMemBase); */
   
   DEBUG_PCI(printk("    SFQconsumerIndex.address = %p\n", 
     cpqfcHBAdata->fcChip.Registers.SFQconsumerIndex.address));
@@ -242,7 +242,7 @@
   cpqfcHBAdata->notify_wt = &sem;
 
   /* must unlock before kernel_thread(), for it may cause a reschedule. */
-  spin_unlock_irq(&io_request_lock);
+  spin_unlock_irq(&HostAdapter->host_lock);
   kernel_thread((int (*)(void *))cpqfcTSWorkerThread, 
                           (void *) HostAdapter, 0);
   /*
@@ -250,7 +250,7 @@
 
    */
   down (&sem);
-  spin_lock_irq(&io_request_lock);
+  spin_lock_irq(&HostAdapter->host_lock);
   cpqfcHBAdata->notify_wt = NULL;
 
   LEAVE("launch_FC_worker_thread");
@@ -312,8 +312,8 @@
       }
 
       // NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes...
-      printk(" scsi_register allocating %d bytes for FC HBA\n",
-		      (ULONG)sizeof(CPQFCHBA));
+      /* printk(" scsi_register allocating %d bytes for FC HBA\n",
+		      (ULONG)sizeof(CPQFCHBA)); */
 
       HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) );
       
@@ -403,9 +403,11 @@
       DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n",
         cpqfcHBAdata->fcChip.Registers.IOBaseU ));
 
-      
+     
+ 
       // start our kernel worker thread
 
+      spin_lock_irq(&HostAdapter->host_lock);
       launch_FCworker_thread(HostAdapter);
 
 
@@ -445,15 +447,16 @@
 	
 	unsigned long stop_time;
 
-        spin_unlock_irq(&io_request_lock);
+	spin_unlock_irq(&HostAdapter->host_lock);
 	stop_time = jiffies + 4*HZ;
         while ( time_before(jiffies, stop_time) ) 
 	  	schedule();  // (our worker task needs to run)
 
-	spin_lock_irq(&io_request_lock);
       }
       
+      spin_lock_irq(&HostAdapter->host_lock);
       NumberOfAdapters++; 
+      spin_unlock_irq(&HostAdapter->host_lock);
     } // end of while()
   }
 
@@ -1593,9 +1596,9 @@
   int retval;
   Scsi_Device *SDpnt = Cmnd->device;
   // printk("   ENTERING cpqfcTS_eh_device_reset() \n");
-  spin_unlock_irq(&io_request_lock);
+  spin_unlock_irq(&Cmnd->host->host_lock);
   retval = cpqfcTS_TargetDeviceReset( SDpnt, 0);
-  spin_lock_irq(&io_request_lock);
+  spin_lock_irq(&Cmnd->host->host_lock);
   return retval;
 }
 
@@ -1650,8 +1653,7 @@
   UCHAR IntPending;
   
   ENTER("intr_handler");
-
-  spin_lock_irqsave( &io_request_lock, flags);
+  spin_lock_irqsave( &HostAdapter->host_lock, flags);
   // is this our INT?
   IntPending = readb( cpqfcHBA->fcChip.Registers.INTPEND.address);
 
@@ -1700,7 +1702,7 @@
       }
     }      
   }
-  spin_unlock_irqrestore( &io_request_lock, flags);
+  spin_unlock_irqrestore( &HostAdapter->host_lock, flags);
   LEAVE("intr_handler");
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/cpqfcTSstructs.h linux/drivers/scsi/cpqfcTSstructs.h
--- v2.5.0/linux/drivers/scsi/cpqfcTSstructs.h	Thu Oct 25 13:53:50 2001
+++ linux/drivers/scsi/cpqfcTSstructs.h	Mon Dec 10 14:15:19 2001
@@ -32,8 +32,8 @@
 #define CPQFCTS_DRIVER_VER(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 // don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c
 #define VER_MAJOR 2
-#define VER_MINOR 1
-#define VER_SUBMINOR 1
+#define VER_MINOR 5
+#define VER_SUBMINOR 0
 
 // Macros for kernel (esp. SMP) tracing using a PCI analyzer
 // (e.g. x86).
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/cpqfcTSworker.c linux/drivers/scsi/cpqfcTSworker.c
--- v2.5.0/linux/drivers/scsi/cpqfcTSworker.c	Thu Oct 25 13:53:50 2001
+++ linux/drivers/scsi/cpqfcTSworker.c	Mon Dec 10 14:15:19 2001
@@ -227,7 +227,7 @@
     PCI_TRACE( 0x90)
     // first, take the IO lock so the SCSI upper layers can't call
     // into our _quecommand function (this also disables INTs)
-    spin_lock_irqsave( &io_request_lock, flags); // STOP _que function
+    spin_lock_irqsave( &HostAdapter->host_lock, flags); // STOP _que function
     PCI_TRACE( 0x90)
          
     CPQ_SPINLOCK_HBA( cpqfcHBAdata)
@@ -241,7 +241,7 @@
     PCI_TRACE( 0x90)
 
     // release the IO lock (and re-enable interrupts)
-    spin_unlock_irqrestore( &io_request_lock, flags);
+    spin_unlock_irqrestore( &HostAdapter->host_lock, flags);
 
     // disable OUR HBA interrupt (keep them off as much as possible
     // during error recovery)
@@ -3077,7 +3077,8 @@
   if( cpqfcHBAdata->BoardLock) // Worker Task Running?
     goto Skip;
 
-  spin_lock_irqsave( &io_request_lock, flags); // STOP _que function
+  // STOP _que function
+  spin_lock_irqsave( &cpqfcHBAdata->HostAdapter->host_lock, flags); 
 
   PCI_TRACE( 0xA8)
 
@@ -3085,7 +3086,7 @@
   cpqfcHBAdata->BoardLock = &BoardLock; // stop Linux SCSI command queuing
   
   // release the IO lock (and re-enable interrupts)
-  spin_unlock_irqrestore( &io_request_lock, flags);
+  spin_unlock_irqrestore( &cpqfcHBAdata->HostAdapter->host_lock, flags);
   
   // Ensure no contention from  _quecommand or Worker process 
   CPQ_SPINLOCK_HBA( cpqfcHBAdata)
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/dc390.h linux/drivers/scsi/dc390.h
--- v2.5.0/linux/drivers/scsi/dc390.h	Thu Jul 19 21:08:49 2001
+++ linux/drivers/scsi/dc390.h	Wed Nov 28 10:22:27 2001
@@ -64,7 +64,6 @@
    this_id:        7,					\
    sg_tablesize:   SG_ALL,				\
    cmd_per_lun:    16,					\
-   NEW_EH						\
    unchecked_isa_dma: 0,				\
    use_clustering: DISABLE_CLUSTERING			\
    }
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/dpt_i2o.c linux/drivers/scsi/dpt_i2o.c
--- v2.5.0/linux/drivers/scsi/dpt_i2o.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/dpt_i2o.c	Wed Nov 28 10:22:27 2001
@@ -178,7 +178,6 @@
 	adpt_hba* pHba;
 
 	adpt_init();
-	sht->use_new_eh_code = 1;
 
 	PINFO("Detecting Adaptec I2O RAID controllers...\n");
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/dpti.h linux/drivers/scsi/dpti.h
--- v2.5.0/linux/drivers/scsi/dpti.h	Fri Sep  7 09:28:38 2001
+++ linux/drivers/scsi/dpti.h	Wed Nov 28 10:22:27 2001
@@ -95,7 +95,6 @@
 	sg_tablesize: 0,		/* max scatter-gather cmds    */\
 	cmd_per_lun: 256,		/* cmds per lun (linked cmds) */\
 	use_clustering: ENABLE_CLUSTERING,				\
-	use_new_eh_code: 1,						\
 	proc_name: "dpt_i2o"	/* this is the name of our proc node*/	\
 }
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v2.5.0/linux/drivers/scsi/eata.h	Sat May 19 17:43:06 2001
+++ linux/drivers/scsi/eata.h	Wed Nov 28 10:22:27 2001
@@ -30,7 +30,6 @@
                 this_id:                 7,                                  \
                 unchecked_isa_dma:       1,                                  \
                 use_clustering:          ENABLE_CLUSTERING,                  \
-                use_new_eh_code:         1    /* Enable new error code */    \
              }
 
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/esp.h linux/drivers/scsi/esp.h
--- v2.5.0/linux/drivers/scsi/esp.h	Mon Sep 18 13:40:17 2000
+++ linux/drivers/scsi/esp.h	Wed Nov 28 10:22:27 2001
@@ -416,7 +416,6 @@
 		sg_tablesize:   SG_ALL,				\
 		cmd_per_lun:    1,				\
 		use_clustering: ENABLE_CLUSTERING,		\
-		use_new_eh_code: 0				\
 }
 
 /* For our interrupt engine. */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/fcal.h linux/drivers/scsi/fcal.h
--- v2.5.0/linux/drivers/scsi/fcal.h	Mon Mar 15 16:11:31 1999
+++ linux/drivers/scsi/fcal.h	Wed Nov 28 10:22:27 2001
@@ -35,7 +35,6 @@
 	sg_tablesize:		1,				\
 	cmd_per_lun:		1,				\
 	use_clustering:		ENABLE_CLUSTERING,		\
-	use_new_eh_code:	FCP_SCSI_USE_NEW_EH_CODE,	\
 	abort:			fcp_old_abort,			\
 	eh_abort_handler:	fcp_scsi_abort,			\
 	eh_device_reset_handler:fcp_scsi_dev_reset,		\
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/gdth.h linux/drivers/scsi/gdth.h
--- v2.5.0/linux/drivers/scsi/gdth.h	Fri Sep  7 09:28:37 2001
+++ linux/drivers/scsi/gdth.h	Thu Nov 29 13:55:59 2001
@@ -1059,8 +1059,7 @@
                cmd_per_lun:     GDTH_MAXC_P_L,                   \
                present:         0,                               \
                unchecked_isa_dma: 1,                             \
-               use_clustering:  ENABLE_CLUSTERING,               \
-               use_new_eh_code: 1       /* use new error code */ }    
+               use_clustering:  ENABLE_CLUSTERING }
 
 #elif LINUX_VERSION_CODE >= 0x02015F
 int gdth_bios_param(Disk *,kdev_t,int *);
@@ -1091,8 +1090,7 @@
                cmd_per_lun:     GDTH_MAXC_P_L,                   \
                present:         0,                               \
                unchecked_isa_dma: 1,                             \
-               use_clustering:  ENABLE_CLUSTERING,               \
-               use_new_eh_code: 1       /* use new error code */ }    
+               use_clustering:  ENABLE_CLUSTERING }
 
 #elif LINUX_VERSION_CODE >= 0x010300
 int gdth_bios_param(Disk *,kdev_t,int *);
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.5.0/linux/drivers/scsi/hosts.c	Thu Jul  5 11:28:17 2001
+++ linux/drivers/scsi/hosts.c	Tue Nov 27 09:23:27 2001
@@ -129,7 +129,7 @@
  * once we are 100% sure that we want to use this host adapter -  it is a
  * pain to reverse this, so we try to avoid it 
  */
-
+extern int blk_nohighio;
 struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){
     struct Scsi_Host * retval, *shpnt, *o_shp;
     Scsi_Host_Name *shn, *shn2;
@@ -160,6 +160,7 @@
 	    break;
 	}
     }
+    spin_lock_init(&retval->host_lock);
     atomic_set(&retval->host_active,0);
     retval->host_busy = 0;
     retval->host_failed = 0;
@@ -235,6 +236,8 @@
     retval->cmd_per_lun = tpnt->cmd_per_lun;
     retval->unchecked_isa_dma = tpnt->unchecked_isa_dma;
     retval->use_clustering = tpnt->use_clustering;   
+    if (!blk_nohighio)
+	retval->highmem_io = tpnt->highmem_io;
 
     retval->select_queue_depths = tpnt->select_queue_depths;
     retval->max_sectors = tpnt->max_sectors;
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.5.0/linux/drivers/scsi/hosts.h	Thu Nov 22 11:49:15 2001
+++ linux/drivers/scsi/hosts.h	Tue Dec 11 09:54:44 2001
@@ -280,17 +280,12 @@
     unsigned use_clustering:1;
 
     /*
-     * True if this driver uses the new error handling code.  This flag is
-     * really only temporary until all of the other drivers get converted
-     * to use the new error handling code.
-     */
-    unsigned use_new_eh_code:1;
-
-    /*
      * True for emulated SCSI host adapters (e.g. ATAPI)
      */
     unsigned emulated:1;
 
+    unsigned highmem_io:1;
+
     /*
      * Name of proc directory
      */
@@ -317,6 +312,7 @@
     struct Scsi_Host      * next;
     Scsi_Device           * host_queue;
 
+    spinlock_t		  host_lock;
 
     struct task_struct    * ehandler;  /* Error recovery thread. */
     struct semaphore      * eh_wait;   /* The error recovery thread waits on
@@ -390,6 +386,7 @@
     unsigned in_recovery:1;
     unsigned unchecked_isa_dma:1;
     unsigned use_clustering:1;
+    unsigned highmem_io:1;
     /*
      * True if this host was loaded as a loadable module
      */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- v2.5.0/linux/drivers/scsi/ide-scsi.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/scsi/ide-scsi.c	Tue Dec 11 09:44:13 2001
@@ -235,14 +235,14 @@
 		kfree(atapi_buf);
 }
 
-static inline void idescsi_free_bh (struct buffer_head *bh)
+static inline void idescsi_free_bio (struct bio *bio)
 {
-	struct buffer_head *bhp;
+	struct bio *bhp;
 
-	while (bh) {
-		bhp = bh;
-		bh = bh->b_reqnext;
-		kfree (bhp);
+	while (bio) {
+		bhp = bio;
+		bio = bio->bi_next;
+		bio_put(bhp);
 	}
 }
 
@@ -261,12 +261,13 @@
 	ide_drive_t *drive = hwgroup->drive;
 	idescsi_scsi_t *scsi = drive->driver_data;
 	struct request *rq = hwgroup->rq;
-	idescsi_pc_t *pc = (idescsi_pc_t *) rq->buffer;
+	idescsi_pc_t *pc = (idescsi_pc_t *) rq->special;
 	int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
+	struct Scsi_Host *host;
 	u8 *scsi_buf;
 	unsigned long flags;
 
-	if (rq->cmd != IDESCSI_PC_RQ) {
+	if (!(rq->flags & REQ_SPECIAL)) {
 		ide_end_request (uptodate, hwgroup);
 		return;
 	}
@@ -291,10 +292,11 @@
 			} else printk("\n");
 		}
 	}
-	spin_lock_irqsave(&io_request_lock,flags);	
+	host = pc->scsi_cmd->host;
+	spin_lock_irqsave(&host->host_lock, flags);
 	pc->done(pc->scsi_cmd);
-	spin_unlock_irqrestore(&io_request_lock,flags);
-	idescsi_free_bh (rq->bh);
+	spin_unlock_irqrestore(&host->host_lock, flags);
+	idescsi_free_bio (rq->bio);
 	kfree(pc); kfree(rq);
 	scsi->pc = NULL;
 }
@@ -427,7 +429,7 @@
 	pc->current_position=pc->buffer;
 	bcount = IDE_MIN (pc->request_transfer, 63 * 1024);		/* Request to transfer the entire buffer at once */
 
-	if (drive->using_dma && rq->bh)
+	if (drive->using_dma && rq->bio)
 		dma_ok=!HWIF(drive)->dmaproc(test_bit (PC_WRITING, &pc->flags) ? ide_dma_write : ide_dma_read, drive);
 
 	SELECT_DRIVE(HWIF(drive), drive);
@@ -461,10 +463,10 @@
 	printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
 #endif /* IDESCSI_DEBUG_LOG */
 
-	if (rq->cmd == IDESCSI_PC_RQ) {
-		return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->buffer);
+	if (rq->flags & REQ_SPECIAL) {
+		return idescsi_issue_pc (drive, (idescsi_pc_t *) rq->special);
 	}
-	printk (KERN_ERR "ide-scsi: %s: unsupported command in request queue (%x)\n", drive->name, rq->cmd);
+	blk_dump_rq_flags(rq, "ide-scsi: unsup command");
 	idescsi_end_request (0,HWGROUP (drive));
 	return ide_stopped;
 }
@@ -653,25 +655,26 @@
 	return -EINVAL;
 }
 
-static inline struct buffer_head *idescsi_kmalloc_bh (int count)
+static inline struct bio *idescsi_kmalloc_bio (int count)
 {
-	struct buffer_head *bh, *bhp, *first_bh;
+	struct bio *bh, *bhp, *first_bh;
 
-	if ((first_bh = bhp = bh = kmalloc (sizeof(struct buffer_head), GFP_ATOMIC)) == NULL)
+	if ((first_bh = bhp = bh = bio_alloc(GFP_ATOMIC, 1)) == NULL)
 		goto abort;
-	memset (bh, 0, sizeof (struct buffer_head));
-	bh->b_reqnext = NULL;
+	bio_init(bh);
+	bh->bi_vcnt = 1;
 	while (--count) {
-		if ((bh = kmalloc (sizeof(struct buffer_head), GFP_ATOMIC)) == NULL)
+		if ((bh = bio_alloc(GFP_ATOMIC, 1)) == NULL)
 			goto abort;
-		memset (bh, 0, sizeof (struct buffer_head));
-		bhp->b_reqnext = bh;
+		bio_init(bh);
+		bh->bi_vcnt = 1;
+		bhp->bi_next = bh;
 		bhp = bh;
-		bh->b_reqnext = NULL;
+		bh->bi_next = NULL;
 	}
 	return first_bh;
 abort:
-	idescsi_free_bh (first_bh);
+	idescsi_free_bio (first_bh);
 	return NULL;
 }
 
@@ -689,9 +692,9 @@
 	}
 }
 
-static inline struct buffer_head *idescsi_dma_bh (ide_drive_t *drive, idescsi_pc_t *pc)
+static inline struct bio *idescsi_dma_bio(ide_drive_t *drive, idescsi_pc_t *pc)
 {
-	struct buffer_head *bh = NULL, *first_bh = NULL;
+	struct bio *bh = NULL, *first_bh = NULL;
 	int segments = pc->scsi_cmd->use_sg;
 	struct scatterlist *sg = pc->scsi_cmd->request_buffer;
 
@@ -700,25 +703,43 @@
 	if (idescsi_set_direction(pc))
 		return NULL;
 	if (segments) {
-		if ((first_bh = bh = idescsi_kmalloc_bh (segments)) == NULL)
+		if ((first_bh = bh = idescsi_kmalloc_bio (segments)) == NULL)
 			return NULL;
 #if IDESCSI_DEBUG_LOG
 		printk ("ide-scsi: %s: building DMA table, %d segments, %dkB total\n", drive->name, segments, pc->request_transfer >> 10);
 #endif /* IDESCSI_DEBUG_LOG */
 		while (segments--) {
-			bh->b_data = sg->address;
-			bh->b_size = sg->length;
-			bh = bh->b_reqnext;
+			struct page *page = sg->page;
+			int offset = sg->offset;
+
+			if (!page) {
+				BUG_ON(!sg->address);
+				page = virt_to_page(sg->address);
+				offset = (unsigned long) sg->address & ~PAGE_MASK;
+			}
+				
+			bh->bi_io_vec[0].bv_page = page;
+			bh->bi_io_vec[0].bv_len = sg->length;
+			bh->bi_io_vec[0].bv_offset = offset;
+			bh->bi_size = sg->length;
+			bh = bh->bi_next;
+			/*
+			 * just until scsi_merge is fixed up...
+			 */
+			BUG_ON(PageHighMem(page));
+			sg->address = page_address(page) + offset;
 			sg++;
 		}
 	} else {
-		if ((first_bh = bh = idescsi_kmalloc_bh (1)) == NULL)
+		if ((first_bh = bh = idescsi_kmalloc_bio (1)) == NULL)
 			return NULL;
 #if IDESCSI_DEBUG_LOG
 		printk ("ide-scsi: %s: building DMA table for a single buffer (%dkB)\n", drive->name, pc->request_transfer >> 10);
 #endif /* IDESCSI_DEBUG_LOG */
-		bh->b_data = pc->scsi_cmd->request_buffer;
-		bh->b_size = pc->request_transfer;
+		bh->bi_io_vec[0].bv_page = virt_to_page(pc->scsi_cmd->request_buffer);
+		bh->bi_io_vec[0].bv_len = pc->request_transfer;
+		bh->bi_io_vec[0].bv_offset = (unsigned long) pc->scsi_cmd->request_buffer & ~PAGE_MASK;
+		bh->bi_size = pc->request_transfer;
 	}
 	return first_bh;
 }
@@ -782,12 +803,12 @@
 	}
 
 	ide_init_drive_cmd (rq);
-	rq->buffer = (char *) pc;
-	rq->bh = idescsi_dma_bh (drive, pc);
-	rq->cmd = IDESCSI_PC_RQ;
-	spin_unlock(&io_request_lock);
+	rq->special = (char *) pc;
+	rq->bio = idescsi_dma_bio (drive, pc);
+	rq->flags = REQ_SPECIAL;
+	spin_unlock(&cmd->host->host_lock);
 	(void) ide_do_drive_cmd (drive, rq, ide_end);
-	spin_lock_irq(&io_request_lock);
+	spin_lock_irq(&cmd->host->host_lock);
 	return 0;
 abort:
 	if (pc) kfree (pc);
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c
--- v2.5.0/linux/drivers/scsi/imm.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/scsi/imm.c	Sat Dec  8 20:02:47 2001
@@ -124,11 +124,6 @@
     int i, nhosts, try_again;
     struct parport *pb;
 
-    /*
-     * unlock to allow the lowlevel parport driver to probe
-     * the irqs
-     */
-    spin_unlock_irq(&io_request_lock);
     pb = parport_enumerate();
 
     printk("imm: Version %s\n", IMM_VERSION);
@@ -137,7 +132,6 @@
 
     if (!pb) {
 	printk("imm: parport reports no devices.\n");
-	spin_lock_irq(&io_request_lock);
 	return 0;
     }
   retry_entry:
@@ -163,7 +157,6 @@
 		      "pardevice is owning the port for too longtime!\n",
 			   i);
 		    parport_unregister_device (imm_hosts[i].dev);
-		    spin_lock_irq(&io_request_lock);
 		    return 0;
 		}
 	    }
@@ -219,13 +212,11 @@
     }
     if (nhosts == 0) {
 	if (try_again == 1) {
-	    spin_lock_irq(&io_request_lock);
 	    return 0;
 	}
 	try_again = 1;
 	goto retry_entry;
     } else {
-	spin_lock_irq (&io_request_lock);
 	return 1;		/* return number of hosts detected */
     }
 }
@@ -834,7 +825,7 @@
 	    if (cmd->SCp.buffers_residual--) {
 		cmd->SCp.buffer++;
 		cmd->SCp.this_residual = cmd->SCp.buffer->length;
-		cmd->SCp.ptr = cmd->SCp.buffer->address;
+		cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
 
 		/*
 		 * Make sure that we transfer even number of bytes
@@ -897,6 +888,7 @@
 {
     imm_struct *tmp = (imm_struct *) data;
     Scsi_Cmnd *cmd = tmp->cur_cmd;
+    struct Scsi_Host *host = cmd->host;
     unsigned long flags;
 
     if (!cmd) {
@@ -948,10 +940,10 @@
     if (cmd->SCp.phase > 0)
 	imm_pb_release(cmd->host->unique_id);
 
-    spin_lock_irqsave(&io_request_lock, flags);
+    spin_lock_irqsave(&host->host_lock, flags);
     tmp->cur_cmd = 0;
     cmd->scsi_done(cmd);
-    spin_unlock_irqrestore(&io_request_lock, flags);
+    spin_unlock_irqrestore(&host->host_lock, flags);
     return;
 }
 
@@ -1008,7 +1000,7 @@
 	    /* if many buffers are available, start filling the first */
 	    cmd->SCp.buffer = (struct scatterlist *) cmd->request_buffer;
 	    cmd->SCp.this_residual = cmd->SCp.buffer->length;
-	    cmd->SCp.ptr = cmd->SCp.buffer->address;
+	    cmd->SCp.ptr = page_address(cmd->SCp.buffer->page) + cmd->SCp.buffer->offset;
 	} else {
 	    /* else fill the only available buffer */
 	    cmd->SCp.buffer = NULL;
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/imm.h linux/drivers/scsi/imm.h
--- v2.5.0/linux/drivers/scsi/imm.h	Fri Mar  2 18:38:38 2001
+++ linux/drivers/scsi/imm.h	Wed Nov 28 10:22:27 2001
@@ -175,7 +175,6 @@
                 eh_device_reset_handler:        NULL,                   \
                 eh_bus_reset_handler:           imm_reset,              \
                 eh_host_reset_handler:          imm_reset,              \
-		use_new_eh_code:		1,			\
 		bios_param:		        imm_biosparam,		\
 		this_id:			7,			\
 		sg_tablesize:			SG_ALL,			\
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/in2000.h linux/drivers/scsi/in2000.h
--- v2.5.0/linux/drivers/scsi/in2000.h	Thu Jul 19 21:08:18 2001
+++ linux/drivers/scsi/in2000.h	Wed Nov 28 10:22:27 2001
@@ -423,7 +423,6 @@
                   sg_tablesize:    IN2000_SG,           /* scatter-gather table size */ \
                   cmd_per_lun:     IN2000_CPL,          /* commands per lun */ \
                   use_clustering:  DISABLE_CLUSTERING,  /* ENABLE_CLUSTERING may speed things up */ \
-                  use_new_eh_code: 0                    /* new error code - not using it yet */ \
                 }
 
 #endif /* IN2000_H */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/ini9100u.h linux/drivers/scsi/ini9100u.h
--- v2.5.0/linux/drivers/scsi/ini9100u.h	Thu Oct 11 09:43:30 2001
+++ linux/drivers/scsi/ini9100u.h	Wed Nov 28 10:22:27 2001
@@ -115,7 +115,6 @@
 	present:	0, \
 	unchecked_isa_dma: 0, \
 	use_clustering:	ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
 }
 
 #define VIRT_TO_BUS(i)  (unsigned int) virt_to_bus((void *)(i))
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/inia100.h linux/drivers/scsi/inia100.h
--- v2.5.0/linux/drivers/scsi/inia100.h	Thu Oct 11 09:43:30 2001
+++ linux/drivers/scsi/inia100.h	Wed Nov 28 10:22:27 2001
@@ -110,7 +110,6 @@
 	present:	0, \
 	unchecked_isa_dma: 0, \
 	use_clustering:	ENABLE_CLUSTERING, \
- use_new_eh_code: 0 \
 }
 
 #define VIRT_TO_BUS(i)  (unsigned int) virt_to_bus((void *)(i))
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/ips.h linux/drivers/scsi/ips.h
--- v2.5.0/linux/drivers/scsi/ips.h	Sun Sep 30 12:26:08 2001
+++ linux/drivers/scsi/ips.h	Wed Nov 28 10:22:27 2001
@@ -472,7 +472,6 @@
     present : 0,                          \
     unchecked_isa_dma : 0,                \
     use_clustering : ENABLE_CLUSTERING,   \
-    use_new_eh_code : 1                   \
 }
 #endif
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/mac53c94.h linux/drivers/scsi/mac53c94.h
--- v2.5.0/linux/drivers/scsi/mac53c94.h	Tue Sep 19 08:31:53 2000
+++ linux/drivers/scsi/mac53c94.h	Wed Nov 28 10:22:27 2001
@@ -28,7 +28,6 @@
 	sg_tablesize:	SG_ALL,				\
 	cmd_per_lun:	1,				\
 	use_clustering:	DISABLE_CLUSTERING,		\
-	use_new_eh_code: 1,				\
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/mac_esp.h linux/drivers/scsi/mac_esp.h
--- v2.5.0/linux/drivers/scsi/mac_esp.h	Sun Jul  9 22:51:43 2000
+++ linux/drivers/scsi/mac_esp.h	Thu Nov 29 13:55:59 2001
@@ -34,8 +34,7 @@
 			    this_id:		7, \
 			    sg_tablesize:	SG_ALL, \
 			    cmd_per_lun:	1, \
-			    use_clustering:	DISABLE_CLUSTERING, \
-			    use_new_eh_code:	0 }
+			    use_clustering:	DISABLE_CLUSTERING }
 
 #endif /* MAC_ESP_H */
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.5.0/linux/drivers/scsi/megaraid.c	Thu Oct 25 13:53:51 2001
+++ linux/drivers/scsi/megaraid.c	Tue Nov 27 09:23:27 2001
@@ -586,8 +586,10 @@
 #define DRIVER_LOCK(p)
 #define DRIVER_UNLOCK(p)
 #define IO_LOCK_T unsigned long io_flags = 0
-#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
-#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
+#define IO_LOCK(host) spin_lock_irqsave(&(host)->host_lock,io_flags)
+#define IO_UNLOCK(host) spin_unlock_irqrestore(&(host)->host_lock,io_flags)
+#define IO_LOCK_IRQ(host) spin_lock_irq(&(host)->host_lock)
+#define IO_UNLOCK_IRQ(host) spin_unlock_irq(&(host)->host_lock)
 
 #define queue_task_irq(a,b)     queue_task(a,b)
 #define queue_task_irq_off(a,b) queue_task(a,b)
@@ -612,8 +614,8 @@
 #define DRIVER_LOCK(p)
 #define DRIVER_UNLOCK(p)
 #define IO_LOCK_T unsigned long io_flags = 0
-#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
-#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
+#define IO_LOCK(host) spin_lock_irqsave(&io_request_lock,io_flags);
+#define IO_UNLOCK(host) spin_unlock_irqrestore(&io_request_lock,io_flags);
 
 #define pci_free_consistent(a,b,c,d)
 #define pci_unmap_single(a,b,c,d)
@@ -2101,7 +2103,7 @@
 		for (idx = 0; idx < MAX_FIRMWARE_STATUS; idx++)
 			completed[idx] = 0;
 
-		IO_LOCK;
+		IO_LOCK(megaCfg->host);
 
 		megaCfg->nInterrupts++;
 		qCnt = 0xff;
@@ -2220,7 +2222,7 @@
 		megaCfg->flag &= ~IN_ISR;
 		/* Loop through any pending requests */
 		mega_runpendq (megaCfg);
-		IO_UNLOCK;
+		IO_UNLOCK(megaCfg->host);
 
 	}
 
@@ -3032,9 +3034,7 @@
 					    sizeof (mega_mailbox64),
 					    &(megaCfg->dma_handle64));
 
-		mega_register_mailbox (megaCfg,
-				       virt_to_bus ((void *) megaCfg->
-						    mailbox64ptr));
+		mega_register_mailbox (megaCfg, megaCfg->dma_handle64);
 #else
 		mega_register_mailbox (megaCfg,
 				       virt_to_bus ((void *) &megaCfg->
@@ -3800,7 +3800,7 @@
 
 		if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
 			init_MUTEX_LOCKED (&pScb->ioctl_sem);
-			spin_unlock_irq (&io_request_lock);
+			IO_UNLOCK_IRQ(megaCfg->host);
 			down (&pScb->ioctl_sem);
     		user_area = (char *)*((u32*)&pScb->SCpnt->cmnd[4]);
 			if (copy_to_user
@@ -3809,7 +3809,7 @@
 				    ("megaraid: Error copying ioctl return value to user buffer.\n");
 				pScb->SCpnt->result = (DID_ERROR << 16);
 			}
-			spin_lock_irq (&io_request_lock);
+		    IO_LOCK_IRQ(megaCfg->host);
 			DRIVER_LOCK (megaCfg);
 			kfree (pScb->buff_ptr);
 			pScb->buff_ptr = NULL;
@@ -4744,10 +4744,10 @@
 
 		init_MUTEX_LOCKED(&mimd_ioctl_sem);
 
-		IO_LOCK;
+		IO_LOCK(shpnt);
 		megaraid_queue(scsicmd, megadev_ioctl_done);
 
-		IO_UNLOCK;
+		IO_UNLOCK(shpnt);
 
 		down(&mimd_ioctl_sem);
 
@@ -4893,10 +4893,10 @@
 
 		init_MUTEX_LOCKED (&mimd_ioctl_sem);
 
-		IO_LOCK;
+		IO_LOCK(shpnt);
 		megaraid_queue (scsicmd, megadev_ioctl_done);
 
-		IO_UNLOCK;
+		IO_UNLOCK(shpnt);
 		down (&mimd_ioctl_sem);
 
 		if (!scsicmd->result && outlen) {
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.5.0/linux/drivers/scsi/megaraid.h	Thu Oct 25 13:53:51 2001
+++ linux/drivers/scsi/megaraid.h	Tue Nov 27 09:23:27 2001
@@ -223,7 +223,8 @@
     cmd_per_lun:    	MAX_CMD_PER_LUN,	/* SCSI Commands per LUN	*/\
     present:	  	0,		       	/* Present			*/\
     unchecked_isa_dma:	0,		       	/* Default Unchecked ISA DMA	*/\
-    use_clustering:   	ENABLE_CLUSTERING  	/* Enable Clustering		*/\
+    use_clustering:   	ENABLE_CLUSTERING,  	/* Enable Clustering		*/\
+	highmem_io:		1,													\
   }
 #endif
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/mesh.h linux/drivers/scsi/mesh.h
--- v2.5.0/linux/drivers/scsi/mesh.h	Tue Sep 19 08:31:53 2000
+++ linux/drivers/scsi/mesh.h	Wed Nov 28 10:22:27 2001
@@ -28,7 +28,6 @@
 	sg_tablesize:	SG_ALL,				\
 	cmd_per_lun:	2,				\
 	use_clustering:	DISABLE_CLUSTERING,		\
-	use_new_eh_code: 1,				\
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/pci2000.h linux/drivers/scsi/pci2000.h
--- v2.5.0/linux/drivers/scsi/pci2000.h	Thu Jul 19 21:07:53 2001
+++ linux/drivers/scsi/pci2000.h	Wed Nov 28 10:22:27 2001
@@ -218,7 +218,6 @@
 	present:	0,						\
 	unchecked_isa_dma:0,						\
 	use_clustering:	DISABLE_CLUSTERING,				\
-	use_new_eh_code:0						\
 }
 
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/pci2220i.h linux/drivers/scsi/pci2220i.h
--- v2.5.0/linux/drivers/scsi/pci2220i.h	Thu Jul 19 21:07:54 2001
+++ linux/drivers/scsi/pci2220i.h	Wed Nov 28 10:22:27 2001
@@ -56,6 +56,5 @@
 	present:		0,			\
 	unchecked_isa_dma:	0,			\
 	use_clustering:		DISABLE_CLUSTERING,	\
-	use_new_eh_code:	0			\
 }
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/pcmcia/nsp_cs.c linux/drivers/scsi/pcmcia/nsp_cs.c
--- v2.5.0/linux/drivers/scsi/pcmcia/nsp_cs.c	Thu Oct 11 09:04:57 2001
+++ linux/drivers/scsi/pcmcia/nsp_cs.c	Wed Nov 28 10:22:27 2001
@@ -149,7 +149,6 @@
 /*	present:		0,*/
 /*	unchecked_isa_dma:	0,*/
 	use_clustering:		DISABLE_CLUSTERING,
-	use_new_eh_code:	0,
 /*	emulated:		0,*/
 };
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/pluto.h linux/drivers/scsi/pluto.h
--- v2.5.0/linux/drivers/scsi/pluto.h	Thu Jan 27 12:53:32 2000
+++ linux/drivers/scsi/pluto.h	Wed Nov 28 10:22:27 2001
@@ -53,7 +53,6 @@
 	sg_tablesize:		1,				\
 	cmd_per_lun:		1,				\
 	use_clustering:		ENABLE_CLUSTERING,		\
-	use_new_eh_code:	FCP_SCSI_USE_NEW_EH_CODE,	\
 	abort:			fcp_old_abort,			\
 	eh_abort_handler:	fcp_scsi_abort,			\
 	eh_device_reset_handler:fcp_scsi_dev_reset,		\
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h
--- v2.5.0/linux/drivers/scsi/ppa.h	Fri Mar  2 18:38:39 2001
+++ linux/drivers/scsi/ppa.h	Wed Nov 28 10:22:27 2001
@@ -183,7 +183,6 @@
 		eh_device_reset_handler:	NULL,			\
 		eh_bus_reset_handler:		ppa_reset,		\
 		eh_host_reset_handler:		ppa_reset,		\
-		use_new_eh_code:		1,			\
 		bios_param:			ppa_biosparam,		\
 		this_id:			-1,			\
 		sg_tablesize:			SG_ALL,			\
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/qla1280.h linux/drivers/scsi/qla1280.h
--- v2.5.0/linux/drivers/scsi/qla1280.h	Mon Sep 17 13:16:31 2001
+++ linux/drivers/scsi/qla1280.h	Wed Nov 28 10:22:27 2001
@@ -1726,7 +1726,6 @@
 	present: 0,		/* number of 7xxx's present   */\
 	unchecked_isa_dma: 0,	/* no memory DMA restrictions */\
 	use_clustering: ENABLE_CLUSTERING,			\
-	use_new_eh_code: 0,					\
 	emulated: 0					        \
 }
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/qlogicfc.c linux/drivers/scsi/qlogicfc.c
--- v2.5.0/linux/drivers/scsi/qlogicfc.c	Thu Oct 25 13:53:51 2001
+++ linux/drivers/scsi/qlogicfc.c	Thu Nov 29 20:43:59 2001
@@ -734,7 +734,6 @@
  			scsi_set_pci_device(host, pdev);
 			host->max_id = QLOGICFC_MAX_ID + 1;
 			host->max_lun = QLOGICFC_MAX_LUN;
-			host->hostt->use_new_eh_code = 1;
 			hostdata = (struct isp2x00_hostdata *) host->hostdata;
 
 			memset(hostdata, 0, sizeof(struct isp2x00_hostdata));
@@ -2042,10 +2041,7 @@
 		return 1;
 	}
 
-	if (!(command & PCI_COMMAND_MASTER)) {
-		printk("qlogicfc%d : bus mastering is disabled\n", hostdata->host_id);
-		return 1;
-	}
+	pci_set_master(pdev);
 	if (revision != ISP2100_REV_ID1 && revision != ISP2100_REV_ID3 && revision != ISP2200_REV_ID5)
 		printk("qlogicfc%d : new isp2x00 revision ID (%d)\n", hostdata->host_id,  revision);
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/qlogicfc.h linux/drivers/scsi/qlogicfc.h
--- v2.5.0/linux/drivers/scsi/qlogicfc.h	Sun Oct 21 10:36:54 2001
+++ linux/drivers/scsi/qlogicfc.h	Tue Nov 27 09:23:27 2001
@@ -95,7 +95,8 @@
 	cmd_per_lun:		QLOGICFC_CMD_PER_LUN, 			   \
         present:                0,                                         \
         unchecked_isa_dma:      0,                                         \
-        use_clustering:         ENABLE_CLUSTERING 			   \
+        use_clustering:         ENABLE_CLUSTERING, 			   \
+	highmem_io:		1					   \
 }
 
 #endif /* _QLOGICFC_H */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/qlogicisp.c linux/drivers/scsi/qlogicisp.c
--- v2.5.0/linux/drivers/scsi/qlogicisp.c	Thu Oct 25 13:53:51 2001
+++ linux/drivers/scsi/qlogicisp.c	Mon Nov 26 14:23:58 2001
@@ -1403,11 +1403,6 @@
 	command &= ~PCI_COMMAND_MEMORY; 
 #endif
 
-	if (!(command & PCI_COMMAND_MASTER)) {
-		printk("qlogicisp : bus mastering is disabled\n");
-		return 1;
-	}
-
 	sh->io_port = io_base;
 
 	if (!request_region(sh->io_port, 0xff, "qlogicisp")) {
@@ -1471,6 +1466,8 @@
 		printk("qlogicisp : can't allocate request queue\n");
 		goto out_unmap;
 	}
+
+	pci_set_master(pdev);
 
 	LEAVE("isp1020_init");
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/qlogicpti.h linux/drivers/scsi/qlogicpti.h
--- v2.5.0/linux/drivers/scsi/qlogicpti.h	Mon Dec 20 22:06:42 1999
+++ linux/drivers/scsi/qlogicpti.h	Wed Nov 28 10:22:27 2001
@@ -524,7 +524,6 @@
 	sg_tablesize:	QLOGICPTI_MAX_SG(QLOGICPTI_REQ_QUEUE_LEN), \
 	cmd_per_lun:	1,					   \
 	use_clustering:	ENABLE_CLUSTERING,			   \
-	use_new_eh_code: 0					   \
 }
 
 /* For our interrupt engine. */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.5.0/linux/drivers/scsi/scsi.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/scsi.c	Mon Dec 10 14:15:19 2001
@@ -151,14 +151,6 @@
 void scsi_build_commandblocks(Scsi_Device * SDpnt);
 
 /*
- * These are the interface to the old error handling code.  It should go away
- * someday soon.
- */
-extern void scsi_old_done(Scsi_Cmnd * SCpnt);
-extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
-
-
-/*
  * Function:    scsi_initialize_queue()
  *
  * Purpose:     Selects queue handler function for a device.
@@ -186,10 +178,26 @@
  *              handler in the list - ultimately they call scsi_request_fn
  *              to do the dirty deed.
  */
-void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt) {
-	blk_init_queue(&SDpnt->request_queue, scsi_request_fn);
-        blk_queue_headactive(&SDpnt->request_queue, 0);
-        SDpnt->request_queue.queuedata = (void *) SDpnt;
+void  scsi_initialize_queue(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt)
+{
+	request_queue_t *q = &SDpnt->request_queue;
+	int max_segments = SHpnt->sg_tablesize;
+
+	blk_init_queue(q, scsi_request_fn);
+	q->queuedata = (void *) SDpnt;
+
+#ifdef DMA_CHUNK_SIZE
+	if (max_segments > 64)
+		max_segments = 64;
+#endif
+
+	blk_queue_max_segments(q, max_segments);
+	blk_queue_max_sectors(q, SHpnt->max_sectors);
+
+	if (!SHpnt->use_clustering)
+		clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+	if (SHpnt->unchecked_isa_dma)
+		blk_queue_segment_boundary(q, ISA_DMA_THRESHOLD);
 }
 
 #ifdef MODULE
@@ -227,9 +235,8 @@
 	req = &SCpnt->request;
 	req->rq_status = RQ_SCSI_DONE;	/* Busy, but indicate request done */
 
-	if (req->waiting != NULL) {
+	if (req->waiting)
 		complete(req->waiting);
-	}
 }
 
 /*
@@ -620,8 +627,6 @@
 	unsigned long flags = 0;
 	unsigned long timeout;
 
-	ASSERT_LOCK(&io_request_lock, 0);
-
 #if DEBUG
 	unsigned long *ret = 0;
 #ifdef __mips__
@@ -633,6 +638,8 @@
 
 	host = SCpnt->host;
 
+	ASSERT_LOCK(&host->host_lock, 0);
+
 	/* Assign a unique nonzero serial_number. */
 	if (++serial_number == 0)
 		serial_number = 1;
@@ -660,12 +667,8 @@
 			mdelay(1 + 999 / HZ);
 		host->resetting = 0;
 	}
-	if (host->hostt->use_new_eh_code) {
-		scsi_add_timer(SCpnt, SCpnt->timeout_per_command, scsi_times_out);
-	} else {
-		scsi_add_timer(SCpnt, SCpnt->timeout_per_command,
-			       scsi_old_times_out);
-	}
+
+	scsi_add_timer(SCpnt, SCpnt->timeout_per_command, scsi_times_out);
 
 	/*
 	 * We will use a queued command if possible, otherwise we will emulate the
@@ -682,59 +685,37 @@
 		SCSI_LOG_MLQUEUE(3, printk("queuecommand : routine at %p\n",
 					   host->hostt->queuecommand));
 		/*
-		 * Use the old error handling code if we haven't converted the driver
-		 * to use the new one yet.  Note - only the new queuecommand variant
-		 * passes a meaningful return value.
+		 * Before we queue this command, check if the command
+		 * length exceeds what the host adapter can handle.
 		 */
-		if (host->hostt->use_new_eh_code) {
-			/*
-			 * Before we queue this command, check if the command
-			 * length exceeds what the host adapter can handle.
-			 */
-			if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
-				spin_lock_irqsave(&io_request_lock, flags);
-				rtn = host->hostt->queuecommand(SCpnt, scsi_done);
-				spin_unlock_irqrestore(&io_request_lock, flags);
-				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 {
-				SCSI_LOG_MLQUEUE(3, printk("queuecommand : command too long.\n"));
-				SCpnt->result = (DID_ABORT << 16);
-				spin_lock_irqsave(&io_request_lock, flags);
-				scsi_done(SCpnt);
-				spin_unlock_irqrestore(&io_request_lock, flags);
-				rtn = 1;
+		if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
+			spin_lock_irqsave(&host->host_lock, flags);
+			rtn = host->hostt->queuecommand(SCpnt, scsi_done);
+			spin_unlock_irqrestore(&host->host_lock, flags);
+			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 {
-			/*
-			 * Before we queue this command, check if the command
-			 * length exceeds what the host adapter can handle.
-			 */
-			if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
-				spin_lock_irqsave(&io_request_lock, flags);
-				host->hostt->queuecommand(SCpnt, scsi_old_done);
-				spin_unlock_irqrestore(&io_request_lock, flags);
-			} else {
-				SCSI_LOG_MLQUEUE(3, printk("queuecommand : command too long.\n"));
-				SCpnt->result = (DID_ABORT << 16);
-				spin_lock_irqsave(&io_request_lock, flags);
-				scsi_old_done(SCpnt);
-				spin_unlock_irqrestore(&io_request_lock, flags);
-				rtn = 1;
-			}
+			SCSI_LOG_MLQUEUE(3,
+				printk("queuecommand : command too long.\n"));
+			SCpnt->result = (DID_ABORT << 16);
+			spin_lock_irqsave(&host->host_lock, flags);
+			scsi_done(SCpnt);
+			spin_unlock_irqrestore(&host->host_lock, flags);
+			rtn = 1;
 		}
 	} else {
 		int temp;
 
 		SCSI_LOG_MLQUEUE(3, printk("command() :  routine at %p\n", host->hostt->command));
-                spin_lock_irqsave(&io_request_lock, flags);
+                spin_lock_irqsave(&host->host_lock, flags);
 		temp = host->hostt->command(SCpnt);
 		SCpnt->result = temp;
 #ifdef DEBUG_DELAY
-                spin_unlock_irqrestore(&io_request_lock, flags);
+                spin_unlock_irqrestore(&host->host_lock, flags);
 		clock = jiffies + 4 * HZ;
 		while (time_before(jiffies, clock)) {
 			barrier();
@@ -742,14 +723,10 @@
 		}
 		printk("done(host = %d, result = %04x) : routine at %p\n",
 		       host->host_no, temp, host->hostt->command);
-                spin_lock_irqsave(&io_request_lock, flags);
+                spin_lock_irqsave(&host->host_lock, flags);
 #endif
-		if (host->hostt->use_new_eh_code) {
-			scsi_done(SCpnt);
-		} else {
-			scsi_old_done(SCpnt);
-		}
-                spin_unlock_irqrestore(&io_request_lock, flags);
+		scsi_done(SCpnt);
+                spin_unlock_irqrestore(&host->host_lock, flags);
 	}
 	SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()\n"));
 	return rtn;
@@ -769,11 +746,13 @@
  		  int timeout, int retries)
 {
 	DECLARE_COMPLETION(wait);
+	request_queue_t *q = &SRpnt->sr_device->request_queue;
 	
 	SRpnt->sr_request.waiting = &wait;
 	SRpnt->sr_request.rq_status = RQ_SCSI_BUSY;
 	scsi_do_req (SRpnt, (void *) cmnd,
 		buffer, bufflen, scsi_wait_done, timeout, retries);
+	generic_unplug_device(q);
 	wait_for_completion(&wait);
 	SRpnt->sr_request.waiting = NULL;
 	if( SRpnt->sr_command != NULL )
@@ -817,7 +796,7 @@
 	Scsi_Device * SDpnt = SRpnt->sr_device;
 	struct Scsi_Host *host = SDpnt->host;
 
-	ASSERT_LOCK(&io_request_lock, 0);
+	ASSERT_LOCK(&host->host_lock, 0);
 
 	SCSI_LOG_MLQUEUE(4,
 			 {
@@ -914,7 +893,7 @@
 {
 	struct Scsi_Host *host = SCpnt->host;
 
-	ASSERT_LOCK(&io_request_lock, 0);
+	ASSERT_LOCK(&host->host_lock, 0);
 
 	SCpnt->owner = SCSI_OWNER_MIDLEVEL;
 	SRpnt->sr_command = SCpnt;
@@ -1004,7 +983,7 @@
 {
 	struct Scsi_Host *host = SCpnt->host;
 
-	ASSERT_LOCK(&io_request_lock, 0);
+	ASSERT_LOCK(&host->host_lock, 0);
 
 	SCpnt->pid = scsi_pid++;
 	SCpnt->owner = SCSI_OWNER_MIDLEVEL;
@@ -1355,11 +1334,11 @@
 	Scsi_Request * SRpnt;
 	unsigned long flags;
 
-	ASSERT_LOCK(&io_request_lock, 0);
-
 	host = SCpnt->host;
 	device = SCpnt->device;
 
+	ASSERT_LOCK(&host->host_lock, 0);
+
         /*
          * We need to protect the decrement, as otherwise a race condition
          * would exist.  Fiddling with SCpnt isn't a problem as the
@@ -1367,10 +1346,10 @@
          * one execution context, but the device and host structures are
          * shared.
          */
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&host->host_lock, flags);
 	host->host_busy--;	/* Indicate that we are free */
 	device->device_busy--;	/* Decrement device usage counter. */
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&host->host_lock, flags);
 
         /*
          * Clear the flags which say that the device/host is no longer
@@ -1858,7 +1837,6 @@
 	Scsi_Device *SDpnt;
 	struct Scsi_Device_Template *sdtpnt;
 	const char *name;
-	unsigned long flags;
 	int out_of_space = 0;
 
 	if (tpnt->next || !tpnt->detect)
@@ -1868,7 +1846,7 @@
 
 	/* If max_sectors isn't set, default to max */
 	if (!tpnt->max_sectors)
-		tpnt->max_sectors = MAX_SECTORS;
+		tpnt->max_sectors = 1024;
 
 	pcount = next_scsi_host;
 
@@ -1876,18 +1854,12 @@
 
 	/* The detect routine must carefully spinunlock/spinlock if 
 	   it enables interrupts, since all interrupt handlers do 
-	   spinlock as well.
-	   All lame drivers are going to fail due to the following 
-	   spinlock. For the time beeing let's use it only for drivers 
-	   using the new scsi code. NOTE: the detect routine could
-	   redefine the value tpnt->use_new_eh_code. (DB, 13 May 1998) */
-
-	if (tpnt->use_new_eh_code) {
-		spin_lock_irqsave(&io_request_lock, flags);
-		tpnt->present = tpnt->detect(tpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
-	} else
-		tpnt->present = tpnt->detect(tpnt);
+	   spinlock as well.  */
+
+	/*
+	 * detect should do its own locking
+	 */
+	tpnt->present = tpnt->detect(tpnt);
 
 	if (tpnt->present) {
 		if (pcount == next_scsi_host) {
@@ -1921,7 +1893,7 @@
 		 * handle error correction.
 		 */
 		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
-			if (shpnt->hostt == tpnt && shpnt->hostt->use_new_eh_code) {
+			if (shpnt->hostt == tpnt) {
 				DECLARE_MUTEX_LOCKED(sem);
 
 				shpnt->eh_notify = &sem;
@@ -2129,7 +2101,6 @@
 	 */
 	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
 		if (shpnt->hostt == tpnt
-		    && shpnt->hostt->use_new_eh_code
 		    && shpnt->ehandler != NULL) {
 			DECLARE_MUTEX_LOCKED(sem);
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
--- v2.5.0/linux/drivers/scsi/scsi.h	Thu Nov 22 11:49:15 2001
+++ linux/drivers/scsi/scsi.h	Tue Dec 11 09:54:44 2001
@@ -386,15 +386,6 @@
 #define ASKED_FOR_SENSE 0x20
 #define SYNC_RESET      0x40
 
-#if defined(__mc68000__) || defined(CONFIG_APUS)
-#include <asm/pgtable.h>
-#define CONTIGUOUS_BUFFERS(X,Y) \
-	(virt_to_phys((X)->b_data+(X)->b_size-1)+1==virt_to_phys((Y)->b_data))
-#else
-#define CONTIGUOUS_BUFFERS(X,Y) ((X->b_data+X->b_size) == Y->b_data)
-#endif
-
-
 /*
  * This is the crap from the old error handling code.  We have it in a special
  * place so that we can more easily delete it later on.
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi_debug.h linux/drivers/scsi/scsi_debug.h
--- v2.5.0/linux/drivers/scsi/scsi_debug.h	Mon Dec 11 13:19:52 2000
+++ linux/drivers/scsi/scsi_debug.h	Wed Nov 28 10:22:27 2001
@@ -37,6 +37,5 @@
 		    cmd_per_lun:       3,			\
 		    unchecked_isa_dma: 0,			\
 		    use_clustering:    ENABLE_CLUSTERING,	\
-		    use_new_eh_code:   1,			\
 }
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.5.0/linux/drivers/scsi/scsi_error.c	Sun Sep  9 10:52:35 2001
+++ linux/drivers/scsi/scsi_error.c	Tue Nov 27 09:23:27 2001
@@ -423,8 +423,6 @@
 	unsigned char scsi_result0[256], *scsi_result = NULL;
 	int saved_result;
 
-	ASSERT_LOCK(&io_request_lock, 0);
-
 	memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
 	       sizeof(generic_sense));
 
@@ -583,16 +581,14 @@
 STATIC void scsi_send_eh_cmnd(Scsi_Cmnd * SCpnt, int timeout)
 {
 	unsigned long flags;
-	struct Scsi_Host *host;
-
-	ASSERT_LOCK(&io_request_lock, 0);
+	struct Scsi_Host *host = SCpnt->host;
 
-	host = SCpnt->host;
+	ASSERT_LOCK(&host->host_lock, 0);
 
-      retry:
+retry:
 	/*
-	 * We will use a queued command if possible, otherwise we will emulate the
-	 * queuing and calling of completion function ourselves.
+	 * We will use a queued command if possible, otherwise we will
+	 * emulate the queuing and calling of completion function ourselves.
 	 */
 	SCpnt->owner = SCSI_OWNER_LOWLEVEL;
 
@@ -609,9 +605,9 @@
 		SCpnt->host->eh_action = &sem;
 		SCpnt->request.rq_status = RQ_SCSI_BUSY;
 
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&SCpnt->host->host_lock, flags);
 		host->hostt->queuecommand(SCpnt, scsi_eh_done);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&SCpnt->host->host_lock, flags);
 
 		down(&sem);
 
@@ -634,10 +630,10 @@
 			 * abort a timed out command or not.  Not sure how
 			 * we should treat them differently anyways.
 			 */
-			spin_lock_irqsave(&io_request_lock, flags);
+			spin_lock_irqsave(&SCpnt->host->host_lock, flags);
 			if (SCpnt->host->hostt->eh_abort_handler)
 				SCpnt->host->hostt->eh_abort_handler(SCpnt);
-			spin_unlock_irqrestore(&io_request_lock, flags);
+			spin_unlock_irqrestore(&SCpnt->host->host_lock, flags);
 			
 			SCpnt->request.rq_status = RQ_SCSI_DONE;
 			SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
@@ -650,13 +646,13 @@
 		int temp;
 
 		/*
-		 * We damn well had better never use this code.  There is no timeout
-		 * protection here, since we would end up waiting in the actual low
-		 * level driver, we don't know how to wake it up.
+		 * We damn well had better never use this code.  There is no
+		 * timeout protection here, since we would end up waiting in
+		 * the actual low level driver, we don't know how to wake it up.
 		 */
-		spin_lock_irqsave(&io_request_lock, flags);
+		spin_lock_irqsave(&host->host_lock, flags);
 		temp = host->hostt->command(SCpnt);
-		spin_unlock_irqrestore(&io_request_lock, flags);
+		spin_unlock_irqrestore(&host->host_lock, flags);
 
 		SCpnt->result = temp;
 		/* Fall through to code below to examine status. */
@@ -664,8 +660,8 @@
 	}
 
 	/*
-	 * Now examine the actual status codes to see whether the command actually
-	 * did complete normally.
+	 * Now examine the actual status codes to see whether the command
+	 * actually did complete normally.
 	 */
 	if (SCpnt->eh_state == SUCCESS) {
 		int ret = scsi_eh_completed_normally(SCpnt);
@@ -776,9 +772,9 @@
 
 	SCpnt->owner = SCSI_OWNER_LOWLEVEL;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&SCpnt->host->host_lock, flags);
 	rtn = SCpnt->host->hostt->eh_abort_handler(SCpnt);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&SCpnt->host->host_lock, flags);
 	return rtn;
 }
 
@@ -808,9 +804,9 @@
 	}
 	SCpnt->owner = SCSI_OWNER_LOWLEVEL;
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&SCpnt->host->host_lock, flags);
 	rtn = SCpnt->host->hostt->eh_device_reset_handler(SCpnt);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&SCpnt->host->host_lock, flags);
 
 	if (rtn == SUCCESS)
 		SCpnt->eh_state = SUCCESS;
@@ -841,9 +837,9 @@
 		return FAILED;
 	}
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&SCpnt->host->host_lock, flags);
 	rtn = SCpnt->host->hostt->eh_bus_reset_handler(SCpnt);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&SCpnt->host->host_lock, flags);
 
 	if (rtn == SUCCESS)
 		SCpnt->eh_state = SUCCESS;
@@ -887,9 +883,9 @@
 	if (SCpnt->host->hostt->eh_host_reset_handler == NULL) {
 		return FAILED;
 	}
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&SCpnt->host->host_lock, flags);
 	rtn = SCpnt->host->hostt->eh_host_reset_handler(SCpnt);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&SCpnt->host->host_lock, flags);
 
 	if (rtn == SUCCESS)
 		SCpnt->eh_state = SUCCESS;
@@ -1230,7 +1226,7 @@
 	Scsi_Device *SDpnt;
 	unsigned long flags;
 
-	ASSERT_LOCK(&io_request_lock, 0);
+	ASSERT_LOCK(&host->host_lock, 0);
 
 	/*
 	 * Next free up anything directly waiting upon the host.  This will be
@@ -1247,19 +1243,22 @@
 	 * now that error recovery is done, we will need to ensure that these
 	 * requests are started.
 	 */
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&host->host_lock, flags);
 	for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-		request_queue_t *q;
+		request_queue_t *q = &SDpnt->request_queue;
+
 		if ((host->can_queue > 0 && (host->host_busy >= host->can_queue))
 		    || (host->host_blocked)
 		    || (host->host_self_blocked)
 		    || (SDpnt->device_blocked)) {
 			break;
 		}
-		q = &SDpnt->request_queue;
+
+		spin_lock(&q->queue_lock);
 		q->request_fn(q);
+		spin_unlock(&q->queue_lock);
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&host->host_lock, flags);
 }
 
 /*
@@ -1306,7 +1305,7 @@
 	Scsi_Cmnd *SCdone;
 	int timed_out;
 
-	ASSERT_LOCK(&io_request_lock, 0);
+	ASSERT_LOCK(&host->host_lock, 0);
 
 	SCdone = NULL;
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- v2.5.0/linux/drivers/scsi/scsi_lib.c	Fri Oct 12 15:35:54 2001
+++ linux/drivers/scsi/scsi_lib.c	Sat Dec  8 20:02:47 2001
@@ -61,7 +61,7 @@
  * 		data - private data
  *		at_head - insert request at head or tail of queue
  *
- * Lock status:	Assumed that io_request_lock is not held upon entry.
+ * Lock status:	Assumed that queue lock is not held upon entry.
  *
  * Returns:	Nothing
  */
@@ -70,11 +70,18 @@
 {
 	unsigned long flags;
 
-	ASSERT_LOCK(&io_request_lock, 0);
+	ASSERT_LOCK(&q->queue_lock, 0);
+
+	/*
+	 * tell I/O scheduler that this isn't a regular read/write (ie it
+	 * must not attempt merges on this) and that it acts as a soft
+	 * barrier
+	 */
+	rq->flags = REQ_SPECIAL | REQ_BARRIER;
 
-	rq->cmd = SPECIAL;
 	rq->special = data;
 	rq->q = NULL;
+	rq->bio = rq->biotail = NULL;
 	rq->nr_segments = 0;
 	rq->elevator_sequence = 0;
 
@@ -84,15 +91,10 @@
 	 * head of the queue for things like a QUEUE_FULL message from a
 	 * device, or a host that is unable to accept a particular command.
 	 */
-	spin_lock_irqsave(&io_request_lock, flags);
-
-	if (at_head)
-		list_add(&rq->queue, &q->queue_head);
-	else
-		list_add_tail(&rq->queue, &q->queue_head);
-
+	spin_lock_irqsave(&q->queue_lock, flags);
+	__elv_add_request(q, rq, !at_head, 0);
 	q->request_fn(q);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&q->queue_lock, flags);
 }
 
 
@@ -167,8 +169,6 @@
  */
 int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt)
 {
-	ASSERT_LOCK(&io_request_lock, 0);
-
 	SCpnt->owner = SCSI_OWNER_MIDLEVEL;
 	SCpnt->reset_chain = NULL;
 	SCpnt->serial_number = 0;
@@ -250,9 +250,9 @@
 	Scsi_Device *SDpnt;
 	struct Scsi_Host *SHpnt;
 
-	ASSERT_LOCK(&io_request_lock, 0);
+	ASSERT_LOCK(&q->queue_lock, 0);
 
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&q->queue_lock, flags);
 	if (SCpnt != NULL) {
 
 		/*
@@ -262,7 +262,7 @@
 		 * the bad sector.
 		 */
 		SCpnt->request.special = (void *) SCpnt;
-		list_add(&SCpnt->request.queue, &q->queue_head);
+		__elv_add_request(q, &SCpnt->request, 0, 0);
 	}
 
 	/*
@@ -280,14 +280,10 @@
 	 * with special case code, then spin off separate versions and
 	 * use function pointers to pick the right one.
 	 */
-	if (SDpnt->single_lun
-	    && list_empty(&q->queue_head)
-	    && SDpnt->device_busy == 0) {
+	if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) {
 		request_queue_t *q;
 
-		for (SDpnt = SHpnt->host_queue;
-		     SDpnt;
-		     SDpnt = SDpnt->next) {
+		for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) {
 			if (((SHpnt->can_queue > 0)
 			     && (SHpnt->host_busy >= SHpnt->can_queue))
 			    || (SHpnt->host_blocked)
@@ -295,6 +291,7 @@
 			    || (SDpnt->device_blocked)) {
 				break;
 			}
+
 			q = &SDpnt->request_queue;
 			q->request_fn(q);
 		}
@@ -328,7 +325,7 @@
 			SHpnt->some_device_starved = 0;
 		}
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&q->queue_lock, flags);
 }
 
 /*
@@ -360,57 +357,19 @@
 				     int requeue,
 				     int frequeue)
 {
-	struct request *req;
-	struct buffer_head *bh;
-        Scsi_Device * SDpnt;
-	int nsect;
-
-	ASSERT_LOCK(&io_request_lock, 0);
-
-	req = &SCpnt->request;
-	req->errors = 0;
-	if (!uptodate) {
-		printk(" I/O error: dev %s, sector %lu\n",
-		       kdevname(req->rq_dev), req->sector);
-	}
-	do {
-		if ((bh = req->bh) != NULL) {
-			nsect = bh->b_size >> 9;
-			blk_finished_io(nsect);
-			req->bh = bh->b_reqnext;
-			bh->b_reqnext = NULL;
-			sectors -= nsect;
-			bh->b_end_io(bh, uptodate);
-			if ((bh = req->bh) != NULL) {
-				req->hard_sector += nsect;
-				req->hard_nr_sectors -= nsect;
-				req->sector += nsect;
-				req->nr_sectors -= nsect;
-
-				req->current_nr_sectors = bh->b_size >> 9;
-				if (req->nr_sectors < req->current_nr_sectors) {
-					req->nr_sectors = req->current_nr_sectors;
-					printk("scsi_end_request: buffer-list destroyed\n");
-				}
-			}
-		}
-	} while (sectors && bh);
+	request_queue_t *q = &SCpnt->device->request_queue;
+	struct request *req = &SCpnt->request;
+
+	ASSERT_LOCK(&q->queue_lock, 0);
 
 	/*
 	 * If there are blocks left over at the end, set up the command
 	 * to queue the remainder of them.
 	 */
-	if (req->bh) {
-                request_queue_t *q;
-
-		if( !requeue )
-		{
+	if (end_that_request_first(req, 1, sectors)) {
+		if (!requeue)
 			return SCpnt;
-		}
 
-                q = &SCpnt->device->request_queue;
-
-		req->buffer = bh->b_data;
 		/*
 		 * Bleah.  Leftovers again.  Stick the leftovers in
 		 * the front of the queue, and goose the queue again.
@@ -418,17 +377,15 @@
 		scsi_queue_next_request(q, SCpnt);
 		return SCpnt;
 	}
+
 	/*
 	 * This request is done.  If there is someone blocked waiting for this
-	 * request, wake them up.  Typically used to wake up processes trying
-	 * to swap a page into memory.
+	 * request, wake them up.
 	 */
-	if (req->waiting != NULL) {
+	if (req->waiting)
 		complete(req->waiting);
-	}
-	add_blkdev_randomness(MAJOR(req->rq_dev));
 
-        SDpnt = SCpnt->device;
+	add_blkdev_randomness(MAJOR(req->rq_dev));
 
 	/*
 	 * This will goose the queue request function at the end, so we don't
@@ -436,12 +393,9 @@
 	 */
 	__scsi_release_command(SCpnt);
 
-	if( frequeue ) {
-		request_queue_t *q;
+	if (frequeue)
+		scsi_queue_next_request(q, NULL);
 
-		q = &SDpnt->request_queue;
-		scsi_queue_next_request(q, NULL);                
-	}
 	return NULL;
 }
 
@@ -489,7 +443,9 @@
  */
 static void scsi_release_buffers(Scsi_Cmnd * SCpnt)
 {
-	ASSERT_LOCK(&io_request_lock, 0);
+	struct request *req = &SCpnt->request;
+
+	ASSERT_LOCK(&SCpnt->device->request_queue.queue_lock, 0);
 
 	/*
 	 * Free up any indirection buffers we allocated for DMA purposes. 
@@ -510,9 +466,8 @@
 		}
 		scsi_free(SCpnt->request_buffer, SCpnt->sglist_len);
 	} else {
-		if (SCpnt->request_buffer != SCpnt->request.buffer) {
-			scsi_free(SCpnt->request_buffer, SCpnt->request_bufflen);
-		}
+		if (SCpnt->request_buffer != req->buffer)
+			scsi_free(SCpnt->request_buffer,SCpnt->request_bufflen);
 	}
 
 	/*
@@ -548,6 +503,7 @@
 	int result = SCpnt->result;
 	int this_count = SCpnt->bufflen >> 9;
 	request_queue_t *q = &SCpnt->device->request_queue;
+	struct request *req = &SCpnt->request;
 
 	/*
 	 * We must do one of several things here:
@@ -562,7 +518,7 @@
 	 *	would be used if we just wanted to retry, for example.
 	 *
 	 */
-	ASSERT_LOCK(&io_request_lock, 0);
+	ASSERT_LOCK(&q->queue_lock, 0);
 
 	/*
 	 * Free up any indirection buffers we allocated for DMA purposes. 
@@ -580,7 +536,7 @@
 		if (bbpnt) {
 			for (i = 0; i < SCpnt->use_sg; i++) {
 				if (bbpnt[i]) {
-					if (SCpnt->request.cmd == READ) {
+					if (rq_data_dir(req) == READ) {
 						memcpy(bbpnt[i],
 						       sgpnt[i].address,
 						       sgpnt[i].length);
@@ -591,10 +547,13 @@
 		}
 		scsi_free(SCpnt->buffer, SCpnt->sglist_len);
 	} else {
-		if (SCpnt->buffer != SCpnt->request.buffer) {
-			if (SCpnt->request.cmd == READ) {
-				memcpy(SCpnt->request.buffer, SCpnt->buffer,
-				       SCpnt->bufflen);
+		if (SCpnt->buffer != req->buffer) {
+			if (rq_data_dir(req) == READ) {
+				unsigned long flags;
+				char *to = bio_kmap_irq(req->bio, &flags);
+
+				memcpy(to, SCpnt->buffer, SCpnt->bufflen);
+				bio_kunmap_irq(to, &flags);
 			}
 			scsi_free(SCpnt->buffer, SCpnt->bufflen);
 		}
@@ -615,11 +574,10 @@
 	 */
 	if (good_sectors > 0) {
 		SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d sectors done.\n",
-					      SCpnt->request.nr_sectors,
-					      good_sectors));
+					      req->nr_sectors, good_sectors));
 		SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n ", SCpnt->use_sg));
 
-		SCpnt->request.errors = 0;
+		req->errors = 0;
 		/*
 		 * If multiple sectors are requested in one buffer, then
 		 * they will have been finished off by the first command.
@@ -716,7 +674,7 @@
 			break;
 		case NOT_READY:
 			printk(KERN_INFO "Device %s not ready.\n",
-			       kdevname(SCpnt->request.rq_dev));
+			       kdevname(req->rq_dev));
 			SCpnt = scsi_end_request(SCpnt, 0, this_count);
 			return;
 			break;
@@ -760,7 +718,7 @@
 		 * 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);
+		SCpnt = scsi_end_request(SCpnt, 0, req->current_nr_sectors);
 		return;
 	}
 }
@@ -774,7 +732,7 @@
  * Arguments:   request   - I/O request we are preparing to queue.
  *
  * Lock status: No locks assumed to be held, but as it happens the
- *              io_request_lock is held when this is called.
+ *              q->queue_lock is held when this is called.
  *
  * Returns:     Nothing
  *
@@ -788,7 +746,7 @@
 	kdev_t dev = req->rq_dev;
 	int major = MAJOR(dev);
 
-	ASSERT_LOCK(&io_request_lock, 1);
+	ASSERT_LOCK(&req->q->queue_lock, 1);
 
 	for (spnt = scsi_devicelist; spnt; spnt = spnt->next) {
 		/*
@@ -846,7 +804,7 @@
 	struct Scsi_Host *SHpnt;
 	struct Scsi_Device_Template *STpnt;
 
-	ASSERT_LOCK(&io_request_lock, 1);
+	ASSERT_LOCK(&q->queue_lock, 1);
 
 	SDpnt = (Scsi_Device *) q->queuedata;
 	if (!SDpnt) {
@@ -864,7 +822,7 @@
 		 * released the lock and grabbed it again, so each time
 		 * we need to check to see if the queue is plugged or not.
 		 */
-		if (SHpnt->in_recovery || q->plugged)
+		if (SHpnt->in_recovery || blk_queue_plugged(q))
 			return;
 
 		/*
@@ -913,9 +871,9 @@
 			 */
 			SDpnt->was_reset = 0;
 			if (SDpnt->removable && !in_interrupt()) {
-				spin_unlock_irq(&io_request_lock);
+				spin_unlock_irq(&q->queue_lock);
 				scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0);
-				spin_lock_irq(&io_request_lock);
+				spin_lock_irq(&q->queue_lock);
 				continue;
 			}
 		}
@@ -924,14 +882,13 @@
 		 * If we couldn't find a request that could be queued, then we
 		 * can also quit.
 		 */
-		if (list_empty(&q->queue_head))
+		if (blk_queue_empty(q))
 			break;
 
 		/*
-		 * Loop through all of the requests in this queue, and find
-		 * one that is queueable.
+		 * get next queueable request.
 		 */
-		req = blkdev_entry_next_request(&q->queue_head);
+		req = elv_next_request(q);
 
 		/*
 		 * Find the actual device driver associated with this command.
@@ -943,7 +900,7 @@
 		 * these two cases differently.  We differentiate by looking
 		 * at request.cmd, as this tells us the real story.
 		 */
-		if (req->cmd == SPECIAL) {
+		if (req->flags & REQ_SPECIAL) {
 			STpnt = NULL;
 			SCpnt = (Scsi_Cmnd *) req->special;
 			SRpnt = (Scsi_Request *) req->special;
@@ -951,13 +908,12 @@
 			if( SRpnt->sr_magic == SCSI_REQ_MAGIC ) {
 				SCpnt = scsi_allocate_device(SRpnt->sr_device, 
 							     FALSE, FALSE);
-				if( !SCpnt ) {
+				if (!SCpnt)
 					break;
-				}
 				scsi_init_cmd_from_req(SCpnt, SRpnt);
 			}
 
-		} else {
+		} else if (req->flags & REQ_CMD) {
 			SRpnt = NULL;
 			STpnt = scsi_get_request_dev(req);
 			if (!STpnt) {
@@ -966,14 +922,14 @@
 			/*
 			 * Now try and find a command block that we can use.
 			 */
-			if( req->special != NULL ) {
+			if (req->special) {
 				SCpnt = (Scsi_Cmnd *) req->special;
 				/*
 				 * We need to recount the number of
 				 * scatter-gather segments here - the
 				 * normal case code assumes this to be
 				 * correct, as it would be a performance
-				 * lose to always recount.  Handling
+				 * loss to always recount.  Handling
 				 * errors is always unusual, of course.
 				 */
 				recount_segments(SCpnt);
@@ -985,9 +941,11 @@
 			 * while the queue is locked and then break out of the
 			 * loop. Otherwise loop around and try another request.
 			 */
-			if (!SCpnt) {
+			if (!SCpnt)
 				break;
-			}
+		} else {
+			blk_dump_rq_flags(req, "SCSI bad req");
+			break;
 		}
 
 		/*
@@ -1024,9 +982,9 @@
 		 * another.  
 		 */
 		req = NULL;
-		spin_unlock_irq(&io_request_lock);
+		spin_unlock_irq(&q->queue_lock);
 
-		if (SCpnt->request.cmd != SPECIAL) {
+		if (SCpnt->request.flags & REQ_CMD) {
 			/*
 			 * This will do a couple of things:
 			 *  1) Fill in the actual SCSI command.
@@ -1039,9 +997,9 @@
 			 * some kinds of consistency checking may cause the	
 			 * request to be rejected immediately.
 			 */
-			if (STpnt == NULL) {
-				STpnt = scsi_get_request_dev(req);
-			}
+			if (STpnt == NULL)
+				STpnt = scsi_get_request_dev(&SCpnt->request);
+
 			/* 
 			 * This sets up the scatter-gather table (allocating if
 			 * required).  Hosts that need bounce buffers will also
@@ -1054,7 +1012,7 @@
 				{
 					panic("Should not have leftover blocks\n");
 				}
-				spin_lock_irq(&io_request_lock);
+				spin_lock_irq(&q->queue_lock);
 				SHpnt->host_busy--;
 				SDpnt->device_busy--;
 				continue;
@@ -1070,7 +1028,7 @@
 				{
 					panic("Should not have leftover blocks\n");
 				}
-				spin_lock_irq(&io_request_lock);
+				spin_lock_irq(&q->queue_lock);
 				SHpnt->host_busy--;
 				SDpnt->device_busy--;
 				continue;
@@ -1091,7 +1049,7 @@
 		 * Now we need to grab the lock again.  We are about to mess
 		 * with the request queue and try to find another command.
 		 */
-		spin_lock_irq(&io_request_lock);
+		spin_lock_irq(&q->queue_lock);
 	}
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c
--- v2.5.0/linux/drivers/scsi/scsi_merge.c	Thu Oct 25 14:05:31 2001
+++ linux/drivers/scsi/scsi_merge.c	Tue Dec 11 09:44:13 2001
@@ -6,6 +6,7 @@
  *                        Based upon conversations with large numbers
  *                        of people at Linux Expo.
  *	Support for dynamic DMA mapping: Jakub Jelinek (jakub@redhat.com).
+ *	Support for highmem I/O: Jens Axboe <axboe@suse.de>
  */
 
 /*
@@ -71,51 +72,6 @@
  */
 #define DMA_SEGMENT_SIZE_LIMITED
 
-#ifdef CONFIG_SCSI_DEBUG_QUEUES
-/*
- * Enable a bunch of additional consistency checking.   Turn this off
- * if you are benchmarking.
- */
-static int dump_stats(struct request *req,
-		      int use_clustering,
-		      int dma_host,
-		      int segments)
-{
-	struct buffer_head *bh;
-
-	/*
-	 * Dump the information that we have.  We know we have an
-	 * inconsistency.
-	 */
-	printk("nr_segments is %x\n", req->nr_segments);
-	printk("counted segments is %x\n", segments);
-	printk("Flags %d %d\n", use_clustering, dma_host);
-	for (bh = req->bh; bh->b_reqnext != NULL; bh = bh->b_reqnext) 
-	{
-		printk("Segment 0x%p, blocks %d, addr 0x%lx\n",
-		       bh,
-		       bh->b_size >> 9,
-		       virt_to_phys(bh->b_data - 1));
-	}
-	panic("Ththththaats all folks.  Too dangerous to continue.\n");
-}
-
-
-/*
- * Simple sanity check that we will use for the first go around
- * in order to ensure that we are doing the counting correctly.
- * This can be removed for optimization.
- */
-#define SANITY_CHECK(req, _CLUSTER, _DMA)				\
-    if( req->nr_segments != __count_segments(req, _CLUSTER, _DMA, NULL) )	\
-    {									\
-	printk("Incorrect segment count at 0x%p", current_text_addr());	\
-	dump_stats(req, _CLUSTER, _DMA, __count_segments(req, _CLUSTER, _DMA, NULL)); \
-    }
-#else
-#define SANITY_CHECK(req, _CLUSTER, _DMA)
-#endif
-
 static void dma_exhausted(Scsi_Cmnd * SCpnt, int i)
 {
 	int jj;
@@ -151,15 +107,6 @@
 }
 
 /*
- * FIXME(eric) - the original disk code disabled clustering for MOD
- * devices.  I have no idea why we thought this was a good idea - my
- * guess is that it was an attempt to limit the size of requests to MOD
- * devices.
- */
-#define CLUSTERABLE_DEVICE(SH,SD) (SH->use_clustering && \
-				   SD->type != TYPE_MOD)
-
-/*
  * This entire source file deals with the new queueing code.
  */
 
@@ -170,7 +117,6 @@
  *
  * Arguments:   q       - Queue for which we are merging request.
  *              req     - request into which we wish to merge.
- *              use_clustering - 1 if this host wishes to use clustering
  *              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).
@@ -185,84 +131,37 @@
  * Notes:       This is only used for diagnostic purposes.
  */
 __inline static int __count_segments(struct request *req,
-				     int use_clustering,
 				     int dma_host,
 				     int * remainder)
 {
 	int ret = 1;
 	int reqsize = 0;
-	struct buffer_head *bh;
-	struct buffer_head *bhnext;
+	int i;
+	struct bio *bio;
+	struct bio_vec *bvec;
 
-	if( remainder != NULL ) {
+	if (remainder)
 		reqsize = *remainder;
-	}
 
 	/*
 	 * Add in the size increment for the first buffer.
 	 */
-	bh = req->bh;
+	bio = req->bio;
 #ifdef DMA_SEGMENT_SIZE_LIMITED
-	if( reqsize + bh->b_size > PAGE_SIZE ) {
+	if (reqsize + bio->bi_size > PAGE_SIZE)
 		ret++;
-		reqsize = bh->b_size;
-	} else {
-		reqsize += bh->b_size;
-	}
-#else
-	reqsize += bh->b_size;
 #endif
 
-	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
-			 * scatter-gather segment.  In the event that this is a
-			 * DMA capable host, make sure that a segment doesn't span
-			 * the DMA threshold boundary.  
-			 */
-			if (dma_host &&
-			    virt_to_phys(bhnext->b_data) - 1 == ISA_DMA_THRESHOLD) {
-				ret++;
-				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 {
+	rq_for_each_bio(bio, req) {
+		bio_for_each_segment(bvec, bio, i)
 			ret++;
-			reqsize = bhnext->b_size;
-		}
+
+		reqsize += bio->bi_size;
 	}
-	if( remainder != NULL ) {
+
+	if (remainder)
 		*remainder = reqsize;
-	}
+
 	return ret;
 }
 
@@ -290,29 +189,26 @@
 void
 recount_segments(Scsi_Cmnd * SCpnt)
 {
-	struct request *req;
-	struct Scsi_Host *SHpnt;
-	Scsi_Device * SDpnt;
-
-	req   = &SCpnt->request;
-	SHpnt = SCpnt->host;
-	SDpnt = SCpnt->device;
-
-	req->nr_segments = __count_segments(req, 
-					    CLUSTERABLE_DEVICE(SHpnt, SDpnt),
-					    SHpnt->unchecked_isa_dma, NULL);
+	struct request *req = &SCpnt->request;
+	struct Scsi_Host *SHpnt = SCpnt->host;
+
+	req->nr_segments = __count_segments(req, SHpnt->unchecked_isa_dma,NULL);
 }
 
+/*
+ * IOMMU hackery for sparc64
+ */
+#ifdef DMA_CHUNK_SIZE
+
 #define MERGEABLE_BUFFERS(X,Y) \
-(((((long)(X)->b_data+(X)->b_size)|((long)(Y)->b_data)) & \
-  (DMA_CHUNK_SIZE - 1)) == 0)
+	((((bvec_to_phys(__BVEC_END((X))) + __BVEC_END((X))->bv_len) | bio_to_phys((Y))) & (DMA_CHUNK_SIZE - 1)) == 0)
 
-#ifdef DMA_CHUNK_SIZE
 static inline int scsi_new_mergeable(request_queue_t * q,
 				     struct request * req,
-				     struct Scsi_Host *SHpnt,
-				     int max_segments)
+				     struct bio *bio)
 {
+	int nr_segs = bio_hw_segments(q, bio);
+
 	/*
 	 * pci_map_sg will be able to merge these two
 	 * into a single hardware sg entry, check if
@@ -320,49 +216,54 @@
 	 * scsi.c allocates for this purpose
 	 * min(64,sg_tablesize) entries.
 	 */
-	if (req->nr_segments >= max_segments ||
-	    req->nr_segments >= SHpnt->sg_tablesize)
+	if (req->nr_segments + nr_segs > q->max_segments)
 		return 0;
-	req->nr_segments++;
+
+	req->nr_segments += nr_segs;
 	return 1;
 }
 
 static inline int scsi_new_segment(request_queue_t * q,
 				   struct request * req,
-				   struct Scsi_Host *SHpnt,
-				   int max_segments)
+				   struct bio *bio)
 {
+	int nr_segs = bio_hw_segments(q, bio);
 	/*
 	 * pci_map_sg won't be able to map these two
 	 * into a single hardware sg entry, so we have to
 	 * check if things fit into sg_tablesize.
 	 */
-	if (req->nr_hw_segments >= SHpnt->sg_tablesize ||
-	     req->nr_segments >= SHpnt->sg_tablesize)
+	if (req->nr_hw_segments + nr_segs > q->max_segments)
+		return 0;
+	else if (req->nr_segments + nr_segs > q->max_segments)
 		return 0;
-	req->nr_hw_segments++;
-	req->nr_segments++;
+
+	req->nr_hw_segments += nr_segs;
+	req->nr_segments += nr_segs;
 	return 1;
 }
-#else
+
+#else /* DMA_CHUNK_SIZE */
+
 static inline int scsi_new_segment(request_queue_t * q,
 				   struct request * req,
-				   struct Scsi_Host *SHpnt,
-				   int max_segments)
+				   struct bio *bio)
 {
-	if (req->nr_segments < SHpnt->sg_tablesize &&
-	    req->nr_segments < max_segments) {
-		/*
-		 * This will form the start of a new segment.  Bump the 
-		 * counter.
-		 */
-		req->nr_segments++;
-		return 1;
-	} else {
+	int nr_segs = bio_hw_segments(q, bio);
+
+	if (req->nr_segments + nr_segs > q->max_segments) {
+		req->flags |= REQ_NOMERGE;
 		return 0;
 	}
+
+	/*
+	 * This will form the start of a new segment.  Bump the 
+	 * counter.
+	 */
+	req->nr_segments += nr_segs;
+	return 1;
 }
-#endif
+#endif /* DMA_CHUNK_SIZE */
 
 /*
  * Function:    __scsi_merge_fn()
@@ -371,8 +272,7 @@
  *
  * Arguments:   q       - Queue for which we are merging request.
  *              req     - request into which we wish to merge.
- *              bh      - Block which we may wish to merge into request
- *              use_clustering - 1 if this host wishes to use clustering
+ *              bio     - Block which we may wish to merge into request
  *              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).
@@ -380,7 +280,7 @@
  * Returns:     1 if it is OK to merge the block into the request.  0
  *              if it is not OK.
  *
- * Lock status: io_request_lock is assumed to be held here.
+ * Lock status: queue lock is assumed to be held here.
  *
  * Notes:       Some drivers have limited scatter-gather table sizes, and
  *              thus they cannot queue an infinitely large command.  This
@@ -390,129 +290,44 @@
  *
  *              This function is not designed to be directly called.  Instead
  *              it should be referenced from other functions where the
- *              use_clustering and dma_host parameters should be integer
- *              constants.  The compiler should thus be able to properly
- *              optimize the code, eliminating stuff that is irrelevant.
+ *              dma_host parameter should be an integer constant. The
+ *              compiler should thus be able to properly optimize the code,
+ *              eliminating stuff that is irrelevant.
  *              It is more maintainable to do this way with a single function
  *              than to have 4 separate functions all doing roughly the
  *              same thing.
  */
 __inline static int __scsi_back_merge_fn(request_queue_t * q,
 					 struct request *req,
-					 struct buffer_head *bh,
-					 int max_segments,
-					 int use_clustering,
-					 int dma_host)
+					 struct bio *bio)
 {
-	unsigned int count;
-	unsigned int segment_size = 0;
-	Scsi_Device *SDpnt;
-	struct Scsi_Host *SHpnt;
-
-	SDpnt = (Scsi_Device *) q->queuedata;
-	SHpnt = SDpnt->host;
-
-#ifdef DMA_CHUNK_SIZE
-	if (max_segments > 64)
-		max_segments = 64;
-#endif
-
-	if ((req->nr_sectors + (bh->b_size >> 9)) > SHpnt->max_sectors)
+	if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
+		req->flags |= REQ_NOMERGE;
 		return 0;
-
-	if (use_clustering) {
-		/* 
-		 * See if we can do this without creating another
-		 * scatter-gather segment.  In the event that this is a
-		 * DMA capable host, make sure that a segment doesn't span
-		 * the DMA threshold boundary.  
-		 */
-		if (dma_host &&
-		    virt_to_phys(req->bhtail->b_data) - 1 == ISA_DMA_THRESHOLD) {
-			goto new_end_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_end_segment;
-				}
-			}
-#endif
-			/*
-			 * This one is OK.  Let it go.
-			 */
-			return 1;
-		}
 	}
- new_end_segment:
+
 #ifdef DMA_CHUNK_SIZE
-	if (MERGEABLE_BUFFERS(req->bhtail, bh))
-		return scsi_new_mergeable(q, req, SHpnt, max_segments);
+	if (MERGEABLE_BUFFERS(bio, req->bio))
+		return scsi_new_mergeable(q, req, bio);
 #endif
-	return scsi_new_segment(q, req, SHpnt, max_segments);
+
+	return scsi_new_segment(q, req, bio);
 }
 
 __inline static int __scsi_front_merge_fn(request_queue_t * q,
 					  struct request *req,
-					  struct buffer_head *bh,
-					  int max_segments,
-					  int use_clustering,
-					  int dma_host)
+					  struct bio *bio)
 {
-	unsigned int count;
-	unsigned int segment_size = 0;
-	Scsi_Device *SDpnt;
-	struct Scsi_Host *SHpnt;
-
-	SDpnt = (Scsi_Device *) q->queuedata;
-	SHpnt = SDpnt->host;
-
-#ifdef DMA_CHUNK_SIZE
-	if (max_segments > 64)
-		max_segments = 64;
-#endif
-
-	if ((req->nr_sectors + (bh->b_size >> 9)) > SHpnt->max_sectors)
+	if (req->nr_sectors + bio_sectors(bio) > q->max_sectors) {
+		req->flags |= REQ_NOMERGE;
 		return 0;
-
-	if (use_clustering) {
-		/* 
-		 * See if we can do this without creating another
-		 * scatter-gather segment.  In the event that this is a
-		 * DMA capable host, make sure that a segment doesn't span
-		 * the DMA threshold boundary. 
-		 */
-		if (dma_host &&
-		    virt_to_phys(bh->b_data) - 1 == ISA_DMA_THRESHOLD) {
-			goto new_start_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_start_segment;
-				}
-			}
-#endif
-			/*
-			 * This one is OK.  Let it go.
-			 */
-			return 1;
-		}
 	}
- new_start_segment:
+
 #ifdef DMA_CHUNK_SIZE
-	if (MERGEABLE_BUFFERS(bh, req->bh))
-		return scsi_new_mergeable(q, req, SHpnt, max_segments);
+	if (MERGEABLE_BUFFERS(bio, req->bio))
+		return scsi_new_mergeable(q, req, bio);
 #endif
-	return scsi_new_segment(q, req, SHpnt, max_segments);
+	return scsi_new_segment(q, req, bio);
 }
 
 /*
@@ -522,86 +337,51 @@
  *
  * Arguments:   q       - Queue for which we are merging request.
  *              req     - request into which we wish to merge.
- *              bh      - Block which we may wish to merge into request
+ *              bio     - Block which we may wish to merge into request
  *
  * Returns:     1 if it is OK to merge the block into the request.  0
  *              if it is not OK.
  *
- * Lock status: io_request_lock is assumed to be held here.
+ * Lock status: queue lock is assumed to be held here.
  *
  * Notes:       Optimized for different cases depending upon whether
  *              ISA DMA is in use and whether clustering should be used.
  */
-#define MERGEFCT(_FUNCTION, _BACK_FRONT, _CLUSTER, _DMA)		\
+#define MERGEFCT(_FUNCTION, _BACK_FRONT)				\
 static int _FUNCTION(request_queue_t * q,				\
 		     struct request * req,				\
-		     struct buffer_head * bh,				\
-		     int max_segments)					\
+		     struct bio *bio)					\
 {									\
     int ret;								\
-    SANITY_CHECK(req, _CLUSTER, _DMA);					\
     ret =  __scsi_ ## _BACK_FRONT ## _merge_fn(q,			\
 					       req,			\
-					       bh,			\
-					       max_segments,		\
-					       _CLUSTER,		\
-					       _DMA);			\
+					       bio);			\
     return ret;								\
 }
 
-/* Version with use_clustering 0 and dma_host 1 is not necessary,
- * since the only use of dma_host above is protected by use_clustering.
- */
-MERGEFCT(scsi_back_merge_fn_, back, 0, 0)
-MERGEFCT(scsi_back_merge_fn_c, back, 1, 0)
-MERGEFCT(scsi_back_merge_fn_dc, back, 1, 1)
-
-MERGEFCT(scsi_front_merge_fn_, front, 0, 0)
-MERGEFCT(scsi_front_merge_fn_c, front, 1, 0)
-MERGEFCT(scsi_front_merge_fn_dc, front, 1, 1)
+MERGEFCT(scsi_back_merge_fn, back)
+MERGEFCT(scsi_front_merge_fn, front)
 
 /*
- * Function:    __scsi_merge_requests_fn()
+ * Function:    scsi_merge_requests_fn_()
  *
- * Purpose:     Prototype for queue merge function.
+ * Purpose:     queue merge function.
  *
  * Arguments:   q       - Queue for which we are merging request.
  *              req     - request into which we wish to merge.
- *              next    - 2nd request that we might want to combine with req
- *              use_clustering - 1 if this host wishes to use clustering
- *              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).
+ *              next    - Block which we may wish to merge into request
  *
- * Returns:     1 if it is OK to merge the two requests.  0
+ * Returns:     1 if it is OK to merge the block into the request.  0
  *              if it is not OK.
  *
- * Lock status: io_request_lock is assumed to be held here.
- *
- * Notes:       Some drivers have limited scatter-gather table sizes, and
- *              thus they cannot queue an infinitely large command.  This
- *              function is called from ll_rw_blk before it attempts to merge
- *              a new block into a request to make sure that the request will
- *              not become too large.
+ * Lock status: queue lock is assumed to be held here.
  *
- *              This function is not designed to be directly called.  Instead
- *              it should be referenced from other functions where the
- *              use_clustering and dma_host parameters should be integer
- *              constants.  The compiler should thus be able to properly
- *              optimize the code, eliminating stuff that is irrelevant.
- *              It is more maintainable to do this way with a single function
- *              than to have 4 separate functions all doing roughly the
- *              same thing.
  */
-__inline static int __scsi_merge_requests_fn(request_queue_t * q,
-					     struct request *req,
-					     struct request *next,
-					     int max_segments,
-					     int use_clustering,
-					     int dma_host)
+inline static int scsi_merge_requests_fn(request_queue_t * q,
+					 struct request *req,
+					 struct request *next)
 {
-	Scsi_Device *SDpnt;
-	struct Scsi_Host *SHpnt;
+	int bio_segs;
 
 	/*
 	 * First check if the either of the requests are re-queued
@@ -610,156 +390,45 @@
 	if (req->special || next->special)
 		return 0;
 
-	SDpnt = (Scsi_Device *) q->queuedata;
-	SHpnt = SDpnt->host;
-
-#ifdef DMA_CHUNK_SIZE
-	if (max_segments > 64)
-		max_segments = 64;
-
-	/* If it would not fit into prepared memory space for sg chain,
-	 * then don't allow the merge.
-	 */
-	if (req->nr_segments + next->nr_segments - 1 > max_segments ||
-	    req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) {
-		return 0;
-	}
-	if (req->nr_hw_segments + next->nr_hw_segments - 1 > SHpnt->sg_tablesize) {
-		return 0;
-	}
-#else
 	/*
-	 * If the two requests together are too large (even assuming that we
-	 * can merge the boundary requests into one segment, then don't
-	 * allow the merge.
+	 * will become to large?
 	 */
-	if (req->nr_segments + next->nr_segments - 1 > SHpnt->sg_tablesize) {
+	if ((req->nr_sectors + next->nr_sectors) > q->max_sectors)
 		return 0;
-	}
-#endif
 
-	if ((req->nr_sectors + next->nr_sectors) > SHpnt->max_sectors)
-		return 0;
+	bio_segs = req->nr_segments + next->nr_segments;
+	if (blk_contig_segment(q, req->biotail, next->bio))
+		bio_segs--;
 
 	/*
-	 * The main question is whether the two segments at the boundaries
-	 * would be considered one or two.
+	 * exceeds our max allowed segments?
 	 */
-	if (use_clustering) {
-		/* 
-		 * See if we can do this without creating another
-		 * scatter-gather segment.  In the event that this is a
-		 * DMA capable host, make sure that a segment doesn't span
-		 * the DMA threshold boundary.  
-		 */
-		if (dma_host &&
-		    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.
-			 */
-			req->nr_segments += next->nr_segments - 1;
-#ifdef DMA_CHUNK_SIZE
-			req->nr_hw_segments += next->nr_hw_segments - 1;
-#endif
-			return 1;
-		}
-	}
-      dont_combine:
-#ifdef DMA_CHUNK_SIZE
-	if (req->nr_segments + next->nr_segments > max_segments ||
-	    req->nr_segments + next->nr_segments > SHpnt->sg_tablesize) {
+	if (bio_segs > q->max_segments)
 		return 0;
-	}
+
+#ifdef DMA_CHUNK_SIZE
+	bio_segs = req->nr_hw_segments + next->nr_hw_segments;
+	if (blk_contig_segment(q, req->biotail, next->bio))
+		bio_segs--;
+
 	/* If dynamic DMA mapping can merge last segment in req with
 	 * first segment in next, then the check for hw segments was
 	 * done above already, so we can always merge.
 	 */
-	if (MERGEABLE_BUFFERS (req->bhtail, next->bh)) {
-		req->nr_hw_segments += next->nr_hw_segments - 1;
-	} else if (req->nr_hw_segments + next->nr_hw_segments > SHpnt->sg_tablesize) {
+	if (bio_segs > q->max_segments)
 		return 0;
-	} else {
-		req->nr_hw_segments += next->nr_hw_segments;
-	}
-	req->nr_segments += next->nr_segments;
-	return 1;
-#else
-	/*
-	 * We know that the two requests at the boundary should not be combined.
-	 * Make sure we can fix something that is the sum of the two.
-	 * A slightly stricter test than we had above.
-	 */
-	if (req->nr_segments + next->nr_segments > max_segments ||
-	    req->nr_segments + next->nr_segments > SHpnt->sg_tablesize) {
-		return 0;
-	} else {
-		/*
-		 * This will form the start of a new segment.  Bump the 
-		 * counter.
-		 */
-		req->nr_segments += next->nr_segments;
-		return 1;
-	}
+
+	req->nr_hw_segments = bio_segs;
 #endif
-}
 
-/*
- * Function:    scsi_merge_requests_fn_()
- *
- * Purpose:     queue merge function.
- *
- * Arguments:   q       - Queue for which we are merging request.
- *              req     - request into which we wish to merge.
- *              bh      - Block which we may wish to merge into request
- *
- * Returns:     1 if it is OK to merge the block into the request.  0
- *              if it is not OK.
- *
- * Lock status: io_request_lock is assumed to be held here.
- *
- * Notes:       Optimized for different cases depending upon whether
- *              ISA DMA is in use and whether clustering should be used.
- */
-#define MERGEREQFCT(_FUNCTION, _CLUSTER, _DMA)		\
-static int _FUNCTION(request_queue_t * q,		\
-		     struct request * req,		\
-		     struct request * next,		\
-		     int max_segments)			\
-{							\
-    int ret;						\
-    SANITY_CHECK(req, _CLUSTER, _DMA);			\
-    ret =  __scsi_merge_requests_fn(q, req, next, max_segments, _CLUSTER, _DMA); \
-    return ret;						\
+	/*
+	 * This will form the start of a new segment.  Bump the 
+	 * counter.
+	 */
+	req->nr_segments = bio_segs;
+	return 1;
 }
 
-/* Version with use_clustering 0 and dma_host 1 is not necessary,
- * since the only use of dma_host above is protected by use_clustering.
- */
-MERGEREQFCT(scsi_merge_requests_fn_, 0, 0)
-MERGEREQFCT(scsi_merge_requests_fn_c, 1, 0)
-MERGEREQFCT(scsi_merge_requests_fn_dc, 1, 1)
 /*
  * Function:    __init_io()
  *
@@ -767,7 +436,6 @@
  *
  * Arguments:   SCpnt   - Command descriptor we wish to initialize
  *              sg_count_valid  - 1 if the sg count in the req is valid.
- *              use_clustering - 1 if this host wishes to use clustering
  *              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).
@@ -795,11 +463,9 @@
  */
 __inline static int __init_io(Scsi_Cmnd * SCpnt,
 			      int sg_count_valid,
-			      int use_clustering,
 			      int dma_host)
 {
-	struct buffer_head * bh;
-	struct buffer_head * bhprev;
+	struct bio	   * bio;
 	char		   * buff;
 	int		     count;
 	int		     i;
@@ -809,35 +475,13 @@
 	int		     this_count;
 	void		   ** bbpnt;
 
-	/*
-	 * FIXME(eric) - don't inline this - it doesn't depend on the
-	 * integer flags.   Come to think of it, I don't think this is even
-	 * needed any more.  Need to play with it and see if we hit the
-	 * panic.  If not, then don't bother.
-	 */
-	if (!SCpnt->request.bh) {
-		/* 
-		 * Case of page request (i.e. raw device), or unlinked buffer 
-		 * Typically used for swapping, but this isn't how we do
-		 * swapping any more.
-		 */
-		panic("I believe this is dead code.  If we hit this, I was wrong");
-#if 0
-		SCpnt->request_bufflen = SCpnt->request.nr_sectors << 9;
-		SCpnt->request_buffer = SCpnt->request.buffer;
-		SCpnt->use_sg = 0;
-		/*
-		 * FIXME(eric) - need to handle DMA here.
-		 */
-#endif
-		return 1;
-	}
 	req = &SCpnt->request;
+
 	/*
 	 * First we need to know how many scatter gather segments are needed.
 	 */
 	if (!sg_count_valid) {
-		count = __count_segments(req, use_clustering, dma_host, NULL);
+		count = __count_segments(req, dma_host, NULL);
 	} else {
 		count = req->nr_segments;
 	}
@@ -848,16 +492,15 @@
 	 * buffer.
 	 */
 	if (dma_host && scsi_dma_free_sectors <= 10) {
-		this_count = SCpnt->request.current_nr_sectors;
+		this_count = req->current_nr_sectors;
 		goto single_segment;
 	}
+
 	/*
-	 * Don't bother with scatter-gather if there is only one segment.
+	 * we used to not use scatter-gather for single segment request,
+	 * but now we do (it makes highmem I/O easier to support without
+	 * kmapping pages)
 	 */
-	if (count == 1) {
-		this_count = SCpnt->request.nr_sectors;
-		goto single_segment;
-	}
 	SCpnt->use_sg = count;
 
 	/* 
@@ -875,29 +518,26 @@
 	 * round it up.
 	 */
 	SCpnt->sglist_len = (SCpnt->sglist_len + 511) & ~511;
-
+ 
 	sgpnt = (struct scatterlist *) scsi_malloc(SCpnt->sglist_len);
 
-	/*
-	 * Now fill the scatter-gather table.
-	 */
 	if (!sgpnt) {
+		struct Scsi_Host *SHpnt = SCpnt->host;
+
 		/*
 		 * If we cannot allocate the scatter-gather table, then
 		 * simply write the first buffer all by itself.
 		 */
 		printk("Warning - running *really* short on DMA buffers\n");
-		this_count = SCpnt->request.current_nr_sectors;
+		this_count = req->current_nr_sectors;
+		printk("SCSI: depth is %d, # segs %d, # hw segs %d\n", SHpnt->host_busy, req->nr_segments, req->nr_hw_segments);
 		goto single_segment;
 	}
-	/* 
-	 * Next, walk the list, and fill in the addresses and sizes of
-	 * each segment.
-	 */
+
 	memset(sgpnt, 0, SCpnt->sglist_len);
 	SCpnt->request_buffer = (char *) sgpnt;
 	SCpnt->request_bufflen = 0;
-	bhprev = NULL;
+	req->buffer = NULL;
 
 	if (dma_host)
 		bbpnt = (void **) ((char *)sgpnt +
@@ -907,62 +547,30 @@
 
 	SCpnt->bounce_buffers = bbpnt;
 
-	for (count = 0, bh = SCpnt->request.bh;
-	     bh; bh = bh->b_reqnext) {
-		if (use_clustering && bhprev != NULL) {
-			if (dma_host &&
-			    virt_to_phys(bhprev->b_data) - 1 == ISA_DMA_THRESHOLD) {
-				/* Nothing - fall through */
-			} else if (CONTIGUOUS_BUFFERS(bhprev, bh)) {
-				/*
-				 * 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.
-				 */
-				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;
-				}
-			}
-		}
-		count++;
-		sgpnt[count - 1].address = bh->b_data;
-		sgpnt[count - 1].page = NULL;
-		sgpnt[count - 1].length += bh->b_size;
-		if (!dma_host) {
-			SCpnt->request_bufflen += bh->b_size;
-		}
-		bhprev = bh;
-	}
+	/* 
+	 * Next, walk the list, and fill in the addresses and sizes of
+	 * each segment.
+	 */
+	SCpnt->request_bufflen = req->nr_sectors << 9;
+	count = blk_rq_map_sg(req->q, req, SCpnt->request_buffer);
 
 	/*
 	 * Verify that the count is correct.
 	 */
-	if (count != SCpnt->use_sg) {
+	if (count > SCpnt->use_sg) {
 		printk("Incorrect number of segments after building list\n");
-#ifdef CONFIG_SCSI_DEBUG_QUEUES
-		dump_stats(req, use_clustering, dma_host, count);
-#endif
+		printk("counted %d, received %d\n", count, SCpnt->use_sg);
+		printk("req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors, req->current_nr_sectors);
+		scsi_free(SCpnt->request_buffer, SCpnt->sglist_len);
+		this_count = req->current_nr_sectors;
+		goto single_segment;
 	}
-	if (!dma_host) {
+
+	SCpnt->use_sg = count;
+
+	if (!dma_host)
 		return 1;
-	}
+
 	/*
 	 * Now allocate bounce buffers, if needed.
 	 */
@@ -971,7 +579,7 @@
 		sectors = (sgpnt[i].length >> 9);
 		SCpnt->request_bufflen += sgpnt[i].length;
 		if (virt_to_phys(sgpnt[i].address) + sgpnt[i].length - 1 >
-		    ISA_DMA_THRESHOLD) {
+                    ISA_DMA_THRESHOLD) {
 			if( scsi_dma_free_sectors - sectors <= 10  ) {
 				/*
 				 * If this would nearly drain the DMA
@@ -989,9 +597,12 @@
 				break;
 			}
 
-			bbpnt[i] = sgpnt[i].address;
-			sgpnt[i].address =
-			    (char *) scsi_malloc(sgpnt[i].length);
+			/*
+			 * this is not a dma host, so it will never
+			 * be a highmem page
+			 */
+			bbpnt[i] = page_address(sgpnt[i].page) +sgpnt[i].offset;
+			sgpnt[i].address = (char *)scsi_malloc(sgpnt[i].length);
 			/*
 			 * If we cannot allocate memory for this DMA bounce
 			 * buffer, then queue just what we have done so far.
@@ -1005,10 +616,9 @@
 				}
 				break;
 			}
-			if (SCpnt->request.cmd == WRITE) {
+			if (rq_data_dir(req) == WRITE)
 				memcpy(sgpnt[i].address, bbpnt[i],
 				       sgpnt[i].length);
-			}
 		}
 	}
 	return 1;
@@ -1050,21 +660,20 @@
 	 * single-block requests if we had hundreds of free sectors.
 	 */
 	if( scsi_dma_free_sectors > 30 ) {
-		for (this_count = 0, bh = SCpnt->request.bh;
-		     bh; bh = bh->b_reqnext) {
+		for (this_count = 0, bio = req->bio; bio; bio = bio->bi_next) {
 			if( scsi_dma_free_sectors - this_count < 30 
 			    || this_count == sectors )
 			{
 				break;
 			}
-			this_count += bh->b_size >> 9;
+			this_count += bio_sectors(bio);
 		}
 
 	} else {
 		/*
 		 * Yow!   Take the absolute minimum here.
 		 */
-		this_count = SCpnt->request.current_nr_sectors;
+		this_count = req->current_nr_sectors;
 	}
 
 	/*
@@ -1077,28 +686,33 @@
 	 * segment.  Possibly the entire request, or possibly a small
 	 * chunk of the entire request.
 	 */
-	bh = SCpnt->request.bh;
-	buff = SCpnt->request.buffer;
 
-	if (dma_host) {
+	bio = req->bio;
+	buff = req->buffer = bio_data(bio);
+
+	if (dma_host || PageHighMem(bio_page(bio))) {
 		/*
 		 * Allocate a DMA bounce buffer.  If the allocation fails, fall
 		 * back and allocate a really small one - enough to satisfy
 		 * the first buffer.
 		 */
-		if (virt_to_phys(SCpnt->request.bh->b_data)
-		    + (this_count << 9) - 1 > ISA_DMA_THRESHOLD) {
+		if (bio_to_phys(bio) + bio->bi_size - 1 > ISA_DMA_THRESHOLD) {
 			buff = (char *) scsi_malloc(this_count << 9);
 			if (!buff) {
 				printk("Warning - running low on DMA memory\n");
-				this_count = SCpnt->request.current_nr_sectors;
+				this_count = req->current_nr_sectors;
 				buff = (char *) scsi_malloc(this_count << 9);
 				if (!buff) {
 					dma_exhausted(SCpnt, 0);
+					return 0;
 				}
 			}
-			if (SCpnt->request.cmd == WRITE)
-				memcpy(buff, (char *) SCpnt->request.buffer, this_count << 9);
+			if (rq_data_dir(req) == WRITE) {
+				unsigned long flags;
+				char *buf = bio_kmap_irq(bio, &flags);
+				memcpy(buff, buf, this_count << 9);
+				bio_kunmap_irq(buf, &flags);
+			}
 		}
 	}
 	SCpnt->request_bufflen = this_count << 9;
@@ -1107,10 +721,10 @@
 	return 1;
 }
 
-#define INITIO(_FUNCTION, _VALID, _CLUSTER, _DMA)	\
-static int _FUNCTION(Scsi_Cmnd * SCpnt)			\
-{							\
-    return __init_io(SCpnt, _VALID, _CLUSTER, _DMA);	\
+#define INITIO(_FUNCTION, _VALID, _DMA)		\
+static int _FUNCTION(Scsi_Cmnd * SCpnt)		\
+{						\
+    return __init_io(SCpnt, _VALID, _DMA);	\
 }
 
 /*
@@ -1119,10 +733,8 @@
  * We always force "_VALID" to 1.  Eventually clean this up
  * and get rid of the extra argument.
  */
-INITIO(scsi_init_io_v, 1, 0, 0)
-INITIO(scsi_init_io_vd, 1, 0, 1)
-INITIO(scsi_init_io_vc, 1, 1, 0)
-INITIO(scsi_init_io_vdc, 1, 1, 1)
+INITIO(scsi_init_io_v, 1, 0)
+INITIO(scsi_init_io_vd, 1, 1)
 
 /*
  * Function:    initialize_merge_fn()
@@ -1139,21 +751,11 @@
  */
 void initialize_merge_fn(Scsi_Device * SDpnt)
 {
-	request_queue_t *q;
-	struct Scsi_Host *SHpnt;
-	SHpnt = SDpnt->host;
-
-	q = &SDpnt->request_queue;
+	struct Scsi_Host *SHpnt = SDpnt->host;
+	request_queue_t *q = &SDpnt->request_queue;
+	dma64_addr_t bounce_limit;
 
 	/*
-	 * If the host has already selected a merge manager, then don't
-	 * pick a new one.
-	 */
-#if 0
-	if (q->back_merge_fn && q->front_merge_fn)
-		return;
-#endif
-	/*
 	 * If this host has an unlimited tablesize, then don't bother with a
 	 * merge manager.  The whole point of the operation is to make sure
 	 * that requests don't grow too large, and this host isn't picky.
@@ -1164,25 +766,29 @@
 	 * is simply easier to do it ourselves with our own functions
 	 * rather than rely upon the default behavior of ll_rw_blk.
 	 */
-	if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
-		q->back_merge_fn = scsi_back_merge_fn_;
-		q->front_merge_fn = scsi_front_merge_fn_;
-		q->merge_requests_fn = scsi_merge_requests_fn_;
+	q->back_merge_fn = scsi_back_merge_fn;
+	q->front_merge_fn = scsi_front_merge_fn;
+	q->merge_requests_fn = scsi_merge_requests_fn;
+
+	if (SHpnt->unchecked_isa_dma == 0) {
 		SDpnt->scsi_init_io_fn = scsi_init_io_v;
-	} else if (!CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) {
-		q->back_merge_fn = scsi_back_merge_fn_;
-		q->front_merge_fn = scsi_front_merge_fn_;
-		q->merge_requests_fn = scsi_merge_requests_fn_;
+	} else {
 		SDpnt->scsi_init_io_fn = scsi_init_io_vd;
-	} else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma == 0) {
-		q->back_merge_fn = scsi_back_merge_fn_c;
-		q->front_merge_fn = scsi_front_merge_fn_c;
-		q->merge_requests_fn = scsi_merge_requests_fn_c;
-		SDpnt->scsi_init_io_fn = scsi_init_io_vc;
-	} else if (CLUSTERABLE_DEVICE(SHpnt, SDpnt) && SHpnt->unchecked_isa_dma != 0) {
-		q->back_merge_fn = scsi_back_merge_fn_dc;
-		q->front_merge_fn = scsi_front_merge_fn_dc;
-		q->merge_requests_fn = scsi_merge_requests_fn_dc;
-		SDpnt->scsi_init_io_fn = scsi_init_io_vdc;
 	}
+
+	/*
+	 * now enable highmem I/O, if appropriate
+	 */
+	bounce_limit = BLK_BOUNCE_HIGH;
+	if (SHpnt->highmem_io && (SDpnt->type == TYPE_DISK)) {
+		if (!PCI_DMA_BUS_IS_PHYS)
+			/* Platforms with virtual-DMA translation
+ 			 * hardware have no practical limit.
+			 */
+			bounce_limit = BLK_BOUNCE_ANY;
+		else
+			bounce_limit = SHpnt->pci_dev->dma_mask;
+	}
+
+	blk_queue_bounce_limit(q, bounce_limit);
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c
--- v2.5.0/linux/drivers/scsi/scsi_obsolete.c	Thu Jul  5 11:28:17 2001
+++ linux/drivers/scsi/scsi_obsolete.c	Wed Dec 31 16:00:00 1969
@@ -1,1119 +0,0 @@
-/*
- *  scsi_obsolete.c Copyright (C) 1992 Drew Eckhardt
- *         Copyright (C) 1993, 1994, 1995 Eric Youngdale
- *
- *  generic mid-level SCSI driver
- *      Initial versions: Drew Eckhardt
- *      Subsequent revisions: Eric Youngdale
- *
- *  <drew@colorado.edu>
- *
- *  Bug correction thanks go to :
- *      Rik Faith <faith@cs.unc.edu>
- *      Tommy Thorn <tthorn>
- *      Thomas Wuensche <tw@fgb1.fgb.mw.tu-muenchen.de>
- *
- *  Modified by Eric Youngdale eric@andante.org to
- *  add scatter-gather, multiple outstanding request, and other
- *  enhancements.
- *
- *  Native multichannel, wide scsi, /proc/scsi and hot plugging
- *  support added by Michael Neuffer <mike@i-connect.net>
- *
- *  Major improvements to the timeout, abort, and reset processing,
- *  as well as performance modifications for large queue depths by
- *  Leonard N. Zubkoff <lnz@dandelion.com>
- *
- *  Improved compatibility with 2.0 behaviour by Manfred Spraul
- *  <masp0008@stud.uni-sb.de>
- */
-
-/*
- *#########################################################################
- *#########################################################################
- *#########################################################################
- *#########################################################################
- *              NOTE - NOTE - NOTE - NOTE - NOTE - NOTE - NOTE
- *
- *#########################################################################
- *#########################################################################
- *#########################################################################
- *#########################################################################
- *
- * This file contains the 'old' scsi error handling.  It is only present
- * while the new error handling code is being debugged, and while the low
- * level drivers are being converted to use the new code.  Once the last
- * driver uses the new code this *ENTIRE* file will be nuked.
- */
-
-#define __NO_VERSION__
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/stat.h>
-#include <linux/blk.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-
-#include "scsi.h"
-#include "hosts.h"
-#include "constants.h"
-
-#undef USE_STATIC_SCSI_MEMORY
-
-/*
-   static const char RCSid[] = "$Header: /mnt/ide/home/eric/CVSROOT/linux/drivers/scsi/scsi_obsolete.c,v 1.1 1997/05/18 23:27:21 eric Exp $";
- */
-
-
-#define INTERNAL_ERROR (panic ("Internal error in file %s, line %d.\n", __FILE__, __LINE__))
-
-
-static int scsi_abort(Scsi_Cmnd *, int code);
-static int scsi_reset(Scsi_Cmnd *, unsigned int);
-
-extern void scsi_old_done(Scsi_Cmnd * SCpnt);
-int update_timeout(Scsi_Cmnd *, int);
-extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
-
-extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt);
-
-#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};
-
-/*
- *  This is the number  of clock ticks we should wait before we time out
- *  and abort the command.  This is for  where the scsi.c module generates
- *  the command, not where it originates from a higher level, in which
- *  case the timeout is specified there.
- *
- *  ABORT_TIMEOUT and RESET_TIMEOUT are the timeouts for RESET and ABORT
- *  respectively.
- */
-
-#ifdef DEBUG_TIMEOUT
-static void scsi_dump_status(void);
-#endif
-
-
-#ifdef DEBUG
-#define SCSI_TIMEOUT (5*HZ)
-#else
-#define SCSI_TIMEOUT (2*HZ)
-#endif
-
-#ifdef DEBUG
-#define SENSE_TIMEOUT SCSI_TIMEOUT
-#define ABORT_TIMEOUT SCSI_TIMEOUT
-#define RESET_TIMEOUT SCSI_TIMEOUT
-#else
-#define SENSE_TIMEOUT (5*HZ/10)
-#define RESET_TIMEOUT (5*HZ/10)
-#define ABORT_TIMEOUT (5*HZ/10)
-#endif
-
-
-/* Do not call reset on error if we just did a reset within 15 sec. */
-#define MIN_RESET_PERIOD (15*HZ)
-
-
-
-/*
- *  Flag bits for the internal_timeout array
- */
-#define IN_ABORT  1
-#define IN_RESET  2
-#define IN_RESET2 4
-#define IN_RESET3 8
-
-/*
- * This is our time out function, called when the timer expires for a
- * given host adapter.  It will attempt to abort the currently executing
- * command, that failing perform a kernel panic.
- */
-
-void scsi_old_times_out(Scsi_Cmnd * SCpnt)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_request_lock, flags);
-
-	/* Set the serial_number_at_timeout to the current serial_number */
-	SCpnt->serial_number_at_timeout = SCpnt->serial_number;
-
-	switch (SCpnt->internal_timeout & (IN_ABORT | IN_RESET | IN_RESET2 | IN_RESET3)) {
-	case NORMAL_TIMEOUT:
-		{
-#ifdef DEBUG_TIMEOUT
-			scsi_dump_status();
-#endif
-		}
-
-		if (!scsi_abort(SCpnt, DID_TIME_OUT))
-			break;
-	case IN_ABORT:
-		printk("SCSI host %d abort (pid %ld) timed out - resetting\n",
-		       SCpnt->host->host_no, SCpnt->pid);
-		if (!scsi_reset(SCpnt, SCSI_RESET_ASYNCHRONOUS))
-			break;
-	case IN_RESET:
-	case (IN_ABORT | IN_RESET):
-		/* This might be controversial, but if there is a bus hang,
-		 * you might conceivably want the machine up and running
-		 * esp if you have an ide disk.
-		 */
-		printk("SCSI host %d channel %d reset (pid %ld) timed out - "
-		       "trying harder\n",
-		       SCpnt->host->host_no, SCpnt->channel, SCpnt->pid);
-		SCpnt->internal_timeout &= ~IN_RESET;
-		SCpnt->internal_timeout |= IN_RESET2;
-		scsi_reset(SCpnt,
-		 SCSI_RESET_ASYNCHRONOUS | SCSI_RESET_SUGGEST_BUS_RESET);
-		break;
-	case IN_RESET2:
-	case (IN_ABORT | IN_RESET2):
-		/* Obviously the bus reset didn't work.
-		 * Let's try even harder and call for an HBA reset.
-		 * Maybe the HBA itself crashed and this will shake it loose.
-		 */
-		printk("SCSI host %d reset (pid %ld) timed out - trying to shake it loose\n",
-		       SCpnt->host->host_no, SCpnt->pid);
-		SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2);
-		SCpnt->internal_timeout |= IN_RESET3;
-		scsi_reset(SCpnt,
-		SCSI_RESET_ASYNCHRONOUS | SCSI_RESET_SUGGEST_HOST_RESET);
-		break;
-
-	default:
-		printk("SCSI host %d reset (pid %ld) timed out again -\n",
-		       SCpnt->host->host_no, SCpnt->pid);
-		printk("probably an unrecoverable SCSI bus or device hang.\n");
-		break;
-
-	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
-
-}
-
-/*
- *  From what I can find in scsi_obsolete.c, this function is only called
- *  by scsi_old_done and scsi_reset.  Both of these functions run with the
- *  io_request_lock already held, so we need do nothing here about grabbing
- *  any locks.
- */
-static void scsi_request_sense(Scsi_Cmnd * SCpnt)
-{
-	SCpnt->flags |= WAS_SENSE | ASKED_FOR_SENSE;
-	update_timeout(SCpnt, SENSE_TIMEOUT);
-
-
-	memcpy((void *) SCpnt->cmnd, (void *) generic_sense,
-	       sizeof(generic_sense));
-	memset((void *) SCpnt->sense_buffer, 0,
-	       sizeof(SCpnt->sense_buffer));
-
-	if (SCpnt->device->scsi_level <= SCSI_2)
-		SCpnt->cmnd[1] = SCpnt->lun << 5;
-	SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer);
-
-	SCpnt->request_buffer = &SCpnt->sense_buffer;
-	SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer);
-	SCpnt->use_sg = 0;
-	SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);
-	SCpnt->result = 0;
-	SCpnt->sc_data_direction = SCSI_DATA_READ;
-
-        /*
-         * Ugly, ugly.  The newer interfaces all assume that the lock
-         * isn't held.  Mustn't disappoint, or we deadlock the system.
-         */
-        spin_unlock_irq(&io_request_lock);
-	scsi_dispatch_cmd(SCpnt);
-        spin_lock_irq(&io_request_lock);
-}
-
-
-
-
-static int check_sense(Scsi_Cmnd * SCpnt)
-{
-	/* If there is no sense information, request it.  If we have already
-	 * requested it, there is no point in asking again - the firmware must
-	 * be confused.
-	 */
-	if (((SCpnt->sense_buffer[0] & 0x70) >> 4) != 7) {
-		if (!(SCpnt->flags & ASKED_FOR_SENSE))
-			return SUGGEST_SENSE;
-		else
-			return SUGGEST_RETRY;
-	}
-	SCpnt->flags &= ~ASKED_FOR_SENSE;
-
-#ifdef DEBUG_INIT
-	printk("scsi%d, channel%d : ", SCpnt->host->host_no, SCpnt->channel);
-	print_sense("", SCpnt);
-	printk("\n");
-#endif
-	if (SCpnt->sense_buffer[2] & 0xe0)
-		return SUGGEST_ABORT;
-
-	switch (SCpnt->sense_buffer[2] & 0xf) {
-	case NO_SENSE:
-		return 0;
-	case RECOVERED_ERROR:
-		return SUGGEST_IS_OK;
-
-	case ABORTED_COMMAND:
-		return SUGGEST_RETRY;
-	case NOT_READY:
-	case UNIT_ATTENTION:
-		/*
-		 * If we are expecting a CC/UA because of a bus reset that we
-		 * performed, treat this just as a retry.  Otherwise this is
-		 * information that we should pass up to the upper-level driver
-		 * so that we can deal with it there.
-		 */
-		if (SCpnt->device->expecting_cc_ua) {
-			SCpnt->device->expecting_cc_ua = 0;
-			return SUGGEST_RETRY;
-		}
-		return SUGGEST_ABORT;
-
-		/* these three are not supported */
-	case COPY_ABORTED:
-	case VOLUME_OVERFLOW:
-	case MISCOMPARE:
-
-	case MEDIUM_ERROR:
-		return SUGGEST_REMAP;
-	case BLANK_CHECK:
-	case DATA_PROTECT:
-	case HARDWARE_ERROR:
-	case ILLEGAL_REQUEST:
-	default:
-		return SUGGEST_ABORT;
-	}
-}
-
-/* This function is the mid-level interrupt routine, which decides how
- *  to handle error conditions.  Each invocation of this function must
- *  do one and *only* one of the following:
- *
- *  (1) Call last_cmnd[host].done.  This is done for fatal errors and
- *      normal completion, and indicates that the handling for this
- *      request is complete.
- *  (2) Call internal_cmnd to requeue the command.  This will result in
- *      scsi_done being called again when the retry is complete.
- *  (3) Call scsi_request_sense.  This asks the host adapter/drive for
- *      more information about the error condition.  When the information
- *      is available, scsi_done will be called again.
- *  (4) Call reset().  This is sort of a last resort, and the idea is that
- *      this may kick things loose and get the drive working again.  reset()
- *      automatically calls scsi_request_sense, and thus scsi_done will be
- *      called again once the reset is complete.
- *
- *      If none of the above actions are taken, the drive in question
- *      will hang. If more than one of the above actions are taken by
- *      scsi_done, then unpredictable behavior will result.
- */
-void scsi_old_done(Scsi_Cmnd * SCpnt)
-{
-	int status = 0;
-	int exit = 0;
-	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;
-	oldto = update_timeout(SCpnt, 0);
-
-#ifdef DEBUG_TIMEOUT
-	if (result)
-		printk("Non-zero result in scsi_done %x %d:%d\n",
-		       result, SCpnt->target, SCpnt->lun);
-#endif
-
-	/* If we requested an abort, (and we got it) then fix up the return
-	 *  status to say why
-	 */
-	if (host_byte(result) == DID_ABORT && SCpnt->abort_reason)
-		SCpnt->result = result = (result & 0xff00ffff) |
-		    (SCpnt->abort_reason << 16);
-
-
-#define CMD_FINISHED 0
-#define MAYREDO  1
-#define REDO     3
-#define PENDING  4
-
-#ifdef DEBUG
-	printk("In scsi_done(host = %d, result = %06x)\n", host->host_no, result);
-#endif
-
-	if (SCpnt->flags & SYNC_RESET) {
-		/*
-		   * The behaviou of scsi_reset(SYNC) was changed in 2.1.? .
-		   * The scsi mid-layer does a REDO after every sync reset, the driver
-		   * must not do that any more. In order to prevent old drivers from
-		   * crashing, all scsi_done() calls during sync resets are ignored.
-		 */
-		printk("scsi%d: device driver called scsi_done() "
-		       "for a synchronous reset.\n", SCpnt->host->host_no);
-		return;
-	}
-	if (SCpnt->flags & WAS_SENSE) {
-		SCpnt->use_sg = SCpnt->old_use_sg;
-		SCpnt->cmd_len = SCpnt->old_cmd_len;
-		SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-		SCpnt->underflow = SCpnt->old_underflow;
-	}
-	switch (host_byte(result)) {
-	case DID_OK:
-		if (status_byte(result) && (SCpnt->flags & WAS_SENSE))
-			/* Failed to obtain sense information */
-		{
-			SCpnt->flags &= ~WAS_SENSE;
-#if 0				/* This cannot possibly be correct. */
-			SCpnt->internal_timeout &= ~SENSE_TIMEOUT;
-#endif
-
-			if (!(SCpnt->flags & WAS_RESET)) {
-				printk("scsi%d : channel %d target %d lun %d request sense"
-				       " failed, performing reset.\n",
-				       SCpnt->host->host_no, SCpnt->channel, SCpnt->target,
-				       SCpnt->lun);
-				scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
-				status = REDO;
-				break;
-			} else {
-				exit = (DRIVER_HARD | SUGGEST_ABORT);
-				status = CMD_FINISHED;
-			}
-		} else
-			switch (msg_byte(result)) {
-			case COMMAND_COMPLETE:
-				switch (status_byte(result)) {
-				case GOOD:
-					if (SCpnt->flags & WAS_SENSE) {
-#ifdef DEBUG
-						printk("In scsi_done, GOOD status, COMMAND COMPLETE, "
-						       "parsing sense information.\n");
-#endif
-						SCpnt->flags &= ~WAS_SENSE;
-#if 0				/* This cannot possibly be correct. */
-						SCpnt->internal_timeout &= ~SENSE_TIMEOUT;
-#endif
-
-						switch (checked = check_sense(SCpnt)) {
-						case SUGGEST_SENSE:
-						case 0:
-#ifdef DEBUG
-							printk("NO SENSE.  status = REDO\n");
-#endif
-							update_timeout(SCpnt, oldto);
-							status = REDO;
-							break;
-						case SUGGEST_IS_OK:
-							break;
-						case SUGGEST_REMAP:
-#ifdef DEBUG
-							printk("SENSE SUGGEST REMAP - status = CMD_FINISHED\n");
-#endif
-							status = CMD_FINISHED;
-							exit = DRIVER_SENSE | SUGGEST_ABORT;
-							break;
-						case SUGGEST_RETRY:
-#ifdef DEBUG
-							printk("SENSE SUGGEST RETRY - status = MAYREDO\n");
-#endif
-							status = MAYREDO;
-							exit = DRIVER_SENSE | SUGGEST_RETRY;
-							break;
-						case SUGGEST_ABORT:
-#ifdef DEBUG
-							printk("SENSE SUGGEST ABORT - status = CMD_FINISHED");
-#endif
-							status = CMD_FINISHED;
-							exit = DRIVER_SENSE | SUGGEST_ABORT;
-							break;
-						default:
-							printk("Internal error %s %d \n", __FILE__,
-							       __LINE__);
-						}
-					}
-					/* end WAS_SENSE */
-					else {
-#ifdef DEBUG
-						printk("COMMAND COMPLETE message returned, "
-						       "status = CMD_FINISHED. \n");
-#endif
-						exit = DRIVER_OK;
-						status = CMD_FINISHED;
-					}
-					break;
-
-				case CHECK_CONDITION:
-				case COMMAND_TERMINATED:
-					switch (check_sense(SCpnt)) {
-					case 0:
-						update_timeout(SCpnt, oldto);
-						status = REDO;
-						break;
-					case SUGGEST_REMAP:
-						status = CMD_FINISHED;
-						exit = DRIVER_SENSE | SUGGEST_ABORT;
-						break;
-					case SUGGEST_RETRY:
-						status = MAYREDO;
-						exit = DRIVER_SENSE | SUGGEST_RETRY;
-						break;
-					case SUGGEST_ABORT:
-						status = CMD_FINISHED;
-						exit = DRIVER_SENSE | SUGGEST_ABORT;
-						break;
-					case SUGGEST_SENSE:
-						scsi_request_sense(SCpnt);
-						status = PENDING;
-						break;
-					}
-					break;
-
-				case CONDITION_GOOD:
-				case INTERMEDIATE_GOOD:
-				case INTERMEDIATE_C_GOOD:
-					break;
-
-				case BUSY:
-				case QUEUE_FULL:
-					update_timeout(SCpnt, oldto);
-					status = REDO;
-					break;
-
-				case RESERVATION_CONFLICT:
-					printk("scsi%d, channel %d : RESERVATION CONFLICT performing"
-					       " reset.\n", SCpnt->host->host_no, SCpnt->channel);
-					scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
-					status = REDO;
-					break;
-				default:
-					printk("Internal error %s %d \n"
-					 "status byte = %d \n", __FILE__,
-					  __LINE__, status_byte(result));
-
-				}
-				break;
-			default:
-				panic("scsi: unsupported message byte %d received\n",
-				      msg_byte(result));
-			}
-		break;
-	case DID_TIME_OUT:
-#ifdef DEBUG
-		printk("Host returned DID_TIME_OUT - ");
-#endif
-
-		if (SCpnt->flags & WAS_TIMEDOUT) {
-#ifdef DEBUG
-			printk("Aborting\n");
-#endif
-			/*
-			   Allow TEST_UNIT_READY and INQUIRY commands to timeout early
-			   without causing resets.  All other commands should be retried.
-			 */
-			if (SCpnt->cmnd[0] != TEST_UNIT_READY &&
-			    SCpnt->cmnd[0] != INQUIRY)
-				status = MAYREDO;
-			exit = (DRIVER_TIMEOUT | SUGGEST_ABORT);
-		} else {
-#ifdef DEBUG
-			printk("Retrying.\n");
-#endif
-			SCpnt->flags |= WAS_TIMEDOUT;
-			SCpnt->internal_timeout &= ~IN_ABORT;
-			status = REDO;
-		}
-		break;
-	case DID_BUS_BUSY:
-	case DID_PARITY:
-		status = REDO;
-		break;
-	case DID_NO_CONNECT:
-#ifdef DEBUG
-		printk("Couldn't connect.\n");
-#endif
-		exit = (DRIVER_HARD | SUGGEST_ABORT);
-		break;
-	case DID_ERROR:
-		status = MAYREDO;
-		exit = (DRIVER_HARD | SUGGEST_ABORT);
-		break;
-	case DID_BAD_TARGET:
-	case DID_ABORT:
-		exit = (DRIVER_INVALID | SUGGEST_ABORT);
-		break;
-	case DID_RESET:
-		if (SCpnt->flags & IS_RESETTING) {
-			SCpnt->flags &= ~IS_RESETTING;
-			status = REDO;
-			break;
-		}
-		if (msg_byte(result) == GOOD &&
-		    status_byte(result) == CHECK_CONDITION) {
-			switch (check_sense(SCpnt)) {
-			case 0:
-				update_timeout(SCpnt, oldto);
-				status = REDO;
-				break;
-			case SUGGEST_REMAP:
-			case SUGGEST_RETRY:
-				status = MAYREDO;
-				exit = DRIVER_SENSE | SUGGEST_RETRY;
-				break;
-			case SUGGEST_ABORT:
-				status = CMD_FINISHED;
-				exit = DRIVER_SENSE | SUGGEST_ABORT;
-				break;
-			case SUGGEST_SENSE:
-				scsi_request_sense(SCpnt);
-				status = PENDING;
-				break;
-			}
-		} else {
-			status = REDO;
-			exit = SUGGEST_RETRY;
-		}
-		break;
-	default:
-		exit = (DRIVER_ERROR | SUGGEST_DIE);
-	}
-
-	switch (status) {
-	case CMD_FINISHED:
-	case PENDING:
-		break;
-	case MAYREDO:
-#ifdef DEBUG
-		printk("In MAYREDO, allowing %d retries, have %d\n",
-		       SCpnt->allowed, SCpnt->retries);
-#endif
-		if ((++SCpnt->retries) < SCpnt->allowed) {
-			if ((SCpnt->retries >= (SCpnt->allowed >> 1))
-			    && !(SCpnt->host->resetting && time_before(jiffies, SCpnt->host->last_reset + MIN_RESET_PERIOD))
-			    && !(SCpnt->flags & WAS_RESET)) {
-				printk("scsi%d channel %d : resetting for second half of retries.\n",
-				   SCpnt->host->host_no, SCpnt->channel);
-				scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
-				/* fall through to REDO */
-			}
-		} else {
-			status = CMD_FINISHED;
-			break;
-		}
-		/* fall through to REDO */
-
-	case REDO:
-
-		if (SCpnt->flags & WAS_SENSE)
-			scsi_request_sense(SCpnt);
-		else {
-			memcpy((void *) SCpnt->cmnd,
-			       (void *) SCpnt->data_cmnd,
-			       sizeof(SCpnt->data_cmnd));
-			memset((void *) SCpnt->sense_buffer, 0,
-			       sizeof(SCpnt->sense_buffer));
-			SCpnt->request_buffer = SCpnt->buffer;
-			SCpnt->request_bufflen = SCpnt->bufflen;
-			SCpnt->use_sg = SCpnt->old_use_sg;
-			SCpnt->cmd_len = SCpnt->old_cmd_len;
-			SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-			SCpnt->underflow = SCpnt->old_underflow;
-			SCpnt->result = 0;
-                        /*
-                         * Ugly, ugly.  The newer interfaces all
-                         * assume that the lock isn't held.  Mustn't
-                         * disappoint, or we deadlock the system.  
-                         */
-                        spin_unlock_irq(&io_request_lock);
-			scsi_dispatch_cmd(SCpnt);
-                        spin_lock_irq(&io_request_lock);
-		}
-		break;
-	default:
-		INTERNAL_ERROR;
-	}
-
-	if (status == CMD_FINISHED) {
-		Scsi_Request *SRpnt;
-#ifdef DEBUG
-		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;
-		SCpnt->cmd_len = SCpnt->old_cmd_len;
-		SCpnt->sc_data_direction = SCpnt->sc_old_data_direction;
-		SCpnt->underflow = SCpnt->old_underflow;
-                /*
-                 * The upper layers assume the lock isn't held.  We mustn't
-                 * disappoint them.  When the new error handling code is in
-                 * use, the upper code is run from a bottom half handler, so
-                 * it isn't an issue.
-                 */
-                spin_unlock_irq(&io_request_lock);
-		SRpnt = SCpnt->sc_request;
-		if( SRpnt != NULL ) {
-			SRpnt->sr_result = SRpnt->sr_command->result;
-			if( SRpnt->sr_result != 0 ) {
-				memcpy(SRpnt->sr_sense_buffer,
-				       SRpnt->sr_command->sense_buffer,
-				       sizeof(SRpnt->sr_sense_buffer));
-			}
-		}
-
-		SCpnt->done(SCpnt);
-                spin_lock_irq(&io_request_lock);
-	}
-#undef CMD_FINISHED
-#undef REDO
-#undef MAYREDO
-#undef PENDING
-}
-
-/*
- * The scsi_abort function interfaces with the abort() function of the host
- * we are aborting, and causes the current command to not complete.  The
- * caller should deal with any error messages or status returned on the
- * next call.
- *
- * This will not be called reentrantly for a given host.
- */
-
-/*
- * Since we're nice guys and specified that abort() and reset()
- * can be non-reentrant.  The internal_timeout flags are used for
- * this.
- */
-
-
-static int scsi_abort(Scsi_Cmnd * SCpnt, int why)
-{
-	int oldto;
-	struct Scsi_Host *host = SCpnt->host;
-
-	while (1) {
-
-		/*
-		 * Protect against races here.  If the command is done, or we are
-		 * on a different command forget it.
-		 */
-		if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) {
-			return 0;
-		}
-		if (SCpnt->internal_timeout & IN_ABORT) {
-			spin_unlock_irq(&io_request_lock);
-			while (SCpnt->internal_timeout & IN_ABORT)
-				barrier();
-			spin_lock_irq(&io_request_lock);
-		} else {
-			SCpnt->internal_timeout |= IN_ABORT;
-			oldto = update_timeout(SCpnt, ABORT_TIMEOUT);
-
-			if ((SCpnt->flags & IS_RESETTING) && SCpnt->device->soft_reset) {
-				/* OK, this command must have died when we did the
-				 *  reset.  The device itself must have lied.
-				 */
-				printk("Stale command on %d %d:%d appears to have died when"
-				       " the bus was reset\n",
-				       SCpnt->channel, SCpnt->target, SCpnt->lun);
-			}
-			if (!host->host_busy) {
-				SCpnt->internal_timeout &= ~IN_ABORT;
-				update_timeout(SCpnt, oldto);
-				return 0;
-			}
-			printk("scsi : aborting command due to timeout : pid %lu, scsi%d,"
-			       " channel %d, id %d, lun %d ",
-			       SCpnt->pid, SCpnt->host->host_no, (int) SCpnt->channel,
-			       (int) SCpnt->target, (int) SCpnt->lun);
-			print_command(SCpnt->cmnd);
-			if (SCpnt->serial_number != SCpnt->serial_number_at_timeout)
-				return 0;
-			SCpnt->abort_reason = why;
-			switch (host->hostt->abort(SCpnt)) {
-				/* We do not know how to abort.  Try waiting another
-				 * time increment and see if this helps. Set the
-				 * WAS_TIMEDOUT flag set so we do not try this twice
-				 */
-			case SCSI_ABORT_BUSY:	/* Tough call - returning 1 from
-						 * this is too severe
-						 */
-			case SCSI_ABORT_SNOOZE:
-				if (why == DID_TIME_OUT) {
-					SCpnt->internal_timeout &= ~IN_ABORT;
-					if (SCpnt->flags & WAS_TIMEDOUT) {
-						return 1;	/* Indicate we cannot handle this.
-								 * We drop down into the reset handler
-								 * and try again
-								 */
-					} else {
-						SCpnt->flags |= WAS_TIMEDOUT;
-						oldto = SCpnt->timeout_per_command;
-						update_timeout(SCpnt, oldto);
-					}
-				}
-				return 0;
-			case SCSI_ABORT_PENDING:
-				if (why != DID_TIME_OUT) {
-					update_timeout(SCpnt, oldto);
-				}
-				return 0;
-			case SCSI_ABORT_SUCCESS:
-				/* We should have already aborted this one.  No
-				 * need to adjust timeout
-				 */
-				SCpnt->internal_timeout &= ~IN_ABORT;
-				return 0;
-			case SCSI_ABORT_NOT_RUNNING:
-				SCpnt->internal_timeout &= ~IN_ABORT;
-				update_timeout(SCpnt, 0);
-				return 0;
-			case SCSI_ABORT_ERROR:
-			default:
-				SCpnt->internal_timeout &= ~IN_ABORT;
-				return 1;
-			}
-		}
-	}
-}
-
-
-/* Mark a single SCSI Device as having been reset. */
-
-static inline void scsi_mark_device_reset(Scsi_Device * Device)
-{
-	Device->was_reset = 1;
-	Device->expecting_cc_ua = 1;
-}
-
-
-/* Mark all SCSI Devices on a specific Host as having been reset. */
-
-void scsi_mark_host_reset(struct Scsi_Host *Host)
-{
-	Scsi_Cmnd *SCpnt;
-	Scsi_Device *SDpnt;
-
-	for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-		for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
-			scsi_mark_device_reset(SCpnt->device);
-	}
-}
-
-
-/* Mark all SCSI Devices on a specific Host Bus as having been reset. */
-
-static void scsi_mark_bus_reset(struct Scsi_Host *Host, int channel)
-{
-	Scsi_Cmnd *SCpnt;
-	Scsi_Device *SDpnt;
-
-	for (SDpnt = Host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-		for (SCpnt = SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next)
-			if (SCpnt->channel == channel)
-				scsi_mark_device_reset(SCpnt->device);
-	}
-}
-
-
-static int scsi_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
-{
-	int temp;
-	Scsi_Cmnd *SCpnt1;
-	Scsi_Device *SDpnt;
-	struct Scsi_Host *host = SCpnt->host;
-
-	printk("SCSI bus is being reset for host %d channel %d.\n",
-	       host->host_no, SCpnt->channel);
-
-#if 0
-	/*
-	 * First of all, we need to make a recommendation to the low-level
-	 * driver as to whether a BUS_DEVICE_RESET should be performed,
-	 * or whether we should do a full BUS_RESET.  There is no simple
-	 * algorithm here - we basically use a series of heuristics
-	 * to determine what we should do.
-	 */
-	SCpnt->host->suggest_bus_reset = FALSE;
-
-	/*
-	 * First see if all of the active devices on the bus have
-	 * been jammed up so that we are attempting resets.  If so,
-	 * then suggest a bus reset.  Forcing a bus reset could
-	 * result in some race conditions, but no more than
-	 * you would usually get with timeouts.  We will cross
-	 * that bridge when we come to it.
-	 *
-	 * This is actually a pretty bad idea, since a sequence of
-	 * commands will often timeout together and this will cause a
-	 * Bus Device Reset followed immediately by a SCSI Bus Reset.
-	 * If all of the active devices really are jammed up, the
-	 * Bus Device Reset will quickly timeout and scsi_times_out
-	 * will follow up with a SCSI Bus Reset anyway.
-	 */
-	SCpnt1 = host->host_queue;
-	while (SCpnt1) {
-		if (SCpnt1->request.rq_status != RQ_INACTIVE
-		    && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0)
-			break;
-		SCpnt1 = SCpnt1->next;
-	}
-	if (SCpnt1 == NULL) {
-		reset_flags |= SCSI_RESET_SUGGEST_BUS_RESET;
-	}
-	/*
-	 * If the code that called us is suggesting a hard reset, then
-	 * definitely request it.  This usually occurs because a
-	 * BUS_DEVICE_RESET times out.
-	 *
-	 * Passing reset_flags along takes care of this automatically.
-	 */
-	if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) {
-		SCpnt->host->suggest_bus_reset = TRUE;
-	}
-#endif
-
-	while (1) {
-
-		/*
-		 * Protect against races here.  If the command is done, or we are
-		 * on a different command forget it.
-		 */
-		if (reset_flags & SCSI_RESET_ASYNCHRONOUS)
-			if (SCpnt->serial_number != SCpnt->serial_number_at_timeout) {
-				return 0;
-			}
-		if (SCpnt->internal_timeout & IN_RESET) {
-			spin_unlock_irq(&io_request_lock);
-			while (SCpnt->internal_timeout & IN_RESET)
-				barrier();
-			spin_lock_irq(&io_request_lock);
-		} else {
-			SCpnt->internal_timeout |= IN_RESET;
-			update_timeout(SCpnt, RESET_TIMEOUT);
-
-			if (reset_flags & SCSI_RESET_SYNCHRONOUS)
-				SCpnt->flags |= SYNC_RESET;
-			if (host->host_busy) {
-				for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-					SCpnt1 = SDpnt->device_queue;
-					while (SCpnt1) {
-						if (SCpnt1->request.rq_status != RQ_INACTIVE) {
-#if 0
-							if (!(SCpnt1->flags & IS_RESETTING) &&
-							    !(SCpnt1->internal_timeout & IN_ABORT))
-								scsi_abort(SCpnt1, DID_RESET);
-#endif
-							SCpnt1->flags |= (WAS_RESET | IS_RESETTING);
-						}
-						SCpnt1 = SCpnt1->next;
-					}
-				}
-
-				host->last_reset = jiffies;
-				host->resetting = 1;
-				/*
-				 * I suppose that the host reset callback will not play
-				 * with the resetting field. We have just set the resetting
-				 * flag here. -arca
-				 */
-				temp = host->hostt->reset(SCpnt, reset_flags);
-				/*
-				   This test allows the driver to introduce an additional bus
-				   settle time delay by setting last_reset up to 20 seconds in
-				   the future.  In the normal case where the driver does not
-				   modify last_reset, it must be assumed that the actual bus
-				   reset occurred immediately prior to the return to this code,
-				   and so last_reset must be updated to the current time, so
-				   that the delay in internal_cmnd will guarantee at least a
-				   MIN_RESET_DELAY bus settle time.
-				 */
-				if (host->last_reset - jiffies > 20UL * HZ)
-					host->last_reset = jiffies;
-			} else {
-				host->host_busy++;
-				host->last_reset = jiffies;
-				host->resetting = 1;
-				SCpnt->flags |= (WAS_RESET | IS_RESETTING);
-				/*
-				 * I suppose that the host reset callback will not play
-				 * with the resetting field. We have just set the resetting
-				 * flag here. -arca
-				 */
-				temp = host->hostt->reset(SCpnt, reset_flags);
-				if (time_before(host->last_reset, jiffies) ||
-				    (time_after(host->last_reset, jiffies + 20 * HZ)))
-					host->last_reset = jiffies;
-				host->host_busy--;
-			}
-			if (reset_flags & SCSI_RESET_SYNCHRONOUS)
-				SCpnt->flags &= ~SYNC_RESET;
-
-#ifdef DEBUG
-			printk("scsi reset function returned %d\n", temp);
-#endif
-
-			/*
-			 * Now figure out what we need to do, based upon
-			 * what the low level driver said that it did.
-			 * If the result is SCSI_RESET_SUCCESS, SCSI_RESET_PENDING,
-			 * or SCSI_RESET_WAKEUP, then the low level driver did a
-			 * bus device reset or bus reset, so we should go through
-			 * and mark one or all of the devices on that bus
-			 * as having been reset.
-			 */
-			switch (temp & SCSI_RESET_ACTION) {
-			case SCSI_RESET_SUCCESS:
-				if (temp & SCSI_RESET_HOST_RESET)
-					scsi_mark_host_reset(host);
-				else if (temp & SCSI_RESET_BUS_RESET)
-					scsi_mark_bus_reset(host, SCpnt->channel);
-				else
-					scsi_mark_device_reset(SCpnt->device);
-				SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3);
-				return 0;
-			case SCSI_RESET_PENDING:
-				if (temp & SCSI_RESET_HOST_RESET)
-					scsi_mark_host_reset(host);
-				else if (temp & SCSI_RESET_BUS_RESET)
-					scsi_mark_bus_reset(host, SCpnt->channel);
-				else
-					scsi_mark_device_reset(SCpnt->device);
-			case SCSI_RESET_NOT_RUNNING:
-				return 0;
-			case SCSI_RESET_PUNT:
-				SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3);
-				scsi_request_sense(SCpnt);
-				return 0;
-			case SCSI_RESET_WAKEUP:
-				if (temp & SCSI_RESET_HOST_RESET)
-					scsi_mark_host_reset(host);
-				else if (temp & SCSI_RESET_BUS_RESET)
-					scsi_mark_bus_reset(host, SCpnt->channel);
-				else
-					scsi_mark_device_reset(SCpnt->device);
-				SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3);
-				scsi_request_sense(SCpnt);
-				/*
-				 * If a bus reset was performed, we
-				 * need to wake up each and every command
-				 * that was active on the bus or if it was a HBA
-				 * reset all active commands on all channels
-				 */
-				if (temp & SCSI_RESET_HOST_RESET) {
-					for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-						SCpnt1 = SDpnt->device_queue;
-						while (SCpnt1) {
-							if (SCpnt1->request.rq_status != RQ_INACTIVE
-							    && SCpnt1 != SCpnt)
-								scsi_request_sense(SCpnt1);
-							SCpnt1 = SCpnt1->next;
-						}
-					}
-				} else if (temp & SCSI_RESET_BUS_RESET) {
-					for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
-						SCpnt1 = SDpnt->device_queue;
-						while (SCpnt1) {
-							if (SCpnt1->request.rq_status != RQ_INACTIVE
-							&& SCpnt1 != SCpnt
-							    && SCpnt1->channel == SCpnt->channel)
-								scsi_request_sense(SCpnt);
-							SCpnt1 = SCpnt1->next;
-						}
-					}
-				}
-				return 0;
-			case SCSI_RESET_SNOOZE:
-				/* In this case, we set the timeout field to 0
-				 * so that this command does not time out any more,
-				 * and we return 1 so that we get a message on the
-				 * screen.
-				 */
-				SCpnt->internal_timeout &= ~(IN_RESET | IN_RESET2 | IN_RESET3);
-				update_timeout(SCpnt, 0);
-				/* If you snooze, you lose... */
-			case SCSI_RESET_ERROR:
-			default:
-				return 1;
-			}
-
-			return temp;
-		}
-	}
-}
-
-/*
- * The strategy is to cause the timer code to call scsi_times_out()
- * when the soonest timeout is pending.
- * The arguments are used when we are queueing a new command, because
- * we do not want to subtract the time used from this time, but when we
- * set the timer, we want to take this value into account.
- */
-
-int update_timeout(Scsi_Cmnd * SCset, int timeout)
-{
-	int rtn;
-
-	/*
-	 * We are using the new error handling code to actually register/deregister
-	 * timers for timeout.
-	 */
-
-	if (!timer_pending(&SCset->eh_timeout)) {
-		rtn = 0;
-	} else {
-		rtn = SCset->eh_timeout.expires - jiffies;
-	}
-
-	if (timeout == 0) {
-		scsi_delete_timer(SCset);
-	} else {
-		scsi_add_timer(SCset, timeout, scsi_old_times_out);
-	}
-
-	return rtn;
-}
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi_queue.c linux/drivers/scsi/scsi_queue.c
--- v2.5.0/linux/drivers/scsi/scsi_queue.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/scsi/scsi_queue.c	Tue Nov 27 09:23:27 2001
@@ -80,6 +80,7 @@
 {
 	struct Scsi_Host *host;
 	unsigned long flags;
+	request_queue_t *q = &cmd->device->request_queue;
 
 	SCSI_LOG_MLQUEUE(1, printk("Inserting command %p into mlqueue\n", cmd));
 
@@ -137,10 +138,10 @@
 	 * Decrement the counters, since these commands are no longer
 	 * active on the host/device.
 	 */
-	spin_lock_irqsave(&io_request_lock, flags);
+	spin_lock_irqsave(&q->queue_lock, flags);
 	cmd->host->host_busy--;
 	cmd->device->device_busy--;
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&q->queue_lock, flags);
 
 	/*
 	 * Insert this command at the head of the queue for it's device.
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.5.0/linux/drivers/scsi/scsi_syms.c	Mon Jul  2 15:27:56 2001
+++ linux/drivers/scsi/scsi_syms.c	Wed Nov 28 10:22:27 2001
@@ -54,7 +54,6 @@
 EXPORT_SYMBOL(scsi_release_command);
 EXPORT_SYMBOL(print_Scsi_Cmnd);
 EXPORT_SYMBOL(scsi_block_when_processing_errors);
-EXPORT_SYMBOL(scsi_mark_host_reset);
 EXPORT_SYMBOL(scsi_ioctl_send_command);
 #if defined(CONFIG_SCSI_LOGGING)	/* { */
 EXPORT_SYMBOL(scsi_logging_level);
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.5.0/linux/drivers/scsi/sd.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/sd.c	Sat Dec  8 20:02:47 2001
@@ -61,10 +61,6 @@
 
 #include <linux/genhd.h>
 
-/*
- *  static const char RCSid[] = "$Header:";
- */
-
 #define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i))
 
 #define SCSI_DISKS_PER_MAJOR	16
@@ -72,8 +68,7 @@
 #define SD_MINOR_NUMBER(i)	((i) & 255)
 #define MKDEV_SD_PARTITION(i)	MKDEV(SD_MAJOR_NUMBER(i), (i) & 255)
 #define MKDEV_SD(index)		MKDEV_SD_PARTITION((index) << 4)
-#define N_USED_SCSI_DISKS  (sd_template.dev_max + SCSI_DISKS_PER_MAJOR - 1)
-#define N_USED_SD_MAJORS   (N_USED_SCSI_DISKS / SCSI_DISKS_PER_MAJOR)
+#define N_USED_SD_MAJORS	(1 + ((sd_template.dev_max - 1) >> 4))
 
 #define MAX_RETRIES 5
 
@@ -89,7 +84,6 @@
 static Scsi_Disk *rscsi_disks;
 static int *sd_sizes;
 static int *sd_blocksizes;
-static int *sd_hardsizes;	/* Hardware sector size */
 static int *sd_max_sectors;
 
 static int check_scsidisk_media_change(kdev_t);
@@ -97,7 +91,6 @@
 
 static int sd_init_onedisk(int);
 
-
 static int sd_init(void);
 static void sd_finish(void);
 static int sd_attach(Scsi_Device *);
@@ -124,7 +117,6 @@
 	init_command:sd_init_command,
 };
 
-
 static void rw_intr(Scsi_Cmnd * SCpnt);
 
 #if defined(CONFIG_PPC)
@@ -191,11 +183,11 @@
 					    &diskinfo[0]);
 			else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
 					dev, &diskinfo[0]);
-
 			if (put_user(diskinfo[0], &loc->heads) ||
 				put_user(diskinfo[1], &loc->sectors) ||
 				put_user(diskinfo[2], &loc->cylinders) ||
-				put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start))
+				put_user((unsigned) get_start_sect(inode->i_rdev),
+					 (unsigned long *) &loc->start))
 				return -EFAULT;
 			return 0;
 		}
@@ -226,7 +218,8 @@
 			if (put_user(diskinfo[0], &loc->heads) ||
 				put_user(diskinfo[1], &loc->sectors) ||
 				put_user(diskinfo[2], (unsigned int *) &loc->cylinders) ||
-				put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start))
+				put_user((unsigned)get_start_sect(inode->i_rdev),
+					 (unsigned long *)&loc->start))
 				return -EFAULT;
 			return 0;
 		}
@@ -239,8 +232,8 @@
 		case BLKFLSBUF:
 		case BLKSSZGET:
 		case BLKPG:
-		case BLKELVGET:
-		case BLKELVSET:
+                case BLKELVGET:
+                case BLKELVSET:
 		case BLKBSZGET:
 		case BLKBSZSET:
 			return blk_ioctl(inode->i_rdev, cmd, arg);
@@ -251,7 +244,8 @@
 			return revalidate_scsidisk(dev, 1);
 
 		default:
-			return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg);
+			return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device,
+					  cmd, (void *) arg);
 	}
 }
 
@@ -292,6 +286,12 @@
 	char nbuff[6];
 #endif
 
+	/*
+	 * don't support specials for nwo
+	 */
+	if (!(SCpnt->request.flags & REQ_CMD))
+		return 0;
+
 	devm = SD_PARTITION(SCpnt->request.rq_dev);
 	dev = DEVICE_NR(SCpnt->request.rq_dev);
 
@@ -301,7 +301,7 @@
 	SCSI_LOG_HLQUEUE(1, printk("Doing sd request, dev = %d, block = %d\n", devm, block));
 
 	dpnt = &rscsi_disks[dev];
-	if (devm >= (sd_template.dev_max << 4) ||
+	if (devm >= (sd_template.dev_max << 4) || (devm & 0xf) ||
 	    !dpnt ||
 	    !dpnt->device->online ||
  	    block + SCpnt->request.nr_sectors > sd[devm].nr_sects) {
@@ -309,7 +309,7 @@
 		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
 		return 0;
 	}
-	block += sd[devm].start_sect;
+
 	if (dpnt->device->changed) {
 		/*
 		 * quietly refuse to do anything to a changed disc until the changed
@@ -360,21 +360,17 @@
 			this_count = this_count >> 3;
 		}
 	}
-	switch (SCpnt->request.cmd) {
-	case WRITE:
+	if (rq_data_dir(&SCpnt->request) == WRITE) {
 		if (!dpnt->device->writeable) {
 			return 0;
 		}
 		SCpnt->cmnd[0] = WRITE_6;
 		SCpnt->sc_data_direction = SCSI_DATA_WRITE;
-		break;
-	case READ:
+	} else if (rq_data_dir(&SCpnt->request) == READ) {
 		SCpnt->cmnd[0] = READ_6;
 		SCpnt->sc_data_direction = SCSI_DATA_READ;
-		break;
-	default:
-		panic("Unknown sd command %d\n", SCpnt->request.cmd);
-	}
+	} else
+		panic("Unknown sd command %lx\n", SCpnt->request.flags);
 
 	SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n",
 				   nbuff,
@@ -618,8 +614,8 @@
 			(SCpnt->sense_buffer[4] << 16) |
 			(SCpnt->sense_buffer[5] << 8) |
 			SCpnt->sense_buffer[6];
-			if (SCpnt->request.bh != NULL)
-				block_sectors = SCpnt->request.bh->b_size >> 9;
+			if (SCpnt->request.bio != NULL)
+				block_sectors = bio_sectors(SCpnt->request.bio);
 			switch (SCpnt->device->sector_size) {
 			case 1024:
 				error_sector <<= 1;
@@ -642,7 +638,7 @@
 			default:
 				break;
 			}
-			error_sector -= sd[SD_PARTITION(SCpnt->request.rq_dev)].start_sect;
+
 			error_sector &= ~(block_sectors - 1);
 			good_sectors = error_sector - SCpnt->request.sector;
 			if (good_sectors < 0 || good_sectors >= this_count)
@@ -970,15 +966,11 @@
 			 * So I have created this table. See ll_rw_blk.c
 			 * Jacques Gelinas (Jacques@solucorp.qc.ca)
 			 */
-			int m;
 			int hard_sector = sector_size;
 			int sz = rscsi_disks[i].capacity * (hard_sector/256);
 
 			/* There are 16 minors allocated for each major device */
-			for (m = i << 4; m < ((i + 1) << 4); m++) {
-				sd_hardsizes[m] = hard_sector;
-			}
-
+			blk_queue_hardsect_size(blk_get_queue(SD_MAJOR(i)), hard_sector);
 			printk("SCSI device %s: "
 			       "%d %d-byte hdwr sectors (%d MB)\n",
 			       nbuff, rscsi_disks[i].capacity,
@@ -1063,7 +1055,7 @@
 
 static int sd_init()
 {
-	int i;
+	int i, maxparts;
 
 	if (sd_template.dev_noticed == 0)
 		return 0;
@@ -1074,10 +1066,17 @@
 	if (sd_template.dev_max > N_SD_MAJORS * SCSI_DISKS_PER_MAJOR)
 		sd_template.dev_max = N_SD_MAJORS * SCSI_DISKS_PER_MAJOR;
 
+	/* At most 16 partitions on each scsi disk. */
+	maxparts = (sd_template.dev_max << 4);
+	if (maxparts == 0)
+		return 0;
+
 	if (!sd_registered) {
 		for (i = 0; i < N_USED_SD_MAJORS; i++) {
-			if (devfs_register_blkdev(SD_MAJOR(i), "sd", &sd_fops)) {
-				printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(i));
+			if (devfs_register_blkdev(SD_MAJOR(i), "sd",
+						  &sd_fops)) {
+				printk("Unable to get major %d for SCSI disk\n",
+				       SD_MAJOR(i));
 				return 1;
 			}
 		}
@@ -1087,32 +1086,26 @@
 	if (rscsi_disks)
 		return 0;
 
-	rscsi_disks = kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
-	if (!rscsi_disks)
-		goto cleanup_devfs;
-	memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk));
-
-	/* for every (necessary) major: */
-	sd_sizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
-	if (!sd_sizes)
-		goto cleanup_disks;
-	memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int));
-
-	sd_blocksizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
-	if (!sd_blocksizes)
-		goto cleanup_sizes;
-	
-	sd_hardsizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
-	if (!sd_hardsizes)
-		goto cleanup_blocksizes;
-
-	sd_max_sectors = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
-	if (!sd_max_sectors)
-		goto cleanup_max_sectors;
+	/* allocate memory */
+#define init_mem_lth(x,n)	x = kmalloc((n) * sizeof(*x), GFP_ATOMIC)
+#define zero_mem_lth(x,n)	memset(x, 0, (n) * sizeof(*x))
+
+	init_mem_lth(rscsi_disks, sd_template.dev_max);
+	init_mem_lth(sd_sizes, maxparts);
+	init_mem_lth(sd_blocksizes, maxparts);
+	init_mem_lth(sd, maxparts);
+	init_mem_lth(sd_gendisks, N_USED_SD_MAJORS);
+	init_mem_lth(sd_max_sectors, sd_template.dev_max << 4);
+
+	if (!rscsi_disks || !sd_sizes || !sd_blocksizes || !sd || !sd_gendisks)
+		goto cleanup_mem;
+
+	zero_mem_lth(rscsi_disks, sd_template.dev_max);
+	zero_mem_lth(sd_sizes, maxparts);
+	zero_mem_lth(sd, maxparts);
 
-	for (i = 0; i < sd_template.dev_max << 4; i++) {
+	for (i = 0; i < maxparts; i++) {
 		sd_blocksizes[i] = 1024;
-		sd_hardsizes[i] = 512;
 		/*
 		 * Allow lowlevel device drivers to generate 512k large scsi
 		 * commands if they know what they're doing and they ask for it
@@ -1122,45 +1115,34 @@
 	}
 
 	for (i = 0; i < N_USED_SD_MAJORS; i++) {
-		blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4);
-		hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4);
-		max_sectors[SD_MAJOR(i)] = sd_max_sectors + i * (SCSI_DISKS_PER_MAJOR << 4);
-	}
-	/*
-	 * FIXME: should unregister blksize_size, hardsect_size and max_sectors when
-	 * the module is unloaded.
-	 */
-	sd = kmalloc((sd_template.dev_max << 4) *
-					  sizeof(struct hd_struct),
-					  GFP_ATOMIC);
-	if (!sd)
-		goto cleanup_sd;
-	memset(sd, 0, (sd_template.dev_max << 4) * sizeof(struct hd_struct));
-
-	if (N_USED_SD_MAJORS > 1)
-		sd_gendisks = kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
-		if (!sd_gendisks)
-			goto cleanup_sd_gendisks;
+		request_queue_t *q = blk_get_queue(SD_MAJOR(i));
+		int parts_per_major = (SCSI_DISKS_PER_MAJOR << 4);
+
+		blksize_size[SD_MAJOR(i)] =
+			sd_blocksizes + i * parts_per_major;
+		blk_queue_hardsect_size(q, 512);
+ 	}
+
 	for (i = 0; i < N_USED_SD_MAJORS; i++) {
+		int N = SCSI_DISKS_PER_MAJOR;
+
 		sd_gendisks[i] = sd_gendisk;
-		sd_gendisks[i].de_arr = kmalloc (SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr,
-                                                 GFP_ATOMIC);
-		if (!sd_gendisks[i].de_arr)
-			goto cleanup_gendisks_de_arr;
-                memset (sd_gendisks[i].de_arr, 0,
-                        SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr);
-		sd_gendisks[i].flags = kmalloc (SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags,
-                                                GFP_ATOMIC);
-		if (!sd_gendisks[i].flags)
-			goto cleanup_gendisks_flags;
-                memset (sd_gendisks[i].flags, 0,
-                        SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags);
+
+		init_mem_lth(sd_gendisks[i].de_arr, N);
+		init_mem_lth(sd_gendisks[i].flags, N);
+
+		if (!sd_gendisks[i].de_arr || !sd_gendisks[i].flags)
+			goto cleanup_gendisks;
+
+		zero_mem_lth(sd_gendisks[i].de_arr, N);
+		zero_mem_lth(sd_gendisks[i].flags, N);
+
 		sd_gendisks[i].major = SD_MAJOR(i);
 		sd_gendisks[i].major_name = "sd";
 		sd_gendisks[i].minor_shift = 4;
 		sd_gendisks[i].max_p = 1 << 4;
-		sd_gendisks[i].part = sd + (i * SCSI_DISKS_PER_MAJOR << 4);
-		sd_gendisks[i].sizes = sd_sizes + (i * SCSI_DISKS_PER_MAJOR << 4);
+		sd_gendisks[i].part = sd + i * (N << 4);
+		sd_gendisks[i].sizes = sd_sizes + i * (N << 4);
 		sd_gendisks[i].nr_real = 0;
 		sd_gendisks[i].real_devices =
 		    (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
@@ -1168,27 +1150,21 @@
 
 	return 0;
 
-cleanup_gendisks_flags:
-	kfree(sd_gendisks[i].de_arr);
-cleanup_gendisks_de_arr:
-	while (--i >= 0 ) {
+#undef init_mem_lth
+#undef zero_mem_lth
+
+cleanup_gendisks:
+	/* kfree can handle NULL, so no test is required here */
+	for (i = 0; i < N_USED_SD_MAJORS; i++) {
 		kfree(sd_gendisks[i].de_arr);
 		kfree(sd_gendisks[i].flags);
 	}
+cleanup_mem:
 	kfree(sd_gendisks);
-cleanup_sd_gendisks:
 	kfree(sd);
-cleanup_sd:
-	kfree(sd_max_sectors);
-cleanup_max_sectors:
-	kfree(sd_hardsizes);
-cleanup_blocksizes:
 	kfree(sd_blocksizes);
-cleanup_sizes:
 	kfree(sd_sizes);
-cleanup_disks:
 	kfree(rscsi_disks);
-cleanup_devfs:
 	for (i = 0; i < N_USED_SD_MAJORS; i++) {
 		devfs_unregister_blkdev(SD_MAJOR(i), "sd");
 	}
@@ -1203,7 +1179,7 @@
 
 	for (i = 0; i < N_USED_SD_MAJORS; i++) {
 		blk_dev[SD_MAJOR(i)].queue = sd_find_queue;
-		add_gendisk(&sd_gendisks[i]);
+		add_gendisk(&(sd_gendisks[i]));
 	}
 
 	for (i = 0; i < sd_template.dev_max; ++i)
@@ -1293,9 +1269,7 @@
 int revalidate_scsidisk(kdev_t dev, int maxusage)
 {
 	int target;
-	int max_p;
-	int start;
-	int i;
+	int res;
 
 	target = DEVICE_NR(dev);
 
@@ -1305,36 +1279,18 @@
 	}
 	DEVICE_BUSY = 1;
 
-	max_p = sd_gendisks->max_p;
-	start = target << sd_gendisks->minor_shift;
-
-	for (i = max_p - 1; i >= 0; i--) {
-		int index = start + i;
-		invalidate_device(MKDEV_SD_PARTITION(index), 1);
-		sd_gendisks->part[index].start_sect = 0;
-		sd_gendisks->part[index].nr_sects = 0;
-		/*
-		 * Reset the blocksize for everything so that we can read
-		 * the partition table.  Technically we will determine the
-		 * correct block size when we revalidate, but we do this just
-		 * to make sure that everything remains consistent.
-		 */
-		sd_blocksizes[index] = 1024;
-		if (rscsi_disks[target].device->sector_size == 2048)
-			sd_blocksizes[index] = 2048;
-		else
-			sd_blocksizes[index] = 1024;
-	}
+	res = wipe_partitions(dev);
+	if (res)
+		goto leave;
 
 #ifdef MAYBE_REINIT
 	MAYBE_REINIT;
 #endif
 
-	grok_partitions(&SD_GENDISK(target), target % SCSI_DISKS_PER_MAJOR,
-			1<<4, CAPACITY);
-
+	grok_partitions(dev, CAPACITY);
+leave:
 	DEVICE_BUSY = 0;
-	return 0;
+	return res;
 }
 
 static int fop_revalidate_scsidisk(kdev_t dev)
@@ -1344,6 +1300,7 @@
 static void sd_detach(Scsi_Device * SDp)
 {
 	Scsi_Disk *dpnt;
+	kdev_t dev;
 	int i, j;
 	int max_p;
 	int start;
@@ -1351,18 +1308,13 @@
 	for (dpnt = rscsi_disks, i = 0; i < sd_template.dev_max; i++, dpnt++)
 		if (dpnt->device == SDp) {
 
-			/* If we are disconnecting a disk driver, sync and invalidate
-			 * everything */
 			max_p = sd_gendisk.max_p;
 			start = i << sd_gendisk.minor_shift;
+			dev = MKDEV_SD_PARTITION(start);
+			wipe_partitions(dev);
+			for (j = max_p - 1; j >= 0; j--)
+				sd_sizes[start + j] = 0;
 
-			for (j = max_p - 1; j >= 0; j--) {
-				int index = start + j;
-				invalidate_device(MKDEV_SD_PARTITION(index), 1);
-				sd_gendisks->part[index].start_sect = 0;
-				sd_gendisks->part[index].nr_sects = 0;
-				sd_sizes[index] = 0;
-			}
                         devfs_register_partitions (&SD_GENDISK (i),
                                                    SD_MINOR_NUMBER (start), 1);
 			/* unregister_disk() */
@@ -1375,7 +1327,6 @@
 			SD_GENDISK(i).nr_real--;
 			return;
 		}
-	return;
 }
 
 static int __init init_sd(void)
@@ -1398,14 +1349,11 @@
 		kfree(rscsi_disks);
 		kfree(sd_sizes);
 		kfree(sd_blocksizes);
-		kfree(sd_hardsizes);
 		kfree((char *) sd);
 	}
 	for (i = 0; i < N_USED_SD_MAJORS; i++) {
-		del_gendisk(&sd_gendisks[i]);
-		blk_size[SD_MAJOR(i)] = NULL;
-		hardsect_size[SD_MAJOR(i)] = NULL;
-		read_ahead[SD_MAJOR(i)] = 0;
+		del_gendisk(&(sd_gendisks[i]));
+		blk_clear(SD_MAJOR(i));
 	}
 	sd_template.dev_max = 0;
 	if (sd_gendisks != &sd_gendisk)
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.5.0/linux/drivers/scsi/sg.c	Sun Nov  4 09:31:57 2001
+++ linux/drivers/scsi/sg.c	Fri Nov 30 08:26:04 2001
@@ -336,9 +336,7 @@
     Sg_device * sdp;
     Sg_fd * sfp;
 
-    lock_kernel();
     if ((! (sfp = (Sg_fd *)filp->private_data)) || (! (sdp = sfp->parentdp))) {
-	unlock_kernel();
         return -ENXIO;
     }
     SCSI_LOG_TIMEOUT(3, printk("sg_release: dev=%d\n", MINOR(sdp->i_rdev)));
@@ -352,7 +350,6 @@
 	sdp->exclude = 0;
 	wake_up_interruptible(&sdp->o_excl_wait);
     }
-    unlock_kernel();
     return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sim710.h linux/drivers/scsi/sim710.h
--- v2.5.0/linux/drivers/scsi/sim710.h	Thu Jul 19 21:07:45 2001
+++ linux/drivers/scsi/sim710.h	Thu Nov 29 13:55:59 2001
@@ -37,8 +37,7 @@
 		      this_id:			7, 			\
 		      sg_tablesize:		128,		 	\
 		      cmd_per_lun:		1,		 	\
-		      use_clustering:		DISABLE_CLUSTERING,	\
-		      use_new_eh_code:		1}
+		      use_clustering:		DISABLE_CLUSTERING }
 
 #ifndef HOSTS_C
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.5.0/linux/drivers/scsi/sr.c	Thu Oct 25 13:58:35 2001
+++ linux/drivers/scsi/sr.c	Thu Dec  6 14:02:57 2001
@@ -88,7 +88,6 @@
 static int *sr_sizes;
 
 static int *sr_blocksizes;
-static int *sr_hardsizes;
 
 static int sr_open(struct cdrom_device_info *, int);
 void get_sectorsize(int);
@@ -218,8 +217,8 @@
 		(SCpnt->sense_buffer[4] << 16) |
 		(SCpnt->sense_buffer[5] << 8) |
 		SCpnt->sense_buffer[6];
-		if (SCpnt->request.bh != NULL)
-			block_sectors = SCpnt->request.bh->b_size >> 9;
+		if (SCpnt->request.bio != NULL)
+			block_sectors = bio_sectors(SCpnt->request.bio);
 		if (block_sectors < 4)
 			block_sectors = 4;
 		if (scsi_CDs[device_nr].device->sector_size == 2048)
@@ -327,11 +326,14 @@
 	}
 	if (old_sg) {
 		memcpy(sg + i, old_sg, SCpnt->use_sg * sizeof(struct scatterlist));
-		memcpy(bbpnt + i, old_bbpnt, SCpnt->use_sg * sizeof(void *));
+		if (old_bbpnt)
+			memcpy(bbpnt + i, old_bbpnt, SCpnt->use_sg * sizeof(void *));
 		scsi_free(old_sg, (((SCpnt->use_sg * sizeof(struct scatterlist)) +
 				    (SCpnt->use_sg * sizeof(void *))) + 511) & ~511);
 	} else {
-		sg[i].address = SCpnt->request_buffer;
+		sg[i].address = NULL;
+		sg[i].page = virt_to_page(SCpnt->request_buffer);
+		sg[i].offset = (unsigned long) SCpnt->request_buffer&~PAGE_MASK;
 		sg[i].length = SCpnt->request_bufflen;
 	}
 
@@ -341,7 +343,9 @@
 	SCpnt->use_sg += i;
 
 	if (bsize) {
-		sg[SCpnt->use_sg].address = back;
+		sg[SCpnt->use_sg].address = NULL;
+		sg[SCpnt->use_sg].page = virt_to_page(back);
+		sg[SCpnt->use_sg].offset = (unsigned long) back & ~PAGE_MASK;
 		bbpnt[SCpnt->use_sg] = back;
 		sg[SCpnt->use_sg].length = bsize;
 		SCpnt->use_sg++;
@@ -384,7 +388,12 @@
 		return 0;
 	}
 
-	if ((SCpnt->request.cmd == WRITE) && !scsi_CDs[dev].device->writeable)
+	if (!(SCpnt->request.flags & REQ_CMD)) {
+		blk_dump_rq_flags(&SCpnt->request, "sr unsup command");
+		return 0;
+	}
+
+	if (rq_data_dir(&SCpnt->request) == WRITE && !scsi_CDs[dev].device->writeable)
 		return 0;
 
 	/*
@@ -404,7 +413,18 @@
 		return 0;
 	}
 
-	block = SCpnt->request.sector / (s_size >> 9);
+	if (rq_data_dir(&SCpnt->request) == WRITE) {
+		if (!scsi_CDs[dev].device->writeable)
+			return 0;
+		SCpnt->cmnd[0] = WRITE_10;
+		SCpnt->sc_data_direction = SCSI_DATA_WRITE;
+	} else if (rq_data_dir(&SCpnt->request) == READ) {
+		SCpnt->cmnd[0] = READ_10;
+		SCpnt->sc_data_direction = SCSI_DATA_READ;
+	} else {
+		blk_dump_rq_flags(&SCpnt->request, "Unknown sr command");
+		return 0;
+	}
 
 	/*
 	 * request doesn't start on hw block boundary, add scatter pads
@@ -415,19 +435,6 @@
 
 	this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9);
 
-	switch (SCpnt->request.cmd) {
-	case WRITE:
-		SCpnt->cmnd[0] = WRITE_10;
-		SCpnt->sc_data_direction = SCSI_DATA_WRITE;
-		break;
-	case READ:
-		SCpnt->cmnd[0] = READ_10;
-		SCpnt->sc_data_direction = SCSI_DATA_READ;
-		break;
-	default:
-		printk("Unknown sr command %d\n", SCpnt->request.cmd);
-		return 0;
-	}
 
 	SCSI_LOG_HLQUEUE(2, printk("sr%d : %s %d/%ld 512 byte blocks.\n",
                                    devm,
@@ -437,6 +444,8 @@
 	SCpnt->cmnd[1] = (SCpnt->device->scsi_level <= SCSI_2) ?
 			 ((SCpnt->lun << 5) & 0xe0) : 0;
 
+	block = SCpnt->request.sector / (s_size >> 9);
+
 	if (this_count > 0xffff)
 		this_count = 0xffff;
 
@@ -663,6 +672,7 @@
 		scsi_CDs[i].needs_sector_size = 0;
 		sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
 	};
+	blk_queue_hardsect_size(blk_get_queue(MAJOR_NR), sector_size);
 	scsi_free(buffer, 512);
 }
 
@@ -811,21 +821,14 @@
 	if (!sr_blocksizes)
 		goto cleanup_sizes;
 
-	sr_hardsizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
-	if (!sr_hardsizes)
-		goto cleanup_blocksizes;
 	/*
 	 * These are good guesses for the time being.
 	 */
-	for (i = 0; i < sr_template.dev_max; i++) {
+	for (i = 0; i < sr_template.dev_max; i++)
 		sr_blocksizes[i] = 2048;
-		sr_hardsizes[i] = 2048;
-        }
+
 	blksize_size[MAJOR_NR] = sr_blocksizes;
-        hardsect_size[MAJOR_NR] = sr_hardsizes;
 	return 0;
-cleanup_blocksizes:
-	kfree(sr_blocksizes);
 cleanup_sizes:
 	kfree(sr_sizes);
 cleanup_cds:
@@ -897,7 +900,6 @@
 	else
 		read_ahead[MAJOR_NR] = 4;	/* 4 sector read-ahead */
 
-	return;
 }
 
 static void sr_detach(Scsi_Device * SDp)
@@ -905,17 +907,18 @@
 	Scsi_CD *cpnt;
 	int i;
 
-	for (cpnt = scsi_CDs, i = 0; i < sr_template.dev_max; i++, cpnt++)
+	for (cpnt = scsi_CDs, i = 0; i < sr_template.dev_max; i++, cpnt++) {
 		if (cpnt->device == SDp) {
 			/*
-			 * Since the cdrom is read-only, no need to sync the device.
+			 * Since the cdrom is read-only, no need to sync
+			 * the device.
 			 * We should be kind to our buffer cache, however.
 			 */
 			invalidate_device(MKDEV(MAJOR_NR, i), 0);
 
 			/*
-			 * Reset things back to a sane state so that one can re-load a new
-			 * driver (perhaps the same one).
+			 * Reset things back to a sane state so that one can
+			 * re-load a new driver (perhaps the same one).
 			 */
 			unregister_cdrom(&(cpnt->cdi));
 			cpnt->device = NULL;
@@ -926,7 +929,7 @@
 			sr_sizes[i] = 0;
 			return;
 		}
-	return;
+	}
 }
 
 static int __init init_sr(void)
@@ -948,13 +951,9 @@
 
 		kfree(sr_blocksizes);
 		sr_blocksizes = NULL;
-		kfree(sr_hardsizes);
-		sr_hardsizes = NULL;
 	}
-	blksize_size[MAJOR_NR] = NULL;
-        hardsect_size[MAJOR_NR] = NULL;
-	blk_size[MAJOR_NR] = NULL;
 	read_ahead[MAJOR_NR] = 0;
+	blk_clear(MAJOR_NR);
 
 	sr_template.dev_max = 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- v2.5.0/linux/drivers/scsi/sym53c8xx.c	Wed Oct 17 14:16:39 2001
+++ linux/drivers/scsi/sym53c8xx.c	Tue Nov 27 09:23:27 2001
@@ -642,10 +642,10 @@
 #define	NCR_LOCK_NCB(np, flags)    spin_lock_irqsave(&np->smp_lock, flags)
 #define	NCR_UNLOCK_NCB(np, flags)  spin_unlock_irqrestore(&np->smp_lock, flags)
 
-#define	NCR_LOCK_SCSI_DONE(np, flags) \
-		spin_lock_irqsave(&io_request_lock, flags)
-#define	NCR_UNLOCK_SCSI_DONE(np, flags) \
-		spin_unlock_irqrestore(&io_request_lock, flags)
+#define	NCR_LOCK_SCSI_DONE(host, flags) \
+		spin_lock_irqsave(&((host)->host_lock), flags)
+#define	NCR_UNLOCK_SCSI_DONE(host, flags) \
+		spin_unlock_irqrestore(&((host)->host_lock), flags)
 
 #else
 
@@ -656,8 +656,8 @@
 #define	NCR_LOCK_NCB(np, flags)    do { save_flags(flags); cli(); } while (0)
 #define	NCR_UNLOCK_NCB(np, flags)  do { restore_flags(flags); } while (0)
 
-#define	NCR_LOCK_SCSI_DONE(np, flags)    do {;} while (0)
-#define	NCR_UNLOCK_SCSI_DONE(np, flags)  do {;} while (0)
+#define	NCR_LOCK_SCSI_DONE(host, flags)    do {;} while (0)
+#define	NCR_UNLOCK_SCSI_DONE(host, flags)  do {;} while (0)
 
 #endif
 
@@ -13676,9 +13676,9 @@
      if (DEBUG_FLAGS & DEBUG_TINY) printk ("]\n");
 
      if (done_list) {
-          NCR_LOCK_SCSI_DONE(np, flags);
+          NCR_LOCK_SCSI_DONE(done_list->host, flags);
           ncr_flush_done_cmds(done_list);
-          NCR_UNLOCK_SCSI_DONE(np, flags);
+          NCR_UNLOCK_SCSI_DONE(done_list->host, flags);
      }
 }
 
@@ -13699,9 +13699,9 @@
      NCR_UNLOCK_NCB(np, flags);
 
      if (done_list) {
-          NCR_LOCK_SCSI_DONE(np, flags);
+          NCR_LOCK_SCSI_DONE(done_list->host, flags);
           ncr_flush_done_cmds(done_list);
-          NCR_UNLOCK_SCSI_DONE(np, flags);
+          NCR_UNLOCK_SCSI_DONE(done_list->host, flags);
      }
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sym53c8xx.h linux/drivers/scsi/sym53c8xx.h
--- v2.5.0/linux/drivers/scsi/sym53c8xx.h	Thu Nov 22 11:49:48 2001
+++ linux/drivers/scsi/sym53c8xx.h	Tue Dec 11 09:55:15 2001
@@ -96,8 +96,9 @@
 			this_id:        7,			\
 			sg_tablesize:   SCSI_NCR_SG_TABLESIZE,	\
 			cmd_per_lun:    SCSI_NCR_CMD_PER_LUN,	\
-			max_sectors:    MAX_SEGMENTS*8,		\
-			use_clustering: DISABLE_CLUSTERING} 
+			max_sectors:	MAX_SEGMENTS*8,		\
+			use_clustering: DISABLE_CLUSTERING,	\
+			highmem_io:	1} 
 
 #else
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h
--- v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h	Fri Nov  9 15:22:54 2001
+++ linux/drivers/scsi/sym53c8xx_2/sym53c8xx.h	Wed Nov 28 10:22:27 2001
@@ -109,7 +109,6 @@
 	release:		sym53c8xx_release,			\
 	info:			sym53c8xx_info, 			\
 	queuecommand:		sym53c8xx_queue_command,		\
-	use_new_eh_code:	1,					\
 	eh_abort_handler:	sym53c8xx_eh_abort_handler,		\
 	eh_device_reset_handler:sym53c8xx_eh_device_reset_handler,	\
 	eh_bus_reset_handler:	sym53c8xx_eh_bus_reset_handler,		\
@@ -119,7 +118,8 @@
 	this_id:		7,					\
 	sg_tablesize:		0,					\
 	cmd_per_lun:		0,					\
-	use_clustering:		DISABLE_CLUSTERING}
+	use_clustering:		DISABLE_CLUSTERING,			\
+	highmem_io:		1}
 
 #endif /* defined(HOSTS_C) || defined(MODULE) */ 
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym_glue.c linux/drivers/scsi/sym53c8xx_2/sym_glue.c
--- v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym_glue.c	Fri Nov  9 15:22:54 2001
+++ linux/drivers/scsi/sym53c8xx_2/sym_glue.c	Tue Nov 27 09:23:27 2001
@@ -138,18 +138,11 @@
 #define	SYM_LOCK_DRIVER(flags)    spin_lock_irqsave(&sym53c8xx_lock, flags)
 #define	SYM_UNLOCK_DRIVER(flags)  spin_unlock_irqrestore(&sym53c8xx_lock,flags)
 
-#define SYM_INIT_LOCK_HCB(np)     spin_lock_init(&np->s.smp_lock);
-#define	SYM_LOCK_HCB(np, flags)   spin_lock_irqsave(&np->s.smp_lock, flags)
-#define	SYM_UNLOCK_HCB(np, flags) spin_unlock_irqrestore(&np->s.smp_lock, flags)
-
-#define	SYM_LOCK_SCSI(np, flags) \
-		spin_lock_irqsave(&io_request_lock, flags)
-#define	SYM_UNLOCK_SCSI(np, flags) \
-		spin_unlock_irqrestore(&io_request_lock, flags)
-
-/* Ugly, but will make things easier if this locking will ever disappear */
-#define	SYM_LOCK_SCSI_NOSAVE(np)	spin_lock_irq(&io_request_lock)
-#define	SYM_UNLOCK_SCSI_NORESTORE(np)	spin_unlock_irq(&io_request_lock)
+#define SYM_INIT_LOCK_HCB(np)		spin_lock_init(&np->s.host->host_lock);
+#define	SYM_LOCK_HCB(np, flags)		\
+			spin_lock_irqsave(&np->s.host->host_lock, flags)
+#define	SYM_UNLOCK_HCB(np, flags)	\
+			spin_unlock_irqrestore(&np->s.host->host_lock, flags)
 
 /*
  *  These simple macros limit expression involving 
@@ -966,14 +959,18 @@
 {
 	hcb_p  np  = SYM_SOFTC_PTR(cmd);
 	ucmd_p ucp = SYM_UCMD_PTR(cmd);
-	u_long flags;
 	int sts = 0;
+#if 0
+	u_long flags;
+#endif
 
 	cmd->scsi_done     = done;
 	cmd->host_scribble = NULL;
 	memset(ucp, 0, sizeof(*ucp));
 
+#if 0
 	SYM_LOCK_HCB(np, flags);
+#endif
 
 	/*
 	 *  Shorten our settle_time if needed for 
@@ -999,7 +996,9 @@
 		sym_insque_tail(&ucp->link_cmdq, &np->s.wait_cmdq);
 	}
 out:
+#if 0
 	SYM_UNLOCK_HCB(np, flags);
+#endif
 
 	return 0;
 }
@@ -1010,21 +1009,21 @@
 static void sym53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
 {
 	unsigned long flags;
-	unsigned long flags1;
 	hcb_p np = (hcb_p) dev_id;
 
 	if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("[");
 
-	SYM_LOCK_SCSI(np, flags1);
 	SYM_LOCK_HCB(np, flags);
 
 	sym_interrupt(np);
 
+	/*
+	 * push queue walk-through to tasklet
+	 */
 	if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid)
 		sym_requeue_awaiting_cmds(np);
 
 	SYM_UNLOCK_HCB(np, flags);
-	SYM_UNLOCK_SCSI(np, flags1);
 
 	if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n");
 }
@@ -1036,9 +1035,7 @@
 {
 	hcb_p np = (hcb_p) npref;
 	unsigned long flags;
-	unsigned long flags1;
 
-	SYM_LOCK_SCSI(np, flags1);
 	SYM_LOCK_HCB(np, flags);
 
 	sym_timer(np);
@@ -1047,7 +1044,6 @@
 		sym_requeue_awaiting_cmds(np);
 
 	SYM_UNLOCK_HCB(np, flags);
-	SYM_UNLOCK_SCSI(np, flags1);
 }
 
 
@@ -1209,9 +1205,7 @@
 		ep->timer.data = (u_long)cmd;
 		ep->timed_out = 1;	/* Be pessimistic for once :) */
 		add_timer(&ep->timer);
-		SYM_UNLOCK_SCSI_NORESTORE(np);
 		down(&ep->sem);
-		SYM_LOCK_SCSI_NOSAVE(np);
 		if (ep->timed_out)
 			sts = -2;
 	}
@@ -1975,6 +1969,7 @@
 		goto attach_failed;
 #endif
 	host_data->ncb = np;
+	np->s.host = instance;
 
 	SYM_INIT_LOCK_HCB(np);
 
@@ -2140,6 +2135,7 @@
 	instance->max_cmd_len	= 16;
 #endif
 	instance->select_queue_depths = sym53c8xx_select_queue_depths;
+	instance->highmem_io	= 1;
 
 	SYM_UNLOCK_HCB(np, flags);
 
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym_glue.h linux/drivers/scsi/sym53c8xx_2/sym_glue.h
--- v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym_glue.h	Thu Nov 22 10:41:14 2001
+++ linux/drivers/scsi/sym53c8xx_2/sym_glue.h	Tue Nov 27 09:23:27 2001
@@ -456,10 +456,10 @@
 	char		chip_name[8];
 	struct pci_dev	*device;
 
+	struct Scsi_Host *host;
+
 	u_char		bus;		/* PCI BUS number		*/
 	u_char		device_fn;	/* PCI BUS device and function	*/
-
-	spinlock_t	smp_lock;	/* Lock for SMP threading       */
 
 	vm_offset_t	mmio_va;	/* MMIO kernel virtual address	*/
 	vm_offset_t	ram_va;		/* RAM  kernel virtual address	*/
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym_hipd.c linux/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym_hipd.c	Fri Nov  9 15:22:54 2001
+++ linux/drivers/scsi/sym53c8xx_2/sym_hipd.c	Tue Nov 27 09:23:27 2001
@@ -4689,8 +4689,8 @@
 	return;
 out_clrack:
 	OUTL_DSP (SCRIPTA_BA (np, clrack));
-	return;
 out_stuck:
+	;
 }
 
 /*
@@ -5223,9 +5223,8 @@
 	 *  And accept tagged commands now.
 	 */
 	lp->head.itlq_tbl_sa = cpu_to_scr(vtobus(lp->itlq_tbl));
-
-	return;
 fail:
+	;
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym_nvram.c linux/drivers/scsi/sym53c8xx_2/sym_nvram.c
--- v2.5.0/linux/drivers/scsi/sym53c8xx_2/sym_nvram.c	Fri Nov  9 15:22:54 2001
+++ linux/drivers/scsi/sym53c8xx_2/sym_nvram.c	Tue Nov 27 09:23:27 2001
@@ -505,10 +505,10 @@
 	return retv;
 }
 
-#undef SET_BIT 0
-#undef CLR_BIT 1
-#undef SET_CLK 2
-#undef CLR_CLK 3
+#undef SET_BIT
+#undef CLR_BIT
+#undef SET_CLK
+#undef CLR_CLK
 
 /*
  *  Try reading Symbios NVRAM.
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v2.5.0/linux/drivers/scsi/u14-34f.h	Sat May 19 17:43:06 2001
+++ linux/drivers/scsi/u14-34f.h	Wed Nov 28 10:22:27 2001
@@ -30,7 +30,6 @@
                 this_id:                 7,                                  \
                 unchecked_isa_dma:       1,                                  \
                 use_clustering:          ENABLE_CLUSTERING,                  \
-                use_new_eh_code:         1    /* Enable new error code */    \
                 }
 
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/scsi/wd7000.h linux/drivers/scsi/wd7000.h
--- v2.5.0/linux/drivers/scsi/wd7000.h	Thu Jul 19 21:08:46 2001
+++ linux/drivers/scsi/wd7000.h	Wed Nov 28 10:22:27 2001
@@ -57,6 +57,5 @@
 	cmd_per_lun:		1,				\
 	unchecked_isa_dma:	1,				\
 	use_clustering:		ENABLE_CLUSTERING,		\
-	use_new_eh_code:	0				\
 }
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c
--- v2.5.0/linux/drivers/sgi/char/graphics.c	Thu Oct 11 09:43:30 2001
+++ linux/drivers/sgi/char/graphics.c	Fri Nov 30 08:26:04 2001
@@ -196,7 +196,6 @@
 	int board = GRAPHICS_CARD (inode->i_rdev);
 
 	/* Tell the rendering manager that one client is going away */
-	lock_kernel();
 	rrm_close (inode, file);
 
 	/* Was this file handle from the board owner?, clear it */
@@ -206,7 +205,6 @@
 			(*cards [board].g_reset_console)();
 		enable_gconsole ();
 	}
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/sgi/char/shmiq.c linux/drivers/sgi/char/shmiq.c
--- v2.5.0/linux/drivers/sgi/char/shmiq.c	Mon Aug 27 08:56:31 2001
+++ linux/drivers/sgi/char/shmiq.c	Fri Nov 30 08:38:44 2001
@@ -79,11 +79,13 @@
 
 /* /dev/qcntlN attached memory regions, location and size of the event queue */
 static struct {
-	int    opened;		/* if this device has been opened */
-	void   *shmiq_vaddr;	/* mapping in kernel-land */
-	int    tail;		/* our copy of the shmiq->tail */
-	int    events;
-	int    mapped;
+	int		opened;
+	void 	 	*shmiq_vaddr;		/* mapping in kernel-land */
+	spinlock_t	shmiq_lock:SPIN_LOCK_UNLOCKED;
+					 	/* protects vaddr and opened */
+	int   		tail;			/* our copy of the shmiq->tail */
+	int    		events;
+	int    		mapped;
 	
 	wait_queue_head_t    proc_list;
 	struct fasync_struct *fasync;
@@ -328,12 +330,11 @@
 
 	size  = vma->vm_end - vma->vm_start;
 	start = vma->vm_start; 
-	lock_kernel();
-	mem = (unsigned long) shmiqs [minor].shmiq_vaddr =  vmalloc_uncached (size);
-	if (!mem) {
-		unlock_kernel();
+	mem = vmalloc_uncached (size);
+	if (!mem)
 		return -EINVAL;
-	}
+	spin_lock( &shmiqs [minor].shmiq_lock );
+	hmiqs [minor].shmiq_vaddr = mem;
 
 	/* Prevent the swapper from considering these pages for swap and touching them */
 	vma->vm_flags    |= (VM_SHM  | VM_LOCKED | VM_IO);
@@ -342,13 +343,12 @@
 	/* Uncache the pages */
 	vma->vm_page_prot = PAGE_USERIO;
 
-	error = vmap_page_range (vma->vm_start, size, mem);
 
 	shmiqs [minor].tail = 0;
 	/* Init the shared memory input queue */
+	spin_unlock( &shmiqs [minor].shmiq_lock );
 	memset (shmiqs [minor].shmiq_vaddr, 0, size);
-	unlock_kernel();
-	
+	error = vmap_page_range (vma->vm_start, size, mem);
 	return error;
 }
 
@@ -393,13 +393,16 @@
 	minor--;
 	if (minor > MAX_SHMI_QUEUES)
 		return -EINVAL;
+	spin_lock( &shmiqs [minor].shmiq_lock );
 	if (shmiqs [minor].opened)
+	{
+		spin_unlock( &shmiqs [minor].shmiq_lock );
 		return -EBUSY;
+	}
 
-	lock_kernel ();
 	shmiqs [minor].opened      = 1;
 	shmiqs [minor].shmiq_vaddr = 0;
-	unlock_kernel ();
+	spin_unlock( &shmiqs [minor].shmiq_lock );
 
 	return 0;
 }
@@ -429,18 +432,21 @@
 
 	if (minor > MAX_SHMI_QUEUES)
 		return -EINVAL;
-	if (shmiqs [minor].opened == 0)
+
+	spin_lock( &shmiqs [minor].shmiq_lock );
+	if (shmiqs [minor].opened == 0) {
+		spin_unlock( &shmiqs [minor].shmiq_lock );
 		return -EINVAL;
+	}
 
-	lock_kernel ();
 	shmiq_qcntl_fasync (-1, filp, 0);
-	shmiqs [minor].opened      = 0;
+	shmiqs [minor].opened 	   = 0;
 	shmiqs [minor].mapped      = 0;
 	shmiqs [minor].events      = 0;
 	shmiqs [minor].fasync      = 0;
 	vfree (shmiqs [minor].shmiq_vaddr);
 	shmiqs [minor].shmiq_vaddr = 0;
-	unlock_kernel ();
+	spin_unlock( &shmiqs [minor].shmiq_lock );
 
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/sgi/char/streamable.c linux/drivers/sgi/char/streamable.c
--- v2.5.0/linux/drivers/sgi/char/streamable.c	Wed Jul 12 21:58:43 2000
+++ linux/drivers/sgi/char/streamable.c	Fri Nov 30 08:26:04 2001
@@ -221,9 +221,7 @@
 static int
 sgi_mouse_close (struct inode *inode, struct file *filp)
 {
-	lock_kernel();
 	mouse_opened = 0;
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c
--- v2.5.0/linux/drivers/sound/ad1816.c	Fri Nov  9 15:22:54 2001
+++ linux/drivers/sound/ad1816.c	Sun Nov 25 09:43:42 2001
@@ -1258,7 +1258,7 @@
 static int __initdata dma = -1;
 static int __initdata dma2 = -1;
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 struct pci_dev	*ad1816_dev  = NULL;
 
 static int activated	= 1;
@@ -1280,7 +1280,7 @@
 MODULE_PARM(ad1816_clockfreq,"i");
 MODULE_PARM(options,"i");
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 
 static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
 {
@@ -1407,7 +1407,7 @@
 static int __init init_ad1816(void)
 {
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	if(isapnp && (ad1816_probe_isapnp(&cfg) < 0) ) {
 		printk(KERN_NOTICE "ad1816: No ISAPnP cards found, trying standard ones...\n");
 		isapnp = 0;
@@ -1447,7 +1447,7 @@
 	}     
 	nr_ad1816_devs=0;
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	if(activated)
 		if(ad1816_dev)
 			ad1816_dev->deactivate(ad1816_dev);
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.5.0/linux/drivers/sound/ad1848.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/ad1848.c	Tue Nov 27 16:44:37 2001
@@ -30,6 +30,12 @@
  * Aki Laukkanen	: added power management support
  * Arnaldo C. de Melo	: added missing restore_flags in ad1848_resume
  * Miguel Freitas       : added ISA PnP support
+ * Alan Cox		: Added CS4236->4239 identification
+ * Daniel T. Cobra	: Alernate config/mixer for later chips
+ * Alan Cox		: Merged chip idents and config code
+ *
+ * TODO
+ *		APM save restore assist code on IBM thinkpad
  *
  * Status:
  *		Tested. Believed fully functional.
@@ -57,7 +63,7 @@
 	int             dual_dma;	/* 1, when two DMA channels allocated */
 	int 		subtype;
 	unsigned char   MCE_bit;
-	unsigned char   saved_regs[32];
+	unsigned char   saved_regs[64];	/* Includes extended register space */
 	int             debug_flag;
 
 	int             audio_flags;
@@ -78,6 +84,9 @@
 #define MD_IWAVE	7
 #define MD_4235         8 /* Crystal Audio CS4235  */
 #define MD_1845_SSCAPE  9 /* Ensoniq Soundscape PNP*/
+#define MD_4236		10 /* 4236 and higher */
+#define MD_42xB		11 /* CS 42xB */
+#define MD_4239		12 /* CS4239 */
 
 	/* Mixer parameters */
 	int             recmask;
@@ -162,7 +171,7 @@
     ,{CAP_F_TIMER} /* MD_1845_SSCAPE */
 };
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 static int isapnp	= 1;
 static int isapnpjump	= 0;
 static int reverse	= 0;
@@ -202,9 +211,22 @@
 
 	save_flags(flags);
 	cli();
-	outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
-	x = inb(io_Indexed_Data(devc));
-/* printk("(%02x<-%02x) ", reg|devc->MCE_bit, x); */
+	
+	if(reg < 32)
+	{
+		outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+		x = inb(io_Indexed_Data(devc));
+	}
+	else
+	{
+		int xreg, xra;
+
+		xreg = (reg & 0xff) - 32;
+		xra = (((xreg & 0x0f) << 4) & 0xf0) | 0x08 | ((xreg & 0x10) >> 2);
+		outb(((unsigned char) (23 & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+		outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
+		x = inb(io_Indexed_Data(devc));
+	}
 	restore_flags(flags);
 
 	return x;
@@ -220,9 +242,22 @@
 
 	save_flags(flags);
 	cli();
-	outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
-	outb(((unsigned char) (data & 0xff)), io_Indexed_Data(devc));
-	/* printk("(%02x->%02x) ", reg|devc->MCE_bit, data); */
+	
+	if(reg < 32)
+	{
+		outb(((unsigned char) (reg & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+		outb(((unsigned char) (data & 0xff)), io_Indexed_Data(devc));
+	}
+	else
+	{
+		int xreg, xra;
+		
+		xreg = (reg & 0xff) - 32;
+		xra = (((xreg & 0x0f) << 4) & 0xf0) | 0x08 | ((xreg & 0x10) >> 2);
+		outb(((unsigned char) (23 & 0xff) | devc->MCE_bit), io_Index_Addr(devc));
+		outb(((unsigned char) (xra & 0xff)), io_Indexed_Data(devc));
+		outb((unsigned char) (data & 0xff), io_Indexed_Data(devc));
+	}
 	restore_flags(flags);
 }
 
@@ -591,7 +626,13 @@
 			devc->mix_devices = &(iwave_mix_devices[0]);
 			break;
 
+		case MD_42xB:
+		case MD_4239:
+			devc->mix_devices = &(cs42xb_mix_devices[0]);
+			devc->supported_devices = MODE3_MIXER_DEVICES;
+			break;
 		case MD_4232:
+		case MD_4236:
 			devc->supported_devices = MODE3_MIXER_DEVICES;
 			break;
 
@@ -1118,7 +1159,7 @@
 	}
 	old_fs = ad_read(devc, 8);
 
-	if (devc->model == MD_4232)
+	if (devc->model == MD_4232 || devc->model >= MD_4236)
 	{
 		tmp = ad_read(devc, 16);
 		ad_write(devc, 16, tmp | 0x30);
@@ -1139,7 +1180,7 @@
 	while (timeout < 10000 && inb(devc->base) == 0x80)
 		timeout++;
 
-	if (devc->model == MD_4232)
+	if (devc->model >= MD_4232)
 		ad_write(devc, 16, tmp & ~0x30);
 
 	ad_leave_MCE(devc);	/*
@@ -1403,11 +1444,12 @@
 static void ad1848_init_hw(ad1848_info * devc)
 {
 	int i;
+	int *init_values;
 
 	/*
 	 * Initial values for the indirect registers of CS4248/AD1848.
 	 */
-	static int      init_values[] =
+	static int      init_values_a[] =
 	{
 		0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
 		0x00, 0x0c, 0x02, 0x00, 0x8a, 0x01, 0x00, 0x00,
@@ -1417,6 +1459,31 @@
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 	};
 
+	static int      init_values_b[] =
+	{
+		/* 
+		   Values for the newer chips
+		   Some of the register initialization values were changed. In
+		   order to get rid of the click that preceded PCM playback,
+		   calibration was disabled on the 10th byte. On that same byte,
+		   dual DMA was enabled; on the 11th byte, ADC dithering was
+		   enabled, since that is theoretically desirable; on the 13th
+		   byte, Mode 3 was selected, to enable access to extended
+		   registers.
+		 */
+		0xa8, 0xa8, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00,
+		0x00, 0x00, 0x06, 0x00, 0xe0, 0x01, 0x00, 0x00,
+ 		0x80, 0x00, 0x10, 0x10, 0x00, 0x00, 0x1f, 0x40,
+ 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+
+	/*
+	 *	Select initialisation data
+	 */
+	 
+	init_values = init_values_a;
+	if(devc->model >= MD_4236)
+		init_values = init_values_b;
 
 	for (i = 0; i < 16; i++)
 		ad_write(devc, i, init_values[i]);
@@ -1768,19 +1835,49 @@
 				else
 				{
 					switch (id & 0x1f) {
-					case 3: /* CS4236/CS4235 */
+					case 3: /* CS4236/CS4235/CS42xB/CS4239 */
 						{
 							int xid;
 							ad_write(devc, 12, ad_read(devc, 12) | 0x60); /* switch to mode 3 */
 							ad_write(devc, 23, 0x9c); /* select extended register 25 */
 							xid = inb(io_Indexed_Data(devc));
 							ad_write(devc, 12, ad_read(devc, 12) & ~0x60); /* back to mode 0 */
-							if ((xid & 0x1f) == 0x1d) {
-								devc->chip_name = "CS4235";
-								devc->model = MD_4235;
-							} else {
-								devc->chip_name = "CS4236";
-								devc->model = MD_4232;
+							switch (xid & 0x1f)
+							{
+								case 0x00:
+									devc->chip_name = "CS4237B(B)";
+									devc->model = MD_42xB;
+									break;
+								case 0x08:
+									/* Seems to be a 4238 ?? */
+									devc->chip_name = "CS4238";
+									devc->model = MD_42xB;
+									break;
+								case 0x09:
+									devc->chip_name = "CS4238B";
+									devc->model = MD_42xB;
+									break;
+								case 0x0b:
+									devc->chip_name = "CS4236B";
+									devc->model = MD_4236;
+									break;
+								case 0x10:
+									devc->chip_name = "CS4237B";
+									devc->model = MD_42xB;
+									break;
+								case 0x1d:
+									devc->chip_name = "CS4235";
+									devc->model = MD_4235;
+									break;
+								case 0x1e:
+									devc->chip_name = "CS4239";
+									devc->model = MD_4239;
+									break;
+								default:
+									printk("Chip ident is %X.\n", xid&0x1F);
+									devc->chip_name = "CS42xx";
+									devc->model = MD_4232;
+									break;
 							}
 						}
 						break;
@@ -2747,6 +2844,10 @@
 
 	save_flags(flags);
 	cli();
+	
+	/* Thinkpad is a bit more of PITA than normal. The BIOS tends to
+	   restore it in a different config to the one we use.  Need to
+	   fix this somehow */
 
 	/* store old mixer levels */
 	memcpy(mixer_levels, devc->levels, sizeof (mixer_levels));  
@@ -2830,7 +2931,7 @@
 MODULE_PARM(deskpro_m, "i");            /* Special magic for Deskpro M box */
 MODULE_PARM(soundpro, "i");             /* More special magic for SoundPro chips */
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 MODULE_PARM(isapnp,	"i");
 MODULE_PARM(isapnpjump,	"i");
 MODULE_PARM(reverse,	"i");
@@ -3000,7 +3101,7 @@
 {
 	printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	if(isapnp && (ad1848_isapnp_probe(&cfg) < 0) ) {
 		printk(KERN_NOTICE "ad1848: No ISAPnP cards found, trying standard ones...\n");
 		isapnp = 0;
@@ -3035,7 +3136,7 @@
 	if(loaded)
 		unload_ms_sound(&cfg);
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	if(audio_activated)
 		if(ad1848_dev)
 			ad1848_dev->deactivate(ad1848_dev);
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/ad1848_mixer.h linux/drivers/sound/ad1848_mixer.h
--- v2.5.0/linux/drivers/sound/ad1848_mixer.h	Sun Mar  7 15:22:06 1999
+++ linux/drivers/sound/ad1848_mixer.h	Tue Nov 27 16:44:37 2001
@@ -57,14 +57,14 @@
 				 SOUND_MASK_OGAIN)
 
 struct mixer_def {
-	unsigned int regno:5;		/* register number for volume */
+	unsigned int regno:6;		/* register number for volume */
 	unsigned int polarity:1;	/* volume polarity: 0=normal, 1=reversed */
 	unsigned int bitpos:3;		/* position of bits in register for volume */
 	unsigned int nbits:3;		/* number of bits in register for volume */
-	unsigned int mutereg:5;		/* register number for mute bit */
+	unsigned int mutereg:6;		/* register number for mute bit */
 	unsigned int mutepol:1;		/* mute polarity: 0=normal, 1=reversed */
 	unsigned int mutepos:4;		/* position of mute bit in register */
-	unsigned int recreg:5;		/* register number for recording bit */
+	unsigned int recreg:6;		/* register number for recording bit */
 	unsigned int recpol:1;		/* recording polarity: 0=normal, 1=reversed */
 	unsigned int recpos:4;		/* position of recording bit in register */
 };
@@ -104,43 +104,69 @@
 		    rec_reg_r, rec_pola_r, rec_pos_r}}
 
 static mixer_ents ad1848_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME,	27, 1, 0, 4,	29, 1, 0, 4,  8),
-MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 6,	 7, 1, 0, 6,  7),
-MIX_ENT(SOUND_MIXER_SPEAKER,	26, 1, 0, 4,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_LINE,	18, 1, 0, 5,	19, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_MIC,	 0, 0, 5, 1,	 1, 0, 5, 1,  8),
-MIX_ENT(SOUND_MIXER_CD,		 2, 1, 0, 5,	 3, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_IMIX,	13, 1, 2, 6,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4,  8),
-MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_LINE1,	 2, 1, 0, 5,	 3, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 0, 5,	19, 1, 0, 5,  7)
+	MIX_ENT(SOUND_MIXER_VOLUME,	27, 1, 0, 4,	29, 1, 0, 4,  8),
+	MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 6,	 7, 1, 0, 6,  7),
+	MIX_ENT(SOUND_MIXER_SPEAKER,	26, 1, 0, 4,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_LINE,	18, 1, 0, 5,	19, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_MIC,	 0, 0, 5, 1,	 1, 0, 5, 1,  8),
+	MIX_ENT(SOUND_MIXER_CD,		 2, 1, 0, 5,	 3, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_IMIX,	13, 1, 2, 6,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4,  8),
+	MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_LINE1,	 2, 1, 0, 5,	 3, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 0, 5,	19, 1, 0, 5,  7)
 };
 
 static mixer_ents iwave_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME,	25, 1, 0, 5,	27, 1, 0, 5,  8),
-MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 6,	 7, 1, 0, 6,  7),
-MIX_ENT(SOUND_MIXER_SPEAKER,	26, 1, 0, 4,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_LINE,	18, 1, 0, 5,	19, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_MIC,	 0, 0, 5, 1,	 1, 0, 5, 1,  8),
-MIX_ENT(SOUND_MIXER_CD,		 2, 1, 0, 5,	 3, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_IMIX,	16, 1, 0, 5,	17, 1, 0, 5,  8),
-MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4,  8),
-MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_LINE1,	 2, 1, 0, 5,	 3, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 0, 5,	19, 1, 0, 5,  7)
+	MIX_ENT(SOUND_MIXER_VOLUME,	25, 1, 0, 5,	27, 1, 0, 5,  8),
+	MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 6,	 7, 1, 0, 6,  7),
+	MIX_ENT(SOUND_MIXER_SPEAKER,	26, 1, 0, 4,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_LINE,	18, 1, 0, 5,	19, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_MIC,	 0, 0, 5, 1,	 1, 0, 5, 1,  8),
+	MIX_ENT(SOUND_MIXER_CD,		 2, 1, 0, 5,	 3, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_IMIX,	16, 1, 0, 5,	17, 1, 0, 5,  8),
+	MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4,  8),
+	MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_LINE1,	 2, 1, 0, 5,	 3, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 0, 5,	19, 1, 0, 5,  7)
+};
+
+static mixer_ents cs42xb_mix_devices[32] = {
+	/* Digital master volume actually has seven bits, but we only use
+	   six to avoid the discontinuity when the analog gain kicks in. */
+	MIX_ENT(SOUND_MIXER_VOLUME,	46, 1, 0, 6,	47, 1, 0, 6,  7),
+	MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 6,	 7, 1, 0, 6,  7),
+	MIX_ENT(SOUND_MIXER_SPEAKER,	26, 1, 0, 4,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_LINE,	18, 1, 0, 5,	19, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_MIC,	34, 1, 0, 5,	35, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_CD,		 2, 1, 0, 5,	 3, 1, 0, 5,  7),
+	/* For the IMIX entry, it was not possible to use the MIX_ENT macro
+	   because the mute bit is in different positions for the two
+	   channels and requires reverse polarity. */
+	[SOUND_MIXER_IMIX] = {{13, 1, 2, 6, 13, 1, 0, 0, 0, 8},
+		      {42, 1, 0, 6, 42, 1, 7, 0, 0, 8}},
+	MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4,  8),
+	MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_LINE1,	 2, 1, 0, 5,	 3, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 0, 5,	 5, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_LINE3,	38, 1, 0, 6,	39, 1, 0, 6,  7)
 };
 
 /* OPTi 82C930 has somewhat different port addresses.
@@ -149,68 +175,68 @@
  * MIC is level of mic monitoring direct to output. Same for CD, LINE, etc.
  */
 static mixer_ents c930_mix_devices[32] = {
-MIX_ENT(SOUND_MIXER_VOLUME,	22, 1, 1, 5,	23, 1, 1, 5,  7),
-MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 1, 4,	 5, 1, 1, 4,  7),
-MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 5,	 7, 1, 0, 5,  7),
-MIX_ENT(SOUND_MIXER_SPEAKER,	22, 1, 1, 5,	23, 1, 1, 5,  7),
-MIX_ENT(SOUND_MIXER_LINE,	18, 1, 1, 4,	19, 1, 1, 4,  7),
-MIX_ENT(SOUND_MIXER_MIC,	20, 1, 1, 4,	21, 1, 1, 4,  7),
-MIX_ENT(SOUND_MIXER_CD,		 2, 1, 1, 4,	 3, 1, 1, 4,  7),
-MIX_ENT(SOUND_MIXER_IMIX,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4,  8),
-MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
-MIX_ENT(SOUND_MIXER_LINE1,	 2, 1, 1, 4,	 3, 1, 1, 4,  7),
-MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 1, 4,	 5, 1, 1, 4,  7),
-MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 1, 4,	19, 1, 1, 4,  7)
+	MIX_ENT(SOUND_MIXER_VOLUME,	22, 1, 1, 5,	23, 1, 1, 5,  7),
+	MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_SYNTH,	 4, 1, 1, 4,	 5, 1, 1, 4,  7),
+	MIX_ENT(SOUND_MIXER_PCM,	 6, 1, 0, 5,	 7, 1, 0, 5,  7),
+	MIX_ENT(SOUND_MIXER_SPEAKER,	22, 1, 1, 5,	23, 1, 1, 5,  7),
+	MIX_ENT(SOUND_MIXER_LINE,	18, 1, 1, 4,	19, 1, 1, 4,  7),
+	MIX_ENT(SOUND_MIXER_MIC,	20, 1, 1, 4,	21, 1, 1, 4,  7),
+	MIX_ENT(SOUND_MIXER_CD,		 2, 1, 1, 4,	 3, 1, 1, 4,  7),
+	MIX_ENT(SOUND_MIXER_IMIX,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_RECLEV,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 4,	 1, 0, 0, 4,  8),
+	MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0,  8),
+	MIX_ENT(SOUND_MIXER_LINE1,	 2, 1, 1, 4,	 3, 1, 1, 4,  7),
+	MIX_ENT(SOUND_MIXER_LINE2,	 4, 1, 1, 4,	 5, 1, 1, 4,  7),
+	MIX_ENT(SOUND_MIXER_LINE3,	18, 1, 1, 4,	19, 1, 1, 4,  7)
 };
 
 static mixer_ents spro_mix_devices[32] = {
-MIX_ENT (SOUND_MIXER_VOLUME,	19, 0, 4, 4,			 19, 0, 0, 4,  8),
-MIX_ENT (SOUND_MIXER_BASS,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
-MIX_ENT (SOUND_MIXER_TREBLE,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
-MIX_ENT2(SOUND_MIXER_SYNTH,	 4, 1, 1, 4, 23, 0, 3,  0, 0, 8,
-	 			 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
-MIX_ENT (SOUND_MIXER_PCM,	 6, 1, 1, 4,			  7, 1, 1, 4,  8),
-MIX_ENT (SOUND_MIXER_SPEAKER,	18, 0, 3, 2,			  0, 0, 0, 0,  8),
-MIX_ENT2(SOUND_MIXER_LINE,	20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
-	 			20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
-MIX_ENT2(SOUND_MIXER_MIC,	18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
-	 			 0, 0, 0, 0,  0, 0, 0,  0, 0, 0),
-MIX_ENT2(SOUND_MIXER_CD,	21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
-				21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
-MIX_ENT (SOUND_MIXER_IMIX,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
-MIX_ENT (SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
-MIX_ENT (SOUND_MIXER_RECLEV,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
-MIX_ENT (SOUND_MIXER_IGAIN,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
-MIX_ENT (SOUND_MIXER_OGAIN,	17, 1, 6, 1,			  0, 0, 0, 0,  8),
-/* This is external wavetable */
-MIX_ENT2(SOUND_MIXER_LINE1,	22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
-	 			22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
+	MIX_ENT (SOUND_MIXER_VOLUME,	19, 0, 4, 4,			 19, 0, 0, 4,  8),
+	MIX_ENT (SOUND_MIXER_BASS,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+	MIX_ENT (SOUND_MIXER_TREBLE,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+	MIX_ENT2(SOUND_MIXER_SYNTH,	 4, 1, 1, 4, 23, 0, 3,  0, 0, 8,
+		 			 5, 1, 1, 4, 23, 0, 3, 0, 0, 8),
+	MIX_ENT (SOUND_MIXER_PCM,	 6, 1, 1, 4,			  7, 1, 1, 4,  8),
+	MIX_ENT (SOUND_MIXER_SPEAKER,	18, 0, 3, 2,			  0, 0, 0, 0,  8),
+	MIX_ENT2(SOUND_MIXER_LINE,	20, 0, 4, 4, 17, 1, 4, 16, 0, 2,
+		 			20, 0, 0, 4, 17, 1, 3, 16, 0, 1),
+	MIX_ENT2(SOUND_MIXER_MIC,	18, 0, 0, 3, 17, 1, 0, 16, 0, 0,
+		 			 0, 0, 0, 0,  0, 0, 0,  0, 0, 0),
+	MIX_ENT2(SOUND_MIXER_CD,	21, 0, 4, 4, 17, 1, 2, 16, 0, 4,
+					21, 0, 0, 4, 17, 1, 1, 16, 0, 3),
+	MIX_ENT (SOUND_MIXER_IMIX,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+	MIX_ENT (SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+	MIX_ENT (SOUND_MIXER_RECLEV,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+	MIX_ENT (SOUND_MIXER_IGAIN,	 0, 0, 0, 0,			  0, 0, 0, 0,  8),
+	MIX_ENT (SOUND_MIXER_OGAIN,	17, 1, 6, 1,			  0, 0, 0, 0,  8),
+	/* This is external wavetable */
+	MIX_ENT2(SOUND_MIXER_LINE1,	22, 0, 4, 4, 23, 1, 1, 23, 0, 4,
+		 			22, 0, 0, 4, 23, 1, 0, 23, 0, 5),
 };
 
 static int default_mixer_levels[32] =
 {
-  0x3232,			/* Master Volume */
-  0x3232,			/* Bass */
-  0x3232,			/* Treble */
-  0x4b4b,			/* FM */
-  0x3232,			/* PCM */
-  0x1515,			/* PC Speaker */
-  0x2020,			/* Ext Line */
-  0x1010,			/* Mic */
-  0x4b4b,			/* CD */
-  0x0000,			/* Recording monitor */
-  0x4b4b,			/* Second PCM */
-  0x4b4b,			/* Recording level */
-  0x4b4b,			/* Input gain */
-  0x4b4b,			/* Output gain */
-  0x2020,			/* Line1 */
-  0x2020,			/* Line2 */
-  0x1515			/* Line3 (usually line in)*/
+	0x3232,			/* Master Volume */
+	0x3232,			/* Bass */
+	0x3232,			/* Treble */
+	0x4b4b,			/* FM */
+	0x3232,			/* PCM */
+	0x1515,			/* PC Speaker */
+	0x2020,			/* Ext Line */
+	0x1010,			/* Mic */
+	0x4b4b,			/* CD */
+	0x0000,			/* Recording monitor */
+	0x4b4b,			/* Second PCM */
+	0x4b4b,			/* Recording level */
+	0x4b4b,			/* Input gain */
+	0x4b4b,			/* Output gain */
+	0x2020,			/* Line1 */
+	0x2020,			/* Line2 */
+	0x1515			/* Line3 (usually line in)*/
 };
 
 #define LEFT_CHN	0
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/awe_wave.c linux/drivers/sound/awe_wave.c
--- v2.5.0/linux/drivers/sound/awe_wave.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/awe_wave.c	Sun Nov 25 09:43:42 2001
@@ -26,9 +26,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
 #include <linux/isapnp.h>
-#endif
 
 #include "sound_config.h"
 
@@ -205,7 +203,7 @@
 
 int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */
 int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 static int isapnp = -1;
 #else
 static int isapnp = 0;
@@ -4772,7 +4770,7 @@
 	return 1;
 }
 	
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 static struct {
 	unsigned short card_vendor, card_device;
 	unsigned short vendor;
@@ -4841,7 +4839,7 @@
 {
 	int base;
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	if (isapnp) {
 		if (awe_probe_isapnp(&io) < 0) {
 			printk(KERN_ERR "AWE32: No ISAPnP cards found\n");
@@ -6132,7 +6130,7 @@
 void __exit unload_awe(void)
 {
 	_unload_awe();
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	if (isapnp)
 		awe_deactivate_isapnp();
 #endif /* isapnp */
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.5.0/linux/drivers/sound/cmpci.c	Fri Nov  9 14:07:41 2001
+++ linux/drivers/sound/cmpci.c	Sun Nov 25 10:17:47 2001
@@ -2496,7 +2496,6 @@
 	spin_unlock_irqrestore(&s->lock, flags);
 	s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE);
 	up(&s->open_sem);
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -2694,7 +2693,6 @@
 	outb(1, s->iosynth+3);  /* enable OPL3 */
 	s->open_mode |= FMODE_DMFM;
 	up(&s->open_sem);
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/maestro3.c linux/drivers/sound/maestro3.c
--- v2.5.0/linux/drivers/sound/maestro3.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/sound/maestro3.c	Sun Nov 25 10:17:47 2001
@@ -2036,7 +2036,6 @@
     set_fmt(s, fmtm, fmts);
     s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 
-    MOD_INC_USE_COUNT;
     up(&s->open_sem);
     spin_unlock_irqrestore(&s->lock, flags);
     return 0;
@@ -2075,7 +2074,6 @@
     up(&s->open_sem);
     wake_up(&s->open_wait);
 
-    MOD_DEC_USE_COUNT;
     return 0;
 }
 
@@ -2142,14 +2140,12 @@
     int minor = MINOR(inode->i_rdev);
     struct m3_card *card = devs;
 
-    MOD_INC_USE_COUNT;
     for (card = devs; card != NULL; card = card->next) {
         if((card->ac97 != NULL) && (card->ac97->dev_mixer == minor))
                 break;
     }
 
     if (!card) {
-        MOD_DEC_USE_COUNT;
         return -ENODEV;
     }
 
@@ -2160,7 +2156,6 @@
 
 static int m3_release_mixdev(struct inode *inode, struct file *file)
 {
-    MOD_DEC_USE_COUNT;
     return 0;
 }
 
@@ -2173,6 +2168,7 @@
 }
 
 static struct file_operations m3_mixer_fops = {
+    owner:          THIS_MODULE,
     llseek:         no_llseek,
     ioctl:          m3_ioctl_mixdev,
     open:           m3_open_mixdev,
@@ -2546,6 +2542,7 @@
 }
 
 static struct file_operations m3_audio_fops = {
+    owner:      THIS_MODULE,
     llseek:     &no_llseek,
     read:       &m3_read,
     write:      &m3_write,
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/opl3sa2.c linux/drivers/sound/opl3sa2.c
--- v2.5.0/linux/drivers/sound/opl3sa2.c	Thu Oct 11 09:43:30 2001
+++ linux/drivers/sound/opl3sa2.c	Sun Nov 25 09:43:42 2001
@@ -99,7 +99,7 @@
 #define CHIPSET_OPL3SA2 0
 #define CHIPSET_OPL3SA3 1
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 #define OPL3SA2_CARDS_MAX 4
 #else
 #define OPL3SA2_CARDS_MAX 1
@@ -147,7 +147,7 @@
 static int __initdata ymode	= -1;
 static int __initdata loopback	= -1;
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 /* PnP specific parameters */
 static int __initdata isapnp = 1;
 static int __initdata multiple = 1;
@@ -191,7 +191,7 @@
 MODULE_PARM(loopback, "i");
 MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)");
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 MODULE_PARM(isapnp, "i");
 MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled");
 
@@ -807,7 +807,7 @@
 }
 
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 
 struct isapnp_device_id isapnp_opl3sa2_list[] __initdata = {
 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
@@ -888,7 +888,7 @@
 
 	return 0;
 }
-#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
+#endif /* __ISAPNP__ */
 
 /* End of component functions */
 
@@ -909,9 +909,9 @@
 	
 	max = (multiple && isapnp) ? OPL3SA2_CARDS_MAX : 1;
 	for(card = 0; card < max; card++, opl3sa2_cards_num++) {
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 		/*
-		 * Please remember that even with CONFIG_ISAPNP defined one
+		 * Please remember that even with __ISAPNP__ defined one
 		 * should still be able to disable PNP support for this 
 		 * single driver!
 		 */
@@ -1039,7 +1039,7 @@
 		unload_opl3sa2_mss(&cfg_mss[card]);
 		unload_opl3sa2(&cfg[card], card);
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 		if(opl3sa2_activated[card] && opl3sa2_dev[card]) {
 			opl3sa2_dev[card]->deactivate(opl3sa2_dev[card]);
 
@@ -1058,7 +1058,7 @@
 static int __init setup_opl3sa2(char *str)
 {
 	/* io, irq, dma, dma2,... */
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	int ints[11];
 #else
 	int ints[9];
@@ -1073,7 +1073,7 @@
 	mpu_io   = ints[6];
 	ymode    = ints[7];
 	loopback = ints[8];
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 	isapnp   = ints[9];
 	multiple = ints[10];
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.5.0/linux/drivers/sound/sb_card.c	Thu Oct 11 09:43:30 2001
+++ linux/drivers/sound/sb_card.c	Sun Nov 25 09:43:42 2001
@@ -69,7 +69,7 @@
 #include "sb_mixer.h"
 #include "sb.h"
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 #define SB_CARDS_MAX 5
 #else
 #define SB_CARDS_MAX 1
@@ -196,7 +196,7 @@
 		*opl_dev[SB_CARDS_MAX]	= {NULL};
 
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 static int isapnp	= 1;
 static int isapnpjump	= 0;
 static int multiple	= 1;
@@ -226,7 +226,7 @@
 MODULE_PARM(esstype,	"i");
 MODULE_PARM(acer,	"i");
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 MODULE_PARM(isapnp,	"i");
 MODULE_PARM(isapnpjump,	"i");
 MODULE_PARM(multiple,	"i");
@@ -251,7 +251,7 @@
 MODULE_PARM_DESC(esstype,	"ESS chip type");
 MODULE_PARM_DESC(acer,		"Set this to detect cards in some ACER notebooks");
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 
 /* Please add new entries at the end of the table */
 static struct {
@@ -909,8 +909,8 @@
 	printk(KERN_INFO "Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 	
 	for(card = 0; card < max; card++, sb_cards_num++) {
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
-		/* Please remember that even with CONFIG_ISAPNP defined one
+#ifdef __ISAPNP__
+		/* Please remember that even with __ISAPNP__ defined one
 		 * should still be able to disable PNP support for this 
 		 * single driver! */
 		if((!pnplegacy||card>0) && isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
@@ -997,7 +997,7 @@
 		if (sbmpu[i])
 			unload_sbmpu(&cfg_mpu[i]);
 
-#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#ifdef __ISAPNP__
 		if(!audio_activated[i] && sb_dev[i])
 			sb_dev[i]->deactivate(sb_dev[i]);
 		if(!mpu_activated[i] && mpu_dev[i])
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.5.0/linux/drivers/sound/sound_core.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/sound_core.c	Sun Nov 25 10:17:47 2001
@@ -115,7 +115,6 @@
 	*list=s;
 	
 	
-	MOD_INC_USE_COUNT;
 	return n;
 }
 
@@ -133,7 +132,6 @@
 			*list=p->next;
 			devfs_unregister (p->de);
 			kfree(p);
-			MOD_DEC_USE_COUNT;
 			return;
 		}
 		list=&(p->next);
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- v2.5.0/linux/drivers/sound/via82cxxx_audio.c	Fri Nov  9 13:45:35 2001
+++ linux/drivers/sound/via82cxxx_audio.c	Mon Dec 10 10:39:20 2001
@@ -1,6 +1,6 @@
 /*
  * Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ * Copyright 1999,2000 Jeff Garzik
  *
  * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
  * See the "COPYING" file distributed with this software for more info.
@@ -8,9 +8,6 @@
  * For a list of known bugs (errata) and documentation,
  * see via-audio.pdf in linux/Documentation/DocBook.
  * If this documentation does not exist, run "make pdfdocs".
- * If "make pdfdocs" fails, obtain the documentation from
- * the driver's Website at
- * http://gtf.org/garzik/drivers/via82cxxx/
  *
  */
 
@@ -3357,7 +3354,7 @@
 module_init(init_via82cxxx_audio);
 module_exit(cleanup_via82cxxx_audio);
 
-MODULE_AUTHOR("Jeff Garzik <jgarzik@mandrakesoft.com>");
+MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("DSP audio and mixer driver for Via 82Cxxx audio devices");
 MODULE_LICENSE("GPL");
 
diff -u --recursive --new-file v2.5.0/linux/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c
--- v2.5.0/linux/drivers/sound/ymfpci.c	Mon Nov 19 14:53:19 2001
+++ linux/drivers/sound/ymfpci.c	Sun Nov 25 10:17:47 2001
@@ -1872,7 +1872,6 @@
 #endif
 	up(&unit->open_sem);
 
-	MOD_INC_USE_COUNT;
 	return 0;
 
 out_nodma:
@@ -1921,7 +1920,6 @@
 
 	up(&codec->open_sem);
 
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -1949,7 +1947,6 @@
  match:
 	file->private_data = unit->ac97_codec[i];
 
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -1963,11 +1960,11 @@
 
 static int ymf_release_mixdev(struct inode *inode, struct file *file)
 {
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
 static /*const*/ struct file_operations ymf_fops = {
+	owner:		THIS_MODULE,
 	llseek:		no_llseek,
 	read:		ymf_read,
 	write:		ymf_write,
@@ -1979,6 +1976,7 @@
 };
 
 static /*const*/ struct file_operations ymf_mixer_fops = {
+	owner:		THIS_MODULE,
 	llseek:		no_llseek,
 	ioctl:		ymf_ioctl_mixdev,
 	open:		ymf_open_mixdev,
@@ -2043,13 +2041,6 @@
 	ymfpci_aclink_reset(unit->pci);
 	ymfpci_codec_ready(unit, 0, 1);		/* prints diag if not ready. */
 
-	for (i = 0; i < NR_AC97; i++) {
-		codec = unit->ac97_codec[i];
-		if (!codec)
-			continue;
-		ac97_restore_state(codec);
-	}
-
 #ifdef CONFIG_SOUND_YMFPCI_LEGACY
 	/* XXX At this time the legacy registers are probably deprogrammed. */
 #endif
@@ -2063,6 +2054,13 @@
 	if (unit->start_count) {
 		ymfpci_writel(unit, YDSXGR_MODE, 3);
 		unit->active_bank = ymfpci_readl(unit, YDSXGR_CTRLSELECT) & 1;
+	}
+
+	for (i = 0; i < NR_AC97; i++) {
+		codec = unit->ac97_codec[i];
+		if (!codec)
+			continue;
+		ac97_restore_state(codec);
 	}
 
 	unit->suspended = 0;
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/CDCEther.c linux/drivers/usb/CDCEther.c
--- v2.5.0/linux/drivers/usb/CDCEther.c	Fri Oct  5 12:06:08 2001
+++ linux/drivers/usb/CDCEther.c	Sat Dec  8 20:28:44 2001
@@ -82,9 +82,9 @@
 	ether_dev->flags |= CDC_ETHER_RX_BUSY;
 
 	switch ( urb->status ) {
-		case USB_ST_NOERROR:
+		case 0:
 			break;
-		case USB_ST_NORESPONSE:
+		case -ETIMEDOUT:
 			dbg( "no repsonse in BULK IN" );
 			ether_dev->flags &= ~CDC_ETHER_RX_BUSY;
 			break;
@@ -179,9 +179,9 @@
 //		return;
 //		
 //	switch ( urb->status ) {
-//		case USB_ST_NOERROR:
+//		case 0:
 //			break;
-//		case USB_ST_URB_KILLED:
+//		case -ENOENT:
 //			return;
 //		default:
 //			info("intr status %d", urb->status);
@@ -337,13 +337,9 @@
 	ether_dev_t *ether_dev = (ether_dev_t *)net->priv;
 	int	res;
 
-	// We are finally getting used!
-	MOD_INC_USE_COUNT;
-
 	// Turn on the USB and let the packets flow!!!
 	if ( (res = enable_net_traffic( ether_dev )) ) {
 		err( __FUNCTION__ "can't enable_net_traffic() - %d", res );
-		MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
 
@@ -391,9 +387,6 @@
 	usb_unlink_urb( &ether_dev->tx_urb );
 	usb_unlink_urb( &ether_dev->intr_urb );
 	
-	// We are not being used now.
-	MOD_DEC_USE_COUNT;
-
 	// That's it.  I'm done.
 	return 0;
 }
@@ -480,6 +473,7 @@
                      i++, mclist = mclist->next) {
 			memcpy(&mclist->dmi_addr, &buff[i * 6], 6);
 		}
+#if 0
 		usb_control_msg(ether_dev->usb,
 				usb_sndctrlpipe(ether_dev->usb, 0),
 				SET_ETHERNET_MULTICAST_FILTER, /* request */
@@ -489,11 +483,13 @@
 				buff,
 				(6* net->mc_count), /* size */
 				HZ); /* timeout */
+#endif
 		kfree(buff);
 	}
- 
+
+#if 0 
 	CDC_SetEthernetPacketFilter(ether_dev);
-	
+#endif	
         // Tell the kernel to start giving frames to us again.
 	netif_wake_queue(net);
 }
@@ -1210,6 +1206,7 @@
 	// Now that we have an ethernet device, let's set it up
 	// (And I don't mean "set [it] up the bomb".)
 	net->priv = ether_dev;
+	SET_MODULE_OWNER(net);
 	net->open = CDCEther_open;
 	net->stop = CDCEther_close;
 	net->watchdog_timeo = CDC_ETHER_TX_TIMEOUT;
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.5.0/linux/drivers/usb/Config.in	Fri Nov  2 17:18:58 2001
+++ linux/drivers/usb/Config.in	Sat Dec  8 20:28:44 2001
@@ -9,7 +9,7 @@
    bool '  USB verbose debug messages' CONFIG_USB_DEBUG
 
 comment 'Miscellaneous USB options'
-   bool '  Preliminary USB device filesystem' CONFIG_USB_DEVICEFS
+   bool '  USB device filesystem' CONFIG_USB_DEVICEFS
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       bool '  Enforce USB bandwidth allocation (EXPERIMENTAL)' CONFIG_USB_BANDWIDTH
    else
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.5.0/linux/drivers/usb/audio.c	Fri Oct  5 12:04:50 2001
+++ linux/drivers/usb/audio.c	Sat Dec  8 20:28:44 2001
@@ -899,7 +899,7 @@
 	struct usbin *u = &as->usbin;
 	unsigned long flags;
 	unsigned int mask;
-	int suret = USB_ST_NOERROR;
+	int suret = 0;
 
 #if 0
 	printk(KERN_DEBUG "usbin_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
@@ -917,7 +917,7 @@
 	if (!usbin_retire_desc(u, urb) &&
 	    u->flags & FLG_RUNNING &&
 	    !usbin_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+	    (suret = usb_submit_urb(urb)) == 0) {
 		u->flags |= mask;
 	} else {
 		u->flags &= ~(mask | FLG_RUNNING);
@@ -964,7 +964,7 @@
 	struct usbin *u = &as->usbin;
 	unsigned long flags;
 	unsigned int mask;
-	int suret = USB_ST_NOERROR;
+	int suret = 0;
 
 #if 0
 	printk(KERN_DEBUG "usbin_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
@@ -982,7 +982,7 @@
 	if (!usbin_sync_retire_desc(u, urb) &&
 	    u->flags & FLG_RUNNING &&
 	    !usbin_sync_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+	    (suret = usb_submit_urb(urb)) == 0) {
 		u->flags |= mask;
 	} else {
 		u->flags &= ~(mask | FLG_RUNNING);
@@ -1257,7 +1257,7 @@
 	struct usbout *u = &as->usbout;
 	unsigned long flags;
 	unsigned int mask;
-	int suret = USB_ST_NOERROR;
+	int suret = 0;
 
 #if 0
 	printk(KERN_DEBUG "usbout_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
@@ -1275,7 +1275,7 @@
 	if (!usbout_retire_desc(u, urb) &&
 	    u->flags & FLG_RUNNING &&
 	    !usbout_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+	    (suret = usb_submit_urb(urb)) == 0) {
 		u->flags |= mask;
 	} else {
 		u->flags &= ~(mask | FLG_RUNNING);
@@ -1329,7 +1329,7 @@
 	struct usbout *u = &as->usbout;
 	unsigned long flags;
 	unsigned int mask;
-	int suret = USB_ST_NOERROR;
+	int suret = 0;
 
 #if 0
 	printk(KERN_DEBUG "usbout_sync_completed: status %d errcnt %d flags 0x%x\n", urb->status, urb->error_count, u->flags);
@@ -1347,7 +1347,7 @@
 	if (!usbout_sync_retire_desc(u, urb) &&
 	    u->flags & FLG_RUNNING &&
 	    !usbout_sync_prepare_desc(u, urb) && 
-	    (suret = usb_submit_urb(urb)) == USB_ST_NOERROR) {
+	    (suret = usb_submit_urb(urb)) == 0) {
 		u->flags |= mask;
 	} else {
 		u->flags &= ~(mask | FLG_RUNNING);
@@ -3362,28 +3362,48 @@
 	struct usb_device *dev = state->s->usbdev;
 	unsigned char data[1];
 #endif
+	unsigned char nr_logical_channels, i;
 
 	usb_audio_recurseunit(state, ftr[4]);
+
+	if (ftr[5] == 0 ) {
+		printk(KERN_ERR "usbaudio: wrong controls size in feature unit %u\n",ftr[3]);
+		return;
+	}
+
 	if (state->nrchannels == 0) {
 		printk(KERN_ERR "usbaudio: feature unit %u source has no channels\n", ftr[3]);
 		return;
 	}
 	if (state->nrchannels > 2)
 		printk(KERN_WARNING "usbaudio: feature unit %u: OSS mixer interface does not support more than 2 channels\n", ftr[3]);
-	if (state->nrchannels == 1 && ftr[0] == 7+ftr[5]) {
-		printk(KERN_DEBUG "usbaudio: workaround for Philips camera microphone descriptor enabled\n");
-		mchftr = ftr[6];
-		chftr = 0;
-	} else {
-		if (ftr[0] < 7+ftr[5]*(1+state->nrchannels)) {
-			printk(KERN_ERR "usbaudio: unit %u: invalid FEATURE_UNIT descriptor\n", ftr[3]);
-			return;
+
+	nr_logical_channels=(ftr[0]-7)/ftr[5]-1;
+
+	if (nr_logical_channels != state->nrchannels) {
+		printk(KERN_WARNING "usbaudio: warning: found %d of %d logical channels.\n", state->nrchannels,nr_logical_channels);
+
+		if (state->nrchannels == 1 && nr_logical_channels==0) {
+			printk(KERN_INFO "usbaudio: assuming the channel found is the master channel (got a Philips camera?). Should be fine.\n");
+		} else if (state->nrchannels == 1 && nr_logical_channels==2) {
+			printk(KERN_INFO "usbaudio: assuming that a stereo channel connected directly to a mixer is missing in search (got Labtec headset?). Should be fine.\n");
+			state->nrchannels=nr_logical_channels;
+		} else {
+			printk(KERN_WARNING "usbaudio: no idea what's going on..., contact linux-usb-devel@lists.sourceforge.net\n");
 		}
-		mchftr = ftr[6];
+	}
+
+	/* There is always a master channel */
+	mchftr = ftr[6];
+	/* Binary AND over logical channels if they exist */
+	if (nr_logical_channels) {
 		chftr = ftr[6+ftr[5]];
-		if (state->nrchannels > 1)
-			chftr &= ftr[6+2*ftr[5]];
+		for (i = 2; i <= nr_logical_channels; i++)
+			chftr &= ftr[6+i*ftr[5]];
+	} else {
+		chftr = 0;
 	}
+
 	/* volume control */
 	if (chftr & 2) {
 		ch = getmixchannel(state, getvolchannel(state));
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c
--- v2.5.0/linux/drivers/usb/bluetooth.c	Tue Nov 13 09:19:41 2001
+++ linux/drivers/usb/bluetooth.c	Sat Dec  8 20:28:44 2001
@@ -1,11 +1,15 @@
 /*
- * bluetooth.c   Version 0.12
+ * bluetooth.c   Version 0.13
  *
  * Copyright (c) 2000, 2001 Greg Kroah-Hartman	<greg@kroah.com>
  * Copyright (c) 2000 Mark Douglas Corner	<mcorner@umich.edu>
  *
  * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
  * 
+ * (2001/11/30) Version 0.13 gkh
+ *	- added locking patch from Masoodur Rahman <rmasoodu@in.ibm.com>
+ *	- removed active variable, as open_count will do.
+ *
  * (2001/07/09) Version 0.12 gkh
  *	- removed in_interrupt() call, as it doesn't make sense to do 
  *	  that anymore.
@@ -118,7 +122,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.12"
+#define DRIVER_VERSION "v0.13"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman, Mark Douglas Corner"
 #define DRIVER_DESC "USB Bluetooth tty driver"
 
@@ -170,8 +174,8 @@
 	struct tty_struct *	tty;		/* the coresponding tty for this port */
 
 	unsigned char		minor;		/* the starting minor number for this device */
-	char			active;		/* someone has this device open */
 	int			throttle;	/* throttled by tty layer */
+	int			open_count;
 	
 	__u8			control_out_bInterfaceNum;
 	struct urb *		control_urb_pool[NUM_CONTROL_URBS];
@@ -200,6 +204,7 @@
 	unsigned char		int_buffer[EVENT_BUFFER_SIZE];
 	unsigned int		bulk_packet_pos;
 	unsigned char		bulk_buffer[ACL_BUFFER_SIZE];	/* 64k preallocated, fix? */
+	struct semaphore	lock;
 };
 
 
@@ -361,43 +366,46 @@
 		return -ENODEV;
 	}
 
-	if (bluetooth->active) {
-		dbg (__FUNCTION__ " - device already open");
-		return -EINVAL;
-	}
-
-	/* set up our structure making the tty driver remember our object, and us it */
-	tty->driver_data = bluetooth;
-	bluetooth->tty = tty;
-
-	/* force low_latency on so that our tty_push actually forces the data through, 
-	 * otherwise it is scheduled, and with high data rates (like with OHCI) data
-	 * can get lost. */
-	bluetooth->tty->low_latency = 1;
+	down (&bluetooth->lock);
+ 
+	++bluetooth->open_count;
+	if (bluetooth->open_count == 1) {
+		/* set up our structure making the tty driver remember our object, and us it */
+		tty->driver_data = bluetooth;
+		bluetooth->tty = tty;
+
+		/* force low_latency on so that our tty_push actually forces the data through, 
+	 	* otherwise it is scheduled, and with high data rates (like with OHCI) data
+	 	* can get lost. */
+		bluetooth->tty->low_latency = 1;
 	
-	bluetooth->active = 1;
-
-	/* Reset the packet position counters */
-	bluetooth->int_packet_pos = 0;
-	bluetooth->bulk_packet_pos = 0;
+		/* Reset the packet position counters */
+		bluetooth->int_packet_pos = 0;
+		bluetooth->bulk_packet_pos = 0;
 
 #ifndef BTBUGGYHARDWARE
-	/* Start reading from the device */
-	FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, 
-		      usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
-		      bluetooth->bulk_in_buffer, bluetooth->bulk_in_buffer_size, 
-		      bluetooth_read_bulk_callback, bluetooth);
-	result = usb_submit_urb(bluetooth->read_urb);
-	if (result)
-		dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result);
+		/* Start reading from the device */
+		FILL_BULK_URB (bluetooth->read_urb, bluetooth->dev, 
+			       usb_rcvbulkpipe(bluetooth->dev, bluetooth->bulk_in_endpointAddress),
+			       bluetooth->bulk_in_buffer,
+			       bluetooth->bulk_in_buffer_size,
+			       bluetooth_read_bulk_callback, bluetooth);
+		result = usb_submit_urb(bluetooth->read_urb);
+		if (result)
+			dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed with status %d", result);
 #endif
-	FILL_INT_URB(bluetooth->interrupt_in_urb, bluetooth->dev, 
-		     usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
-		     bluetooth->interrupt_in_buffer, bluetooth->interrupt_in_buffer_size, 
-		     bluetooth_int_callback, bluetooth, bluetooth->interrupt_in_interval);
-	result = usb_submit_urb(bluetooth->interrupt_in_urb);
-	if (result)
-		dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result);
+		FILL_INT_URB (bluetooth->interrupt_in_urb, bluetooth->dev,
+			      usb_rcvintpipe(bluetooth->dev, bluetooth->interrupt_in_endpointAddress),
+			      bluetooth->interrupt_in_buffer,
+			      bluetooth->interrupt_in_buffer_size,
+			      bluetooth_int_callback, bluetooth,
+			      bluetooth->interrupt_in_interval);
+		result = usb_submit_urb(bluetooth->interrupt_in_urb);
+		if (result)
+			dbg(__FUNCTION__ " - usb_submit_urb(interrupt in) failed with status %d", result);
+	}
+	
+	up(&bluetooth->lock);
 
 	return 0;
 }
@@ -414,18 +422,24 @@
 
 	dbg(__FUNCTION__);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not opened");
 		return;
 	}
 
-	/* shutdown any bulk reads and writes that might be going on */
-	for (i = 0; i < NUM_BULK_URBS; ++i)
-		usb_unlink_urb (bluetooth->write_urb_pool[i]);
-	usb_unlink_urb (bluetooth->read_urb);
-	usb_unlink_urb (bluetooth->interrupt_in_urb);
-
-	bluetooth->active = 0;
+	down (&bluetooth->lock);
+ 
+	--bluetooth->open_count;
+	if (bluetooth->open_count <= 0) {
+		bluetooth->open_count = 0;
+
+		/* shutdown any bulk reads and writes that might be going on */
+		for (i = 0; i < NUM_BULK_URBS; ++i)
+			usb_unlink_urb (bluetooth->write_urb_pool[i]);
+		usb_unlink_urb (bluetooth->read_urb);
+		usb_unlink_urb (bluetooth->interrupt_in_urb);
+	}
+	up(&bluetooth->lock);
 }
 
 
@@ -447,7 +461,7 @@
 
 	dbg(__FUNCTION__ " - %d byte(s)", count);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not opened");
 		return -EINVAL;
 	}
@@ -572,7 +586,7 @@
 
 	dbg(__FUNCTION__);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not open");
 		return -EINVAL;
 	}
@@ -598,7 +612,7 @@
 		return -ENODEV;
 	}
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not open");
 		return -EINVAL;
 	}
@@ -624,7 +638,7 @@
 
 	dbg(__FUNCTION__);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not open");
 		return;
 	}
@@ -645,7 +659,7 @@
 
 	dbg(__FUNCTION__);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not open");
 		return;
 	}
@@ -664,7 +678,7 @@
 
 	dbg(__FUNCTION__ " - cmd 0x%.4x", cmd);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not open");
 		return -ENODEV;
 	}
@@ -684,7 +698,7 @@
 
 	dbg(__FUNCTION__);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not open");
 		return;
 	}
@@ -706,7 +720,7 @@
 
 	dbg(__FUNCTION__);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not open");
 		return;
 	}
@@ -731,7 +745,7 @@
 
 	dbg(__FUNCTION__);
 
-	if (!bluetooth->active) {
+	if (!bluetooth->open_count) {
 		dbg (__FUNCTION__ " - device not open");
 		return;
 	}
@@ -961,7 +975,7 @@
 	}	
 
 exit:
-	if (!bluetooth || !bluetooth->active)
+	if (!bluetooth || !bluetooth->open_count)
 		return;
 
 	FILL_BULK_URB(bluetooth->read_urb, bluetooth->dev, 
@@ -1102,6 +1116,7 @@
 	bluetooth->minor = minor;
 	bluetooth->tqueue.routine = bluetooth_softint;
 	bluetooth->tqueue.data = bluetooth;
+	init_MUTEX(&bluetooth->lock);
 
 	/* record the interface number for the control out */
 	bluetooth->control_out_bInterfaceNum = control_out_endpoint;
@@ -1217,10 +1232,10 @@
 	int i;
 
 	if (bluetooth) {
-		if ((bluetooth->active) && (bluetooth->tty))
+		if ((bluetooth->open_count) && (bluetooth->tty))
 			tty_hangup(bluetooth->tty);
 
-		bluetooth->active = 0;
+		bluetooth->open_count = 0;
 
 		if (bluetooth->read_urb) {
 			usb_unlink_urb (bluetooth->read_urb);
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
--- v2.5.0/linux/drivers/usb/dabusb.c	Fri Sep 14 14:04:07 2001
+++ linux/drivers/usb/dabusb.c	Fri Nov 30 08:26:04 2001
@@ -224,7 +224,7 @@
 			err("kmalloc(sizeof(buff_t))==NULL");
 			goto err;
 		}
-		memset (b, sizeof (buff_t), 0);
+		memset (b, 0, sizeof (buff_t));
 		b->s = s;
 		b->purb = usb_alloc_urb(packets);
 		if (!b->purb) {
@@ -622,7 +622,6 @@
 
 	dbg("dabusb_release");
 
-	lock_kernel();
 	down (&s->mutex);
 	dabusb_stop (s);
 	dabusb_free_buffers (s);
@@ -636,7 +635,6 @@
 		wake_up (&s->remove_ok);
 
 	s->opened = 0;
-	unlock_kernel();
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c
--- v2.5.0/linux/drivers/usb/dc2xx.c	Fri Sep 14 14:04:07 2001
+++ linux/drivers/usb/dc2xx.c	Sat Dec  8 20:28:45 2001
@@ -112,12 +112,15 @@
 	/* These have a different application level protocol which
 	 * is part of the Flashpoint "DigitaOS".  That supports some
 	 * non-camera devices, and some non-Kodak cameras.
+	 * Use this driver to get USB and "OpenDis" to talk.
 	 */  
 	{ USB_DEVICE(0x040a, 0x0100) },		// Kodak DC-220
 	{ USB_DEVICE(0x040a, 0x0110) },		// Kodak DC-260
 	{ USB_DEVICE(0x040a, 0x0111) },		// Kodak DC-265
 	{ USB_DEVICE(0x040a, 0x0112) },		// Kodak DC-290
 	{ USB_DEVICE(0xf003, 0x6002) },		// HP PhotoSmart C500
+	{ USB_DEVICE(0x03f0, 0x4102) },		// HP PhotoSmart C618
+	{ USB_DEVICE(0x0a17, 0x1001) },		// Pentax EI-200
 
 	/* Other USB devices may well work here too, so long as they
 	 * just stick to half duplex bulk packet exchanges.  That
@@ -196,7 +199,7 @@
 				retval = count;
 			break;
 		}
-		if (retval != USB_ST_TIMEOUT)
+		if (retval != -ETIMEDOUT)
 			break;
 		interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
 
@@ -264,7 +267,7 @@
 			} else if (!result)
 				break;
 				
-			if (result == USB_ST_TIMEOUT) {	/* NAK - delay a bit */
+			if (result == -ETIMEDOUT) {	/* NAK - delay a bit */
 				if (!maxretry--) {
 					if (!bytes_written)
 						bytes_written = -ETIME;
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/devices.c linux/drivers/usb/devices.c
--- v2.5.0/linux/drivers/usb/devices.c	Sat Oct 20 19:13:11 2001
+++ linux/drivers/usb/devices.c	Sat Dec  8 20:25:02 2001
@@ -139,9 +139,12 @@
 	{USB_CLASS_PHYSICAL,		"PID"},
 	{USB_CLASS_PRINTER,		"print"},
 	{USB_CLASS_MASS_STORAGE,	"stor."},
-	{USB_CLASS_DATA,		"data"},
+	{USB_CLASS_CDC_DATA,		"data"},
 	{USB_CLASS_APP_SPEC,		"app."},
 	{USB_CLASS_VENDOR_SPEC,		"vend."},
+	{USB_CLASS_STILL_IMAGE,		"still"},
+	{USB_CLASS_CSCID,		"scard"},
+	{USB_CLASS_CONTENT_SEC,		"c-sec"},
 	{-1,				"unk."}		/* leave as last */
 };
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/devio.c linux/drivers/usb/devio.c
--- v2.5.0/linux/drivers/usb/devio.c	Fri Nov  2 17:18:58 2001
+++ linux/drivers/usb/devio.c	Sat Dec  8 20:28:44 2001
@@ -276,7 +276,7 @@
                 list_del(&as->asynclist);
                 INIT_LIST_HEAD(&as->asynclist);
                 spin_unlock_irqrestore(&ps->lock, flags);
-                /* usb_unlink_urb calls the completion handler with status == USB_ST_URB_KILLED */
+                /* usb_unlink_urb calls the completion handler with status == -ENOENT */
                 usb_unlink_urb(&as->urb);
                 spin_lock_irqsave(&ps->lock, flags);
         }
@@ -299,11 +299,12 @@
 {
 	struct dev_state *ps = (struct dev_state *)context;
 
-	ps->ifclaimed = 0;
+	if (ps)
+		ps->ifclaimed = 0;
 }
 
 struct usb_driver usbdevfs_driver = {
-	name:		"usbdevfs",
+	name:		"usbfs",
 	probe:		driver_probe,
 	disconnect:	driver_disconnect,
 };
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/hid-core.c linux/drivers/usb/hid-core.c
--- v2.5.0/linux/drivers/usb/hid-core.c	Sun Sep 16 11:07:43 2001
+++ linux/drivers/usb/hid-core.c	Sat Dec  8 20:28:45 2001
@@ -897,7 +897,7 @@
 	u8 data[len];
 	int read;
 
-	if ((read = usb_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, data, len)) != len) {
+	if ((read = hid_get_report(hid->dev, hid->ifnum, report->type + 1, report->id, data, len)) != len) {
 		dbg("reading report type %d id %d failed len %d read %d", report->type + 1, report->id, len, read);
 		return;
 	}
@@ -1064,7 +1064,7 @@
 			list = report_enum->report_list.next;
 			while (list != &report_enum->report_list) {
 				report = (struct hid_report *) list;
-				usb_set_idle(hid->dev, hid->ifnum, 0, report->id);
+				hid_set_idle(hid->dev, hid->ifnum, 0, report->id);
 				hid_read_report(hid, report);
 				list = list->next;
 			}
@@ -1089,6 +1089,16 @@
 	{ 0, 0 }
 };
 
+static int get_class_descriptor(struct usb_device *dev, int ifnum,
+		unsigned char type, void *buf, int size)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
+		(type << 8), ifnum, buf, size,
+		HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+
 static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
 {
 	struct usb_interface_descriptor *interface = dev->actconfig->interface[ifnum].altsetting + 0;
@@ -1102,14 +1112,14 @@
 		if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
 			(hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL;
 
-	if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
-		usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc))) {
+	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) && ((!interface->bNumEndpoints) ||
+		usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
 			dbg("class descriptor not present\n");
 			return NULL;
 	}
 
 	for (n = 0; n < hdesc->bNumDescriptors; n++)
-		if (hdesc->desc[n].bDescriptorType == USB_DT_REPORT)
+		if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
 			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
 
 	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
@@ -1120,7 +1130,7 @@
 	{
 		__u8 rdesc[rsize];
 
-		if ((n = usb_get_class_descriptor(dev, interface->bInterfaceNumber, USB_DT_REPORT, 0, rdesc, rsize)) < 0) {
+		if ((n = get_class_descriptor(dev, interface->bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) {
 			dbg("reading report descriptor failed");
 			return NULL;
 		}
@@ -1170,7 +1180,7 @@
 
 	for (n = 0; n < HID_CONTROL_FIFO_SIZE; n++) {
 		hid->out[n].dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-		hid->out[n].dr.request = USB_REQ_SET_REPORT;
+		hid->out[n].dr.request = HID_REQ_SET_REPORT;
 		hid->out[n].dr.index = cpu_to_le16(hid->ifnum);
 	}
 
@@ -1198,7 +1208,7 @@
 
 #if 0
 	if (interface->bInterfaceSubClass == 1)
-		usb_set_protocol(dev, hid->ifnum, 1);
+		hid_set_protocol(dev, hid->ifnum, 1);
 #endif
 
 	return hid;
@@ -1236,7 +1246,7 @@
 
 	c = "Device";
 	for (i = 0; i < hid->maxapplication; i++)
-		if (IS_INPUT_APPLICATION(hid->application[i])) {
+		if ((hid->application[i] & 0xffff) < ARRAY_SIZE(hid_types)) {
 			c = hid_types[hid->application[i] & 0xffff];
 			break;
 		}
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/hid.h linux/drivers/usb/hid.h
--- v2.5.0/linux/drivers/usb/hid.h	Tue Nov 13 17:45:27 2001
+++ linux/drivers/usb/hid.h	Sat Dec  8 20:28:45 2001
@@ -30,6 +30,88 @@
  * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
  */
 
+/*
+ * HID class requests
+ */
+#define HID_REQ_GET_REPORT		0x01
+#define HID_REQ_GET_IDLE		0x02
+#define HID_REQ_GET_PROTOCOL		0x03
+#define HID_REQ_SET_REPORT		0x09
+#define HID_REQ_SET_IDLE		0x0A
+#define HID_REQ_SET_PROTOCOL		0x0B
+
+/*
+ * HID class descriptor types
+ */
+#define HID_DT_HID			(USB_TYPE_CLASS | 0x01)
+#define HID_DT_REPORT			(USB_TYPE_CLASS | 0x02)
+#define HID_DT_PHYSICAL			(USB_TYPE_CLASS | 0x03)
+
+/*
+ * Utilities for class control messaging
+ */
+static inline int
+hid_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		(duration << 8) | report_id, ifnum, NULL, 0,
+		HZ * USB_CTRL_SET_TIMEOUT);
+}
+
+static inline int
+hid_get_protocol(struct usb_device *dev, int ifnum)
+{
+	unsigned char type;
+	int ret;
+
+	if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			HID_REQ_GET_PROTOCOL,
+			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+			0, ifnum, &type, 1, 
+			HZ * USB_CTRL_GET_TIMEOUT)) < 0)
+		return ret;
+
+	return type;
+}
+
+static inline int
+hid_set_protocol(struct usb_device *dev, int ifnum, int protocol)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		HID_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		protocol, ifnum, NULL, 0, 
+		HZ * USB_CTRL_SET_TIMEOUT);
+}
+
+static inline int
+hid_get_report(struct usb_device *dev, int ifnum, unsigned char type,
+	unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		HID_REQ_GET_REPORT,
+		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		(type << 8) + id, ifnum, buf, size, 
+		HZ * USB_CTRL_GET_TIMEOUT);
+}
+
+static inline int
+hid_set_report(struct usb_device *dev, int ifnum, unsigned char type,
+	unsigned char id, void *buf, int size)
+{
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		HID_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		(type << 8) + id, ifnum, buf, size, HZ);
+		// FIXME USB_CTRL_SET_TIMEOUT
+}
+
+
+/*
+ * "Boot Protocol" keyboard/mouse drivers use don't use all of HID;
+ * they're a lot smaller but can't support all the device features.
+ */
+#ifndef	_HID_BOOT_PROTOCOL
+
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/list.h>
@@ -359,9 +441,7 @@
 #else
 #define hid_dump_input(a,b)	do { } while (0)
 #define hid_dump_device(c)	do { } while (0)
-#endif
-
-#endif
+#endif /* DEBUG */
 
 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || ( a == 0x000c0001))
 
@@ -372,3 +452,8 @@
 void hid_write_report(struct hid_device *, struct hid_report *);
 void hid_read_report(struct hid_device *, struct hid_report *);
 void hid_init_reports(struct hid_device *hid);
+
+#endif	/* !_HID_BOOT_PROTOCOL */
+
+#endif	/* !__HID_H */
+
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/hiddev.c linux/drivers/usb/hiddev.c
--- v2.5.0/linux/drivers/usb/hiddev.c	Sat Oct 20 19:13:11 2001
+++ linux/drivers/usb/hiddev.c	Fri Nov 30 08:26:04 2001
@@ -193,7 +193,6 @@
 	struct hiddev_list *list = file->private_data;
 	struct hiddev_list **listptr;
 
-	lock_kernel();
 	listptr = &list->hiddev->list;
 	hiddev_fasync(-1, file, 0);
 
@@ -209,7 +208,6 @@
 	}
 
 	kfree(list);
-	unlock_kernel();
 
 	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/hpusbscsi.h linux/drivers/usb/hpusbscsi.h
--- v2.5.0/linux/drivers/usb/hpusbscsi.h	Fri Oct  5 12:04:51 2001
+++ linux/drivers/usb/hpusbscsi.h	Wed Nov 28 10:22:27 2001
@@ -73,7 +73,6 @@
 	present:		0,
 	unchecked_isa_dma:	FALSE,
 	use_clustering:		TRUE,
-	use_new_eh_code:	TRUE,
 	emulated:		TRUE
 };
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/inode.c linux/drivers/usb/inode.c
--- v2.5.0/linux/drivers/usb/inode.c	Sat Oct 20 19:13:11 2001
+++ linux/drivers/usb/inode.c	Sat Dec  8 20:28:44 2001
@@ -654,7 +654,13 @@
         return NULL;
 }
 
+/*
+ * The usbdevfs name is now depreciated (as of 2.5.1).
+ * It will be removed when the 2.7.x development cycle is started.
+ * You have been warned :)
+ */
 static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, FS_SINGLE);
+static DECLARE_FSTYPE(usb_fs_type, "usbfs", usbdevfs_read_super, FS_SINGLE);
 
 /* --------------------------------------------------------------------- */
 
@@ -747,7 +753,12 @@
 	}
 	if ((ret = usb_register(&usbdevfs_driver)))
 		return ret;
+	if ((ret = register_filesystem(&usb_fs_type))) {
+		usb_deregister(&usbdevfs_driver);
+		return ret;
+	}
 	if ((ret = register_filesystem(&usbdevice_fs_type))) {
+		unregister_filesystem(&usb_fs_type);
 		usb_deregister(&usbdevfs_driver);
 		return ret;
 	}
@@ -761,6 +772,7 @@
 void __exit usbdevfs_cleanup(void)
 {
 	usb_deregister(&usbdevfs_driver);
+	unregister_filesystem(&usb_fs_type);
 	unregister_filesystem(&usbdevice_fs_type);
 #ifdef CONFIG_PROC_FS	
         if (usbdir)
@@ -768,7 +780,3 @@
 #endif
 }
 
-#if 0
-module_init(usbdevfs_init);
-module_exit(usbdevfs_cleanup);
-#endif
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/kaweth.c linux/drivers/usb/kaweth.c
--- v2.5.0/linux/drivers/usb/kaweth.c	Tue Nov 13 09:19:41 2001
+++ linux/drivers/usb/kaweth.c	Sat Dec  8 20:28:45 2001
@@ -944,6 +944,13 @@
 }
 
 
+// FIXME this completion stuff is a modified clone of
+// an OLD version of some stuff in usb.c ... 
+struct usb_api_data {
+	wait_queue_head_t wqh;
+	int done;
+};
+
 /*-------------------------------------------------------------------*
  * completion handler for compatibility wrappers (sync control/bulk) *
  *-------------------------------------------------------------------*/
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c
--- v2.5.0/linux/drivers/usb/mdc800.c	Tue Oct  9 15:15:02 2001
+++ linux/drivers/usb/mdc800.c	Sat Dec  8 20:28:44 2001
@@ -30,8 +30,14 @@
  *
  * The driver supports only one camera.
  * 
- * (08/04/2001) gb
+ * Fix: mdc800 used sleep_on and slept with io_lock held.
+ * Converted sleep_on to waitqueues with schedule_timeout and made io_lock
+ * a semaphore from a spinlock.
+ * by Oliver Neukum <520047054719-0001@t-online.de>
+ * (02/12/2001)
+ * 
  * Identify version on module load.
+ * (08/04/2001) gb
  *
  * version 0.7.5
  * Fixed potential SMP races with Spinlocks.
@@ -136,6 +142,7 @@
 
 	purb_t			irq_urb;
 	wait_queue_head_t	irq_wait;
+	int			irq_woken;
 	char*			irq_urb_buffer;
 
 	int			camera_busy;          // is camera busy ?
@@ -145,11 +152,13 @@
 	purb_t   		write_urb;
 	char*			write_urb_buffer;
 	wait_queue_head_t	write_wait;
+	int			written;
 
 
 	purb_t	   		download_urb;
 	char*			download_urb_buffer;
 	wait_queue_head_t	download_wait;
+	int			downloaded;
 	int			download_left;		// Bytes left to download ?
 
 
@@ -159,7 +168,7 @@
 	int			out_count;	// Bytes in the buffer
 
 	int			open;		// Camera device open ?
-	spinlock_t		io_lock;	// IO -lock	
+	struct semaphore	io_lock;	// IO -lock
 
 	char 			in [8];		// Command Input Buffer
 	int  			in_count;
@@ -284,6 +293,7 @@
 	if (wake_up)
 	{
 		mdc800->camera_request_ready=0;
+		mdc800->irq_woken=1;
 		wake_up_interruptible (&mdc800->irq_wait);
 	}
 }
@@ -300,9 +310,19 @@
  */
 static int mdc800_usb_waitForIRQ (int mode, int msec)
 {
+        DECLARE_WAITQUEUE(wait, current);
+
 	mdc800->camera_request_ready=1+mode;
 
-	interruptible_sleep_on_timeout (&mdc800->irq_wait, msec*HZ/1000);
+	add_wait_queue(&mdc800->irq_wait, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	if (!mdc800->irq_woken)
+	{
+		schedule_timeout (msec*HZ/1000);
+	}
+        remove_wait_queue(&mdc800->irq_wait, &wait);
+	set_current_state(TASK_RUNNING);
+	mdc800->irq_woken = 0;
 
 	if (mdc800->camera_request_ready>0)
 	{
@@ -337,6 +357,7 @@
 	{	
 		mdc800->state=READY;
 	}
+	mdc800->written = 1;
 	wake_up_interruptible (&mdc800->write_wait);
 }
 
@@ -364,6 +385,7 @@
 	{
 		err ("request bytes fails (status:%i)", urb->status);
 	}
+	mdc800->downloaded = 1;
 	wake_up_interruptible (&mdc800->download_wait);
 }
 
@@ -445,7 +467,7 @@
 
 	info ("Found Mustek MDC800 on USB.");
 
-	spin_lock (&mdc800->io_lock);
+	down (&mdc800->io_lock);
 
 	mdc800->dev=dev;
 	mdc800->open=0;
@@ -484,7 +506,7 @@
 
 	mdc800->state=READY;
 
-	spin_unlock (&mdc800->io_lock);
+	up (&mdc800->io_lock);
 	
 	return mdc800;
 }
@@ -558,7 +580,7 @@
 	int retval=0;
 	int errn=0;
 
-	spin_lock (&mdc800->io_lock);
+	down (&mdc800->io_lock);
 	
 	if (mdc800->state == NOT_CONNECTED)
 	{
@@ -594,7 +616,7 @@
 	dbg ("Mustek MDC800 device opened.");
 
 error_out:
-	spin_unlock (&mdc800->io_lock);
+	up (&mdc800->io_lock);
 	return errn;
 }
 
@@ -607,10 +629,9 @@
 	int retval=0;
 	dbg ("Mustek MDC800 device closed.");
 
-	spin_lock (&mdc800->io_lock);
+	down (&mdc800->io_lock);
 	if (mdc800->open && (mdc800->state != NOT_CONNECTED))
 	{
-		spin_unlock(&mdc800->io_lock);
 		usb_unlink_urb (mdc800->irq_urb);
 		usb_unlink_urb (mdc800->write_urb);
 		usb_unlink_urb (mdc800->download_urb);
@@ -618,11 +639,10 @@
 	}
 	else
 	{
-		spin_unlock (&mdc800->io_lock);
 		retval=-EIO;
 	}
 
-
+	up(&mdc800->io_lock);
 	return retval;
 }
 
@@ -634,22 +654,23 @@
 {
 	int   left=len, sts=len; /* single transfer size */
 	char* ptr=buf;
+	DECLARE_WAITQUEUE(wait, current);
 
-	spin_lock (&mdc800->io_lock);
+	down (&mdc800->io_lock);
 	if (mdc800->state == NOT_CONNECTED)
 	{
-		spin_unlock (&mdc800->io_lock);
+		up (&mdc800->io_lock);
 		return -EBUSY;
 	}
 	if (mdc800->state == WORKING)
 	{
 		warn ("Illegal State \"working\" reached during read ?!");
-		spin_unlock (&mdc800->io_lock);
+		up (&mdc800->io_lock);
 		return -EBUSY;
 	}
 	if (!mdc800->open)
 	{
-		spin_unlock (&mdc800->io_lock);
+		up (&mdc800->io_lock);
 		return -EBUSY;
 	}
 
@@ -657,7 +678,7 @@
 	{
 		if (signal_pending (current)) 
 		{
-			spin_unlock (&mdc800->io_lock);
+			up (&mdc800->io_lock);
 			return -EINTR;
 		}
 
@@ -676,21 +697,29 @@
 				if (usb_submit_urb (mdc800->download_urb))
 				{
 					err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
-					spin_unlock (&mdc800->io_lock);
+					up (&mdc800->io_lock);
 					return len-left;
 				}
-				interruptible_sleep_on_timeout (&mdc800->download_wait, TO_DOWNLOAD_GET_READY*HZ/1000);
+				add_wait_queue(&mdc800->download_wait, &wait);
+				set_current_state(TASK_INTERRUPTIBLE);
+				if (!mdc800->downloaded)
+				{
+					schedule_timeout (TO_DOWNLOAD_GET_READY*HZ/1000);
+				}
+				set_current_state(TASK_RUNNING);
+				remove_wait_queue(&mdc800->download_wait, &wait);
+				mdc800->downloaded = 0;
 				if (mdc800->download_urb->status != 0)
 				{
 					err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
-					spin_unlock (&mdc800->io_lock);
+					up (&mdc800->io_lock);
 					return len-left;
 				}
 			}
 			else
 			{
 				/* No more bytes -> that's an error*/
-				spin_unlock (&mdc800->io_lock);
+				up (&mdc800->io_lock);
 				return -EIO;
 			}
 		}
@@ -704,7 +733,7 @@
 		}
 	}
 
-	spin_unlock (&mdc800->io_lock);
+	up (&mdc800->io_lock);
 	return len-left;
 }
 
@@ -718,16 +747,17 @@
 static ssize_t mdc800_device_write (struct file *file, const char *buf, size_t len, loff_t *pos)
 {
 	int i=0;
+	DECLARE_WAITQUEUE(wait, current);
 
-	spin_lock (&mdc800->io_lock);
+	down (&mdc800->io_lock);
 	if (mdc800->state != READY)
 	{
-		spin_unlock (&mdc800->io_lock);
+		up (&mdc800->io_lock);
 		return -EBUSY;
 	}
 	if (!mdc800->open )
 	{
-		spin_unlock (&mdc800->io_lock);
+		up (&mdc800->io_lock);
 		return -EBUSY;
 	}
 
@@ -735,7 +765,7 @@
 	{
 		if (signal_pending (current)) 
 		{
-			spin_unlock (&mdc800->io_lock);
+			up (&mdc800->io_lock);
 			return -EINTR;
 		}
 
@@ -757,7 +787,7 @@
 		else
 		{
 			err ("Command is to long !\n");
-			spin_unlock (&mdc800->io_lock);
+			up (&mdc800->io_lock);
 			return -EIO;
 		}
 
@@ -769,7 +799,7 @@
 			if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
 			{
 				err ("Camera didn't get ready.\n");
-				spin_unlock (&mdc800->io_lock);
+				up (&mdc800->io_lock);
 				return -EIO;
 			}
 
@@ -781,14 +811,22 @@
 			if (usb_submit_urb (mdc800->write_urb))
 			{
 				err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
-				spin_unlock (&mdc800->io_lock);
+				up (&mdc800->io_lock);
 				return -EIO;
 			}
-			interruptible_sleep_on_timeout (&mdc800->write_wait, TO_WRITE_GET_READY*HZ/1000);
+			add_wait_queue(&mdc800->write_wait, &wait);
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (!mdc800->written)
+			{
+				schedule_timeout (TO_WRITE_GET_READY*HZ/1000);
+			}
+                        set_current_state(TASK_RUNNING);
+			remove_wait_queue(&mdc800->write_wait, &wait);
+			mdc800->written = 0;
 			if (mdc800->state == WORKING)
 			{
 				usb_unlink_urb (mdc800->write_urb);
-				spin_unlock (&mdc800->io_lock);
+				up (&mdc800->io_lock);
 				return -EIO;
 			}
 
@@ -800,7 +838,7 @@
 					{
 						err ("call 0x07 before 0x05,0x3e");
 						mdc800->state=READY;
-						spin_unlock (&mdc800->io_lock);
+						up (&mdc800->io_lock);
 						return -EIO;
 					}
 					mdc800->pic_len=-1;
@@ -819,7 +857,7 @@
 						if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
 						{
 							err ("requesting answer from irq fails");
-							spin_unlock (&mdc800->io_lock);
+							up (&mdc800->io_lock);
 							return -EIO;
 						}
 
@@ -847,7 +885,7 @@
 						if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
 						{
 							err ("Command Timeout.");
-							spin_unlock (&mdc800->io_lock);
+							up (&mdc800->io_lock);
 							return -EIO;
 						}
 					}
@@ -857,7 +895,7 @@
 		}
 		i++;
 	}
-	spin_unlock (&mdc800->io_lock);
+	up (&mdc800->io_lock);
 	return i;
 }
 
@@ -916,11 +954,15 @@
 	mdc800->dev=0;
 	mdc800->open=0;
 	mdc800->state=NOT_CONNECTED;
-	spin_lock_init (&mdc800->io_lock);
+	init_MUTEX (&mdc800->io_lock);
 
 	init_waitqueue_head (&mdc800->irq_wait);
 	init_waitqueue_head (&mdc800->write_wait);
 	init_waitqueue_head (&mdc800->download_wait);
+
+	mdc800->irq_woken = 0;
+	mdc800->downloaded = 0;
+	mdc800->written = 0;
 
 	try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
 	try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/microtek.c linux/drivers/usb/microtek.c
--- v2.5.0/linux/drivers/usb/microtek.c	Fri Oct  5 12:04:51 2001
+++ linux/drivers/usb/microtek.c	Wed Nov 28 10:22:27 2001
@@ -760,7 +760,6 @@
 	present:		0,
 	unchecked_isa_dma:	FALSE,
 	use_clustering:		TRUE,
-	use_new_eh_code:	TRUE,
 	emulated:		TRUE
 };
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c
--- v2.5.0/linux/drivers/usb/pegasus.c	Fri Sep 14 14:04:07 2001
+++ linux/drivers/usb/pegasus.c	Sat Dec  8 20:25:02 2001
@@ -53,7 +53,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.4.21 (2001/08/27)"
+#define DRIVER_VERSION "v0.4.22 (2001/12/07)"
 #define DRIVER_AUTHOR "Petko Manolov <pmanolov@lnxw.com>"
 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
 
@@ -102,7 +102,7 @@
 		return;
 
 	switch ( urb->status ) {
-		case USB_ST_NOERROR:
+		case 0:
 			if ( pegasus->flags & ETH_REGS_CHANGE ) {
 				pegasus->flags &= ~ETH_REGS_CHANGE;
 				pegasus->flags |= ETH_REGS_CHANGED;
@@ -110,9 +110,9 @@
 				return;
 			}
 			break;
-		case USB_ST_URB_PENDING:
+		case -EINPROGRESS:
 			return;
-		case USB_ST_URB_KILLED:
+		case -ENOENT:
 			break;
 		default:
 			warn( __FUNCTION__ " status %d", urb->status);
@@ -526,9 +526,9 @@
 	pegasus->flags |= PEGASUS_RX_BUSY;
 
 	switch ( urb->status ) {
-		case USB_ST_NOERROR:
+		case 0:
 			break;
-		case USB_ST_NORESPONSE:
+		case -ETIMEDOUT:
 			dbg( "reset MAC" );
 			pegasus->flags &= ~PEGASUS_RX_BUSY;
 			break;
@@ -607,9 +607,9 @@
 		return;
 		
 	switch ( urb->status ) {
-		case USB_ST_NOERROR:
+		case 0:
 			break;
-		case USB_ST_URB_KILLED:
+		case -ENOENT:
 			return;
 		default:
 			info("intr status %d", urb->status);
@@ -713,10 +713,8 @@
 	pegasus_t *pegasus = (pegasus_t *)net->priv;
 	int	res;
 
-	MOD_INC_USE_COUNT;
 	if ( (res = enable_net_traffic(net, pegasus->usb)) ) {
 		err("can't enable_net_traffic() - %d", res);
-		MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
 	FILL_BULK_URB( &pegasus->rx_urb, pegasus->usb,
@@ -755,7 +753,6 @@
 #ifdef	PEGASUS_USE_INTR
 	usb_unlink_urb( &pegasus->intr_urb );
 #endif
-	MOD_DEC_USE_COUNT;
 
 	return 0;
 }
@@ -867,6 +864,7 @@
 	
 	pegasus->usb = dev;
 	pegasus->net = net;
+	SET_MODULE_OWNER(net);
 	net->priv = pegasus;
 	net->open = pegasus_open;
 	net->stop = pegasus_close;
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/pegasus.h linux/drivers/usb/pegasus.h
--- v2.5.0/linux/drivers/usb/pegasus.h	Wed Oct 17 14:34:06 2001
+++ linux/drivers/usb/pegasus.h	Sat Dec  8 20:25:02 2001
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 1999,2000 Petko Manolov - Petkan (petkan@dce.bg)
+ *  Copyright (c) 1999,2000 Petko Manolov - Petkan (pmanolov@lnxw.com)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -138,6 +138,7 @@
 #define	VENDOR_DLINK		0x2001
 #define	VENDOR_ELSA		0x05cc
 #define	VENDOR_IODATA		0x04bb
+#define	VENDOR_KINGSTON		0x0951
 #define	VENDOR_LANEED		0x056e
 #define	VENDOR_LINKSYS		0x066b
 #define	VENDOR_MELCO		0x0411
@@ -210,6 +211,8 @@
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904,
 		DEFAULT_GPIO_RESET )
+PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a,
+		DEFAULT_GPIO_RESET)
 PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002,
 		DEFAULT_GPIO_RESET )
 PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b,
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/pwc-ctrl.c linux/drivers/usb/pwc-ctrl.c
--- v2.5.0/linux/drivers/usb/pwc-ctrl.c	Wed Oct 17 14:34:06 2001
+++ linux/drivers/usb/pwc-ctrl.c	Mon Nov 26 17:09:10 2001
@@ -782,7 +782,7 @@
 {
 	char buf;
 
-	if (pdev->type < 675 || pdev->release < 6)
+	if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
 		return 0;	/* Not supported by Nala or Timon < release 6 */
 
 	if (power)
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/pwc-if.c linux/drivers/usb/pwc-if.c
--- v2.5.0/linux/drivers/usb/pwc-if.c	Wed Oct 17 14:34:06 2001
+++ linux/drivers/usb/pwc-if.c	Mon Nov 26 17:09:10 2001
@@ -91,6 +91,8 @@
 	disconnect:		usb_pwc_disconnect,	/* disconnect() */
 };
 
+#define MAX_DEV_HINTS 10
+
 static int default_size = PSZ_QCIF;
 static int default_fps = 10;
 static int default_palette = VIDEO_PALETTE_YUV420P; /* This format is understood by most tools */
@@ -99,13 +101,17 @@
        int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
 static int power_save = 0;
 static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
-int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+       int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+static struct {
+	int type;
+	char serial_number[30];
+	int device_node;
+	struct pwc_device *pdev;
+} device_hint[MAX_DEV_HINTS];
 
 static struct semaphore mem_lock;
 static void *mem_leak = NULL; /* For delayed kfree()s. See below */
 
-static int video_nr = -1;
-
 /***/
 
 static int  pwc_video_open(struct video_device *vdev, int mode);
@@ -647,7 +653,8 @@
 		errmsg = "Unknown";
 		switch(urb->status) {
 			case -ENOSR:		errmsg = "Buffer error (overrun)"; break;
-			case -EPIPE:		errmsg = "Babble/stalled (bad cable?)"; break;
+			case -EPIPE:		errmsg = "Stalled (device not responding)"; break;
+			case -EOVERFLOW:	errmsg = "Babble (bad cable?)"; break;
 			case -EPROTO:		errmsg = "Bit-stuff error (bad cable?)"; break;
 			case -EILSEQ:		errmsg = "CRC/Timeout"; break;
 			case -ETIMEDOUT:	errmsg = "NAK (device does not respond)"; break;
@@ -765,6 +772,11 @@
 			} /* .. flen < last_packet_size */
 			pdev->vlast_packet_size = flen;
 		} /* ..status == 0 */
+#ifdef PWC_DEBUG
+		/* This is normally not interesting to the user, unless you are really debugging something */
+		else 
+			Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+#endif			
 	}
 	if (awake)
 		wake_up_interruptible(&pdev->frameq);
@@ -1140,7 +1152,7 @@
 	                	return -ERESTARTSYS;
 	                }
 	                schedule();
-	                set_current_state(TASK_INTERRUPTIBLE);
+	               	set_current_state(TASK_INTERRUPTIBLE);
 		}
 		remove_wait_queue(&pdev->frameq, &wait);
 		set_current_state(TASK_RUNNING);
@@ -1595,7 +1607,9 @@
 	struct pwc_device *pdev = NULL;
 	struct video_device *vdev;
 	int vendor_id, product_id, type_id;
-	int i;
+	int i, hint;
+	int video_nr = -1; /* default: use next available device */
+	char serial_number[30];
 
 	free_mem_leak();
 	
@@ -1698,6 +1712,10 @@
 	}
 	else return NULL; /* Not Philips, Askey, Logitech or Samsung, for sure. */
 
+	memset(serial_number, 0, 30);
+	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
+	Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
+
 	if (udev->descriptor.bNumConfigurations > 1)
 		Info("Warning: more than 1 configuration available.\n");
 
@@ -1734,6 +1752,21 @@
 	pdev->release = udev->descriptor.bcdDevice;
 	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
 
+
+	/* Now search device_hint[] table for a match, so we can hint a node number. */
+	for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
+		if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
+		     (device_hint[hint].pdev == NULL)) {
+			/* so far, so good... try serial number */
+			if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
+			    	/* match! */
+			    	video_nr = device_hint[hint].device_node;
+			    	Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
+			    	break;
+			}
+		}
+	}
+
 	i = video_register_device(vdev, VFL_TYPE_GRABBER, video_nr);
 	if (i < 0) {
 		Err("Failed to register as video device (%d).\n", i);
@@ -1743,6 +1776,9 @@
 		Trace(TRACE_PROBE, "Registered video struct at 0x%p.\n", vdev);
 		Info("Registered as /dev/video%d.\n", vdev->minor & 0x3F);
 	}
+	/* occupy slot */
+	if (hint < MAX_DEV_HINTS) 
+		device_hint[hint].pdev = pdev;
 
 #if 0
 	/* Shut down camera now (some people like the LED off) */
@@ -1762,6 +1798,7 @@
 static void usb_pwc_disconnect(struct usb_device *udev, void *ptr)
 {
 	struct pwc_device *pdev;
+	int hint;
 
 	lock_kernel();
 	free_mem_leak();
@@ -1815,12 +1852,31 @@
 			pdev->vdev = NULL;
 		}
 	}
+
+	/* search device_hint[] table if we occupy a slot, by any chance */
+	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+		if (device_hint[hint].pdev == pdev)
+			device_hint[hint].pdev = NULL;
+
 	pdev->udev = NULL;
 	unlock_kernel();
 	kfree(pdev);
 }
 
 
+/* *grunt* We have to do atoi ourselves :-( */
+static int pwc_atoi(char *s)
+{
+	int k = 0;
+	
+	k = 0;
+	while (*s != '\0' && *s >= '0' && *s <= '9') {
+		k = 10 * k + (*s - '0');
+		s++;
+	}
+	return k;
+}
+
 
 /* 
  * Initialization code & module stuff 
@@ -1833,8 +1889,8 @@
 static int trace = -1;
 static int compression = -1;
 static int leds[2] = { -1, -1 };
+static char *dev_hint[10] = { };
 
-MODULE_PARM(video_nr, "i");
 MODULE_PARM(size, "s");
 MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
 MODULE_PARM(fps, "i");
@@ -1851,13 +1907,16 @@
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
 MODULE_PARM(leds, "2i");
 MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
+MODULE_PARM(dev_hint, "0-10s");
+MODULE_PARM_DESC(dev_hint, "Device node hints");
+
 MODULE_DESCRIPTION("Philips USB webcam driver");
 MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
 MODULE_LICENSE("GPL");
 
 static int __init usb_pwc_init(void)
 {
-	int s;
+	int i, sz;
 	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
 
 	Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version " PWC_VERSION " loaded.\n");
@@ -1874,13 +1933,13 @@
 	
 	if (size) {
 		/* string; try matching with array */
-		for (s = 0; s < PSZ_MAX; s++) {
-			if (!strcmp(sizenames[s], size)) { /* Found! */
-				default_size = s;
+		for (sz = 0; sz < PSZ_MAX; sz++) {
+			if (!strcmp(sizenames[sz], size)) { /* Found! */
+				default_size = sz;
 				break;
 			}
 		}
-		if (s == PSZ_MAX) {
+		if (sz == PSZ_MAX) {
 			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
 			return -EINVAL;
 		}
@@ -1920,6 +1979,74 @@
 		led_on = leds[0] / 100;
 	if (leds[1] >= 0)
 		led_off = leds[1] / 100;
+
+	/* Big device node whoopla. Basicly, it allows you to assign a 
+	   device node (/dev/videoX) to a camera, based on its type 
+	   & serial number. The format is [type[.serialnumber]:]node.
+
+           Any camera that isn't matched by these rules gets the next 
+           available free device node.
+	 */
+	for (i = 0; i < MAX_DEV_HINTS; i++) {
+		char *s, *colon, *dot;
+
+		/* This loop also initializes the array */
+		device_hint[i].pdev = NULL;
+		s = dev_hint[i];
+		if (s != NULL && *s != '\0') {
+			device_hint[i].type = -1; /* wildcard */
+			strcpy(device_hint[i].serial_number, "*");
+
+			/* parse string: chop at ':' & '/' */
+			colon = dot = s;
+			while (*colon != '\0' && *colon != ':')
+				colon++;
+			while (*dot != '\0' && *dot != '.')
+				dot++;
+			/* Few sanity checks */
+			if (*dot != '\0' && dot > colon) {
+				Err("Malformed camera hint: the colon must be after the dot.\n");
+				return -EINVAL;
+			}
+
+			if (*colon == '\0') {
+				/* No colon */
+				if (*dot != '\0') {
+					Err("Malformed camera hint: no colon + device node given.\n");
+					return -EINVAL;
+				}
+				else {
+					/* No type or serial number specified, just a number. */
+					device_hint[i].device_node = pwc_atoi(s);
+				}
+			}
+			else {
+				/* There's a colon, so we have at least a type and a device node */
+				device_hint[i].type = pwc_atoi(s);
+				device_hint[i].device_node = pwc_atoi(colon + 1);
+				if (*dot != '\0') {
+					/* There's a serial number as well */
+					int k;
+					
+					dot++;
+					k = 0;
+					while (*dot != ':' && k < 29) {
+						device_hint[i].serial_number[k++] = *dot;
+						dot++;
+					}
+					device_hint[i].serial_number[k] = '\0';
+				}
+			}
+#ifdef PWC_DEBUG		
+			Debug("device_hint[%d]:\n", i);
+			Debug("  type    : %d\n", device_hint[i].type);
+			Debug("  serial# : %s\n", device_hint[i].serial_number);
+			Debug("  node    : %d\n", device_hint[i].device_node);
+#endif			
+		}
+		else
+			device_hint[i].type = 0; /* not filled */
+	} /* ..for MAX_DEV_HINTS */
 
 	init_MUTEX(&mem_lock);
  	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/pwc.h linux/drivers/usb/pwc.h
--- v2.5.0/linux/drivers/usb/pwc.h	Wed Oct 17 14:34:06 2001
+++ linux/drivers/usb/pwc.h	Mon Nov 26 17:09:10 2001
@@ -60,8 +60,8 @@
 
 /* Version block */
 #define PWC_MAJOR	8
-#define PWC_MINOR	3
-#define PWC_VERSION 	"8.3"
+#define PWC_MINOR	4
+#define PWC_VERSION 	"8.4"
 #define PWC_NAME 	"pwc"
 
 /* Turn certain features on/off */
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c
--- v2.5.0/linux/drivers/usb/rio500.c	Fri Sep 14 14:04:07 2001
+++ linux/drivers/usb/rio500.c	Sat Dec  8 20:28:45 2001
@@ -324,7 +324,7 @@
 			dbg("write stats: result:%d thistime:%lu partial:%u",
 			     result, thistime, partial);
 
-			if (result == USB_ST_TIMEOUT) {	/* NAK - so hold for a while */
+			if (result == -ETIMEDOUT) {	/* NAK - so hold for a while */
 				if (!maxretry--) {
 					errn = -ETIME;
 					goto error;
@@ -403,7 +403,7 @@
 
 		if (partial) {
 			count = this_read = partial;
-		} else if (result == USB_ST_TIMEOUT || result == 15) {	/* FIXME: 15 ??? */
+		} else if (result == -ETIMEDOUT || result == 15) {	/* FIXME: 15 ??? */
 			if (!maxretry--) {
 				up(&(rio->lock));
 				err("read_rio: maxretry timeout");
@@ -412,7 +412,7 @@
 			interruptible_sleep_on_timeout(&rio->wait_q,
 						       NAK_TIMEOUT);
 			continue;
-		} else if (result != USB_ST_DATAUNDERRUN) {
+		} else if (result != -EREMOTEIO) {
 			up(&(rio->lock));
 			err("Read Whoops - result:%u partial:%u this_read:%u",
 			     result, partial, this_read);
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c
--- v2.5.0/linux/drivers/usb/scanner.c	Sat Oct 20 19:13:11 2001
+++ linux/drivers/usb/scanner.c	Sat Dec  8 20:28:44 2001
@@ -278,6 +278,28 @@
  *    - Users are now notified to consult the Documentation/usb/scanner.txt
  *      for common error messages rather than the maintainer.
  *
+ * 0.4.7  11/28/2001
+ *    - Fixed typo in Documentation/scanner.txt.  Thanks to
+ *      Karel <karel.vervaeke@pandora.be> for pointing it out.
+ *    - Added ID's for a Memorex 6136u. Thanks to =C1lvaro Gaspar de
+ *      Valenzuela" <agaspard@utsi.edu>.
+ *    - Added ID's for Agfa e25.  Thanks to Heinrich 
+ *      Rust <Heinrich.Rust@gmx.de>.  Also reported to work with
+ *      Linux and SANE (?).
+ *    - Added Canon FB620U, D646U, and 1220U ID's.  Thanks to Paul
+ *      Rensing <Paul_Rensing@StanfordAlumni.org>.  For more info
+ *      on Linux support for these models, contact 
+ *      salvestrini@users.sourceforge.net.
+ *    - Added Plustek OpticPro UT12, OpticPro U24, KYE/Genius
+ *      ColorPage-HR6 V2 ID's in addition to many "Unknown" models
+ *      under those vendors.  Thanks to
+ *      Jaeger, Gerhard" <g.jaeger@earthling.net>.  These scanner are
+ *      apparently based upon the LM983x IC's.
+ *    - Applied Frank's patch that addressed some locking and module
+ *      referencing counts.  Thanks to both
+ *      Frank Zago <fzago@greshamstorage.com> and
+ *      Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
+ *
  * TODO
  *    - Performance
  *    - Select/poll methods
@@ -324,17 +346,16 @@
 	struct scn_usb_data *scn;
 	unsigned char *data;
 	scn = urb->context;
-	down(&(scn->sem));
+
 	data = &scn->button;
 	data += 0;		/* Keep gcc from complaining about unused var */
 
 	if (urb->status) {
-		up(&(scn->sem));
 		return;
 	}
 
 	dbg("irq_scanner(%d): data:%x", scn->scn_minor, *data);
-	up(&(scn->sem));
+
 	return;
 }
 
@@ -358,6 +379,7 @@
 
 	if (!p_scn_table[scn_minor]) {
 		up(&scn_mutex);
+		MOD_DEC_USE_COUNT;
 		err("open_scanner(%d): Unable to access minor data", scn_minor);
 		return -ENODEV;
 	}
@@ -606,7 +628,7 @@
 			}
 			ret = result;
 			break;
-		} else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {
+		} else if ((result < 0) && (result != -EREMOTEIO)) {
 			warn("read_scanner(%d): funky result:%d. Consult Documentation/usb/scanner.txt.", scn_minor, (int)result);
 			ret = -EIO;
 			break;
@@ -939,6 +961,7 @@
 /* Check to make sure that the last slot isn't already taken */
 	if (p_scn_table[scn_minor]) {
 		err("probe_scanner: No more minor devices remaining.");
+		up(&scn_mutex);
 		return NULL;
 	}
 
@@ -946,6 +969,7 @@
 
 	if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) {
 		err("probe_scanner: Out of memory.");
+		up(&scn_mutex);
 		return NULL;
 	}
 	memset (scn, 0, sizeof(struct scn_usb_data));
@@ -1028,9 +1052,11 @@
 	if (scn->devfs == NULL)
 		dbg("scanner%d: device node registration failed", scn_minor);
 
+	p_scn_table[scn_minor] = scn;
+
 	up(&scn_mutex);
 
-	return p_scn_table[scn_minor] = scn;
+	return scn;
 }
 
 static void
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/scanner.h linux/drivers/usb/scanner.h
--- v2.5.0/linux/drivers/usb/scanner.h	Sat Oct 20 19:13:11 2001
+++ linux/drivers/usb/scanner.h	Sat Dec  8 20:28:44 2001
@@ -86,12 +86,23 @@
 	{ USB_DEVICE(0x06bd, 0x2061) },	/* Another SnapScan 1212U (?)*/
 	{ USB_DEVICE(0x06bd, 0x0100) },	/* SnapScan Touch */
 	{ USB_DEVICE(0x06bd, 0x2091) }, /* SnapScan e20 */
+	{ USB_DEVICE(0x06bd, 0x2095) }, /* SnapScan e25 */
 	{ USB_DEVICE(0x06bd, 0x2097) }, /* SnapScan e26 */
 	{ USB_DEVICE(0x06bd, 0x208d) }, /* Snapscan e40 */
+	/* Canon */
+	{ USB_DEVICE(0x04a9, 0x2202) }, /* FB620U */
+	{ USB_DEVICE(0x04a9, 0x220b) }, /* D646U */
+	{ USB_DEVICE(0x04a9, 0x2207) }, /* 1220U */
 	/* Colorado -- See Primax/Colorado below */
 	/* Epson -- See Seiko/Epson below */
 	/* Genius */
 	{ USB_DEVICE(0x0458, 0x2001) },	/* ColorPage-Vivid Pro */
+	{ USB_DEVICE(0x0458, 0x2007) },	/* ColorPage HR6 V2 */
+	{ USB_DEVICE(0x0458, 0x2008) },	/* Unknown */
+	{ USB_DEVICE(0x0458, 0x2009) },	/* Unknown */
+	{ USB_DEVICE(0x0458, 0x2013) },	/* Unknown */
+	{ USB_DEVICE(0x0458, 0x2015) },	/* Unknown  */
+	{ USB_DEVICE(0x0458, 0x2016) },	/* Unknown  */
 	/* Hewlett Packard */
 	{ USB_DEVICE(0x03f0, 0x0205) },	/* 3300C */
 	{ USB_DEVICE(0x03f0, 0x0405) }, /* 3400C */
@@ -108,6 +119,8 @@
 	{ USB_DEVICE(0x0638, 0x0268) }, /* 1200U */
 	/* Lifetec */
 	{ USB_DEVICE(0x05d8, 0x4002) }, /* Lifetec LT9385 */
+	/* Memorex */
+	{ USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */
 	/* Microtek -- No longer supported - Enable SCSI and USB Microtek in kernel config */
 	//	{ USB_DEVICE(0x05da, 0x0099) },	/* ScanMaker X6 - X6U */
 	//	{ USB_DEVICE(0x05da, 0x0094) },	/* Phantom 336CX - C3 */
@@ -128,6 +141,19 @@
 	{ USB_DEVICE(0x0400, 0x1001) }, /* BearPaw 2400 */
 	{ USB_DEVICE(0x055f, 0x0008) }, /* 1200 CU Plus */
 	{ USB_DEVICE(0x0ff5, 0x0010) }, /* BearPaw 1200F */
+	/* Plustek */
+	{ USB_DEVICE(0x07b3, 0x0017) }, /* OpticPro UT12 */
+	{ USB_DEVICE(0x07b3, 0x0011) }, /* OpticPro UT24 */
+	{ USB_DEVICE(0x07b3, 0x0005) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0007) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x000F) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0010) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0013) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0014) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0015) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0016) }, /* Unknown */
+	{ USB_DEVICE(0x07b3, 0x0012) }, /* Unknown */
 	/* Primax/Colorado */
 	{ USB_DEVICE(0x0461, 0x0300) },	/* G2-300 #1 */
 	{ USB_DEVICE(0x0461, 0x0380) },	/* G2-600 #1 */
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/belkin_sa.c linux/drivers/usb/serial/belkin_sa.c
--- v2.5.0/linux/drivers/usb/serial/belkin_sa.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/belkin_sa.c	Sat Dec  8 20:28:45 2001
@@ -1,8 +1,8 @@
 /*
  * Belkin USB Serial Adapter Driver
  *
- *  Copyright (C) 2000
- *      William Greathouse (wgreathouse@smva.com)
+ *  Copyright (C) 2000		William Greathouse (wgreathouse@smva.com)
+ *  Copyright (C) 2000-2001 	Greg Kroah-Hartman (greg@kroah.com)
  *
  *  This program is largely derived from work by the linux-usb group
  *  and associated source files.  Please see the usb/serial files for
@@ -24,6 +24,9 @@
  * -- Add support for flush commands
  * -- Add everything that is missing :)
  *
+ * 27-Nov-2001 gkh
+ * 	compressed all the differnent device entries into 1.
+ *
  * 30-May-2001 gkh
  *	switched from using spinlock to a semaphore, which fixes lots of problems.
  *
@@ -88,7 +91,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.1"
+#define DRIVER_VERSION "v1.2"
 #define DRIVER_AUTHOR "William Greathouse <wgreathouse@smva.com>"
 #define DRIVER_DESC "USB Belkin Serial converter driver"
 
@@ -112,125 +115,12 @@
 	{ }							/* Terminating entry */
 };
 
-static __devinitdata struct usb_device_id belkin_dockstation_table [] = {
-	{ USB_DEVICE(BELKIN_DOCKSTATION_VID, BELKIN_DOCKSTATION_PID) },
-	{ }							/* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id belkin_sa_table [] = {
-	{ USB_DEVICE(BELKIN_SA_VID, BELKIN_SA_PID) },
-	{ }							/* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id belkin_old_table [] = {
-	{ USB_DEVICE(BELKIN_OLD_VID, BELKIN_OLD_PID) },
-	{ }							/* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id peracom_table [] = {
-	{ USB_DEVICE(PERACOM_VID, PERACOM_PID) },
-	{ }							/* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id gocom232_table [] = {
-	{ USB_DEVICE(GOHUBS_VID, GOHUBS_PID) },
-	{ }							/* Terminating entry */
-};
-
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
-/* All of the device info needed for the Belkin dockstation serial converter */
-struct usb_serial_device_type belkin_dockstation_device = {
-	name:			"Belkin F5U120-PC USB Serial Adapter",
-	id_table:		belkin_dockstation_table,		/* the Belkin F5U103 device */
-	needs_interrupt_in:	MUST_HAVE,			/* this device must have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,			/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,			/* this device must have a bulk out endpoint */
-	num_interrupt_in:	1,
-	num_bulk_in:		1,
-	num_bulk_out:		1,
-	num_ports:		1,
-	open:			belkin_sa_open,
-	close:			belkin_sa_close,
-	read_int_callback:	belkin_sa_read_int_callback,	/* How we get the status info */
-	ioctl:			belkin_sa_ioctl,
-	set_termios:		belkin_sa_set_termios,
-	break_ctl:		belkin_sa_break_ctl,
-	startup:		belkin_sa_startup,
-	shutdown:		belkin_sa_shutdown,
-};
-
-/* All of the device info needed for the Belkin serial converter */
-struct usb_serial_device_type belkin_sa_device = {
-	name:			"Belkin F5U103 USB Serial Adapter",
-	id_table:		belkin_sa_table,		/* the Belkin F5U103 device */
-	needs_interrupt_in:	MUST_HAVE,			/* this device must have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,			/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,			/* this device must have a bulk out endpoint */
-	num_interrupt_in:	1,
-	num_bulk_in:		1,
-	num_bulk_out:		1,
-	num_ports:		1,
-	open:			belkin_sa_open,
-	close:			belkin_sa_close,
-	read_int_callback:	belkin_sa_read_int_callback,	/* How we get the status info */
-	ioctl:			belkin_sa_ioctl,
-	set_termios:		belkin_sa_set_termios,
-	break_ctl:		belkin_sa_break_ctl,
-	startup:		belkin_sa_startup,
-	shutdown:		belkin_sa_shutdown,
-};
-
-
-/* This driver also supports the "old" school Belkin single port adaptor */
-struct usb_serial_device_type belkin_old_device = {
-	name:			"Belkin USB Serial Adapter",
-	id_table:		belkin_old_table,		/* the old Belkin device */
-	needs_interrupt_in:	MUST_HAVE,			/* this device must have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,			/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,			/* this device must have a bulk out endpoint */
-	num_interrupt_in:	1,
-	num_bulk_in:		1,
-	num_bulk_out:		1,
-	num_ports:		1,
-	open:			belkin_sa_open,
-	close:			belkin_sa_close,
-	read_int_callback:	belkin_sa_read_int_callback,	/* How we get the status info */
-	ioctl:			belkin_sa_ioctl,
-	set_termios:		belkin_sa_set_termios,
-	break_ctl:		belkin_sa_break_ctl,
-	startup:		belkin_sa_startup,
-	shutdown:		belkin_sa_shutdown,
-};
-
-/* this driver also works for the Peracom single port adapter */
-struct usb_serial_device_type peracom_device = {
-	name:			"Peracom single port USB Serial Adapter",
-	id_table:		peracom_table,			/* the Peracom device */
-	needs_interrupt_in:	MUST_HAVE,			/* this device must have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,			/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,			/* this device must have a bulk out endpoint */
-	num_interrupt_in:	1,
-	num_bulk_in:		1,
-	num_bulk_out:		1,
-	num_ports:		1,
-	open:			belkin_sa_open,
-	close:			belkin_sa_close,
-	read_int_callback:	belkin_sa_read_int_callback,	/* How we get the status info */
-	ioctl:			belkin_sa_ioctl,
-	set_termios:		belkin_sa_set_termios,
-	break_ctl:		belkin_sa_break_ctl,
-	startup:		belkin_sa_startup,
-	shutdown:		belkin_sa_shutdown,
-};
-
-/* the GoHubs Go-COM232 device is the same as the Peracom single port adapter */
-struct usb_serial_device_type gocom232_device = {
-	name:			"GO-COM232 USB Serial Converter",
-	id_table:		gocom232_table,			/* the GO-COM232 device */
-	needs_interrupt_in:	MUST_HAVE,			/* this device must have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,			/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,			/* this device must have a bulk out endpoint */
+/* All of the device info needed for the serial converters */
+static struct usb_serial_device_type belkin_device = {
+	name:			"Belkin / Peracom / GoHubs USB Serial Adapter",
+	id_table:		id_table_combined,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -321,9 +211,7 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 	
-	if (!port->active) {
-		port->active = 1;
-
+	if (port->open_count == 1) {
 		/*Start reading from the device*/
 		/* TODO: Look at possibility of submitting mulitple URBs to device to
 		 *       enhance buffering.  Win trace shows 16 initial read URBs.
@@ -372,7 +260,7 @@
 			usb_unlink_urb (port->read_urb);
 			usb_unlink_urb (port->interrupt_in_urb);
 		}
-		port->active = 0;
+		port->open_count = 0;
 	}
 	
 	up (&port->sem);
@@ -642,11 +530,7 @@
 
 static int __init belkin_sa_init (void)
 {
-	usb_serial_register (&belkin_dockstation_device);
-	usb_serial_register (&belkin_sa_device);
-	usb_serial_register (&belkin_old_device);
-	usb_serial_register (&peracom_device);
-	usb_serial_register (&gocom232_device);
+	usb_serial_register (&belkin_device);
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
@@ -654,11 +538,7 @@
 
 static void __exit belkin_sa_exit (void)
 {
-	usb_serial_deregister (&belkin_dockstation_device);
-	usb_serial_deregister (&belkin_sa_device);
-	usb_serial_deregister (&belkin_old_device);
-	usb_serial_deregister (&peracom_device);
-	usb_serial_deregister (&gocom232_device);
+	usb_serial_deregister (&belkin_device);
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/cyberjack.c linux/drivers/usb/serial/cyberjack.c
--- v2.5.0/linux/drivers/usb/serial/cyberjack.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/cyberjack.c	Sat Dec  8 20:28:45 2001
@@ -76,12 +76,9 @@
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
-struct usb_serial_device_type cyberjack_device = {
+static struct usb_serial_device_type cyberjack_device = {
 	name:			"Reiner SCT Cyberjack USB card reader",
 	id_table:		id_table,
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -159,8 +156,7 @@
 
 	++port->open_count;
 
-	if (!port->active) {
-		port->active = 1;
+	if (port->open_count == 1) {
 		/* force low_latency on so that our tty_push actually forces
 		 * the data through, otherwise it is scheduled, and with high
 		 * data rates (like with OHCI) data can get lost.
@@ -204,8 +200,6 @@
 			usb_unlink_urb (port->read_urb);
 			usb_unlink_urb (port->interrupt_in_urb);
 		}
-
-		port->active = 0;
 		port->open_count = 0;
 	}
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c
--- v2.5.0/linux/drivers/usb/serial/digi_acceleport.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/digi_acceleport.c	Sat Dec  8 20:28:45 2001
@@ -14,6 +14,10 @@
 *  Peter Berger (pberger@brimson.com)
 *  Al Borchers (borchers@steinerpoint.com)
 * 
+* (12/03/2001) gkh
+*	switched to using port->open_count instead of private version.
+*	Removed port->active
+*
 * (04/08/2001) gb
 *	Identify version on module load.
 *
@@ -429,7 +433,6 @@
 	int dp_write_urb_in_use;
 	unsigned int dp_modem_signals;
 	wait_queue_head_t dp_modem_change_wait;
-	int dp_open_count;			/* inc on open, dec on close */
 	int dp_transmit_idle;
 	wait_queue_head_t dp_transmit_idle_wait;
 	int dp_throttled;
@@ -500,9 +503,6 @@
 static struct usb_serial_device_type digi_acceleport_2_device = {
 	name:				"Digi USB",
 	id_table:			id_table_2,
-	needs_interrupt_in:		DONT_CARE,
-	needs_bulk_in:			MUST_HAVE,
-	needs_bulk_out:			MUST_HAVE,
 	num_interrupt_in:		0,
 	num_bulk_in:			4,
 	num_bulk_out:			4,
@@ -526,9 +526,6 @@
 static struct usb_serial_device_type digi_acceleport_4_device = {
 	name:				"Digi USB",
 	id_table:			id_table_4,
-	needs_interrupt_in:		DONT_CARE,
-	needs_bulk_in:			MUST_HAVE,
-	needs_bulk_out:			MUST_HAVE,
 	num_interrupt_in:		0,
 	num_bulk_in:			5,
 	num_bulk_out:			5,
@@ -1386,7 +1383,7 @@
 	/* try to send any buffered data on this port, if it is open */
 	spin_lock( &priv->dp_port_lock );
 	priv->dp_write_urb_in_use = 0;
-	if( priv->dp_open_count && port->write_urb->status != -EINPROGRESS
+	if( port->open_count && port->write_urb->status != -EINPROGRESS
 	&& priv->dp_out_buf_len > 0 ) {
 
 		*((unsigned char *)(port->write_urb->transfer_buffer))
@@ -1480,7 +1477,7 @@
 	unsigned long flags = 0;
 
 
-dbg( "digi_open: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, port->active, priv->dp_open_count );
+dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
 
 	/* be sure the device is started up */
 	if( digi_startup_device( port->serial ) != 0 )
@@ -1495,7 +1492,7 @@
 	}
 
 	/* inc module use count before sleeping to wait for closes */
-	++priv->dp_open_count;
+	++port->open_count;
 	MOD_INC_USE_COUNT;
 
 	/* wait for a close in progress to finish */
@@ -1504,7 +1501,7 @@
 			&priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
 			&priv->dp_port_lock, flags );
 		if( signal_pending(current) ) {
-			--priv->dp_open_count;
+			--port->open_count;
 			MOD_DEC_USE_COUNT;
 			return( -EINTR );
 		}
@@ -1513,13 +1510,11 @@
 
 	/* if port is already open, just return */
 	/* be sure exactly one open proceeds */
-	if( port->active ) {
+	if( port->open_count != 1)  {
 		spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 		return( 0 );
 	}
 
-	/* first open, mark port as active */
-	port->active = 1;
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
  
 	/* read modem signals automatically whenever they change */
@@ -1560,17 +1555,17 @@
 	unsigned long flags = 0;
 
 
-dbg( "digi_close: TOP: port=%d, active=%d, open_count=%d", priv->dp_port_num, port->active, priv->dp_open_count );
+dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
 
 
 	/* do cleanup only after final close on this port */
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
-	if( priv->dp_open_count > 1 ) {
-		--priv->dp_open_count;
+	if( port->open_count > 1 ) {
+		--port->open_count;
 		MOD_DEC_USE_COUNT;
 		spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 		return;
-	} else if( priv->dp_open_count <= 0 ) {
+	} else if( port->open_count <= 0 ) {
 		spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 		return;
 	}
@@ -1644,10 +1639,9 @@
 	tty->closing = 0;
 
 	spin_lock_irqsave( &priv->dp_port_lock, flags );
-	port->active = 0;
 	priv->dp_write_urb_in_use = 0;
 	priv->dp_in_close = 0;
-	--priv->dp_open_count;
+	--port->open_count;
 	MOD_DEC_USE_COUNT;
 	wake_up_interruptible( &priv->dp_close_wait );
 	spin_unlock_irqrestore( &priv->dp_port_lock, flags );
@@ -1716,8 +1710,6 @@
 	/* number of regular ports + 1 for the out-of-band port */
 	for( i=0; i<serial->type->num_ports+1; i++ ) {
 
-		serial->port[i].active = 0;
-
 		/* allocate port private structure */
 		priv = serial->port[i].private =
 			(digi_port_t *)kmalloc( sizeof(digi_port_t),
@@ -1736,7 +1728,6 @@
 		priv->dp_write_urb_in_use = 0;
 		priv->dp_modem_signals = 0;
 		init_waitqueue_head( &priv->dp_modem_change_wait );
-		priv->dp_open_count = 0;
 		priv->dp_transmit_idle = 0;
 		init_waitqueue_head( &priv->dp_transmit_idle_wait );
 		priv->dp_throttled = 0;
@@ -1795,9 +1786,9 @@
 	for( i=0; i<serial->type->num_ports; i++ ) {
 		priv = serial->port[i].private;
 		spin_lock_irqsave( &priv->dp_port_lock, flags );
-		while( priv->dp_open_count > 0 ) {
+		while( serial->port[i].open_count > 0 ) {
 			MOD_DEC_USE_COUNT;
-			--priv->dp_open_count;
+			--serial->port[i].open_count;
 		}
 		spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 	}
@@ -1889,7 +1880,7 @@
 
 	/* do not process callbacks on closed ports */
 	/* but do continue the read chain */
-	if( priv->dp_open_count == 0 )
+	if( port->open_count == 0 )
 		return( 0 );
 
 	/* short/multiple packet check */
@@ -2023,7 +2014,7 @@
 			if( val & DIGI_READ_INPUT_SIGNALS_CTS ) {
 				priv->dp_modem_signals |= TIOCM_CTS;
 				/* port must be open to use tty struct */
-				if( priv->dp_open_count
+				if( port->open_count
 				&& port->tty->termios->c_cflag & CRTSCTS ) {
 					port->tty->hw_stopped = 0;
 					digi_wakeup_write( port );
@@ -2031,7 +2022,7 @@
 			} else {
 				priv->dp_modem_signals &= ~TIOCM_CTS;
 				/* port must be open to use tty struct */
-				if( priv->dp_open_count
+				if( port->open_count
 				&& port->tty->termios->c_cflag & CRTSCTS ) {
 					port->tty->hw_stopped = 1;
 				}
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c
--- v2.5.0/linux/drivers/usb/serial/empeg.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/empeg.c	Sat Dec  8 20:28:45 2001
@@ -113,12 +113,9 @@
 
 MODULE_DEVICE_TABLE (usb, id_table);
 
-struct usb_serial_device_type empeg_device = {
+static struct usb_serial_device_type empeg_device = {
 	name:			"Empeg",
 	id_table:		id_table,
-	needs_interrupt_in:	MUST_HAVE_NOT,	/* must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,	/* must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,	/* must have a bulk out endpoint */
 	num_interrupt_in:	0,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -164,12 +161,11 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 
-	if (!port->active) {
+	if (port->open_count == 1) {
 
 		/* Force default termio settings */
 		empeg_set_termios (port, NULL) ;
 
-		port->active = 1;
 		bytes_in = 0;
 		bytes_out = 0;
 
@@ -221,7 +217,6 @@
 			/* shutdown our bulk read */
 			usb_unlink_urb (port->read_urb);
 		}
-		port->active = 0;
 		port->open_count = 0;
 	}
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c
--- v2.5.0/linux/drivers/usb/serial/ftdi_sio.c	Tue Nov 13 09:19:41 2001
+++ linux/drivers/usb/serial/ftdi_sio.c	Sat Dec  8 20:28:45 2001
@@ -173,12 +173,9 @@
 /* Should rename most ftdi_sio's to ftdi_ now since there are two devices 
    which share common code */ 
 
-struct usb_serial_device_type ftdi_sio_device = {
+static struct usb_serial_device_type ftdi_sio_device = {
 	name:			"FTDI SIO",
 	id_table:		id_table_sio,
-	needs_interrupt_in:	MUST_HAVE_NOT,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	0,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -196,12 +193,9 @@
         shutdown:               ftdi_sio_shutdown,
 };
 
-struct usb_serial_device_type ftdi_8U232AM_device = {
+static struct usb_serial_device_type ftdi_8U232AM_device = {
 	name:			"FTDI 8U232AM",
 	id_table:		id_table_8U232AM,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	0,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -327,9 +321,7 @@
 	MOD_INC_USE_COUNT;
 	++port->open_count;
 
-	if (!port->active){
-		port->active = 1;
-
+	if (port->open_count == 1){
 		/* This will push the characters through immediately rather 
 		   than queue a task to deliver them */
 		port->tty->low_latency = 1;
@@ -410,7 +402,6 @@
 			usb_unlink_urb (port->write_urb);
 			usb_unlink_urb (port->read_urb);
 		}
-		port->active = 0;
 		port->open_count = 0;
 	} else {  
 		/* Send a HUP if necessary */
@@ -660,7 +651,7 @@
 } /* ftdi_sio_serial_read_bulk_callback */
 
 
-__u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type) 
+static __u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type) 
 { /* translate_baudrate_to_ftdi */
 	
 	__u16 urb_value = ftdi_sio_b9600;
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/io_edgeport.c linux/drivers/usb/serial/io_edgeport.c
--- v2.5.0/linux/drivers/usb/serial/io_edgeport.c	Wed Nov 21 09:59:11 2001
+++ linux/drivers/usb/serial/io_edgeport.c	Sat Dec  8 20:28:45 2001
@@ -318,11 +318,6 @@
 };
 
 
-/* the info for all of the devices that this driver supports */
-int EdgeportDevices[] = EDGEPORT_DEVICE_IDS;
-#define NUM_EDGEPORT_DEVICES (sizeof(EdgeportDevices) / sizeof(int))
-
-
 /* Transmit Fifo 
  * This Transmit queue is an extension of the edgeport Rx buffer. 
  * The maximum amount of data buffered in both the edgeport 
@@ -495,17 +490,15 @@
 // ************************************************************************
 // ************************************************************************
 
-// These functions should be in firmware.c
-
 /************************************************************************
  *									*
- *	update_edgeport_E2PROM()	Compare current versions of		*
+ * update_edgeport_E2PROM()	Compare current versions of		*
  *				Boot ROM and Manufacture 		*
  *				Descriptors with versions		*
  *				embedded in this driver			*
  *									*
  ************************************************************************/
-void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
+static void update_edgeport_E2PROM (struct edgeport_serial *edge_serial)
 {
 	__u32 BootCurVer;
 	__u32 BootNewVer;
@@ -994,9 +987,7 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 	
-	if (!port->active) {
-		port->active = 1;
-
+	if (port->open_count == 1) {
 		/* force low_latency on so that our tty_push actually forces the data through, 
 		   otherwise it is scheduled, and with high data rates (like with OHCI) data
 		   can get lost. */
@@ -1007,7 +998,6 @@
 		serial = port->serial;
 		edge_serial = (struct edgeport_serial *)serial->private;
 		if (edge_serial == NULL) {
-			port->active = 0;
 			port->open_count = 0;
 			MOD_DEC_USE_COUNT;
 			return -ENODEV;
@@ -1071,7 +1061,6 @@
 		if (response < 0) {
 			err(__FUNCTION__" - error sending open port command");
 			edge_port->openPending = FALSE;
-			port->active = 0;
 			port->open_count = 0;
 			MOD_DEC_USE_COUNT;
 			return -ENODEV;
@@ -1087,7 +1076,6 @@
 			/* open timed out */
 			dbg(__FUNCTION__" - open timedout");
 			edge_port->openPending = FALSE;
-			port->active = 0;
 			port->open_count = 0;
 			MOD_DEC_USE_COUNT;
 			return -ENODEV;
@@ -1292,7 +1280,6 @@
 		if (edge_port->txfifo.fifo) {
 			kfree(edge_port->txfifo.fifo);
 		}
-		port->active = 0;
 		port->open_count = 0;
 	}
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/io_tables.h linux/drivers/usb/serial/io_tables.h
--- v2.5.0/linux/drivers/usb/serial/io_tables.h	Tue Nov 13 17:45:27 2001
+++ linux/drivers/usb/serial/io_tables.h	Thu Nov 29 13:45:52 2001
@@ -74,9 +74,6 @@
 static struct usb_serial_device_type edgeport_1port_device = {
 	name:			"Edgeport 1 port adapter",
 	id_table:		edgeport_1port_id_table,
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -98,9 +95,6 @@
 static struct usb_serial_device_type edgeport_2port_device = {
 	name:			"Edgeport 2 port adapter",
 	id_table:		edgeport_2port_id_table,
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -122,9 +116,6 @@
 static struct usb_serial_device_type edgeport_4port_device = {
 	name:			"Edgeport 4 port adapter",
 	id_table:		edgeport_4port_id_table,
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -146,9 +137,6 @@
 static struct usb_serial_device_type edgeport_8port_device = {
 	name:			"Edgeport 8 port adapter",
 	id_table:		edgeport_8port_id_table,
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/ir-usb.c linux/drivers/usb/serial/ir-usb.c
--- v2.5.0/linux/drivers/usb/serial/ir-usb.c	Mon Nov 12 09:53:56 2001
+++ linux/drivers/usb/serial/ir-usb.c	Sat Dec  8 20:28:45 2001
@@ -93,9 +93,6 @@
 struct usb_serial_device_type ir_device = {
 	name:			"IR Dongle",
 	id_table:		id_table,
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -209,9 +206,7 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 	
-	if (!port->active) {
-		port->active = 1;
-
+	if (port->open_count == 1) {
 		if (buffer_size) {
 			/* override the default buffer sizes */
 			buffer = kmalloc (buffer_size, GFP_KERNEL);
@@ -271,7 +266,6 @@
 			/* shutdown our bulk read */
 			usb_unlink_urb (port->read_urb);
 		}
-		port->active = 0;
 		port->open_count = 0;
 
 	}
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c
--- v2.5.0/linux/drivers/usb/serial/keyspan.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/keyspan.c	Sat Dec  8 20:28:45 2001
@@ -176,7 +176,7 @@
 
 
 /* Functions used by new usb-serial code. */
-int keyspan_init (void)
+static int __init keyspan_init (void)
 {
 	usb_serial_register (&keyspan_usa18x_pre_device);
 	usb_serial_register (&keyspan_usa19_pre_device);
@@ -201,7 +201,7 @@
 	return 0;
 }
 
-void keyspan_exit (void)
+static void __exit keyspan_exit (void)
 {
 	usb_serial_deregister (&keyspan_usa18x_pre_device);
 	usb_serial_deregister (&keyspan_usa19_pre_device);
@@ -468,7 +468,7 @@
 	p_priv = (struct keyspan_port_private *)(port->private);
 	dbg (__FUNCTION__ " urb %d\n", urb == p_priv->out_urbs[1]); 
 
-	if (port->active) {
+	if (port->open_count) {
 		queue_task(&port->tqueue, &tq_immediate);
 		mark_bh(IMMEDIATE_BH);
 	}
@@ -880,9 +880,8 @@
 	MOD_INC_USE_COUNT;
 
 	down (&port->sem);
+	already_active = port->open_count;
 	++port->open_count;
-	already_active = port->active;
-	port->active = 1;
 	up (&port->sem);
 
 	if (already_active)
@@ -948,18 +947,15 @@
 	down (&port->sem);
 
 	if (--port->open_count <= 0) {
-		if (port->active) {
-			if (serial->dev) {
-				/* Stop reading/writing urbs */
-				stop_urb(p_priv->inack_urb);
-				stop_urb(p_priv->outcont_urb);
-				for (i = 0; i < 2; i++) {
-					stop_urb(p_priv->in_urbs[i]);
-					stop_urb(p_priv->out_urbs[i]);
-				}
+		if (serial->dev) {
+			/* Stop reading/writing urbs */
+			stop_urb(p_priv->inack_urb);
+			stop_urb(p_priv->outcont_urb);
+			for (i = 0; i < 2; i++) {
+				stop_urb(p_priv->in_urbs[i]);
+				stop_urb(p_priv->out_urbs[i]);
 			}
 		}
-		port->active = 0;
 		port->open_count = 0;
 		port->tty = 0;
 	}
@@ -1089,7 +1085,7 @@
 	return urb;
 }
 
-struct callbacks {
+static struct callbacks {
 	void	(*instat_callback)(urb_t *);
 	void	(*glocont_callback)(urb_t *);
 	void	(*indat_callback)(urb_t *);
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/keyspan.h linux/drivers/usb/serial/keyspan.h
--- v2.5.0/linux/drivers/usb/serial/keyspan.h	Tue Oct  9 15:15:02 2001
+++ linux/drivers/usb/serial/keyspan.h	Thu Nov 29 13:45:52 2001
@@ -448,12 +448,9 @@
 };
 
     /* Structs for the devices, pre and post renumeration. */
-struct usb_serial_device_type keyspan_usa18x_pre_device = {
+static struct usb_serial_device_type keyspan_usa18x_pre_device = {
 	name:			"Keyspan USA18X - (without firmware)",
 	id_table:		keyspan_usa18x_pre_ids,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -461,12 +458,9 @@
 	startup:		keyspan_fake_startup	
 };
 
-struct usb_serial_device_type keyspan_usa19_pre_device = {
+static struct usb_serial_device_type keyspan_usa19_pre_device = {
 	name:			"Keyspan USA19 - (without firmware)",
 	id_table:		keyspan_usa19_pre_ids,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -475,12 +469,9 @@
 };
 
 
-struct usb_serial_device_type keyspan_usa19w_pre_device = {
+static struct usb_serial_device_type keyspan_usa19w_pre_device = {
 	name:			"Keyspan USA19W - (without firmware)",
 	id_table:		keyspan_usa19w_pre_ids,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -489,12 +480,9 @@
 };
 
 
-struct usb_serial_device_type keyspan_usa28_pre_device = {
+static struct usb_serial_device_type keyspan_usa28_pre_device = {
 	name:			"Keyspan USA28 - (without firmware)",
 	id_table:		keyspan_usa28_pre_ids,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -502,12 +490,9 @@
 	startup:		keyspan_fake_startup	
 };
 
-struct usb_serial_device_type keyspan_usa28x_pre_device = {
+static struct usb_serial_device_type keyspan_usa28x_pre_device = {
 	name:			"Keyspan USA28X - (without firmware)",
 	id_table:		keyspan_usa28x_pre_ids,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -515,12 +500,9 @@
 	startup:		keyspan_fake_startup	
 };
 
-struct usb_serial_device_type keyspan_usa28xa_pre_device = {
+static struct usb_serial_device_type keyspan_usa28xa_pre_device = {
 	name:			"Keyspan USA28XA - (without firmware)",
 	id_table:		keyspan_usa28xa_pre_ids,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -528,12 +510,9 @@
 	startup:		keyspan_fake_startup	
 };
 
-struct usb_serial_device_type keyspan_usa28xb_pre_device = {
+static struct usb_serial_device_type keyspan_usa28xb_pre_device = {
 	name:			"Keyspan USA28XB - (without firmware)",
 	id_table:		keyspan_usa28xb_pre_ids,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -541,12 +520,9 @@
 	startup:		keyspan_fake_startup	
 };
 
-struct usb_serial_device_type keyspan_usa49w_pre_device = {
+static struct usb_serial_device_type keyspan_usa49w_pre_device = {
 	name:			"Keyspan USA49W - (without firmware)",
 	id_table:		keyspan_usa49w_pre_ids,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -554,12 +530,9 @@
 	startup:		keyspan_fake_startup	
 };
 
-struct usb_serial_device_type keyspan_usa18x_device = {
+static struct usb_serial_device_type keyspan_usa18x_device = {
 	name:			"Keyspan USA18X",
 	id_table:		keyspan_usa18x_ids,
-	needs_interrupt_in:	DONT_CARE,	
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		3,
 	num_bulk_out:		4,
@@ -580,12 +553,9 @@
 	shutdown:		keyspan_shutdown,
 };
 
-struct usb_serial_device_type keyspan_usa19_device = {
+static struct usb_serial_device_type keyspan_usa19_device = {
 	name:			"Keyspan USA19",
 	id_table:		keyspan_usa19_ids,
-	needs_interrupt_in:	DONT_CARE,	
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		3,
 	num_bulk_out:		4,
@@ -607,12 +577,9 @@
 };
 
 
-struct usb_serial_device_type keyspan_usa19w_device = {
+static struct usb_serial_device_type keyspan_usa19w_device = {
 	name:			"Keyspan USA19W",
 	id_table:		keyspan_usa19w_ids,
-	needs_interrupt_in:	DONT_CARE,	
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		3,
 	num_bulk_out:		4,
@@ -634,12 +601,9 @@
 };
 
 
-struct usb_serial_device_type keyspan_usa28_device = {
+static struct usb_serial_device_type keyspan_usa28_device = {
 	name:			"Keyspan USA28",
 	id_table:		keyspan_usa28_ids,
-	needs_interrupt_in:	DONT_CARE,	
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -652,12 +616,9 @@
 };
 
 
-struct usb_serial_device_type keyspan_usa28x_device = {
+static struct usb_serial_device_type keyspan_usa28x_device = {
 	name:			"Keyspan USA28X/XB",
 	id_table:		keyspan_usa28x_ids,
-	needs_interrupt_in:	DONT_CARE,	
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -679,12 +640,9 @@
 
 };
 
-struct usb_serial_device_type keyspan_usa28xa_device = {
+static struct usb_serial_device_type keyspan_usa28xa_device = {
 	name:			"Keyspan USA28XA",
 	id_table:		keyspan_usa28xa_ids,
-	needs_interrupt_in:	DONT_CARE,	
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -706,12 +664,9 @@
 
 };
 
-struct usb_serial_device_type keyspan_usa49w_device = {
+static struct usb_serial_device_type keyspan_usa49w_device = {
 	name:			"Keyspan USA49W",
 	id_table:		keyspan_usa49w_ids,
-	needs_interrupt_in:	DONT_CARE,	
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		5,
 	num_bulk_out:		5,
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c
--- v2.5.0/linux/drivers/usb/serial/keyspan_pda.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/keyspan_pda.c	Sat Dec  8 20:28:45 2001
@@ -172,10 +172,6 @@
 #ifdef XIRCOM
 static __devinitdata struct usb_device_id id_table_fake_xircom [] = {
         { USB_DEVICE(XIRCOM_VENDOR_ID, XIRCOM_FAKE_ID) },
-        { }                                             
-};
-
-static __devinitdata struct usb_device_id id_table_fake_entregra [] = {
         { USB_DEVICE(ENTREGRA_VENDOR_ID, ENTREGRA_FAKE_ID) },
         { }                                             
 };
@@ -679,9 +675,7 @@
 	MOD_INC_USE_COUNT;
 	++port->open_count;
 
-	if (!port->active) {
-		port->active = 1;
- 
+	if (port->open_count == 1) {
 		/* find out how much room is in the Tx ring */
 		rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				     6, /* write_room */
@@ -727,7 +721,6 @@
 	return rc;
 error:
 	--port->open_count;
-	port->active = 0;
 	MOD_DEC_USE_COUNT;
 	up (&port->sem);
 	return rc;
@@ -752,7 +745,6 @@
 			usb_unlink_urb (port->write_urb);
 			usb_unlink_urb (port->interrupt_in_urb);
 		}
-		port->active = 0;
 		port->open_count = 0;
 	}
 
@@ -843,9 +835,6 @@
 static struct usb_serial_device_type keyspan_pda_fake_device = {
 	name:			"Keyspan PDA - (prerenumeration)",
 	id_table:		id_table_fake,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		DONT_CARE,
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -856,24 +845,8 @@
 
 #ifdef XIRCOM
 static struct usb_serial_device_type xircom_pgs_fake_device = {
-        name:                   "Xircom PGS - (prerenumeration)",
+        name:                   "Xircom / Entregra PGS - (prerenumeration)",
         id_table:               id_table_fake_xircom,
-        needs_interrupt_in:     DONT_CARE,
-        needs_bulk_in:          DONT_CARE,
-        needs_bulk_out:         DONT_CARE,
-        num_interrupt_in:       NUM_DONT_CARE,
-        num_bulk_in:            NUM_DONT_CARE,
-        num_bulk_out:           NUM_DONT_CARE,
-        num_ports:              1,
-        startup:                keyspan_pda_fake_startup,
-};
-
-static struct usb_serial_device_type entregra_pgs_fake_device = {
-        name:                   "Entregra PGS - (prerenumeration)",
-        id_table:               id_table_fake_entregra,
-        needs_interrupt_in:     DONT_CARE,
-        needs_bulk_in:          DONT_CARE,
-        needs_bulk_out:         DONT_CARE,
         num_interrupt_in:       NUM_DONT_CARE,
         num_bulk_in:            NUM_DONT_CARE,
         num_bulk_out:           NUM_DONT_CARE,
@@ -885,9 +858,6 @@
 static struct usb_serial_device_type keyspan_pda_device = {
 	name:			"Keyspan PDA",
 	id_table:		id_table_std,
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	1,
 	num_bulk_in:		0,
 	num_bulk_out:		1,
@@ -917,7 +887,6 @@
 #endif
 #ifdef XIRCOM
 	usb_serial_register (&xircom_pgs_fake_device);
-	usb_serial_register (&entregra_pgs_fake_device);
 #endif
 	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
@@ -931,7 +900,6 @@
 	usb_serial_deregister (&keyspan_pda_fake_device);
 #endif
 #ifdef XIRCOM
-	usb_serial_deregister (&entregra_pgs_fake_device);
 	usb_serial_deregister (&xircom_pgs_fake_device);
 #endif
 }
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/mct_u232.c linux/drivers/usb/serial/mct_u232.c
--- v2.5.0/linux/drivers/usb/serial/mct_u232.c	Mon Nov 12 09:53:56 2001
+++ linux/drivers/usb/serial/mct_u232.c	Sat Dec  8 20:28:44 2001
@@ -27,6 +27,9 @@
  * 10-Nov-2001 Wolfgang Grandegger
  *   - Fixed an endianess problem with the baudrate selection for PowerPC.
  *
+ * 06-Dec-2001 Martin Hamilton <martinh@gnu.org>
+ *	Added support for the Belkin F5U109 DB9 adaptor
+ *
  * 30-May-2001 Greg Kroah-Hartman
  *	switched from using spinlock to a semaphore, which fixes lots of problems.
  *
@@ -133,57 +136,16 @@
 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
 	{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
+	{ USB_DEVICE(MCT_U232_BELKIN_F5U109_VID, MCT_U232_BELKIN_F5U109_PID) },
 	{ }		/* Terminating entry */
 };
 
-static __devinitdata struct usb_device_id mct_u232_table [] = {
-        { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
-        { }                        /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id mct_u232_sitecom_table [] = {
-        { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
-        { }                        /* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id mct_u232_du_h3sp_table [] = {
-        { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
-        { }                        /* Terminating entry */
-};
-
 MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 
-struct usb_serial_device_type mct_u232_device = {
+static struct usb_serial_device_type mct_u232_device = {
 	name:		     "Magic Control Technology USB-RS232",
-	id_table:	     mct_u232_table,
-	needs_interrupt_in:  MUST_HAVE,	 /* 2 interrupt-in endpoints */
-	needs_bulk_in:	     MUST_HAVE_NOT,   /* no bulk-in endpoint */
-	needs_bulk_out:	     MUST_HAVE,	      /* 1 bulk-out endpoint */
-	num_interrupt_in:    2,
-	num_bulk_in:	     0,
-	num_bulk_out:	     1,
-	num_ports:	     1,
-	open:		     mct_u232_open,
-	close:		     mct_u232_close,
-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
-	write:		     mct_u232_write,
-	write_bulk_callback: mct_u232_write_bulk_callback,
-#endif
-	read_int_callback:   mct_u232_read_int_callback,
-	ioctl:		     mct_u232_ioctl,
-	set_termios:	     mct_u232_set_termios,
-	break_ctl:	     mct_u232_break_ctl,
-	startup:	     mct_u232_startup,
-	shutdown:	     mct_u232_shutdown,
-};
-
-struct usb_serial_device_type mct_u232_sitecom_device = {
-	name:		     "MCT/Sitecom USB-RS232",
-	id_table:	     mct_u232_sitecom_table,
-	needs_interrupt_in:  MUST_HAVE,	 /* 2 interrupt-in endpoints */
-	needs_bulk_in:	     MUST_HAVE_NOT,   /* no bulk-in endpoint */
-	needs_bulk_out:	     MUST_HAVE,	      /* 1 bulk-out endpoint */
+	id_table:	     id_table_combined,
 	num_interrupt_in:    2,
 	num_bulk_in:	     0,
 	num_bulk_out:	     1,
@@ -202,32 +164,6 @@
 	shutdown:	     mct_u232_shutdown,
 };
 
-struct usb_serial_device_type mct_u232_du_h3sp_device = {
-        name:                "MCT/D-Link DU-H3SP USB BAY",
-        id_table:            mct_u232_du_h3sp_table,
-        needs_interrupt_in:  MUST_HAVE,  /* 2 interrupt-in endpoints */
-        needs_bulk_in:       MUST_HAVE_NOT,   /* no bulk-in endpoint */
-        needs_bulk_out:      MUST_HAVE,       /* 1 bulk-out endpoint */
-        num_interrupt_in:    2,
-        num_bulk_in:         0,
-        num_bulk_out:        1,
-        num_ports:           1,
-        open:                mct_u232_open,
-        close:               mct_u232_close,
-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
-        write:               mct_u232_write,
-        write_bulk_callback: mct_u232_write_bulk_callback,
-#endif
-        read_int_callback:   mct_u232_read_int_callback,
-        ioctl:               mct_u232_ioctl,
-        set_termios:         mct_u232_set_termios,
-        break_ctl:           mct_u232_break_ctl,
-        startup:             mct_u232_startup,
-        shutdown:            mct_u232_shutdown,
-};
-
-
-
 
 struct mct_u232_private {
 	unsigned long	     control_state; /* Modem Line Setting (TIOCM) */
@@ -243,7 +179,8 @@
 #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
 
 static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
-	if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID) {
+	if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
+	  || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
 		switch (value) {
 			case    300: return 0x01;
 			case    600: return 0x02; /* this one not tested */
@@ -408,9 +345,7 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 
-	if (!port->active) {
-		port->active = 1;
-
+	if (port->open_count == 1) {
 		/* Compensate for a hardware bug: although the Sitecom U232-P25
 		 * device reports a maximum output packet size of 32 bytes,
 		 * it seems to be able to accept only 16 bytes (and that's what
@@ -484,7 +419,7 @@
 			usb_unlink_urb (port->read_urb);
 			usb_unlink_urb (port->interrupt_in_urb);
 		}
-		port->active = 0;
+		port->open_count = 0;
 	}
 	
 	up (&port->sem);
@@ -880,9 +815,7 @@
 static int __init mct_u232_init (void)
 {
 	usb_serial_register (&mct_u232_device);
-	usb_serial_register (&mct_u232_sitecom_device);
-	usb_serial_register (&mct_u232_du_h3sp_device);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
+	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
 
@@ -890,8 +823,6 @@
 static void __exit mct_u232_exit (void)
 {
 	usb_serial_deregister (&mct_u232_device);
-	usb_serial_deregister (&mct_u232_sitecom_device);
-	usb_serial_deregister (&mct_u232_du_h3sp_device);
 }
 
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/mct_u232.h linux/drivers/usb/serial/mct_u232.h
--- v2.5.0/linux/drivers/usb/serial/mct_u232.h	Thu Feb  8 16:30:40 2001
+++ linux/drivers/usb/serial/mct_u232.h	Sat Dec  8 20:28:45 2001
@@ -30,9 +30,12 @@
 #define MCT_U232_SITECOM_PID		0x0230	/* Sitecom Product Id */
 
 /* DU-H3SP USB BAY hub */
-
 #define MCT_U232_DU_H3SP_PID		0x0200	/* D-Link DU-H3SP USB BAY */
 
+/* Belkin badge the MCT U232-P9 as the F5U109 */
+#define MCT_U232_BELKIN_F5U109_VID	0x050d	/* Vendor Id */
+#define MCT_U232_BELKIN_F5U109_PID	0x0109	/* Product Id */
+
 /*
  * Vendor Request Interface
  */
@@ -363,6 +366,25 @@
  * 	  bmAttributes        =   03 (Interrupt)
  * 	  wMaxPacketSize      = 0002
  * 	  bInterval           =   02
+ *
+ *
+ * Hardware details (added by Martin Hamilton, 2001/12/06)
+ * -----------------------------------------------------------------
+ *
+ * This info was gleaned from opening a Belkin F5U109 DB9 USB serial
+ * adaptor, which turns out to simply be a re-badged U232-P9.  We
+ * know this because there is a sticky label on the circuit board
+ * which says "U232-P9" ;-)
+ * 
+ * The circuit board inside the adaptor contains a Philips PDIUSBD12
+ * USB endpoint chip and a Phillips P87C52UBAA microcontroller with
+ * embedded UART.  Exhaustive documentation for these is available at:
+ *
+ *   http://www.semiconductors.philips.com/pip/p87c52ubaa
+ *   http://www.semiconductors.philips.com/pip/pdiusbd12
+ *
+ * Thanks to Julian Highfield for the pointer to the Philips database.
+ * 
  */
 
 #endif /* __LINUX_USB_SERIAL_MCT_U232_H */
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c
--- v2.5.0/linux/drivers/usb/serial/omninet.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/omninet.c	Sat Dec  8 20:28:45 2001
@@ -87,12 +87,9 @@
 MODULE_DEVICE_TABLE (usb, id_table);
 
 
-struct usb_serial_device_type zyxel_omninet_device = {
+static struct usb_serial_device_type zyxel_omninet_device = {
 	name:			"ZyXEL - omni.net lcd plus usb",
 	id_table:		id_table,
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		2,
@@ -164,14 +161,11 @@
 	MOD_INC_USE_COUNT;
 	++port->open_count;
 
-	if (!port->active) {
-		port->active = 1;
-
+	if (port->open_count == 1) {
 		od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
 		if( !od ) {
 			err(__FUNCTION__"- kmalloc(%Zd) failed.", sizeof(struct omninet_data));
-			--port->open_count;
-			port->active = 0;
+			port->open_count = 0;
 			up (&port->sem);
 			MOD_DEC_USE_COUNT;
 			return -ENOMEM;
@@ -222,7 +216,6 @@
 			usb_unlink_urb (port->read_urb);
 		}
 
-		port->active = 0;
 		port->open_count = 0;
 		od = (struct omninet_data *)port->private;
 		if (od)
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/pl2303.c linux/drivers/usb/serial/pl2303.c
--- v2.5.0/linux/drivers/usb/serial/pl2303.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/pl2303.c	Sat Dec  8 20:28:45 2001
@@ -118,9 +118,6 @@
 static struct usb_serial_device_type pl2303_device = {
 	name:			"PL-2303",
 	id_table:		id_table,
-	needs_interrupt_in:	DONT_CARE,		/* this device must have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -374,9 +371,7 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 
-	if (!port->active) {
-		port->active = 1;
-
+	if (port->open_count == 1) {
 #define FISH(a,b,c,d)									\
 		result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0),	\
 				       b, a, c, d, buf, 1, 100);			\
@@ -481,8 +476,6 @@
 				     "(interrupt_in_urb) failed with reason: %d",
 				     result);
 		}
-
-		port->active = 0;
 		port->open_count = 0;
 	}
 
@@ -651,7 +644,7 @@
 
 	if (urb->status) {
 		dbg (__FUNCTION__ " - urb->status = %d", urb->status);
-		if (!port->active) {
+		if (!port->open_count) {
 			dbg (__FUNCTION__ " - port is closed, exiting.");
 			return;
 		}
@@ -683,7 +676,7 @@
 	}
 
 	/* Schedule the next read _if_ we are still open */
-	if (port->active) {
+	if (port->open_count) {
 		urb->dev = serial->dev;
 		result = usb_submit_urb(urb);
 		if (result)
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h
--- v2.5.0/linux/drivers/usb/serial/usb-serial.h	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/usb-serial.h	Sat Dec  8 20:28:45 2001
@@ -11,6 +11,10 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (12/03/2001) gkh
+ *	removed active from the port structure.
+ *	added documentation to the usb_serial_device_type structure
+ *
  * (10/10/2001) gkh
  *	added vendor and product to serial structure.  Needed to determine device
  *	owner when the device is disconnected.
@@ -65,7 +69,6 @@
 	struct usb_serial	*serial;	/* pointer back to the owner of this port */
 	struct tty_struct *	tty;		/* the coresponding tty for this port */
 	unsigned char		number;
-	char			active;		/* someone has this device open */
 
 	unsigned char *		interrupt_in_buffer;
 	struct urb *		interrupt_in_urb;
@@ -108,34 +111,43 @@
 };
 
 
-#define MUST_HAVE_NOT	0x01
-#define MUST_HAVE	0x02
-#define DONT_CARE	0x03
-
-#define	HAS		0x02
-#define HAS_NOT		0x01
-
 #define NUM_DONT_CARE	(-1)
 
 
-/* This structure defines the individual serial converter. */
+/**
+ * usb_serial_device_type - a structure that defines a usb serial device
+ * @name: pointer to a string that describes this device.  This string used
+ *	in the syslog messages when a device is inserted or removed.
+ * @id_table: pointer to a list of usb_device_id structures that define all
+ *	of the devices this structure can support.
+ * @num_interrupt_in: the number of interrupt in endpoints this device will
+ *	have.
+ * @num_bulk_in: the number of bulk in endpoints this device will have.
+ * @num_bulk_out: the number of bulk out endpoints this device will have.
+ * @num_ports: the number of different ports this device will have.
+ * @startup: pointer to the driver's startup function.  This will be called
+ *	when the driver is inserted into the system.  Return 0 to continue
+ *	on with the initialization sequence.  Anything else will abort it.
+ * @shutdown: pointer to the driver's shutdown function.  This will be
+ *	called when the device is removed from the system.
+ *
+ * This structure is defines a USB Serial device.  It provides all of
+ * the information that the USB serial core code needs.  If the function
+ * pointers are defined, then the USB serial core code will call them when
+ * the corresponding tty port functions are called.  If they are not
+ * called, the generic serial function will be used instead.
+ */
 struct usb_serial_device_type {
 	char	*name;
 	const struct usb_device_id *id_table;
-	char	needs_interrupt_in;
-	char	needs_bulk_in;
-	char	needs_bulk_out;
 	char	num_interrupt_in;
 	char	num_bulk_in;
 	char	num_bulk_out;
-	char	num_ports;		/* number of serial ports this device has */
+	char	num_ports;
 
 	struct list_head	driver_list;
 	
-	/* function call to make before accepting driver */
-	/* return 0 to continue initialization, anything else to abort */
 	int (*startup) (struct usb_serial *serial);
-	
 	void (*shutdown) (struct usb_serial *serial);
 
 	/* serial function calls */
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- v2.5.0/linux/drivers/usb/serial/usbserial.c	Wed Oct 10 23:42:47 2001
+++ linux/drivers/usb/serial/usbserial.c	Sat Dec  8 20:28:45 2001
@@ -339,9 +339,6 @@
 static struct usb_serial_device_type generic_device = {
 	name:			"Generic",
 	id_table:		generic_device_ids,
-	needs_interrupt_in:	DONT_CARE,		/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,		/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,		/* don't have to have a bulk out endpoint */
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -397,7 +394,7 @@
 static struct usb_serial	*serial_table[SERIAL_TTY_MINORS];	/* initially all NULL */
 
 
-LIST_HEAD(usb_serial_driver_list);
+static LIST_HEAD(usb_serial_driver_list);
 
 
 static struct usb_serial *get_serial_by_minor (int minor)
@@ -548,7 +545,7 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 	
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not opened");
 		return;
 	}
@@ -573,7 +570,7 @@
 	
 	dbg(__FUNCTION__ " - port %d, %d byte(s)", port->number, count);
 
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not opened");
 		return -EINVAL;
 	}
@@ -598,7 +595,7 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 	
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not open");
 		return -EINVAL;
 	}
@@ -621,7 +618,7 @@
 		return -ENODEV;
 	}
 
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not open");
 		return -EINVAL;
 	}
@@ -646,7 +643,7 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not open");
 		return;
 	}
@@ -671,7 +668,7 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not open");
 		return;
 	}
@@ -696,7 +693,7 @@
 
 	dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd);
 
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not open");
 		return -ENODEV;
 	}
@@ -721,7 +718,7 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not open");
 		return;
 	}
@@ -746,7 +743,7 @@
 
 	dbg(__FUNCTION__ " - port %d", port->number);
 
-	if (!port->active) {
+	if (!port->open_count) {
 		dbg (__FUNCTION__ " - port not open");
 		return;
 	}
@@ -790,9 +787,7 @@
 	
 	++port->open_count;
 	
-	if (!port->active) {
-		port->active = 1;
-
+	if (port->open_count == 1) {
 		/* force low_latency on so that our tty_push actually forces the data through, 
 		   otherwise it is scheduled, and with high data rates (like with OHCI) data
 		   can get lost. */
@@ -801,13 +796,14 @@
 		/* if we have a bulk interrupt, start reading from it */
 		if (serial->num_bulk_in) {
 			/* Start reading from the device */
-			FILL_BULK_URB(port->read_urb, serial->dev, 
-				      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-				      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-				      ((serial->type->read_bulk_callback) ?
-				       serial->type->read_bulk_callback :
-				       generic_read_bulk_callback), 
-				      port);
+			usb_fill_bulk_urb (port->read_urb, serial->dev,
+					   usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
+					   port->read_urb->transfer_buffer,
+					   port->read_urb->transfer_buffer_length,
+					   ((serial->type->read_bulk_callback) ?
+					     serial->type->read_bulk_callback :
+					     generic_read_bulk_callback),
+					   port);
 			result = usb_submit_urb(port->read_urb);
 			if (result)
 				err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
@@ -838,8 +834,6 @@
 			if (serial->num_bulk_in)
 				usb_unlink_urb (port->read_urb);
 		}
-		
-		port->active = 0;
 		port->open_count = 0;
 	}
 
@@ -882,13 +876,13 @@
 		usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
 
 		/* set up our urb */
-		FILL_BULK_URB(port->write_urb, serial->dev, 
-			      usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
-			      port->write_urb->transfer_buffer, count,
-			      ((serial->type->write_bulk_callback) ? 
-			       serial->type->write_bulk_callback : 
-			       generic_write_bulk_callback), 
-			      port);
+		usb_fill_bulk_urb (port->write_urb, serial->dev,
+				   usb_sndbulkpipe (serial->dev,
+					   	    port->bulk_out_endpointAddress),
+				   port->write_urb->transfer_buffer, count,
+				   ((serial->type->write_bulk_callback) ? 
+				     serial->type->write_bulk_callback :
+				     generic_write_bulk_callback), port);
 
 		/* send the data out the bulk port */
 		result = usb_submit_urb(port->write_urb);
@@ -976,13 +970,14 @@
 	}
 
 	/* Continue trying to always read  */
-	FILL_BULK_URB(port->read_urb, serial->dev, 
-		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-		      ((serial->type->read_bulk_callback) ?
-		       serial->type->read_bulk_callback :
-		       generic_read_bulk_callback), 
-		      port);
+	usb_fill_bulk_urb (port->read_urb, serial->dev,
+			   usb_rcvbulkpipe (serial->dev,
+				   	    port->bulk_in_endpointAddress),
+			   port->read_urb->transfer_buffer,
+			   port->read_urb->transfer_buffer_length,
+			   ((serial->type->read_bulk_callback) ? 
+			     serial->type->read_bulk_callback : 
+			     generic_read_bulk_callback), port);
 	result = usb_submit_urb(port->read_urb);
 	if (result)
 		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
@@ -1068,9 +1063,6 @@
 	int minor;
 	int buffer_size;
 	int i;
-	char interrupt_pipe;
-	char bulk_in_pipe;
-	char bulk_out_pipe;
 	int num_interrupt_in = 0;
 	int num_bulk_in = 0;
 	int num_bulk_out = 0;
@@ -1097,10 +1089,8 @@
 		dbg("none matched");
 		return(NULL);
 	}
-	
+
 	/* descriptor matches, let's find the endpoints needed */
-	interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
-			
 	/* check out the endpoints */
 	iface_desc = &interface->altsetting[0];
 	for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
@@ -1110,7 +1100,6 @@
 		    ((endpoint->bmAttributes & 3) == 0x02)) {
 			/* we found a bulk in endpoint */
 			dbg("found bulk in");
-			bulk_in_pipe = HAS;
 			bulk_in_endpoint[num_bulk_in] = endpoint;
 			++num_bulk_in;
 		}
@@ -1119,7 +1108,6 @@
 		    ((endpoint->bmAttributes & 3) == 0x02)) {
 			/* we found a bulk out endpoint */
 			dbg("found bulk out");
-			bulk_out_pipe = HAS;
 			bulk_out_endpoint[num_bulk_out] = endpoint;
 			++num_bulk_out;
 		}
@@ -1128,7 +1116,6 @@
 		    ((endpoint->bmAttributes & 3) == 0x03)) {
 			/* we found a interrupt in endpoint */
 			dbg("found interrupt in");
-			interrupt_pipe = HAS;
 			interrupt_in_endpoint[num_interrupt_in] = endpoint;
 			++num_interrupt_in;
 		}
@@ -1151,7 +1138,6 @@
 				    ((endpoint->bmAttributes & 3) == 0x03)) {
 					/* we found a interrupt in endpoint */
 					dbg("found interrupt in for Prolific device on separate interface");
-					interrupt_pipe = HAS;
 					interrupt_in_endpoint[num_interrupt_in] = endpoint;
 					++num_interrupt_in;
 				}
@@ -1161,15 +1147,6 @@
 	/* END HORRIBLE HACK FOR PL2303 */
 #endif
 	
-	/* verify that we found all of the endpoints that we need */
-	if (!((interrupt_pipe & type->needs_interrupt_in) &&
-	      (bulk_in_pipe & type->needs_bulk_in) &&
-	      (bulk_out_pipe & type->needs_bulk_out))) {
-		/* nope, they don't match what we expected */
-		info("descriptors matched, but endpoints did not");
-		return NULL;
-	}
-
 	/* found all that we need */
 	info("%s converter detected", type->name);
 
@@ -1224,13 +1201,14 @@
 			err("Couldn't allocate bulk_in_buffer");
 			goto probe_error;
 		}
-		FILL_BULK_URB(port->read_urb, dev, 
-			      usb_rcvbulkpipe(dev, endpoint->bEndpointAddress),
-			      port->bulk_in_buffer, buffer_size, 
-			      ((serial->type->read_bulk_callback) ?
-			       serial->type->read_bulk_callback :
-			       generic_read_bulk_callback), 
-			      port);
+		usb_fill_bulk_urb (port->read_urb, dev,
+				   usb_rcvbulkpipe (dev,
+					   	    endpoint->bEndpointAddress),
+				   port->bulk_in_buffer, buffer_size,
+				   ((serial->type->read_bulk_callback) ? 
+				     serial->type->read_bulk_callback : 
+				     generic_read_bulk_callback),
+				   port);
 	}
 
 	for (i = 0; i < num_bulk_out; ++i) {
@@ -1249,13 +1227,14 @@
 			err("Couldn't allocate bulk_out_buffer");
 			goto probe_error;
 		}
-		FILL_BULK_URB(port->write_urb, dev, 
-			      usb_sndbulkpipe(dev, endpoint->bEndpointAddress),
-			      port->bulk_out_buffer, buffer_size,
-			      ((serial->type->write_bulk_callback) ? 
-			       serial->type->write_bulk_callback : 
-			       generic_write_bulk_callback), 
-			      port);
+		usb_fill_bulk_urb (port->write_urb, dev,
+				   usb_sndbulkpipe (dev,
+						    endpoint->bEndpointAddress),
+				   port->bulk_out_buffer, buffer_size, 
+				   ((serial->type->write_bulk_callback) ? 
+				     serial->type->write_bulk_callback : 
+				     generic_write_bulk_callback),
+				   port);
 	}
 
 	for (i = 0; i < num_interrupt_in; ++i) {
@@ -1273,12 +1252,12 @@
 			err("Couldn't allocate interrupt_in_buffer");
 			goto probe_error;
 		}
-		FILL_INT_URB(port->interrupt_in_urb, dev, 
-			     usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-			     port->interrupt_in_buffer, buffer_size, 
-			     serial->type->read_int_callback,
-			     port, 
-			     endpoint->bInterval);
+		usb_fill_int_urb (port->interrupt_in_urb, dev, 
+				  usb_rcvintpipe (dev,
+						  endpoint->bEndpointAddress),
+				  port->interrupt_in_buffer, buffer_size, 
+				  serial->type->read_int_callback, port, 
+				  endpoint->bInterval);
 	}
 
 	/* initialize some parts of the port structures */
@@ -1356,7 +1335,7 @@
 		serial_shutdown (serial);
 
 		for (i = 0; i < serial->num_ports; ++i)
-			serial->port[i].active = 0;
+			serial->port[i].open_count = 0;
 
 		for (i = 0; i < serial->num_bulk_in; ++i) {
 			port = &serial->port[i];
@@ -1433,7 +1412,7 @@
 };
 
 
-int usb_serial_init(void)
+static int __init usb_serial_init(void)
 {
 	int i;
 	int result;
@@ -1473,7 +1452,7 @@
 }
 
 
-void usb_serial_exit(void)
+static void __exit usb_serial_exit(void)
 {
 
 #ifdef CONFIG_USB_SERIAL_GENERIC
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c
--- v2.5.0/linux/drivers/usb/serial/visor.c	Mon Nov 12 09:53:56 2001
+++ linux/drivers/usb/serial/visor.c	Sat Dec  8 20:28:45 2001
@@ -127,7 +127,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.5"
+#define DRIVER_VERSION "v1.7"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver"
 
@@ -147,15 +147,12 @@
 static void visor_read_bulk_callback	(struct urb *urb);
 
 
-static __devinitdata struct usb_device_id visor_id_table [] = {
-	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
-	{ }					/* Terminating entry */
-};
-
-static __devinitdata struct usb_device_id palm_4_0_id_table [] = {
+static __devinitdata struct usb_device_id combined_id_table [] = {
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M505_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M125_ID) },
+	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
+	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
 	{ }					/* Terminating entry */
 };
 
@@ -164,11 +161,6 @@
 	{ }					/* Terminating entry */
 };
 
-static __devinitdata struct usb_device_id clie_id_4_0_table [] = {
-	{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_4_0_ID) },
-	{ }					/* Terminating entry */
-};
-
 static __devinitdata struct usb_device_id id_table [] = {
 	{ USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID) },
 	{ USB_DEVICE(PALM_VENDOR_ID, PALM_M500_ID) },
@@ -183,39 +175,10 @@
 
 
 
-/* All of the device info needed for the Handspring Visor */
-struct usb_serial_device_type handspring_device = {
-	name:			"Handspring Visor",
-	id_table:		visor_id_table,
-	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
-	num_interrupt_in:	0,
-	num_bulk_in:		2,
-	num_bulk_out:		2,
-	num_ports:		2,
-	open:			visor_open,
-	close:			visor_close,
-	throttle:		visor_throttle,
-	unthrottle:		visor_unthrottle,
-	startup:		visor_startup,
-	shutdown:		visor_shutdown,
-	ioctl:			visor_ioctl,
-	set_termios:		visor_set_termios,
-	write:			visor_write,
-	write_room:		visor_write_room,
-	chars_in_buffer:	visor_chars_in_buffer,
-	write_bulk_callback:	visor_write_bulk_callback,
-	read_bulk_callback:	visor_read_bulk_callback,
-};
-
-/* device info for the Palm 4.0 devices */
-struct usb_serial_device_type palm_4_0_device = {
-	name:			"Palm 4.0",
-	id_table:		palm_4_0_id_table,
-	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
+/* All of the device info needed for the Handspring Visor, and Palm 4.0 devices */
+static struct usb_serial_device_type handspring_device = {
+	name:			"Handspring Visor / Palm 4.0 / Clié 4.0",
+	id_table:		combined_id_table,
 	num_interrupt_in:	0,
 	num_bulk_in:		2,
 	num_bulk_out:		2,
@@ -235,14 +198,10 @@
 	read_bulk_callback:	visor_read_bulk_callback,
 };
 
-
 /* device info for the Sony Clie OS version 3.5 */
 static struct usb_serial_device_type clie_3_5_device = {
 	name:			"Sony Clié 3.5",
 	id_table:		clie_id_3_5_table,
-	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
 	num_interrupt_in:	0,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
@@ -260,31 +219,6 @@
 	read_bulk_callback:	visor_read_bulk_callback,
 };
 
-/* device info for the Sony Clie OS version 4.0 */
-static struct usb_serial_device_type clie_4_0_device = {
-	name:			"Sony Clié 4.0",
-	id_table:		clie_id_4_0_table,
-	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
-	num_interrupt_in:	0,
-	num_bulk_in:		2,
-	num_bulk_out:		2,
-	num_ports:		2,
-	open:			visor_open,
-	close:			visor_close,
-	throttle:		visor_throttle,
-	unthrottle:		visor_unthrottle,
-	startup:		visor_startup,
-	shutdown:		visor_shutdown,
-	ioctl:			visor_ioctl,
-	set_termios:		visor_set_termios,
-	write:			visor_write,
-	write_room:		visor_write_room,
-	chars_in_buffer:	visor_chars_in_buffer,
-	write_bulk_callback:	visor_write_bulk_callback,
-	read_bulk_callback:	visor_read_bulk_callback,
-};
 
 #define NUM_URBS			24
 #define URB_TRANSFER_BUFFER_SIZE	768
@@ -317,8 +251,7 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 	
-	if (!port->active) {
-		port->active = 1;
+	if (port->open_count == 1) {
 		bytes_in = 0;
 		bytes_out = 0;
 
@@ -328,10 +261,12 @@
 		port->tty->low_latency = 1;
 		
 		/* Start reading from the device */
-		FILL_BULK_URB(port->read_urb, serial->dev, 
-			      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-			      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-			      visor_read_bulk_callback, port);
+		usb_fill_bulk_urb (port->read_urb, serial->dev,
+				   usb_rcvbulkpipe (serial->dev, 
+						    port->bulk_in_endpointAddress),
+				   port->read_urb->transfer_buffer,
+				   port->read_urb->transfer_buffer_length,
+				   visor_read_bulk_callback, port);
 		result = usb_submit_urb(port->read_urb);
 		if (result)
 			err(__FUNCTION__ " - failed submitting read urb, error %d", result);
@@ -380,7 +315,6 @@
 			/* shutdown our bulk read */
 			usb_unlink_urb (port->read_urb);
 		}
-		port->active = 0;
 		port->open_count = 0;
 	}
 	up (&port->sem);
@@ -441,8 +375,11 @@
 		usb_serial_debug_data (__FILE__, __FUNCTION__, transfer_size, urb->transfer_buffer);
 
 		/* build up our urb */
-		FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), 
-				urb->transfer_buffer, transfer_size, visor_write_bulk_callback, port);
+		usb_fill_bulk_urb (urb, serial->dev,
+				   usb_sndbulkpipe (serial->dev,
+						    port->bulk_out_endpointAddress),
+				   urb->transfer_buffer, transfer_size, 
+				   visor_write_bulk_callback, port);
 		urb->transfer_flags |= USB_QUEUE_BULK;
 
 		/* send it down the pipe */
@@ -572,10 +509,12 @@
 	}
 
 	/* Continue trying to always read  */
-	FILL_BULK_URB(port->read_urb, serial->dev, 
-		      usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress),
-		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
-		      visor_read_bulk_callback, port);
+	usb_fill_bulk_urb (port->read_urb, serial->dev,
+			   usb_rcvbulkpipe (serial->dev,
+					    port->bulk_in_endpointAddress),
+			   port->read_urb->transfer_buffer,
+			   port->read_urb->transfer_buffer_length,
+			   visor_read_bulk_callback, port);
 	result = usb_submit_urb(port->read_urb);
 	if (result)
 		err(__FUNCTION__ " - failed resubmitting read urb, error %d", result);
@@ -713,11 +652,8 @@
 	dbg (__FUNCTION__);
 
 	/* stop reads and writes on all ports */
-	for (i=0; i < serial->num_ports; ++i) {
-		while (serial->port[i].open_count > 0) {
-			visor_close (&serial->port[i], NULL);
-		}
-	}
+	for (i=0; i < serial->num_ports; ++i)
+		serial->port[i].open_count = 0;
 }
 
 
@@ -801,9 +737,7 @@
 	int i;
 
 	usb_serial_register (&handspring_device);
-	usb_serial_register (&palm_4_0_device);
 	usb_serial_register (&clie_3_5_device);
-	usb_serial_register (&clie_4_0_device);
 	
 	/* create our write urb pool and transfer buffers */ 
 	spin_lock_init (&write_urb_pool_lock);
@@ -835,9 +769,7 @@
 	unsigned long flags;
 
 	usb_serial_deregister (&handspring_device);
-	usb_serial_deregister (&palm_4_0_device);
 	usb_serial_deregister (&clie_3_5_device);
-	usb_serial_deregister (&clie_4_0_device);
 
 	spin_lock_irqsave (&write_urb_pool_lock, flags);
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c
--- v2.5.0/linux/drivers/usb/serial/whiteheat.c	Fri Sep 14 14:04:07 2001
+++ linux/drivers/usb/serial/whiteheat.c	Sat Dec  8 20:28:45 2001
@@ -88,7 +88,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.1"
+#define DRIVER_VERSION "v1.2"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>"
 #define DRIVER_DESC "USB ConnectTech WhiteHEAT driver"
 
@@ -128,28 +128,23 @@
 static void whiteheat_set_termios	(struct usb_serial_port *port, struct termios * old);
 static void whiteheat_throttle		(struct usb_serial_port *port);
 static void whiteheat_unthrottle	(struct usb_serial_port *port);
-static int  whiteheat_startup		(struct usb_serial *serial);
-static void whiteheat_shutdown		(struct usb_serial *serial);
+static int  whiteheat_fake_startup	(struct usb_serial *serial);
+static int  whiteheat_real_startup	(struct usb_serial *serial);
+static void whiteheat_real_shutdown	(struct usb_serial *serial);
 
-struct usb_serial_device_type whiteheat_fake_device = {
+static struct usb_serial_device_type whiteheat_fake_device = {
 	name:			"Connect Tech - WhiteHEAT - (prerenumeration)",
 	id_table:		id_table_prerenumeration,
-	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
 	num_ports:		1,
-	startup:		whiteheat_startup	
+	startup:		whiteheat_fake_startup,
 };
 
-struct usb_serial_device_type whiteheat_device = {
+static struct usb_serial_device_type whiteheat_device = {
 	name:			"Connect Tech - WhiteHEAT",
 	id_table:		id_table_std,
-	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
@@ -160,7 +155,8 @@
 	unthrottle:		whiteheat_unthrottle,
 	ioctl:			whiteheat_ioctl,
 	set_termios:		whiteheat_set_termios,
-	shutdown:		whiteheat_shutdown,
+	startup:		whiteheat_real_startup,
+	shutdown:		whiteheat_real_shutdown,
 };
 
 struct whiteheat_private {
@@ -313,9 +309,7 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 	
-	if (!port->active) {
-		port->active = 1;
-
+	if (port->open_count == 1) {
 		/* set up some stuff for our command port */
 		command_port = &port->serial->port[COMMAND_PORT];
 		if (command_port->private == NULL) {
@@ -395,7 +389,7 @@
 		/* shutdown our bulk reads and writes */
 		usb_unlink_urb (port->write_urb);
 		usb_unlink_urb (port->read_urb);
-		port->active = 0;
+		port->open_count = 0;
 	}
 	MOD_DEC_USE_COUNT;
 	up (&port->sem);
@@ -539,7 +533,7 @@
  - device renumerated itself and comes up as new device id with all
    firmware download completed.
 */
-static int  whiteheat_startup (struct usb_serial *serial)
+static int  whiteheat_fake_startup (struct usb_serial *serial)
 {
 	int response;
 	const struct whiteheat_hex_record *record;
@@ -598,7 +592,66 @@
 }
 
 
-static void whiteheat_shutdown (struct usb_serial *serial)
+static int  whiteheat_real_startup (struct usb_serial *serial)
+{
+	struct whiteheat_hw_info *hw_info;
+	int pipe;
+	int ret;
+	int alen;
+	__u8 command[2] = { WHITEHEAT_GET_HW_INFO, 0 };
+	__u8 result[sizeof(*hw_info) + 1];
+
+	pipe = usb_rcvbulkpipe (serial->dev, 7);
+	usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, 2 * HZ);
+	/*
+	 * We ignore the return code. In the case where rmmod/insmod is
+	 * performed with a WhiteHEAT connected, the above times out
+	 * because the endpoint is already prepped, meaning the below succeeds
+	 * regardless. All other cases the above succeeds.
+	 */
+
+	pipe = usb_sndbulkpipe (serial->dev, 7);
+	ret = usb_bulk_msg (serial->dev, pipe, command, sizeof(command), &alen, 2 * HZ);
+	if (ret) {
+		err("%s: Couldn't send command [%d]", serial->type->name, ret);
+		goto error_out;
+	} else if (alen != sizeof(command)) {
+		err("%s: Send command incomplete [%d]", serial->type->name, alen);
+		goto error_out;
+	}
+
+	pipe = usb_rcvbulkpipe (serial->dev, 7);
+	ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(result), &alen, 2 * HZ);
+	if (ret) {
+		err("%s: Couldn't get results [%d]", serial->type->name, ret);
+		goto error_out;
+	} else if (alen != sizeof(result)) {
+		err("%s: Get results incomplete [%d]", serial->type->name, alen);
+		goto error_out;
+	} else if (result[0] != command[0]) {
+		err("%s: Command failed [%d]", serial->type->name, result[0]);
+		goto error_out;
+	}
+
+	hw_info = (struct whiteheat_hw_info *)&result[1];
+
+	info("%s: Driver %s: Firmware v%d.%02d", serial->type->name,
+	     DRIVER_VERSION, hw_info->sw_major_rev, hw_info->sw_minor_rev);
+
+	return 0;
+
+error_out:
+	err("%s: Unable to retrieve firmware version, try replugging\n", serial->type->name);
+	/*
+	 * Return that we've claimed the interface. A failure here may be
+	 * due to interception by the command_callback routine or other
+	 * causes that don't mean that the firmware isn't running. This may
+	 * change in the future. Probably should actually.
+	 */
+	return 0;
+}
+
+static void whiteheat_real_shutdown (struct usb_serial *serial)
 {
 	struct usb_serial_port 		*command_port;
 	int i;
@@ -660,7 +713,7 @@
 {
 	usb_serial_register (&whiteheat_fake_device);
 	usb_serial_register (&whiteheat_device);
-	info(DRIVER_VERSION ":" DRIVER_DESC);
+	info(DRIVER_DESC " " DRIVER_VERSION);
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/serial/whiteheat_fw.h linux/drivers/usb/serial/whiteheat_fw.h
--- v2.5.0/linux/drivers/usb/serial/whiteheat_fw.h	Mon Oct  9 14:25:56 2000
+++ linux/drivers/usb/serial/whiteheat_fw.h	Thu Nov 29 13:45:52 2001
@@ -47,28 +47,28 @@
 };
 
 static const struct whiteheat_hex_record whiteheat_firmware[] = {
-{ 0x0000,	3,	{0x02, 0x95, 0x09} },
+{ 0x0000,	3,	{0x02, 0x95, 0xe7} },
 { 0x0003,	3,	{0x02, 0x13, 0x12} },
-{ 0x000b,	3,	{0x02, 0x0a, 0x91} },
-{ 0x0033,	3,	{0x02, 0x08, 0x1b} },
+{ 0x000b,	3,	{0x02, 0x0b, 0xb5} },
+{ 0x0033,	3,	{0x02, 0x08, 0x18} },
 { 0x0043,	3,	{0x02, 0x0a, 0x00} },
-{ 0x005b,	3,	{0x02, 0x1a, 0xd2} },
+{ 0x005b,	3,	{0x02, 0x11, 0xdd} },
 { 0x0370,	16,	{0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x73, 0x14, 0x70, 0x03, 0x02, 0x04, 0xe7, 0x24} },
 { 0x0380,	16,	{0xfe, 0x70, 0x03, 0x02, 0x05, 0x4f, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x64, 0x14, 0x70, 0x03} },
 { 0x0390,	16,	{0x02, 0x04, 0x52, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x49, 0x24} },
 { 0x03a0,	16,	{0x05, 0x60, 0x03, 0x02, 0x05, 0x9e, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60} },
 { 0x03b0,	16,	{0x36, 0x24, 0x02, 0x70, 0x7b, 0x74, 0x12, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5} },
-{ 0x03c0,	16,	{0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x09, 0x81, 0xea, 0x49, 0x60, 0x0d} },
+{ 0x03c0,	16,	{0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0a, 0x99, 0xea, 0x49, 0x60, 0x0d} },
 { 0x03d0,	16,	{0xea, 0x90, 0x7f, 0xd4, 0xf0, 0xe9, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xb4} },
-{ 0x03e0,	16,	{0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x09, 0x40, 0xea} },
-{ 0x03f0,	16,	{0x49, 0x60, 0x33, 0x12, 0x9f, 0x48, 0xf5, 0x4b, 0x90, 0x7f, 0xee, 0xe0, 0xff, 0xe5, 0x4b, 0xd3} },
-{ 0x0400,	16,	{0x9f, 0x40, 0x03, 0xe0, 0xf5, 0x4b, 0xe5, 0x4b, 0xd3, 0x94, 0x40, 0x40, 0x03, 0x75, 0x4b, 0x40} },
-{ 0x0410,	16,	{0xae, 0x02, 0xaf, 0x01, 0x7c, 0x7f, 0x7d, 0x00, 0xab, 0x4b, 0x12, 0x8e, 0x81, 0x90, 0x7f, 0xb5} },
-{ 0x0420,	16,	{0xe5, 0x4b, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa5} },
+{ 0x03e0,	16,	{0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0a, 0x58, 0xea} },
+{ 0x03f0,	16,	{0x49, 0x60, 0x33, 0x12, 0xa0, 0x3f, 0xf5, 0x4c, 0x90, 0x7f, 0xee, 0xe0, 0xff, 0xe5, 0x4c, 0xd3} },
+{ 0x0400,	16,	{0x9f, 0x40, 0x03, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xd3, 0x94, 0x40, 0x40, 0x03, 0x75, 0x4c, 0x40} },
+{ 0x0410,	16,	{0xae, 0x02, 0xaf, 0x01, 0x7c, 0x7f, 0x7d, 0x00, 0xab, 0x4c, 0x12, 0x8f, 0x3b, 0x90, 0x7f, 0xb5} },
+{ 0x0420,	16,	{0xe5, 0x4c, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa5} },
 { 0x0430,	16,	{0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0x00, 0xe5, 0x21, 0xf0} },
 { 0x0440,	16,	{0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x21, 0x02} },
-{ 0x0450,	16,	{0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x31, 0xd2, 0x02, 0x43, 0x88, 0x10, 0xd2, 0xeb, 0xd2} },
-{ 0x0460,	16,	{0xa8, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0x00, 0xe5, 0x31, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0} },
+{ 0x0450,	16,	{0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x32, 0xd2, 0x02, 0x43, 0x88, 0x10, 0xd2, 0xeb, 0xd2} },
+{ 0x0460,	16,	{0xa8, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0x00, 0xe5, 0x32, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0} },
 { 0x0470,	16,	{0x02, 0x05, 0xa5, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02} },
 { 0x0480,	16,	{0x70, 0x5b, 0xa2, 0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x05, 0xe4, 0x33, 0x4f, 0x90} },
 { 0x0490,	16,	{0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa5, 0xe4} },
@@ -79,8 +79,8 @@
 { 0x04e0,	16,	{0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24} },
 { 0x04f0,	16,	{0x02, 0x60, 0x03, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02} },
 { 0x0500,	16,	{0x05, 0xa5, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa5, 0x90, 0x7f, 0xea, 0xe0} },
-{ 0x0510,	16,	{0x70, 0x34, 0x90, 0x7f, 0xec, 0xe0, 0xff, 0x54, 0x07, 0xfe, 0xf5, 0x4b, 0xef, 0x30, 0xe7, 0x03} },
-{ 0x0520,	16,	{0x43, 0x4b, 0x10, 0x90, 0x7f, 0xd7, 0xe5, 0x4b, 0xf0, 0xe5, 0x4b, 0x44, 0x20, 0xf0, 0xef, 0xf4} },
+{ 0x0510,	16,	{0x70, 0x34, 0x90, 0x7f, 0xec, 0xe0, 0xff, 0x54, 0x07, 0xfe, 0xf5, 0x4c, 0xef, 0x30, 0xe7, 0x03} },
+{ 0x0520,	16,	{0x43, 0x4c, 0x10, 0x90, 0x7f, 0xd7, 0xe5, 0x4c, 0xf0, 0xe5, 0x4c, 0x44, 0x20, 0xf0, 0xef, 0xf4} },
 { 0x0530,	16,	{0x54, 0x80, 0xfd, 0xc4, 0x54, 0x0f, 0x2e, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} },
 { 0x0540,	16,	{0xf5, 0x83, 0xe4, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x56, 0x90} },
 { 0x0550,	16,	{0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea, 0xe0, 0xb4} },
@@ -90,229 +90,226 @@
 { 0x0590,	16,	{0x74, 0x01, 0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f} },
 { 0x05a0,	12,	{0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} },
 { 0x05ac,	1,	{0x22} },
-{ 0x05ad,	16,	{0x75, 0x47, 0xff, 0x75, 0x46, 0xff, 0x75, 0x45, 0x0f, 0x75, 0x44, 0x00, 0xd2, 0x03, 0xc2, 0x06} },
+{ 0x05ad,	16,	{0x75, 0x48, 0xff, 0x75, 0x47, 0xff, 0x75, 0x46, 0x0f, 0x75, 0x45, 0x00, 0xd2, 0x03, 0xc2, 0x06} },
 { 0x05bd,	16,	{0xc2, 0x02, 0xc2, 0x00, 0xc2, 0x05, 0xc2, 0x01, 0x90, 0x03, 0x00, 0x74, 0x19, 0xf0, 0xe4, 0x90} },
 { 0x05cd,	16,	{0x01, 0xbc, 0xf0, 0xc2, 0x04, 0x90, 0x01, 0xc0, 0xf0, 0xa3, 0xf0, 0xc2, 0xaf, 0xc2, 0xa8, 0x12} },
-{ 0x05dd,	16,	{0x0b, 0x8d, 0xe4, 0x90, 0x02, 0xaf, 0xf0, 0x90, 0x01, 0x00, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x05dd,	16,	{0x0c, 0x22, 0xe4, 0x90, 0x02, 0xaf, 0xf0, 0x90, 0x01, 0x00, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
 { 0x05ed,	16,	{0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0x7e} },
-{ 0x05fd,	16,	{0x01, 0x7f, 0x00, 0x12, 0x10, 0x2c, 0x75, 0x49, 0x12, 0x75, 0x4a, 0x0a, 0x90, 0x01, 0x0b, 0xe0} },
-{ 0x060d,	16,	{0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14, 0xf5, 0x82, 0x8c, 0x83} },
-{ 0x061d,	16,	{0xef, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x80, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70} },
-{ 0x062d,	16,	{0x02, 0x05, 0x49, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0d, 0xe0, 0xff, 0x05} },
-{ 0x063d,	16,	{0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
-{ 0x064d,	16,	{0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14} },
+{ 0x05fd,	16,	{0x01, 0x7f, 0x00, 0x12, 0x19, 0xc1, 0x75, 0x4a, 0x12, 0x75, 0x4b, 0x0a, 0x90, 0x01, 0x0b, 0xe0} },
+{ 0x060d,	16,	{0xff, 0x05, 0x4b, 0xe5, 0x4b, 0xac, 0x4a, 0x70, 0x02, 0x05, 0x4a, 0x14, 0xf5, 0x82, 0x8c, 0x83} },
+{ 0x061d,	16,	{0xef, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x80, 0xff, 0x05, 0x4b, 0xe5, 0x4b, 0xac, 0x4a, 0x70} },
+{ 0x062d,	16,	{0x02, 0x05, 0x4a, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0d, 0xe0, 0xff, 0x05} },
+{ 0x063d,	16,	{0x4b, 0xe5, 0x4b, 0xac, 0x4a, 0x70, 0x02, 0x05, 0x4a, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
+{ 0x064d,	16,	{0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x4b, 0xe5, 0x4b, 0xac, 0x4a, 0x70, 0x02, 0x05, 0x4a, 0x14} },
 { 0x065d,	16,	{0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x12, 0x0a, 0xe4, 0x93, 0xff, 0x74, 0x01, 0x93, 0x90} },
 { 0x066d,	16,	{0x01, 0x1c, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0xff, 0xa3, 0xe0, 0xfe, 0xef} },
 { 0x067d,	16,	{0x6e, 0xff, 0x90, 0x01, 0x1c, 0xf0, 0xa3, 0xe0, 0x6f, 0xff, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0x6f} },
-{ 0x068d,	16,	{0xf0, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe4, 0xfc, 0xfd, 0x75, 0x4f, 0x10, 0x75, 0x50, 0x02, 0x75} },
-{ 0x069d,	16,	{0x51, 0x12, 0x75, 0x52, 0xac, 0x12, 0x91, 0x7a, 0x75, 0x49, 0x12, 0x75, 0x4a, 0xb2, 0x90, 0x01} },
-{ 0x06ad,	16,	{0x0d, 0xe0, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14, 0xf5, 0x82} },
-{ 0x06bd,	16,	{0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70} },
-{ 0x06cd,	16,	{0x02, 0x05, 0x49, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4} },
-{ 0x06dd,	16,	{0x54, 0x0f, 0x24, 0x41, 0xff, 0x05, 0x4a, 0xe5, 0x4a, 0xac, 0x49, 0x70, 0x02, 0x05, 0x49, 0x14} },
-{ 0x06ed,	16,	{0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x05, 0x4a, 0xe5, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x05, 0x49} },
+{ 0x068d,	16,	{0xf0, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe4, 0xfc, 0xfd, 0x75, 0x50, 0x10, 0x75, 0x51, 0x02, 0x75} },
+{ 0x069d,	16,	{0x52, 0x12, 0x75, 0x53, 0xac, 0x12, 0x92, 0x2a, 0x75, 0x4a, 0x12, 0x75, 0x4b, 0xb2, 0x90, 0x01} },
+{ 0x06ad,	16,	{0x0d, 0xe0, 0xff, 0x05, 0x4b, 0xe5, 0x4b, 0xac, 0x4a, 0x70, 0x02, 0x05, 0x4a, 0x14, 0xf5, 0x82} },
+{ 0x06bd,	16,	{0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x4b, 0xe5, 0x4b, 0xac, 0x4a, 0x70} },
+{ 0x06cd,	16,	{0x02, 0x05, 0x4a, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4} },
+{ 0x06dd,	16,	{0x54, 0x0f, 0x24, 0x41, 0xff, 0x05, 0x4b, 0xe5, 0x4b, 0xac, 0x4a, 0x70, 0x02, 0x05, 0x4a, 0x14} },
+{ 0x06ed,	16,	{0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x05, 0x4b, 0xe5, 0x4b, 0xae, 0x4a, 0x70, 0x02, 0x05, 0x4a} },
 { 0x06fd,	16,	{0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x75, 0x82, 0x10, 0x75, 0x83, 0x01, 0xe0, 0xfc, 0xa3} },
-{ 0x070d,	16,	{0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x01, 0x18, 0x12, 0xa0, 0xfb, 0x7e, 0x01} },
-{ 0x071d,	16,	{0x7f, 0x18, 0x12, 0x85, 0x2f, 0x90, 0x01, 0x18, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} },
-{ 0x072d,	16,	{0xa3, 0xe0, 0xff, 0x75, 0x4f, 0x0a, 0x75, 0x50, 0x06, 0x75, 0x51, 0x12, 0x75, 0x52, 0xb8, 0x12} },
-{ 0x073d,	16,	{0x91, 0x7a, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x53, 0x91, 0xef} },
+{ 0x070d,	16,	{0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x01, 0x18, 0x12, 0xa1, 0xf2, 0x7e, 0x01} },
+{ 0x071d,	16,	{0x7f, 0x18, 0x12, 0x85, 0xcf, 0x90, 0x01, 0x18, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} },
+{ 0x072d,	16,	{0xa3, 0xe0, 0xff, 0x75, 0x50, 0x0a, 0x75, 0x51, 0x06, 0x75, 0x52, 0x12, 0x75, 0x53, 0xb8, 0x12} },
+{ 0x073d,	16,	{0x92, 0x2a, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x53, 0x91, 0xef} },
 { 0x074d,	16,	{0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0x44, 0x1f, 0xf0, 0xd2, 0xaf} },
-{ 0x075d,	16,	{0x20, 0x01, 0x2e, 0x20, 0x01, 0x2b, 0xa2, 0x03, 0x92, 0x07, 0x12, 0x09, 0xd0, 0x75, 0x43, 0x50} },
-{ 0x076d,	16,	{0x75, 0x42, 0x6d, 0x75, 0x41, 0x33, 0x75, 0x40, 0x00, 0x20, 0x01, 0xe4, 0x7f, 0xff, 0x7e, 0xff} },
-{ 0x077d,	16,	{0x7d, 0xff, 0x7c, 0xff, 0x78, 0x40, 0x12, 0xa0, 0xe4, 0xec, 0x4d, 0x4e, 0x4f, 0x60, 0xd1, 0x80} },
-{ 0x078d,	16,	{0xe8, 0x30, 0x01, 0x05, 0x12, 0x03, 0x70, 0xc2, 0x01, 0x30, 0x06, 0x0d, 0x12, 0x09, 0xf5, 0x50} },
-{ 0x079d,	16,	{0x06, 0x12, 0x0b, 0x00, 0x12, 0x09, 0xfa, 0xc2, 0x06, 0x12, 0x93, 0x98, 0x90, 0x01, 0xbd, 0xe0} },
-{ 0x07ad,	16,	{0x60, 0x0c, 0x12, 0x8f, 0x55, 0xe4, 0x90, 0x01, 0xbd, 0xf0, 0x90, 0x7f, 0xd3, 0xf0, 0x90, 0x02} },
-{ 0x07bd,	16,	{0xaf, 0xe0, 0xb4, 0x0f, 0x03, 0x12, 0x96, 0xe2, 0x12, 0x9d, 0xa2, 0xe4, 0xff, 0x74, 0x01, 0xa8} },
-{ 0x07cd,	16,	{0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x90, 0x01, 0xbc, 0xe0, 0x5e, 0x60, 0x14} },
-{ 0x07dd,	16,	{0x74, 0x27, 0x2f, 0xf8, 0xe6, 0xd3, 0x94, 0x0a, 0x40, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00} },
-{ 0x07ed,	16,	{0x8e, 0x48, 0x80, 0x03, 0x75, 0x48, 0x01, 0x74, 0x68, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5} },
-{ 0x07fd,	16,	{0x83, 0xe5, 0x48, 0xf0, 0x0f, 0xbf, 0x04, 0xc5, 0xe5, 0x2b, 0xd3, 0x94, 0x0a, 0x40, 0x04, 0x7f} },
-{ 0x080d,	13,	{0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x20, 0x6c, 0xef, 0xf0, 0x02, 0x07, 0x8e} },
-{ 0x081a,	1,	{0x22} },
-{ 0x081b,	4,	{0x53, 0xd8, 0xef, 0x32} },
-{ 0x081f,	16,	{0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x09, 0x29, 0x90, 0x7f, 0x96, 0x74, 0x89} },
-{ 0x082f,	16,	{0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x09, 0x29, 0x90, 0x7f} },
-{ 0x083f,	16,	{0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x7f, 0x02, 0x7d, 0xff} },
-{ 0x084f,	16,	{0x12, 0x11, 0x77, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02} },
-{ 0x085f,	16,	{0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x90, 0x7f, 0x96, 0xe0} },
-{ 0x086f,	16,	{0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf} },
-{ 0x087f,	16,	{0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f} },
-{ 0x088f,	7,	{0x32, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x22} },
-{ 0x0896,	16,	{0x90, 0x7f, 0x96, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x80, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12} },
-{ 0x08a6,	16,	{0x09, 0x29, 0x7f, 0x02, 0xe4, 0xfd, 0x12, 0x11, 0x77, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29} },
-{ 0x08b6,	16,	{0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x90, 0x7f} },
-{ 0x08c6,	16,	{0x96, 0xe0, 0x44, 0x04, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x90, 0x7f, 0x96, 0xe0} },
-{ 0x08d6,	16,	{0x54, 0xf7, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x01} },
-{ 0x08e6,	12,	{0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x12, 0x0b, 0x00, 0x22} },
-{ 0x08f2,	16,	{0x90, 0x95, 0xbe, 0xe4, 0x93, 0x70, 0x2f, 0x90, 0x7f, 0x93, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x94} },
-{ 0x0902,	16,	{0x74, 0x3c, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0xc6, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90, 0x7f} },
-{ 0x0912,	16,	{0x9d, 0x74, 0x02, 0xf0, 0x90, 0x7f, 0xe2, 0x74, 0x12, 0xf0, 0x12, 0x08, 0x1f, 0x75, 0x82, 0xbe} },
-{ 0x0922,	7,	{0x75, 0x83, 0x95, 0x74, 0xff, 0xf0, 0x22} },
-{ 0x0929,	16,	{0x8e, 0x58, 0x8f, 0x59, 0xe5, 0x59, 0x15, 0x59, 0xae, 0x58, 0x70, 0x02, 0x15, 0x58, 0x4e, 0x60} },
-{ 0x0939,	7,	{0x05, 0x12, 0x0a, 0x58, 0x80, 0xee, 0x22} },
-{ 0x0940,	2,	{0x8f, 0x4c} },
-{ 0x0942,	16,	{0xe4, 0xf5, 0x4d, 0x75, 0x4e, 0xff, 0x75, 0x4f, 0x12, 0x75, 0x50, 0x6a, 0xab, 0x4e, 0xaa, 0x4f} },
-{ 0x0952,	16,	{0xa9, 0x50, 0x90, 0x00, 0x01, 0x12, 0x9f, 0x61, 0xb4, 0x03, 0x1d, 0xaf, 0x4d, 0x05, 0x4d, 0xef} },
-{ 0x0962,	16,	{0xb5, 0x4c, 0x01, 0x22, 0x12, 0x9f, 0x48, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
-{ 0x0972,	14,	{0x4e, 0xff, 0xf5, 0x4f, 0x89, 0x50, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
-{ 0x0980,	1,	{0x22} },
-{ 0x0981,	16,	{0xe4, 0xfe, 0x75, 0x4e, 0xff, 0x75, 0x4f, 0x12, 0x75, 0x50, 0x12, 0xab, 0x4e, 0xaa, 0x4f, 0xa9} },
-{ 0x0991,	16,	{0x50, 0x90, 0x00, 0x01, 0x12, 0x9f, 0x61, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} },
-{ 0x09a1,	16,	{0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x9f, 0xba, 0x85, 0xf0, 0x4c, 0xf5, 0x4d, 0x62, 0x4c} },
-{ 0x09b1,	16,	{0xe5, 0x4c, 0x62, 0x4d, 0xe5, 0x4d, 0x62, 0x4c, 0x29, 0xfd, 0xe5, 0x4c, 0x3a, 0xa9, 0x05, 0x75} },
-{ 0x09c1,	14,	{0x4e, 0xff, 0xf5, 0x4f, 0x89, 0x50, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
-{ 0x09cf,	1,	{0x22} },
-{ 0x09d0,	16,	{0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x07, 0x04, 0xe0, 0x44} },
-{ 0x09e0,	16,	{0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x09, 0x29, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
-{ 0x09f0,	5,	{0xe0, 0x44, 0x04, 0xf0, 0x22} },
-{ 0x09f5,	5,	{0x12, 0x08, 0x96, 0xd3, 0x22} },
-{ 0x09fa,	5,	{0x12, 0x08, 0x1f, 0xd3, 0x22} },
+{ 0x075d,	16,	{0x20, 0x01, 0x2e, 0x20, 0x01, 0x2b, 0xa2, 0x03, 0x92, 0x07, 0x12, 0x09, 0xc1, 0x75, 0x44, 0x50} },
+{ 0x076d,	16,	{0x75, 0x43, 0x6d, 0x75, 0x42, 0x33, 0x75, 0x41, 0x00, 0x20, 0x01, 0xe4, 0x7f, 0xff, 0x7e, 0xff} },
+{ 0x077d,	16,	{0x7d, 0xff, 0x7c, 0xff, 0x78, 0x41, 0x12, 0xa1, 0xdb, 0xec, 0x4d, 0x4e, 0x4f, 0x60, 0xd1, 0x80} },
+{ 0x078d,	16,	{0xe8, 0x30, 0x01, 0x05, 0x12, 0x03, 0x70, 0xc2, 0x01, 0x30, 0x06, 0x0a, 0x12, 0x09, 0xf7, 0x50} },
+{ 0x079d,	16,	{0x03, 0x12, 0x0a, 0xe8, 0xc2, 0x06, 0x12, 0x94, 0x62, 0x90, 0x01, 0xbd, 0xe0, 0x60, 0x0c, 0x12} },
+{ 0x07ad,	16,	{0x90, 0x05, 0xe4, 0x90, 0x01, 0xbd, 0xf0, 0x90, 0x7f, 0xd3, 0xf0, 0x90, 0x02, 0xaf, 0xe0, 0xb4} },
+{ 0x07bd,	16,	{0x0f, 0x03, 0x12, 0x97, 0xbd, 0x12, 0x9e, 0x99, 0xe4, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80} },
+{ 0x07cd,	16,	{0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x90, 0x01, 0xbc, 0xe0, 0x5e, 0x60, 0x14, 0x74, 0x27, 0x2f} },
+{ 0x07dd,	16,	{0xf8, 0xe6, 0xd3, 0x94, 0x0a, 0x40, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0x8e, 0x49, 0x80} },
+{ 0x07ed,	16,	{0x03, 0x75, 0x49, 0x01, 0x74, 0x68, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe5, 0x49} },
+{ 0x07fd,	16,	{0xf0, 0x0f, 0xbf, 0x04, 0xc5, 0xe5, 0x2b, 0xd3, 0x94, 0x0a, 0x40, 0x04, 0x7f, 0x01, 0x80, 0x02} },
+{ 0x080d,	10,	{0x7f, 0x00, 0x90, 0x20, 0x6c, 0xef, 0xf0, 0x02, 0x07, 0x8e} },
+{ 0x0817,	1,	{0x22} },
+{ 0x0818,	4,	{0x53, 0xd8, 0xef, 0x32} },
+{ 0x081c,	16,	{0xe5, 0x30, 0xc3, 0x94, 0x01, 0x40, 0x0e, 0x90, 0x7f, 0x93, 0xe0, 0x44, 0x30, 0xf0, 0x90, 0x7f} },
+{ 0x082c,	16,	{0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0} },
+{ 0x083c,	16,	{0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x08} },
+{ 0x084c,	16,	{0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xfb, 0xf0, 0x7f} },
+{ 0x085c,	16,	{0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0xe5, 0x30, 0xc3, 0x94, 0x01, 0x50, 0x0e, 0x7f, 0x02, 0x7d} },
+{ 0x086c,	16,	{0xff, 0x12, 0x82, 0xa8, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x44} },
+{ 0x087c,	16,	{0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96} },
+{ 0x088c,	16,	{0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x54} },
+{ 0x089c,	16,	{0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0} },
+{ 0x08ac,	8,	{0x7f, 0x32, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x22} },
+{ 0x08b4,	16,	{0x90, 0x7f, 0x96, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x80, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12} },
+{ 0x08c4,	16,	{0x09, 0xaa, 0xe5, 0x30, 0xc3, 0x94, 0x01, 0x50, 0x0e, 0x7f, 0x02, 0xe4, 0xfd, 0x12, 0x82, 0xa8} },
+{ 0x08d4,	16,	{0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x05} },
+{ 0x08e4,	16,	{0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x04, 0xf0, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x08f4,	16,	{0x12, 0x09, 0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xf7, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09} },
+{ 0x0904,	16,	{0xaa, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0xe5} },
+{ 0x0914,	16,	{0x30, 0xc3, 0x94, 0x01, 0x40, 0x0e, 0x90, 0x7f, 0x93, 0xe0, 0x54, 0xcf, 0xf0, 0x90, 0x7f, 0x95} },
+{ 0x0924,	8,	{0xe0, 0x54, 0x3f, 0xf0, 0x12, 0x0b, 0x00, 0x22} },
+{ 0x092c,	16,	{0x90, 0x0a, 0xf0, 0xe4, 0x93, 0x70, 0x76, 0x90, 0x7f, 0x93, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x94} },
+{ 0x093c,	16,	{0x74, 0x3c, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0xc6, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x09, 0xaa} },
+{ 0x094c,	16,	{0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x90, 0x7f, 0x96, 0x74, 0x08, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf} },
+{ 0x095c,	16,	{0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x20, 0x70, 0xe0, 0xff, 0xc4, 0x54, 0x0f} },
+{ 0x096c,	16,	{0xf5, 0x30, 0xc3, 0x94, 0x01, 0x50, 0x07, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x80, 0xf0, 0xe4, 0x90} },
+{ 0x097c,	16,	{0x7f, 0x97, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0x02, 0xf0, 0xe5, 0x30, 0xc3, 0x94, 0x01, 0x40, 0x0b} },
+{ 0x098c,	16,	{0xe4, 0x90, 0x7f, 0x98, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0xc0, 0xf0, 0x90, 0x7f, 0xe2, 0x74, 0x12} },
+{ 0x099c,	14,	{0xf0, 0x12, 0x08, 0x1c, 0x75, 0x82, 0xf0, 0x75, 0x83, 0x0a, 0x74, 0xff, 0xf0, 0x22} },
+{ 0x09aa,	16,	{0x8e, 0x5b, 0x8f, 0x5c, 0xe5, 0x5c, 0x15, 0x5c, 0xae, 0x5b, 0x70, 0x02, 0x15, 0x5b, 0x4e, 0x60} },
+{ 0x09ba,	7,	{0x05, 0x12, 0x09, 0xe6, 0x80, 0xee, 0x22} },
+{ 0x09c1,	16,	{0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x07, 0x04, 0xe0, 0x44} },
+{ 0x09d1,	16,	{0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
+{ 0x09e1,	5,	{0xe0, 0x44, 0x04, 0xf0, 0x22} },
+{ 0x09e6,	16,	{0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
+{ 0x09f6,	1,	{0x22} },
+{ 0x09f7,	5,	{0x12, 0x08, 0xb4, 0xd3, 0x22} },
+{ 0x09fc,	1,	{0x32} },
+{ 0x09fd,	1,	{0x32} },
+{ 0x09fe,	1,	{0x32} },
 { 0x09ff,	1,	{0x32} },
-{ 0x0a00,	16,	{0x02, 0x0b, 0xaa, 0x00, 0x02, 0x0b, 0xdd, 0x00, 0x02, 0x0b, 0xc2, 0x00, 0x02, 0x0c, 0x1c, 0x00} },
-{ 0x0a10,	16,	{0x02, 0x0c, 0x06, 0x00, 0x02, 0x09, 0xff, 0x00, 0x02, 0x0a, 0xfe, 0x00, 0x02, 0x0a, 0xff, 0x00} },
-{ 0x0a20,	16,	{0x02, 0x0c, 0x37, 0x00, 0x02, 0x0d, 0x29, 0x00, 0x02, 0x0c, 0x73, 0x00, 0x02, 0x0d, 0x7d, 0x00} },
-{ 0x0a30,	16,	{0x02, 0x0c, 0xaf, 0x00, 0x02, 0x0d, 0xd1, 0x00, 0x02, 0x0c, 0xeb, 0x00, 0x02, 0x0e, 0x25, 0x00} },
-{ 0x0a40,	16,	{0x02, 0x0d, 0x27, 0x00, 0x02, 0x0e, 0x79, 0x00, 0x02, 0x0d, 0x28, 0x00, 0x02, 0x0e, 0x7a, 0x00} },
-{ 0x0a50,	8,	{0x02, 0x0e, 0x7b, 0x00, 0x02, 0x0e, 0x91, 0x00} },
-{ 0x0a58,	16,	{0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
-{ 0x0a68,	1,	{0x22} },
-{ 0x0a69,	16,	{0x53, 0x8e, 0xf7, 0xe5, 0x89, 0x54, 0xf1, 0x44, 0x01, 0xf5, 0x89, 0x75, 0x8c, 0xb1, 0xd2, 0xa9} },
-{ 0x0a79,	16,	{0x75, 0x98, 0x40, 0x75, 0xcb, 0xff, 0x75, 0xca, 0xf3, 0x75, 0xc8, 0x34, 0xe4, 0xff, 0x7f, 0x05} },
-{ 0x0a89,	7,	{0x78, 0x27, 0xe4, 0xf6, 0x08, 0xdf, 0xfc} },
-{ 0x0a90,	1,	{0x22} },
-{ 0x0a91,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x06, 0xc0} },
-{ 0x0aa1,	1,	{0x07} },
-{ 0x0aa2,	16,	{0x30, 0x04, 0x16, 0x75, 0x8c, 0xf8, 0x75, 0x8a, 0x30, 0x7f, 0x2f, 0xae, 0x07, 0x1f, 0xee, 0x60} },
-{ 0x0ab2,	16,	{0x3c, 0x90, 0x20, 0x00, 0x74, 0x55, 0xf0, 0x80, 0xf2, 0x75, 0x8c, 0xb1, 0x7f, 0x27, 0xef, 0xd3} },
-{ 0x0ac2,	16,	{0x94, 0x2b, 0x50, 0x09, 0xa8, 0x07, 0xe6, 0x60, 0x01, 0x16, 0x0f, 0x80, 0xf1, 0x90, 0x03, 0x00} },
-{ 0x0ad2,	16,	{0xe0, 0x60, 0x02, 0x14, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x0e, 0x90} },
-{ 0x0ae2,	13,	{0x01, 0xc1, 0xe0, 0x24, 0xff, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x34, 0xff, 0xf0} },
-{ 0x0aef,	15,	{0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0afe,	1,	{0x32} },
-{ 0x0aff,	1,	{0x32} },
+{ 0x0a00,	16,	{0x02, 0x0c, 0x4e, 0x00, 0x02, 0x0c, 0x81, 0x00, 0x02, 0x0c, 0x66, 0x00, 0x02, 0x0c, 0xc0, 0x00} },
+{ 0x0a10,	16,	{0x02, 0x0c, 0xaa, 0x00, 0x02, 0x09, 0xfc, 0x00, 0x02, 0x09, 0xfd, 0x00, 0x02, 0x09, 0xfe, 0x00} },
+{ 0x0a20,	16,	{0x02, 0x0c, 0xdb, 0x00, 0x02, 0x0d, 0xcb, 0x00, 0x02, 0x0d, 0x17, 0x00, 0x02, 0x0e, 0x1f, 0x00} },
+{ 0x0a30,	16,	{0x02, 0x0d, 0x53, 0x00, 0x02, 0x0e, 0x73, 0x00, 0x02, 0x0d, 0x8f, 0x00, 0x02, 0x0e, 0xc7, 0x00} },
+{ 0x0a40,	16,	{0x02, 0x09, 0xff, 0x00, 0x02, 0x0a, 0xee, 0x00, 0x02, 0x0a, 0xed, 0x00, 0x02, 0x0a, 0xef, 0x00} },
+{ 0x0a50,	8,	{0x02, 0x0f, 0x1b, 0x00, 0x02, 0x0f, 0x31, 0x00} },
+{ 0x0a58,	2,	{0x8f, 0x4d} },
+{ 0x0a5a,	16,	{0xe4, 0xf5, 0x4e, 0x75, 0x4f, 0xff, 0x75, 0x50, 0x12, 0x75, 0x51, 0x6a, 0xab, 0x4f, 0xaa, 0x50} },
+{ 0x0a6a,	16,	{0xa9, 0x51, 0x90, 0x00, 0x01, 0x12, 0xa0, 0x58, 0xb4, 0x03, 0x1d, 0xaf, 0x4e, 0x05, 0x4e, 0xef} },
+{ 0x0a7a,	16,	{0xb5, 0x4d, 0x01, 0x22, 0x12, 0xa0, 0x3f, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
+{ 0x0a8a,	14,	{0x4f, 0xff, 0xf5, 0x50, 0x89, 0x51, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x0a98,	1,	{0x22} },
+{ 0x0a99,	16,	{0xe4, 0xfe, 0x75, 0x4f, 0xff, 0x75, 0x50, 0x12, 0x75, 0x51, 0x12, 0xab, 0x4f, 0xaa, 0x50, 0xa9} },
+{ 0x0aa9,	16,	{0x51, 0x90, 0x00, 0x01, 0x12, 0xa0, 0x58, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} },
+{ 0x0ab9,	16,	{0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0xa0, 0xb1, 0x85, 0xf0, 0x4d, 0xf5, 0x4e, 0x62, 0x4d} },
+{ 0x0ac9,	16,	{0xe5, 0x4d, 0x62, 0x4e, 0xe5, 0x4e, 0x62, 0x4d, 0x29, 0xfd, 0xe5, 0x4d, 0x3a, 0xa9, 0x05, 0x75} },
+{ 0x0ad9,	14,	{0x4f, 0xff, 0xf5, 0x50, 0x89, 0x51, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x0ae7,	1,	{0x22} },
+{ 0x0ae8,	5,	{0x12, 0x08, 0x1c, 0xd3, 0x22} },
+{ 0x0aed,	1,	{0x32} },
+{ 0x0aee,	1,	{0x32} },
+{ 0x0aef,	1,	{0x32} },
+{ 0x0af0,	3,	{0x00, 0x04, 0x00} },
 { 0x0b00,	9,	{0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} },
 { 0x0b7d,	16,	{0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} },
-{ 0x0b8d,	16,	{0xd2, 0x00, 0x75, 0x8e, 0x10, 0xe4, 0x90, 0x7f, 0x92, 0xf0, 0x12, 0x80, 0x00, 0x12, 0x08, 0xf2} },
-{ 0x0b9d,	13,	{0x12, 0x0e, 0xad, 0x12, 0x11, 0xe5, 0x12, 0x11, 0xc8, 0x12, 0x0a, 0x69, 0x22} },
-{ 0x0baa,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} },
-{ 0x0bba,	8,	{0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0bc2,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
-{ 0x0bd2,	11,	{0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0bdd,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0x90} },
-{ 0x0bed,	16,	{0x7f, 0xd8, 0xe0, 0x70, 0x0d, 0x90, 0x7f, 0xd9, 0xe0, 0x70, 0x07, 0xe5, 0x2b, 0x70, 0x03, 0x75} },
-{ 0x0bfd,	9,	{0x2b, 0x14, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0c06,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} },
-{ 0x0c16,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0c1c,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x30, 0x02, 0x02, 0xd2, 0x06, 0x53, 0x91, 0xef, 0x90, 0x7f} },
-{ 0x0c2c,	11,	{0xab, 0x74, 0x08, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0c37,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} },
-{ 0x0c47,	16,	{0xa9, 0x74, 0x02, 0xf0, 0xe5, 0x30, 0x30, 0xe0, 0x13, 0xe5, 0x3b, 0x30, 0xe0, 0x07, 0x90, 0x20} },
-{ 0x0c57,	16,	{0x04, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} },
-{ 0x0c67,	12,	{0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0c73,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} },
-{ 0x0c83,	16,	{0xa9, 0x74, 0x04, 0xf0, 0xe5, 0x30, 0x30, 0xe1, 0x13, 0xe5, 0x3b, 0x30, 0xe1, 0x07, 0x90, 0x20} },
-{ 0x0c93,	16,	{0x0c, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} },
-{ 0x0ca3,	12,	{0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0caf,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} },
-{ 0x0cbf,	16,	{0xa9, 0x74, 0x08, 0xf0, 0xe5, 0x30, 0x30, 0xe2, 0x13, 0xe5, 0x3b, 0x30, 0xe2, 0x07, 0x90, 0x20} },
-{ 0x0ccf,	16,	{0x14, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} },
-{ 0x0cdf,	12,	{0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0ceb,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} },
-{ 0x0cfb,	16,	{0xa9, 0x74, 0x10, 0xf0, 0xe5, 0x30, 0x30, 0xe3, 0x13, 0xe5, 0x3b, 0x30, 0xe3, 0x07, 0x90, 0x20} },
-{ 0x0d0b,	16,	{0x1c, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} },
-{ 0x0d1b,	12,	{0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0d27,	1,	{0x32} },
-{ 0x0d28,	1,	{0x32} },
-{ 0x0d29,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
-{ 0x0d39,	16,	{0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x02, 0xf0, 0xe5, 0x30, 0x20} },
-{ 0x0d49,	16,	{0xe0, 0x06, 0x90, 0x7f, 0xc7, 0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x90, 0x7f, 0xc7} },
-{ 0x0d59,	16,	{0xe0, 0x90, 0x02, 0xf8, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} },
-{ 0x0d69,	16,	{0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} },
-{ 0x0d79,	4,	{0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0d7d,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
-{ 0x0d8d,	16,	{0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x04, 0xf0, 0xe5, 0x30, 0x20} },
-{ 0x0d9d,	16,	{0xe1, 0x06, 0x90, 0x7f, 0xc9, 0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x90, 0x7f, 0xc9} },
-{ 0x0dad,	16,	{0xe0, 0x90, 0x02, 0xf9, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} },
-{ 0x0dbd,	16,	{0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} },
-{ 0x0dcd,	4,	{0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0dd1,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
-{ 0x0de1,	16,	{0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x08, 0xf0, 0xe5, 0x30, 0x20} },
-{ 0x0df1,	16,	{0xe2, 0x06, 0x90, 0x7f, 0xcb, 0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x90, 0x7f, 0xcb} },
-{ 0x0e01,	16,	{0xe0, 0x90, 0x02, 0xfa, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} },
-{ 0x0e11,	16,	{0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} },
-{ 0x0e21,	4,	{0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0e25,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
-{ 0x0e35,	16,	{0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x10, 0xf0, 0xe5, 0x30, 0x20} },
-{ 0x0e45,	16,	{0xe3, 0x06, 0x90, 0x7f, 0xcd, 0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x90, 0x7f, 0xcd} },
-{ 0x0e55,	16,	{0xe0, 0x90, 0x02, 0xfb, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} },
-{ 0x0e65,	16,	{0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} },
-{ 0x0e75,	4,	{0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0e79,	1,	{0x32} },
-{ 0x0e7a,	1,	{0x32} },
-{ 0x0e7b,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x80, 0xf0, 0xd0} },
-{ 0x0e8b,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0e91,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x80, 0xf0, 0x90} },
-{ 0x0ea1,	12,	{0x01, 0xbd, 0x74, 0xff, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x0ead,	16,	{0x90, 0x01, 0x20, 0x12, 0xa1, 0x07, 0x00, 0x00, 0x25, 0x80, 0x90, 0x01, 0x24, 0x74, 0x08, 0xf0} },
-{ 0x0ebd,	16,	{0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x6e, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x13, 0xf0, 0xa3, 0x74} },
-{ 0x0ecd,	16,	{0x11, 0xf0, 0xe4, 0xa3, 0xf0, 0xa3, 0xf0, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff} },
-{ 0x0edd,	16,	{0x04, 0xa3, 0xf0, 0xef, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x01, 0xf9, 0x74, 0x03, 0x35, 0xf0, 0xa8} },
-{ 0x0eed,	16,	{0x01, 0xfc, 0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x01, 0x79, 0x1f, 0x7e, 0x00, 0x7f, 0x0d, 0x12, 0x9f} },
-{ 0x0efd,	16,	{0x1f, 0x7e, 0x01, 0x7f, 0x1f, 0x12, 0x86, 0x17, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0xe0, 0xc3} },
-{ 0x0f0d,	16,	{0x94, 0x04, 0x40, 0xc7, 0xe4, 0xf5, 0x26, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff} },
-{ 0x0f1d,	16,	{0xc3, 0x94, 0x04, 0x50, 0x1a, 0x74, 0xf8, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4} },
-{ 0x0f2d,	16,	{0xf0, 0x74, 0x22, 0x2f, 0xf8, 0xe4, 0xf6, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0xe4} },
-{ 0x0f3d,	16,	{0xf5, 0x30, 0xe5, 0xc0, 0x60, 0x2f, 0x90, 0x01, 0x1e, 0x74, 0x01, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
-{ 0x0f4d,	16,	{0xff, 0xd3, 0x94, 0x04, 0x50, 0x1f, 0xef, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02} },
-{ 0x0f5d,	16,	{0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x30, 0x7e, 0x01, 0x7f, 0x1e, 0x12, 0x83, 0xb7, 0x90, 0x01, 0x1e} },
-{ 0x0f6d,	16,	{0xe0, 0x04, 0xf0, 0x80, 0xd7, 0xe4, 0xf5, 0x3a, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
-{ 0x0f7d,	16,	{0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54} },
-{ 0x0f8d,	16,	{0xf0, 0xfe, 0x74, 0xc5, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xee, 0xf0, 0x74, 0x36} },
-{ 0x0f9d,	16,	{0x2f, 0xf8, 0xa6, 0x06, 0x74, 0x32, 0x2f, 0xf8, 0xe4, 0xf6, 0x74, 0x2c, 0x2f, 0xf8, 0xe4, 0xf6} },
-{ 0x0fad,	16,	{0x74, 0xfc, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
-{ 0x0fbd,	16,	{0x04, 0xf0, 0xe0, 0xb4, 0x04, 0xb6, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0x4b, 0x60, 0x5e} },
-{ 0x0fcd,	4,	{0xe4, 0x90, 0x01, 0x1e} },
-{ 0x0fd1,	16,	{0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50, 0xe7, 0x74, 0x01, 0xa8, 0x07, 0x08} },
-{ 0x0fe1,	16,	{0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x55, 0x4b, 0x60, 0x38, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0x75} },
-{ 0x0ff1,	16,	{0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xfe, 0xef, 0x75} },
-{ 0x1001,	16,	{0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xef, 0x75, 0xf0} },
-{ 0x1011,	16,	{0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xfe, 0x7d, 0x06, 0x12} },
-{ 0x1021,	11,	{0x83, 0x2d, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xa7, 0x22} },
-{ 0x102c,	4,	{0xad, 0x07, 0xac, 0x06} },
-{ 0x1030,	16,	{0x79, 0x06, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb} },
-{ 0x1040,	16,	{0x4a, 0x70, 0x03, 0x02, 0x11, 0x74, 0xe9, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x11, 0x46, 0x90} },
-{ 0x1050,	16,	{0x10, 0x56, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x11, 0x24, 0x02, 0x10, 0xdc, 0x02, 0x10, 0xc5, 0x02} },
-{ 0x1060,	16,	{0x10, 0xab, 0x02, 0x10, 0x9a, 0x02, 0x10, 0x85, 0x02, 0x10, 0x6b, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
-{ 0x1070,	16,	{0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6} },
-{ 0x1080,	16,	{0xf0, 0x19, 0x02, 0x11, 0x46, 0x19, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x0a} },
-{ 0x1090,	16,	{0xa3, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x02, 0x11, 0x46, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} },
-{ 0x10a0,	16,	{0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x19, 0x02, 0x11, 0x46, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
-{ 0x10b0,	16,	{0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa1, 0x90, 0x7f, 0xa6} },
-{ 0x10c0,	16,	{0xf0, 0x19, 0x02, 0x11, 0x46, 0xeb, 0x64, 0x01, 0x4a, 0x70, 0x08, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
-{ 0x10d0,	16,	{0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xf5, 0x54, 0x19, 0x80, 0x6a, 0xed, 0x24, 0x04, 0xf5} },
-{ 0x10e0,	16,	{0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0x64, 0x02, 0x4e, 0x70, 0x08, 0x90, 0x7f} },
-{ 0x10f0,	16,	{0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xff, 0xed, 0x24, 0x06, 0xf5, 0x82} },
-{ 0x1100,	16,	{0xe4, 0x3c, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9f, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83} },
-{ 0x1110,	16,	{0xef, 0xf0, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12} },
-{ 0x1120,	16,	{0x9f, 0x8e, 0x80, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xff} },
-{ 0x1130,	16,	{0xed, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xf5, 0x82, 0x8a} },
-{ 0x1140,	16,	{0x83, 0xef, 0xf0, 0x7f, 0x08, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x54, 0x30, 0xe0, 0xf7, 0x30} },
-{ 0x1150,	16,	{0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xe9, 0xd3, 0x94, 0x02, 0x50, 0x03, 0x02} },
-{ 0x1160,	16,	{0x10, 0x32, 0xe5, 0x54, 0x30, 0xe1, 0x03, 0x02, 0x10, 0x32, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40} },
-{ 0x1170,	6,	{0xf0, 0x7f, 0x07, 0x22, 0x7f, 0x08} },
-{ 0x1176,	1,	{0x22} },
-{ 0x1177,	2,	{0xae, 0x07} },
-{ 0x1179,	16,	{0x7c, 0x02, 0xec, 0x14, 0x60, 0x15, 0x14, 0x70, 0x1e, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0} },
-{ 0x1189,	16,	{0xee, 0x25, 0xe0, 0x44, 0x40, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xa6, 0xed, 0xf0} },
-{ 0x1199,	16,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xfb, 0x30, 0xe0, 0xf8, 0xbc} },
-{ 0x11a9,	16,	{0x02, 0x0a, 0x20, 0xe1, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22, 0xeb, 0x30, 0xe2, 0x0a} },
-{ 0x11b9,	14,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xdc, 0xb6, 0x7f, 0x08} },
-{ 0x11c7,	1,	{0x22} },
-{ 0x11c8,	16,	{0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x7f, 0x02, 0x7d, 0xff, 0x12, 0x11, 0x77, 0x7f, 0x05} },
-{ 0x11d8,	13,	{0x7e, 0x00, 0x12, 0x09, 0x29, 0x7f, 0x03, 0x7d, 0xff, 0x12, 0x11, 0x77, 0x22} },
-{ 0x11e5,	16,	{0xe4, 0x90, 0x01, 0xc9, 0xf0, 0x7e, 0x01, 0x7f, 0xca, 0x90, 0x01, 0xbe, 0xee, 0xf0, 0xa3, 0xef} },
-{ 0x11f5,	10,	{0xf0, 0x90, 0x01, 0xc2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} },
+{ 0x0b8d,	16,	{0x53, 0x8e, 0xf7, 0xe5, 0x89, 0x54, 0xf1, 0x44, 0x01, 0xf5, 0x89, 0x75, 0x8c, 0xb1, 0xd2, 0xa9} },
+{ 0x0b9d,	16,	{0x75, 0x98, 0x40, 0x75, 0xcb, 0xff, 0x75, 0xca, 0xf3, 0x75, 0xc8, 0x34, 0xe4, 0xff, 0x7f, 0x05} },
+{ 0x0bad,	7,	{0x78, 0x27, 0xe4, 0xf6, 0x08, 0xdf, 0xfc} },
+{ 0x0bb4,	1,	{0x22} },
+{ 0x0bb5,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x06, 0xc0} },
+{ 0x0bc5,	1,	{0x07} },
+{ 0x0bc6,	16,	{0x30, 0x04, 0x16, 0x75, 0x8c, 0xf8, 0x75, 0x8a, 0x30, 0x7f, 0x2f, 0xae, 0x07, 0x1f, 0xee, 0x60} },
+{ 0x0bd6,	16,	{0x3c, 0x90, 0x20, 0x00, 0x74, 0x55, 0xf0, 0x80, 0xf2, 0x75, 0x8c, 0xb1, 0x7f, 0x27, 0xef, 0xd3} },
+{ 0x0be6,	16,	{0x94, 0x2b, 0x50, 0x09, 0xa8, 0x07, 0xe6, 0x60, 0x01, 0x16, 0x0f, 0x80, 0xf1, 0x90, 0x03, 0x00} },
+{ 0x0bf6,	16,	{0xe0, 0x60, 0x02, 0x14, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x0e, 0x90} },
+{ 0x0c06,	13,	{0x01, 0xc1, 0xe0, 0x24, 0xff, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x34, 0xff, 0xf0} },
+{ 0x0c13,	15,	{0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c22,	16,	{0xd2, 0x00, 0x75, 0x8e, 0x10, 0x12, 0x09, 0x2c, 0xe5, 0x30, 0xc3, 0x94, 0x01, 0x40, 0x08, 0x90} },
+{ 0x0c32,	16,	{0x7f, 0x92, 0x74, 0x02, 0xf0, 0x80, 0x05, 0xe4, 0x90, 0x7f, 0x92, 0xf0, 0x12, 0x80, 0x00, 0x12} },
+{ 0x0c42,	12,	{0x0f, 0x4d, 0x12, 0x92, 0xfb, 0x12, 0x1b, 0x0c, 0x12, 0x0b, 0x8d, 0x22} },
+{ 0x0c4e,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} },
+{ 0x0c5e,	8,	{0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c66,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0c76,	11,	{0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c81,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0x90} },
+{ 0x0c91,	16,	{0x7f, 0xd8, 0xe0, 0x70, 0x0d, 0x90, 0x7f, 0xd9, 0xe0, 0x70, 0x07, 0xe5, 0x2b, 0x70, 0x03, 0x75} },
+{ 0x0ca1,	9,	{0x2b, 0x14, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0caa,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} },
+{ 0x0cba,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0cc0,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x30, 0x02, 0x02, 0xd2, 0x06, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0cd0,	11,	{0xab, 0x74, 0x08, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0cdb,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0ceb,	16,	{0xa9, 0x74, 0x02, 0xf0, 0xe5, 0x31, 0x30, 0xe0, 0x13, 0xe5, 0x3c, 0x30, 0xe0, 0x07, 0x90, 0x20} },
+{ 0x0cfb,	16,	{0x04, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} },
+{ 0x0d0b,	12,	{0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d17,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0d27,	16,	{0xa9, 0x74, 0x04, 0xf0, 0xe5, 0x31, 0x30, 0xe1, 0x13, 0xe5, 0x3c, 0x30, 0xe1, 0x07, 0x90, 0x20} },
+{ 0x0d37,	16,	{0x0c, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} },
+{ 0x0d47,	12,	{0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d53,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0d63,	16,	{0xa9, 0x74, 0x08, 0xf0, 0xe5, 0x31, 0x30, 0xe2, 0x13, 0xe5, 0x3c, 0x30, 0xe2, 0x07, 0x90, 0x20} },
+{ 0x0d73,	16,	{0x14, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} },
+{ 0x0d83,	12,	{0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d8f,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0d9f,	16,	{0xa9, 0x74, 0x10, 0xf0, 0xe5, 0x31, 0x30, 0xe3, 0x13, 0xe5, 0x3c, 0x30, 0xe3, 0x07, 0x90, 0x20} },
+{ 0x0daf,	16,	{0x1c, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03} },
+{ 0x0dbf,	12,	{0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dcb,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
+{ 0x0ddb,	16,	{0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x02, 0xf0, 0xe5, 0x31, 0x20} },
+{ 0x0deb,	16,	{0xe0, 0x06, 0x90, 0x7f, 0xc7, 0xf0, 0x80, 0x16, 0xe5, 0x3c, 0x30, 0xe0, 0x0a, 0x90, 0x7f, 0xc7} },
+{ 0x0dfb,	16,	{0xe0, 0x90, 0x02, 0xf8, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} },
+{ 0x0e0b,	16,	{0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} },
+{ 0x0e1b,	4,	{0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0e1f,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
+{ 0x0e2f,	16,	{0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x04, 0xf0, 0xe5, 0x31, 0x20} },
+{ 0x0e3f,	16,	{0xe1, 0x06, 0x90, 0x7f, 0xc9, 0xf0, 0x80, 0x16, 0xe5, 0x3c, 0x30, 0xe1, 0x0a, 0x90, 0x7f, 0xc9} },
+{ 0x0e4f,	16,	{0xe0, 0x90, 0x02, 0xf9, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} },
+{ 0x0e5f,	16,	{0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} },
+{ 0x0e6f,	4,	{0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0e73,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
+{ 0x0e83,	16,	{0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x08, 0xf0, 0xe5, 0x31, 0x20} },
+{ 0x0e93,	16,	{0xe2, 0x06, 0x90, 0x7f, 0xcb, 0xf0, 0x80, 0x16, 0xe5, 0x3c, 0x30, 0xe2, 0x0a, 0x90, 0x7f, 0xcb} },
+{ 0x0ea3,	16,	{0xe0, 0x90, 0x02, 0xfa, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} },
+{ 0x0eb3,	16,	{0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} },
+{ 0x0ec3,	4,	{0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0ec7,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
+{ 0x0ed7,	16,	{0xd0, 0x75, 0xd0, 0x10, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x10, 0xf0, 0xe5, 0x31, 0x20} },
+{ 0x0ee7,	16,	{0xe3, 0x06, 0x90, 0x7f, 0xcd, 0xf0, 0x80, 0x16, 0xe5, 0x3c, 0x30, 0xe3, 0x0a, 0x90, 0x7f, 0xcd} },
+{ 0x0ef7,	16,	{0xe0, 0x90, 0x02, 0xfb, 0xf0, 0x80, 0x07, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b} },
+{ 0x0f07,	16,	{0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0} },
+{ 0x0f17,	4,	{0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0f1b,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x80, 0xf0, 0xd0} },
+{ 0x0f2b,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0f31,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x80, 0xf0, 0x90} },
+{ 0x0f41,	12,	{0x01, 0xbd, 0x74, 0xff, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0f4d,	16,	{0x90, 0x01, 0x20, 0x12, 0xa1, 0xfe, 0x00, 0x00, 0x25, 0x80, 0x90, 0x01, 0x24, 0x74, 0x08, 0xf0} },
+{ 0x0f5d,	16,	{0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x6e, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x13, 0xf0, 0xa3, 0x74} },
+{ 0x0f6d,	16,	{0x11, 0xf0, 0xe4, 0xa3, 0xf0, 0xa3, 0xf0, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff} },
+{ 0x0f7d,	16,	{0x04, 0xa3, 0xf0, 0xef, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x01, 0xf9, 0x74, 0x03, 0x35, 0xf0, 0xa8} },
+{ 0x0f8d,	16,	{0x01, 0xfc, 0x7d, 0x01, 0x7b, 0x01, 0x7a, 0x01, 0x79, 0x1f, 0x7e, 0x00, 0x7f, 0x0d, 0x12, 0xa0} },
+{ 0x0f9d,	16,	{0x16, 0x7e, 0x01, 0x7f, 0x1f, 0x12, 0x86, 0xb7, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0xe0, 0xc3} },
+{ 0x0fad,	16,	{0x94, 0x04, 0x40, 0xc7, 0xe4, 0xf5, 0x26, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff} },
+{ 0x0fbd,	16,	{0xc3, 0x94, 0x04, 0x50, 0x1a, 0x74, 0xf8, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4} },
+{ 0x0fcd,	16,	{0xf0, 0x74, 0x22, 0x2f, 0xf8, 0xe4, 0xf6, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0xe4} },
+{ 0x0fdd,	16,	{0xf5, 0x31, 0xe5, 0xc0, 0x60, 0x2f, 0x90, 0x01, 0x1e, 0x74, 0x01, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0fed,	16,	{0xff, 0xd3, 0x94, 0x04, 0x50, 0x1f, 0xef, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02} },
+{ 0x0ffd,	16,	{0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x31, 0x7e, 0x01, 0x7f, 0x1e, 0x12, 0x84, 0x08, 0x90, 0x01, 0x1e} },
+{ 0x100d,	16,	{0xe0, 0x04, 0xf0, 0x80, 0xd7, 0xe4, 0xf5, 0x3b, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x101d,	16,	{0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54} },
+{ 0x102d,	16,	{0xf0, 0xfe, 0x74, 0xc5, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xee, 0xf0, 0x74, 0x37} },
+{ 0x103d,	16,	{0x2f, 0xf8, 0xa6, 0x06, 0x74, 0x33, 0x2f, 0xf8, 0xe4, 0xf6, 0x74, 0x2c, 0x2f, 0xf8, 0xe4, 0xf6} },
+{ 0x104d,	16,	{0x74, 0xfc, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x105d,	16,	{0x04, 0xf0, 0xe0, 0xb4, 0x04, 0xb6, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0x4c, 0x60, 0x5e} },
+{ 0x106d,	4,	{0xe4, 0x90, 0x01, 0x1e} },
+{ 0x1071,	16,	{0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50, 0xe7, 0x74, 0x01, 0xa8, 0x07, 0x08} },
+{ 0x1081,	16,	{0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x55, 0x4c, 0x60, 0x38, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0x75} },
+{ 0x1091,	16,	{0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xfe, 0xef, 0x75} },
+{ 0x10a1,	16,	{0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xef, 0x75, 0xf0} },
+{ 0x10b1,	16,	{0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xfe, 0x7d, 0x06, 0x12} },
+{ 0x10c1,	11,	{0x83, 0x7e, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xa7, 0x22} },
+{ 0x10cc,	4,	{0x8e, 0x57, 0x8f, 0x58} },
+{ 0x10d0,	16,	{0x75, 0x59, 0x03, 0xe5, 0x58, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x57, 0xf5, 0x83, 0xe0, 0xfe} },
+{ 0x10e0,	16,	{0xa3, 0xe0, 0x4e, 0x70, 0x03, 0x02, 0x11, 0xda, 0xe5, 0x59, 0x60, 0x4e, 0x14, 0x60, 0x38, 0x14} },
+{ 0x10f0,	16,	{0x60, 0x20, 0x14, 0x60, 0x03, 0x02, 0x11, 0x7e, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0x85} },
+{ 0x1100,	16,	{0x58, 0x82, 0x85, 0x57, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6, 0xf0} },
+{ 0x1110,	16,	{0x80, 0x6c, 0x85, 0x58, 0x82, 0x85, 0x57, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x09, 0xa3, 0xa3} },
+{ 0x1120,	16,	{0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x57, 0x15, 0x59, 0x85, 0x58, 0x82, 0x85, 0x57, 0x83, 0xa3} },
+{ 0x1130,	16,	{0xa3, 0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x44, 0xe5, 0x58, 0x24, 0x06, 0xf5, 0x82} },
+{ 0x1140,	16,	{0xe4, 0x35, 0x57, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0xa0, 0x9b, 0x85, 0xf0, 0x82, 0xf5} },
+{ 0x1150,	16,	{0x83, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe5, 0x58, 0x24} },
+{ 0x1160,	16,	{0x04, 0xf5, 0x82, 0xe4, 0x35, 0x57, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12, 0xa0, 0x85, 0x85} },
+{ 0x1170,	16,	{0x58, 0x82, 0x85, 0x57, 0x83, 0xa3, 0xa3, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0xa0, 0x85, 0x90, 0x7f} },
+{ 0x1180,	16,	{0xa5, 0xe0, 0xf5, 0x5a, 0x30, 0xe0, 0xf7, 0x30, 0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06} },
+{ 0x1190,	16,	{0x22, 0xe5, 0x5a, 0x20, 0xe1, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22} },
+{ 0x11a0,	16,	{0xe5, 0x59, 0x70, 0x31, 0x7f, 0x01, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x11b0,	16,	{0x80, 0xf0, 0x85, 0x58, 0x82, 0x85, 0x57, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90} },
+{ 0x11c0,	16,	{0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x5a, 0x30, 0xe0, 0xf7, 0x30, 0xe1, 0xd5, 0x75} },
+{ 0x11d0,	12,	{0x59, 0x03, 0x02, 0x10, 0xd3, 0x15, 0x59, 0x02, 0x10, 0xd3, 0x7f, 0x08} },
+{ 0x11dc,	1,	{0x22} },
+{ 0x11dd,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc2, 0xa9, 0x90, 0x03, 0x00, 0x74, 0x19, 0xf0, 0xd2, 0xa9} },
+{ 0x11ed,	15,	{0x53, 0x91, 0x7f, 0x90, 0x01, 0xc4, 0xe4, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
 { 0x1200,	16,	{0x12, 0x01, 0x00, 0x01, 0xff, 0xff, 0xff, 0x40, 0x10, 0x07, 0x01, 0x80, 0x42, 0x00, 0x01, 0x02} },
 { 0x1210,	16,	{0x03, 0x01, 0x09, 0x02, 0x58, 0x00, 0x01, 0x01, 0x04, 0x80, 0x3c, 0x09, 0x04, 0x00, 0x00, 0x0a} },
 { 0x1220,	16,	{0xff, 0xff, 0xff, 0x05, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40} },
@@ -339,14 +336,14 @@
 { 0x1362,	16,	{0x75, 0x28, 0x14, 0x02, 0x15, 0x0d, 0xe5, 0x29, 0x70, 0x03, 0x75, 0x29, 0x14, 0x02, 0x16, 0x9e} },
 { 0x1372,	16,	{0xe5, 0x2a, 0x70, 0x03, 0x75, 0x2a, 0x14, 0x02, 0x18, 0x2f, 0x90, 0x20, 0x02, 0xe0, 0x54, 0x3f} },
 { 0x1382,	16,	{0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14, 0x60, 0x09, 0x02, 0x13} },
-{ 0x1392,	16,	{0x43, 0x02, 0x14, 0x65, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x36, 0x02, 0x13, 0x43} },
+{ 0x1392,	16,	{0x43, 0x02, 0x14, 0x65, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x37, 0x02, 0x13, 0x43} },
 { 0x13a2,	16,	{0x43, 0x82, 0x04, 0xe0, 0x43, 0x2c, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x05} },
-{ 0x13b2,	16,	{0xe0, 0x42, 0x32, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1, 0x02} },
-{ 0x13c2,	16,	{0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04, 0xe0} },
+{ 0x13b2,	16,	{0xe0, 0x42, 0x33, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1, 0x02} },
+{ 0x13c2,	16,	{0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3c, 0x30, 0xe0, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04, 0xe0} },
 { 0x13d2,	16,	{0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74, 0x00, 0xf0, 0x90, 0x20} },
 { 0x13e2,	16,	{0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86} },
 { 0x13f2,	16,	{0x90, 0x7e, 0x80, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f} },
-{ 0x1402,	16,	{0xe5, 0xe5, 0x3c, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} },
+{ 0x1402,	16,	{0xe5, 0xe5, 0x3d, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} },
 { 0x1412,	16,	{0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x90} },
 { 0x1422,	16,	{0x7f, 0xb7, 0xed, 0xf0, 0x90, 0x20, 0x01, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x7f, 0x40} },
 { 0x1432,	16,	{0x90, 0x7e, 0x80, 0x05, 0x86, 0x90, 0x20, 0x00, 0xe5, 0x84, 0xfe, 0x24, 0x05, 0xfd, 0x8d, 0x84} },
@@ -364,14 +361,14 @@
 { 0x14f2,	16,	{0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x90, 0x20, 0x01} },
 { 0x1502,	16,	{0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xc7, 0xf0, 0x02, 0x13, 0x43, 0x90, 0x20, 0x0a, 0xe0, 0x54} },
 { 0x1512,	16,	{0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14, 0x60, 0x09, 0x02} },
-{ 0x1522,	16,	{0x13, 0x43, 0x02, 0x15, 0xf6, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x37, 0x02, 0x13} },
+{ 0x1522,	16,	{0x13, 0x43, 0x02, 0x15, 0xf6, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5, 0x38, 0x02, 0x13} },
 { 0x1532,	16,	{0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2d, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82, 0xf8, 0x43, 0x82} },
-{ 0x1542,	16,	{0x05, 0xe0, 0x42, 0x33, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1} },
-{ 0x1552,	16,	{0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04} },
+{ 0x1542,	16,	{0x05, 0xe0, 0x42, 0x34, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13, 0x43, 0x30, 0xe1} },
+{ 0x1552,	16,	{0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3c, 0x30, 0xe1, 0x0a, 0x53, 0x82, 0xf8, 0x43, 0x82, 0x04} },
 { 0x1562,	16,	{0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74, 0x01, 0xf0, 0x90} },
 { 0x1572,	16,	{0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05} },
 { 0x1582,	16,	{0x86, 0x90, 0x7e, 0x00, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90} },
-{ 0x1592,	16,	{0x7f, 0xe5, 0xe5, 0x3d, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} },
+{ 0x1592,	16,	{0x7f, 0xe5, 0xe5, 0x3e, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0} },
 { 0x15a2,	16,	{0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} },
 { 0x15b2,	16,	{0x90, 0x7f, 0xb9, 0xed, 0xf0, 0x90, 0x20, 0x09, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x7f} },
 { 0x15c2,	16,	{0x40, 0x90, 0x7e, 0x00, 0x05, 0x86, 0x90, 0x20, 0x08, 0xe5, 0x84, 0xfe, 0x24, 0x05, 0xfd, 0x8d} },
@@ -390,13 +387,13 @@
 { 0x1690,	16,	{0x90, 0x20, 0x09, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x02, 0x13, 0x43, 0x90, 0x20} },
 { 0x16a0,	16,	{0x12, 0xe0, 0x54, 0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5, 0x14} },
 { 0x16b0,	16,	{0x60, 0x09, 0x02, 0x13, 0x43, 0x02, 0x17, 0x87, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0xf5} },
-{ 0x16c0,	16,	{0x38, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2e, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82} },
-{ 0x16d0,	16,	{0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x34, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13} },
-{ 0x16e0,	16,	{0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x53, 0x82, 0xf8} },
+{ 0x16c0,	16,	{0x39, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2e, 0x01, 0x02, 0x13, 0x43, 0x53, 0x82} },
+{ 0x16d0,	16,	{0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x35, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02, 0x13} },
+{ 0x16e0,	16,	{0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3c, 0x30, 0xe2, 0x0a, 0x53, 0x82, 0xf8} },
 { 0x16f0,	16,	{0x43, 0x82, 0x04, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50, 0x74} },
 { 0x1700,	16,	{0x02, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90} },
 { 0x1710,	16,	{0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x80, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0} },
-{ 0x1720,	16,	{0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3e, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0} },
+{ 0x1720,	16,	{0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3f, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0, 0xf0} },
 { 0x1730,	16,	{0xf0, 0xf0, 0xf0, 0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58} },
 { 0x1740,	16,	{0x74, 0x00, 0xf0, 0x90, 0x7f, 0xbb, 0xed, 0xf0, 0x90, 0x20, 0x11, 0xe0, 0x54, 0xfe, 0xf0, 0x02} },
 { 0x1750,	16,	{0x13, 0x43, 0x7f, 0x40, 0x90, 0x7d, 0x80, 0x05, 0x86, 0x90, 0x20, 0x10, 0xe5, 0x84, 0xfe, 0x24} },
@@ -415,13 +412,13 @@
 { 0x1820,	16,	{0xf0, 0x90, 0x20, 0x11, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xcb, 0xf0, 0x02, 0x13, 0x43, 0x90} },
 { 0x1830,	16,	{0x20, 0x1a, 0xe0, 0x54, 0x3f, 0x20, 0xe2, 0x3a, 0x20, 0xe1, 0x0b, 0x20, 0xe4, 0x0b, 0x20, 0xe5} },
 { 0x1840,	16,	{0x14, 0x60, 0x09, 0x02, 0x13, 0x43, 0x02, 0x19, 0x18, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0} },
-{ 0x1850,	16,	{0xf5, 0x39, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2f, 0x01, 0x02, 0x13, 0x43, 0x53} },
-{ 0x1860,	16,	{0x82, 0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x35, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02} },
-{ 0x1870,	16,	{0x13, 0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x53, 0x82} },
+{ 0x1850,	16,	{0xf5, 0x3a, 0x02, 0x13, 0x43, 0x43, 0x82, 0x04, 0xe0, 0x43, 0x2f, 0x01, 0x02, 0x13, 0x43, 0x53} },
+{ 0x1860,	16,	{0x82, 0xf8, 0x43, 0x82, 0x05, 0xe0, 0x42, 0x36, 0x53, 0x82, 0xfb, 0xe0, 0x54, 0xfb, 0xf0, 0x02} },
+{ 0x1870,	16,	{0x13, 0x43, 0x30, 0xe1, 0x02, 0x80, 0xe8, 0xf5, 0x85, 0xe5, 0x3c, 0x30, 0xe3, 0x0a, 0x53, 0x82} },
 { 0x1880,	16,	{0xf8, 0x43, 0x82, 0x04, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x85, 0x20, 0xe3, 0x56, 0x90, 0x20, 0x50} },
 { 0x1890,	16,	{0x74, 0x03, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0} },
 { 0x18a0,	16,	{0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x00, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84} },
-{ 0x18b0,	16,	{0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x3f, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0} },
+{ 0x18b0,	16,	{0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xe5, 0x40, 0xfd, 0x03, 0x03, 0x03, 0xfe, 0xf0, 0xf0, 0xf0} },
 { 0x18c0,	16,	{0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xde, 0xf6, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20} },
 { 0x18d0,	16,	{0x58, 0x74, 0x00, 0xf0, 0x90, 0x7f, 0xbd, 0xed, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x54, 0xfe, 0xf0} },
 { 0x18e0,	16,	{0x02, 0x13, 0x43, 0x7f, 0x40, 0x90, 0x7d, 0x00, 0x05, 0x86, 0x90, 0x20, 0x18, 0xe5, 0x84, 0xfe} },
@@ -439,63 +436,61 @@
 { 0x19a0,	16,	{0x80, 0x1b, 0xe0, 0xde, 0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74} },
 { 0x19b0,	16,	{0x00, 0xf0, 0x90, 0x20, 0x19, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0x7f, 0xcd, 0xf0, 0x02, 0x13, 0x43} },
 { 0x19c0,	1,	{0x32} },
-{ 0x19c1,	4,	{0x8e, 0x54, 0x8f, 0x55} },
-{ 0x19c5,	16,	{0x75, 0x56, 0x03, 0xe5, 0x55, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xfe} },
-{ 0x19d5,	16,	{0xa3, 0xe0, 0x4e, 0x70, 0x03, 0x02, 0x1a, 0xcf, 0xe5, 0x56, 0x60, 0x4e, 0x14, 0x60, 0x38, 0x14} },
-{ 0x19e5,	16,	{0x60, 0x20, 0x14, 0x60, 0x03, 0x02, 0x1a, 0x73, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0x85} },
-{ 0x19f5,	16,	{0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6, 0xf0} },
-{ 0x1a05,	16,	{0x80, 0x6c, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x09, 0xa3, 0xa3} },
-{ 0x1a15,	16,	{0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x57, 0x15, 0x56, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3} },
-{ 0x1a25,	16,	{0xa3, 0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x44, 0xe5, 0x55, 0x24, 0x06, 0xf5, 0x82} },
-{ 0x1a35,	16,	{0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9f, 0xa4, 0x85, 0xf0, 0x82, 0xf5} },
-{ 0x1a45,	16,	{0x83, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe5, 0x55, 0x24} },
-{ 0x1a55,	16,	{0x04, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12, 0x9f, 0x8e, 0x85} },
-{ 0x1a65,	16,	{0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xa3, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9f, 0x8e, 0x90, 0x7f} },
-{ 0x1a75,	16,	{0xa5, 0xe0, 0xf5, 0x57, 0x30, 0xe0, 0xf7, 0x30, 0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06} },
-{ 0x1a85,	16,	{0x22, 0xe5, 0x57, 0x20, 0xe1, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22} },
-{ 0x1a95,	16,	{0xe5, 0x56, 0x70, 0x31, 0x7f, 0x01, 0x7e, 0x00, 0x12, 0x09, 0x29, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
-{ 0x1aa5,	16,	{0x80, 0xf0, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90} },
-{ 0x1ab5,	16,	{0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x57, 0x30, 0xe0, 0xf7, 0x30, 0xe1, 0xd5, 0x75} },
-{ 0x1ac5,	12,	{0x56, 0x03, 0x02, 0x19, 0xc8, 0x15, 0x56, 0x02, 0x19, 0xc8, 0x7f, 0x08} },
-{ 0x1ad1,	1,	{0x22} },
-{ 0x1ad2,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc2, 0xa9, 0x90, 0x03, 0x00, 0x74, 0x19, 0xf0, 0xd2, 0xa9} },
-{ 0x1ae2,	15,	{0x53, 0x91, 0x7f, 0x90, 0x01, 0xc4, 0xe4, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x1af1,	4,	{0x8e, 0x54, 0x8f, 0x55} },
-{ 0x1af5,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x56, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22} },
-{ 0x1b05,	16,	{0xe5, 0x56, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0} },
-{ 0x1b15,	16,	{0x54, 0x03, 0x70, 0x24, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0x30, 0xe0, 0x07, 0xaf} },
-{ 0x1b25,	16,	{0x56, 0x7d, 0x02, 0x12, 0x83, 0x2d, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0x30, 0xe1} },
-{ 0x1b35,	10,	{0x07, 0xaf, 0x56, 0x7d, 0x04, 0x12, 0x83, 0x2d, 0x7f, 0x00} },
-{ 0x1b3f,	1,	{0x22} },
-{ 0x8000,	16,	{0x7b, 0xff, 0x7a, 0x12, 0x79, 0x1b, 0x90, 0x00, 0x04, 0x12, 0x9f, 0x61, 0xfd, 0x8b, 0x4d, 0x75} },
-{ 0x8010,	16,	{0x4e, 0x12, 0x75, 0x4f, 0x24, 0xe4, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x7f, 0xe0, 0xf0, 0xf5, 0x4b} },
-{ 0x8020,	16,	{0xf5, 0x4c, 0x90, 0x02, 0xae, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f} },
+{ 0x19c1,	4,	{0xad, 0x07, 0xac, 0x06} },
+{ 0x19c5,	16,	{0x79, 0x06, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb} },
+{ 0x19d5,	16,	{0x4a, 0x70, 0x03, 0x02, 0x1b, 0x09, 0xe9, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x1a, 0xdb, 0x90} },
+{ 0x19e5,	16,	{0x19, 0xeb, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x1a, 0xb9, 0x02, 0x1a, 0x71, 0x02, 0x1a, 0x5a, 0x02} },
+{ 0x19f5,	16,	{0x1a, 0x40, 0x02, 0x1a, 0x2f, 0x02, 0x1a, 0x1a, 0x02, 0x1a, 0x00, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x1a05,	16,	{0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6} },
+{ 0x1a15,	16,	{0xf0, 0x19, 0x02, 0x1a, 0xdb, 0x19, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x0a} },
+{ 0x1a25,	16,	{0xa3, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x02, 0x1a, 0xdb, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} },
+{ 0x1a35,	16,	{0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x19, 0x02, 0x1a, 0xdb, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x1a45,	16,	{0x80, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa1, 0x90, 0x7f, 0xa6} },
+{ 0x1a55,	16,	{0xf0, 0x19, 0x02, 0x1a, 0xdb, 0xeb, 0x64, 0x01, 0x4a, 0x70, 0x08, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x1a65,	16,	{0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xf5, 0x57, 0x19, 0x80, 0x6a, 0xed, 0x24, 0x04, 0xf5} },
+{ 0x1a75,	16,	{0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0x64, 0x02, 0x4e, 0x70, 0x08, 0x90, 0x7f} },
+{ 0x1a85,	16,	{0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x19, 0x90, 0x7f, 0xa6, 0xe0, 0xff, 0xed, 0x24, 0x06, 0xf5, 0x82} },
+{ 0x1a95,	16,	{0xe4, 0x3c, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0xa0, 0x9b, 0x85, 0xf0, 0x82, 0xf5, 0x83} },
+{ 0x1aa5,	16,	{0xef, 0xf0, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12} },
+{ 0x1ab5,	16,	{0xa0, 0x85, 0x80, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xff} },
+{ 0x1ac5,	16,	{0xed, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3c, 0xf5, 0x83, 0xe0, 0xfa, 0xa3, 0xe0, 0xf5, 0x82, 0x8a} },
+{ 0x1ad5,	16,	{0x83, 0xef, 0xf0, 0x7f, 0x08, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x57, 0x30, 0xe0, 0xf7, 0x30} },
+{ 0x1ae5,	16,	{0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xe9, 0xd3, 0x94, 0x02, 0x50, 0x03, 0x02} },
+{ 0x1af5,	16,	{0x19, 0xc7, 0xe5, 0x57, 0x30, 0xe1, 0x03, 0x02, 0x19, 0xc7, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40} },
+{ 0x1b05,	6,	{0xf0, 0x7f, 0x07, 0x22, 0x7f, 0x08} },
+{ 0x1b0b,	1,	{0x22} },
+{ 0x1b0c,	16,	{0xe5, 0x30, 0xc3, 0x94, 0x01, 0x50, 0x1c, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x7f, 0x02} },
+{ 0x1b1c,	16,	{0x7d, 0xff, 0x12, 0x82, 0xa8, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x09, 0xaa, 0x7f, 0x03, 0x7d, 0xff} },
+{ 0x1b2c,	4,	{0x12, 0x82, 0xa8, 0x22} },
+{ 0x8000,	16,	{0x7b, 0xff, 0x7a, 0x12, 0x79, 0x1b, 0x90, 0x00, 0x04, 0x12, 0xa0, 0x58, 0xfd, 0x8b, 0x4e, 0x75} },
+{ 0x8010,	16,	{0x4f, 0x12, 0x75, 0x50, 0x24, 0xe4, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x7f, 0xe0, 0xf0, 0xf5, 0x4c} },
+{ 0x8020,	16,	{0xf5, 0x4d, 0x90, 0x02, 0xae, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f} },
 { 0x8030,	16,	{0xa9, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0xe4, 0xfc, 0xec, 0x25, 0xe0, 0x24, 0xb4, 0xf5} },
 { 0x8040,	16,	{0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x0c, 0xbc, 0x10, 0xee, 0xe4, 0x90, 0x7f, 0xdd} },
-{ 0x8050,	16,	{0xf0, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03, 0x02, 0x81, 0xc6, 0xab, 0x4d, 0xaa, 0x4e, 0xa9, 0x4f} },
-{ 0x8060,	16,	{0x90, 0x00, 0x01, 0x12, 0x9f, 0x61, 0x64, 0x05, 0x60, 0x03, 0x02, 0x81, 0xb5, 0x90, 0x00, 0x03} },
-{ 0x8070,	16,	{0x12, 0x9f, 0x61, 0x64, 0x01, 0x60, 0x03, 0x02, 0x81, 0x3c, 0x90, 0x00, 0x02, 0x12, 0x9f, 0x61} },
+{ 0x8050,	16,	{0xf0, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03, 0x02, 0x81, 0xc6, 0xab, 0x4e, 0xaa, 0x4f, 0xa9, 0x50} },
+{ 0x8060,	16,	{0x90, 0x00, 0x01, 0x12, 0xa0, 0x58, 0x64, 0x05, 0x60, 0x03, 0x02, 0x81, 0xb5, 0x90, 0x00, 0x03} },
+{ 0x8070,	16,	{0x12, 0xa0, 0x58, 0x64, 0x01, 0x60, 0x03, 0x02, 0x81, 0x3c, 0x90, 0x00, 0x02, 0x12, 0xa0, 0x58} },
 { 0x8080,	16,	{0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x81, 0x16, 0xec, 0xc3, 0x94, 0x10} },
-{ 0x8090,	16,	{0x40, 0x03, 0x02, 0x81, 0x16, 0xef, 0x30, 0xe7, 0x42, 0xe5, 0x4c, 0xae, 0x4b, 0x78, 0x02, 0xce} },
+{ 0x8090,	16,	{0x40, 0x03, 0x02, 0x81, 0x16, 0xef, 0x30, 0xe7, 0x42, 0xe5, 0x4d, 0xae, 0x4c, 0x78, 0x02, 0xce} },
 { 0x80a0,	16,	{0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xf0, 0x2c, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} },
 { 0x80b0,	16,	{0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe0, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01, 0xa8, 0x06} },
 { 0x80c0,	16,	{0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe0, 0xf0, 0x90, 0x02, 0xae, 0xe0} },
-{ 0x80d0,	16,	{0x04, 0xf0, 0x90, 0x7f, 0xdd, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x3e, 0xe5, 0x4c, 0xae, 0x4b, 0x78} },
+{ 0x80d0,	16,	{0x04, 0xf0, 0x90, 0x7f, 0xdd, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x3e, 0xe5, 0x4d, 0xae, 0x4c, 0x78} },
 { 0x80e0,	16,	{0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xe8, 0x2c, 0xf5, 0x82, 0xe4, 0x34} },
 { 0x80f0,	16,	{0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe1, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01} },
 { 0x8100,	16,	{0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x02} },
-{ 0x8110,	16,	{0xae, 0xe0, 0x04, 0xf0, 0x80, 0x03, 0x7f, 0xff, 0x22, 0x90, 0x00, 0x04, 0x12, 0x9f, 0x61, 0x25} },
-{ 0x8120,	16,	{0x4c, 0xf5, 0x4c, 0xe4, 0x35, 0x4b, 0xf5, 0x4b, 0x90, 0x00, 0x05, 0x12, 0x9f, 0x61, 0xfe, 0xe4} },
-{ 0x8130,	16,	{0x25, 0x4c, 0xf5, 0x4c, 0xee, 0x35, 0x4b, 0xf5, 0x4b, 0x02, 0x81, 0xb8, 0xab, 0x4d, 0xaa, 0x4e} },
-{ 0x8140,	16,	{0xa9, 0x4f, 0x90, 0x00, 0x03, 0x12, 0x9f, 0x61, 0xff, 0x64, 0x02, 0x60, 0x05, 0xef, 0x64, 0x03} },
-{ 0x8150,	16,	{0x70, 0x60, 0x90, 0x00, 0x02, 0x12, 0x9f, 0x61, 0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50} },
+{ 0x8110,	16,	{0xae, 0xe0, 0x04, 0xf0, 0x80, 0x03, 0x7f, 0xff, 0x22, 0x90, 0x00, 0x04, 0x12, 0xa0, 0x58, 0x25} },
+{ 0x8120,	16,	{0x4d, 0xf5, 0x4d, 0xe4, 0x35, 0x4c, 0xf5, 0x4c, 0x90, 0x00, 0x05, 0x12, 0xa0, 0x58, 0xfe, 0xe4} },
+{ 0x8130,	16,	{0x25, 0x4d, 0xf5, 0x4d, 0xee, 0x35, 0x4c, 0xf5, 0x4c, 0x02, 0x81, 0xb8, 0xab, 0x4e, 0xaa, 0x4f} },
+{ 0x8140,	16,	{0xa9, 0x50, 0x90, 0x00, 0x03, 0x12, 0xa0, 0x58, 0xff, 0x64, 0x02, 0x60, 0x05, 0xef, 0x64, 0x03} },
+{ 0x8150,	16,	{0x70, 0x60, 0x90, 0x00, 0x02, 0x12, 0xa0, 0x58, 0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50} },
 { 0x8160,	16,	{0x4e, 0xef, 0x30, 0xe7, 0x1e, 0x90, 0x7f, 0xde, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80} },
 { 0x8170,	16,	{0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x4e} },
 { 0x8180,	16,	{0xf0, 0x80, 0x35, 0x90, 0x7f, 0xdf, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80, 0x02, 0xc3} },
 { 0x8190,	16,	{0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xad, 0xe0, 0x4e, 0xf0, 0xec} },
 { 0x81a0,	16,	{0x25, 0xe0, 0x24, 0xc5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x09, 0x7f} },
-{ 0x81b0,	16,	{0xff, 0x22, 0x7f, 0xff, 0x22, 0x7f, 0xff, 0x22, 0x74, 0x07, 0x25, 0x4f, 0xf5, 0x4f, 0xe4, 0x35} },
-{ 0x81c0,	16,	{0x4e, 0xf5, 0x4e, 0x02, 0x80, 0x51, 0x20, 0x03, 0x0d, 0x90, 0x02, 0xae, 0xe0, 0x60, 0x07, 0x90} },
+{ 0x81b0,	16,	{0xff, 0x22, 0x7f, 0xff, 0x22, 0x7f, 0xff, 0x22, 0x74, 0x07, 0x25, 0x50, 0xf5, 0x50, 0xe4, 0x35} },
+{ 0x81c0,	16,	{0x4f, 0xf5, 0x4f, 0x02, 0x80, 0x51, 0x20, 0x03, 0x0d, 0x90, 0x02, 0xae, 0xe0, 0x60, 0x07, 0x90} },
 { 0x81d0,	8,	{0x7f, 0xae, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0x00} },
 { 0x81d8,	1,	{0x22} },
 { 0x81d9,	2,	{0xac, 0x07} },
@@ -513,549 +508,569 @@
 { 0x828b,	16,	{0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f, 0xfa, 0x22, 0xc2, 0xaf, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
 { 0x829b,	12,	{0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0xd2, 0xaf, 0xff, 0x7e, 0x00} },
 { 0x82a7,	1,	{0x22} },
-{ 0x82a8,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xf5} },
-{ 0x82b8,	16,	{0x83, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x5e, 0x74, 0xbf} },
-{ 0x82c8,	16,	{0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x44, 0x10, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3} },
-{ 0x82d8,	16,	{0xa3, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xf0, 0xf9, 0xed, 0x60, 0x1d, 0x74, 0x01} },
-{ 0x82e8,	16,	{0x7e, 0x00, 0xa8, 0x07, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe4} },
-{ 0x82f8,	16,	{0xef, 0x55, 0x3b, 0x60, 0x04, 0x79, 0x09, 0x80, 0x02, 0x79, 0x0d, 0x8b, 0x82, 0x8a, 0x83, 0xa3} },
-{ 0x8308,	16,	{0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x54, 0xef, 0xf0, 0x8b} },
-{ 0x8318,	16,	{0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe5, 0x5e, 0xf0, 0xae, 0x02, 0xaf, 0x03, 0x8f, 0x82, 0x8e} },
-{ 0x8328,	4,	{0x83, 0xa3, 0xe9, 0xf0} },
-{ 0x832c,	1,	{0x22} },
-{ 0x832d,	4,	{0x8f, 0x5e, 0x8d, 0x5f} },
-{ 0x8331,	16,	{0xe4, 0xf5, 0x60, 0x74, 0x3c, 0x2f, 0xf8, 0x76, 0x08, 0xe5, 0x5e, 0x75, 0xf0, 0x0d, 0xa4, 0x24} },
-{ 0x8341,	16,	{0x02, 0xf5, 0x82, 0xe4, 0x34, 0x03, 0xf5, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} },
-{ 0x8351,	16,	{0xa3, 0xe0, 0xff, 0x7b, 0x80, 0x7a, 0x25, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0xa0, 0xc0, 0x50} },
-{ 0x8361,	16,	{0x3c, 0xe5, 0x5e, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34, 0x03, 0xf5, 0x83} },
-{ 0x8371,	16,	{0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x96, 0x78} },
-{ 0x8381,	16,	{0x00, 0xc3, 0x12, 0xa0, 0xc0, 0x40, 0x0c, 0x75, 0x60, 0x40, 0x74, 0x3c, 0x25, 0x5e, 0xf8, 0x76} },
-{ 0x8391,	16,	{0x10, 0x80, 0x0a, 0x75, 0x60, 0x80, 0x74, 0x3c, 0x25, 0x5e, 0xf8, 0x76, 0x38, 0xe5, 0x60, 0x45} },
-{ 0x83a1,	16,	{0x5f, 0x44, 0x01, 0xff, 0xe5, 0x5e, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34} },
-{ 0x83b1,	5,	{0x20, 0xf5, 0x83, 0xef, 0xf0} },
-{ 0x83b6,	1,	{0x22} },
-{ 0x83b7,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x54, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22} },
-{ 0x83c7,	16,	{0xe5, 0x54, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5} },
-{ 0x83d7,	16,	{0x55, 0x8f, 0x56, 0xe5, 0x54, 0x25, 0xe0, 0x24, 0xc6, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} },
-{ 0x83e7,	16,	{0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x54, 0x25, 0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} },
-{ 0x83f7,	16,	{0x83, 0xe4, 0xf0, 0x74, 0x22, 0x25, 0x54, 0xf8, 0xe4, 0xf6, 0xe5, 0x56, 0x24, 0x04, 0xf5, 0x82} },
-{ 0x8407,	16,	{0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0x44, 0x03, 0xf0, 0xaf, 0x54, 0x7d, 0x06, 0x12, 0x83, 0x2d} },
-{ 0x8417,	16,	{0xaf, 0x54, 0x7d, 0x01, 0x12, 0x82, 0xa8, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xa3, 0xe0} },
-{ 0x8427,	16,	{0x20, 0xe0, 0x22, 0xe0, 0xff, 0xe5, 0x56, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83} },
-{ 0x8437,	16,	{0xe0, 0xe5, 0x56, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0xff, 0xaf, 0x54} },
-{ 0x8447,	16,	{0x7d, 0x06, 0x12, 0x83, 0x2d, 0x74, 0xf8, 0x25, 0x54, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} },
-{ 0x8457,	16,	{0xe4, 0xf0, 0xe5, 0x54, 0x25, 0xe0, 0xff, 0xc3, 0x74, 0x0c, 0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24} },
-{ 0x8467,	16,	{0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82, 0xfe, 0xe5, 0x54, 0x25, 0xe0, 0x24, 0xef} },
-{ 0x8477,	16,	{0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xaf, 0x54, 0x74, 0x01} },
-{ 0x8487,	13,	{0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x30, 0x7f, 0x00} },
-{ 0x8494,	1,	{0x22} },
-{ 0x8495,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x54, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22} },
-{ 0x84a5,	16,	{0xaf, 0x54, 0xe4, 0xfd, 0x12, 0x82, 0xa8, 0x74, 0xf8, 0x25, 0x54, 0xf5, 0x82, 0xe4, 0x34, 0x02} },
-{ 0x84b5,	16,	{0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x54, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34} },
-{ 0x84c5,	16,	{0x20, 0xaf, 0x82, 0xf5, 0x56, 0x8f, 0x57, 0xf5, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82, 0xe4} },
-{ 0x84d5,	16,	{0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf, 0x54, 0x7d, 0x06, 0x12, 0x83, 0x2d, 0xe5} },
-{ 0x84e5,	16,	{0x57, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x56, 0xf5, 0x83, 0xe0, 0x30, 0xe0, 0x09, 0x85, 0x57} },
-{ 0x84f5,	16,	{0x82, 0x85, 0x56, 0x83, 0xe0, 0xf5, 0x55, 0xaf, 0x54, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02} },
-{ 0x8505,	16,	{0xc3, 0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x30, 0xe5, 0x54, 0x25, 0xe0, 0x24, 0xc6, 0xf5, 0x82, 0xe4} },
-{ 0x8515,	16,	{0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x54, 0x25, 0xe0, 0x24, 0xc7, 0xf5, 0x82} },
-{ 0x8525,	9,	{0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x7f, 0x00} },
-{ 0x852e,	1,	{0x22} },
-{ 0x852f,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0xa3, 0xa3, 0xa3, 0xe0, 0xfc, 0xed} },
-{ 0x853f,	16,	{0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xc0, 0x83, 0xc0} },
-{ 0x854f,	16,	{0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0} },
-{ 0x855f,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0xe0, 0xfd, 0xec, 0x6d, 0xd0} },
-{ 0x856f,	16,	{0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f} },
-{ 0x857f,	16,	{0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82} },
-{ 0x858f,	16,	{0x8e, 0x83, 0xa3, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0} },
-{ 0x859f,	16,	{0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0} },
-{ 0x85af,	16,	{0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xff, 0xed, 0x6f, 0xd0, 0x82, 0xd0} },
-{ 0x85bf,	3,	{0x83, 0xf0, 0x22} },
-{ 0x85c2,	4,	{0xad, 0x07, 0xac, 0x06} },
-{ 0x85c6,	16,	{0x79, 0x0d, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff} },
-{ 0x85d6,	16,	{0x22, 0x8c, 0x54, 0x8d, 0x55, 0xee, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34} },
-{ 0x85e6,	16,	{0x03, 0xaf, 0x82, 0xfe, 0xad, 0x01, 0x19, 0xed, 0x60, 0x24, 0x0f, 0xef, 0xac, 0x06, 0x70, 0x01} },
-{ 0x85f6,	16,	{0x0e, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe0, 0xfd, 0x05, 0x55, 0xe5, 0x55, 0xaa, 0x54, 0x70, 0x02} },
-{ 0x8606,	16,	{0x05, 0x54, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xe0, 0x6d, 0x60, 0xd9, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
-{ 0x8616,	1,	{0x22} },
-{ 0x8617,	4,	{0x8e, 0x54, 0x8f, 0x55} },
-{ 0x861b,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x5b, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22} },
-{ 0x862b,	16,	{0xe5, 0x5b, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5} },
-{ 0x863b,	16,	{0x5c, 0x8f, 0x5d, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3} },
-{ 0x864b,	16,	{0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x08, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xd3, 0x12, 0xa0} },
-{ 0x865b,	16,	{0xc0, 0x40, 0x10, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0x12, 0xa1, 0x07, 0x00, 0x00, 0x00} },
-{ 0x866b,	16,	{0x08, 0x80, 0x2e, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3} },
-{ 0x867b,	16,	{0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x08, 0x79, 0x07, 0x78, 0x00, 0xc3, 0x12, 0xa0} },
-{ 0x868b,	16,	{0xc0, 0x50, 0x0e, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0x12, 0xa1, 0x07, 0x00, 0x07, 0x08} },
-{ 0x869b,	16,	{0x00, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa} },
-{ 0x86ab,	16,	{0xa3, 0xe0, 0xfb, 0x7f, 0x00, 0x7e, 0x50, 0x7d, 0x46, 0x7c, 0x00, 0x12, 0xa0, 0x2e, 0x8f, 0x59} },
-{ 0x86bb,	16,	{0x8e, 0x58, 0x8d, 0x57, 0x8c, 0x56, 0x7b, 0x0a, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0x12, 0xa0} },
-{ 0x86cb,	16,	{0x2e, 0xaf, 0x03, 0x8f, 0x5a, 0xaf, 0x59, 0xae, 0x58, 0xad, 0x57, 0xac, 0x56, 0x7b, 0x0a, 0x7a} },
-{ 0x86db,	16,	{0x00, 0x79, 0x00, 0x78, 0x00, 0x12, 0xa0, 0x2e, 0x8f, 0x59, 0x8e, 0x58, 0x8d, 0x57, 0x8c, 0x56} },
-{ 0x86eb,	16,	{0xe5, 0x5a, 0xc3, 0x94, 0x05, 0x40, 0x15, 0xe5, 0x59, 0x24, 0x01, 0xf5, 0x59, 0xe4, 0x35, 0x58} },
-{ 0x86fb,	16,	{0xf5, 0x58, 0xe4, 0x35, 0x57, 0xf5, 0x57, 0xe4, 0x35, 0x56, 0xf5, 0x56, 0x85, 0x5d, 0x82, 0x85} },
-{ 0x870b,	16,	{0x5c, 0x83, 0xa3, 0xe4, 0xf0, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44} },
-{ 0x871b,	16,	{0x80, 0xf0, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xe5, 0x59, 0xf0, 0xaf, 0x59, 0xae, 0x58, 0xad} },
-{ 0x872b,	16,	{0x57, 0xac, 0x56, 0x78, 0x08, 0x12, 0xa0, 0xd1, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xef} },
-{ 0x873b,	16,	{0xf0, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0xe4, 0xf5} },
-{ 0x874b,	16,	{0x5a, 0xe5, 0x55, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0xb4, 0x62} },
-{ 0x875b,	16,	{0x05, 0x43, 0x5a, 0x0a, 0x80, 0x1a, 0xef, 0xb4, 0x72, 0x05, 0x43, 0x5a, 0x08, 0x80, 0x11, 0xef} },
-{ 0x876b,	16,	{0xb4, 0x74, 0x05, 0x43, 0x5a, 0x02, 0x80, 0x08, 0xef, 0x64, 0x6e, 0x60, 0x03, 0x7f, 0xff, 0x22} },
-{ 0x877b,	16,	{0xe5, 0x55, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0x30, 0xe3, 0x03} },
-{ 0x878b,	16,	{0x43, 0x5a, 0x80, 0xef, 0x30, 0xe7, 0x12, 0x43, 0x5a, 0x40, 0xe5, 0x5d, 0x24, 0x04, 0xf5, 0x82} },
-{ 0x879b,	16,	{0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x55, 0x24, 0x0b, 0xf5, 0x82, 0xe4} },
-{ 0x87ab,	16,	{0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0x20, 0xe1, 0x03, 0x30, 0xe4, 0x23, 0xaf, 0x5b, 0x74, 0x01} },
-{ 0x87bb,	16,	{0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x3b, 0xe5, 0x5d, 0x24, 0x04, 0xf5} },
-{ 0x87cb,	16,	{0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0xe4, 0xf5, 0x5a, 0x80, 0x10, 0xaf} },
-{ 0x87db,	16,	{0x5b, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x3b, 0x85} },
-{ 0x87eb,	16,	{0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x85, 0x5d, 0x82, 0x85, 0x5c} },
-{ 0x87fb,	16,	{0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5a, 0xf0, 0xe5, 0x55, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35} },
-{ 0x880b,	16,	{0x54, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x5d, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83} },
-{ 0x881b,	16,	{0xef, 0xf0, 0xe5, 0x55, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0xe5} },
-{ 0x882b,	16,	{0x5d, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x55, 0x24, 0x09} },
-{ 0x883b,	16,	{0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x5d, 0x24, 0x06, 0xf5, 0x82, 0xe4} },
-{ 0x884b,	16,	{0x35, 0x5c, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x55, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5} },
-{ 0x885b,	16,	{0x83, 0xe0, 0xff, 0xe5, 0x5d, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xef, 0xf0} },
-{ 0x886b,	16,	{0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3, 0xa3, 0xa3, 0xe4, 0xf0, 0x85, 0x5d, 0x82, 0x85, 0x5c} },
-{ 0x887b,	16,	{0x83, 0xa3, 0xa3, 0xf0, 0xaf, 0x5b, 0x7d, 0x06, 0x12, 0x83, 0x2d, 0x75, 0x5a, 0x08, 0xe5, 0x55} },
-{ 0x888b,	16,	{0x24, 0x0c, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0x43, 0x5a, 0x10, 0xe5} },
-{ 0x889b,	16,	{0x5d, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x5c, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x45, 0x5a, 0xf0} },
-{ 0x88ab,	16,	{0xe5, 0x55, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xfe, 0xc3, 0x94, 0x05} },
-{ 0x88bb,	16,	{0x40, 0x06, 0xee, 0xd3, 0x94, 0x08, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xe5, 0x55, 0x24, 0x06, 0xf5} },
-{ 0x88cb,	16,	{0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0, 0xfd, 0xc3, 0x94, 0x01, 0x40, 0x06, 0xed, 0xd3, 0x94} },
-{ 0x88db,	16,	{0x02, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xed, 0x14, 0xff, 0x25, 0xe0, 0x25, 0xe0, 0xff, 0xee, 0x24} },
-{ 0x88eb,	16,	{0xfb, 0x4f, 0xf5, 0x5a, 0xe5, 0x55, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x54, 0xf5, 0x83, 0xe0} },
-{ 0x88fb,	16,	{0x24, 0xd0, 0x60, 0x18, 0x14, 0x60, 0x1a, 0x24, 0xc3, 0x60, 0x1e, 0x14, 0x60, 0x09, 0x24, 0x0a} },
-{ 0x890b,	16,	{0x70, 0x14, 0x43, 0x5a, 0x18, 0x80, 0x12, 0x43, 0x5a, 0x08, 0x80, 0x0d, 0x43, 0x5a, 0x38, 0x80} },
-{ 0x891b,	16,	{0x08, 0x43, 0x5a, 0x28, 0x80, 0x03, 0x7f, 0xff, 0x22, 0x85, 0x5d, 0x82, 0x85, 0x5c, 0x83, 0xa3} },
-{ 0x892b,	16,	{0xa3, 0xa3, 0xe5, 0x5a, 0xf0, 0xaf, 0x5b, 0x7d, 0x01, 0x12, 0x82, 0xa8, 0xaa, 0x54, 0xa9, 0x55} },
-{ 0x893b,	16,	{0x7b, 0x01, 0xc0, 0x01, 0xe5, 0x5b, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x01, 0xf9, 0x74, 0x03, 0x35} },
-{ 0x894b,	15,	{0xf0, 0xa8, 0x01, 0xfc, 0xd0, 0x01, 0x7e, 0x00, 0x7f, 0x0d, 0x12, 0x9f, 0x1f, 0x7f, 0x00} },
-{ 0x895a,	1,	{0x22} },
-{ 0x895b,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
-{ 0x896b,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xad, 0x82, 0xfc, 0x90, 0x01} },
-{ 0x897b,	16,	{0x2c, 0x74, 0x08, 0xf0, 0xee, 0x04, 0xa3, 0xf0, 0xe4, 0xa3, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xe5} },
-{ 0x898b,	16,	{0x82, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x90, 0x01, 0x2f, 0xf0, 0x8d} },
-{ 0x899b,	16,	{0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54} },
-{ 0x89ab,	16,	{0x1e, 0x90, 0x01, 0x30, 0xf0, 0x74, 0x2c, 0x2e, 0xf8, 0xe6, 0xa3, 0xf0, 0xaf, 0x06, 0x74, 0x01} },
-{ 0x89bb,	16,	{0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x54, 0x7f, 0x02, 0x12, 0x81, 0xd9} },
-{ 0x89cb,	16,	{0xc3, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xe5, 0x54, 0x5f, 0x90, 0x01, 0x32, 0xf0, 0x7e} },
-{ 0x89db,	10,	{0x01, 0x7f, 0x2c, 0x7d, 0x07, 0x12, 0x8e, 0xb4, 0x7f, 0x00} },
-{ 0x89e5,	1,	{0x22} },
-{ 0x89e6,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
-{ 0x89f6,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0x90, 0x01} },
-{ 0x8a06,	16,	{0x33, 0x74, 0x0a, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35} },
-{ 0x8a16,	16,	{0x83, 0xf5, 0x83, 0xe0, 0x90, 0x01, 0x34, 0xf0, 0x7e, 0x01, 0x7f, 0x33, 0x7d, 0x02, 0x12, 0x8e} },
-{ 0x8a26,	3,	{0xb4, 0x7f, 0x00} },
-{ 0x8a29,	1,	{0x22} },
-{ 0x8a2a,	4,	{0xad, 0x07, 0xac, 0x06} },
-{ 0x8a2e,	16,	{0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
-{ 0x8a3e,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0x8d, 0x82} },
-{ 0x8a4e,	16,	{0x8c, 0x83, 0xa3, 0xe0, 0x60, 0x0f, 0xef, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0} },
-{ 0x8a5e,	16,	{0x44, 0x02, 0xf0, 0x80, 0x0d, 0xef, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54} },
-{ 0x8a6e,	4,	{0xfd, 0xf0, 0x7f, 0x00} },
-{ 0x8a72,	1,	{0x22} },
-{ 0x8a73,	4,	{0xad, 0x07, 0xac, 0x06} },
-{ 0x8a77,	16,	{0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
-{ 0x8a87,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0x8d, 0x82} },
-{ 0x8a97,	16,	{0x8c, 0x83, 0xa3, 0xe0, 0x60, 0x0f, 0xef, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0} },
-{ 0x8aa7,	16,	{0x44, 0x01, 0xf0, 0x80, 0x0d, 0xef, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54} },
-{ 0x8ab7,	4,	{0xfe, 0xf0, 0x7f, 0x00} },
-{ 0x8abb,	1,	{0x22} },
-{ 0x8abc,	4,	{0xad, 0x07, 0xac, 0x06} },
-{ 0x8ac0,	16,	{0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
-{ 0x8ad0,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0x8d, 0x82} },
-{ 0x8ae0,	16,	{0x8c, 0x83, 0xa3, 0xe0, 0x60, 0x0d, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x40} },
-{ 0x8af0,	16,	{0xf0, 0x80, 0x0b, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x00} },
-{ 0x8b00,	1,	{0x22} },
-{ 0x8b01,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xaf} },
-{ 0x8b11,	16,	{0x06, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x3a, 0x7f, 0x00} },
-{ 0x8b21,	1,	{0x22} },
-{ 0x8b22,	4,	{0x8e, 0x54, 0x8f, 0x55} },
-{ 0x8b26,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0, 0xf5, 0x59, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x56, 0xc3} },
-{ 0x8b36,	16,	{0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xe5, 0x56, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x1f} },
-{ 0x8b46,	16,	{0x14, 0x60, 0x28, 0x24, 0x03, 0x70, 0x2e, 0x7e, 0x7e, 0x7f, 0x80, 0x75, 0x57, 0x7e, 0x75, 0x58} },
-{ 0x8b56,	16,	{0x80, 0x80, 0x22, 0x7e, 0x7e, 0x7f, 0x00, 0x75, 0x57, 0x7e, 0x75, 0x58, 0x00, 0x80, 0x16, 0x7e} },
-{ 0x8b66,	16,	{0x7d, 0x7f, 0x80, 0x75, 0x57, 0x7d, 0x75, 0x58, 0x80, 0x80, 0x0a, 0x7e, 0x7d, 0x7f, 0x00, 0x75} },
-{ 0x8b76,	16,	{0x57, 0x7d, 0x75, 0x58, 0x00, 0xe5, 0x59, 0x70, 0x1b, 0x85, 0x58, 0x82, 0x85, 0x57, 0x83, 0x74} },
-{ 0x8b86,	16,	{0xff, 0xf0, 0xe5, 0x56, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74} },
-{ 0x8b96,	16,	{0x01, 0xf0, 0x80, 0x48, 0xe5, 0x55, 0x24, 0x02, 0xff, 0xe4, 0x35, 0x54, 0xfe, 0xe5, 0x59, 0x60} },
-{ 0x8ba6,	16,	{0x23, 0x0f, 0xef, 0xac, 0x06, 0x70, 0x01, 0x0e, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe0, 0xfd, 0x05} },
-{ 0x8bb6,	16,	{0x58, 0xe5, 0x58, 0xaa, 0x57, 0x70, 0x02, 0x05, 0x57, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xed, 0xf0} },
-{ 0x8bc6,	16,	{0x15, 0x59, 0x80, 0xd9, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xff, 0xe5, 0x56, 0x25} },
-{ 0x8bd6,	14,	{0xe0, 0x24, 0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x7f, 0x00} },
-{ 0x8be4,	1,	{0x22} },
-{ 0x8be5,	16,	{0xef, 0x24, 0x05, 0xf5, 0x55, 0xe4, 0x3e, 0xf5, 0x54, 0x90, 0x01, 0x35, 0x74, 0x07, 0xf0, 0x90} },
-{ 0x8bf5,	16,	{0x01, 0x7a, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x36, 0xf0, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3} },
-{ 0x8c05,	16,	{0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0x8e, 0x56, 0xf5, 0x57, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83} },
-{ 0x8c15,	16,	{0xe0, 0x24, 0x9e, 0x60, 0x61, 0x24, 0xf9, 0x60, 0x0e, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8c, 0xc6} },
-{ 0x8c25,	16,	{0x24, 0x14, 0x60, 0x03, 0x02, 0x8d, 0x12, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe} },
-{ 0x8c35,	16,	{0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f, 0xf5, 0x59, 0x74, 0x01, 0x9e, 0xf5, 0x58, 0xd3, 0xe5, 0x59} },
-{ 0x8c45,	16,	{0x94, 0x40, 0xe5, 0x58, 0x94, 0x00, 0x40, 0x06, 0x75, 0x58, 0x00, 0x75, 0x59, 0x40, 0xd3, 0xe5} },
-{ 0x8c55,	16,	{0x57, 0x95, 0x59, 0xe5, 0x56, 0x95, 0x58, 0x50, 0x03, 0x02, 0x8d, 0x15, 0xae, 0x58, 0xaf, 0x59} },
-{ 0x8c65,	16,	{0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e} },
-{ 0x8c75,	16,	{0x56, 0xf5, 0x57, 0x02, 0x8d, 0x15, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe, 0xa3} },
-{ 0x8c85,	16,	{0xe0, 0xff, 0xc3, 0x74, 0x30, 0x9f, 0xf5, 0x59, 0xe4, 0x9e, 0xf5, 0x58, 0xd3, 0xe5, 0x59, 0x94} },
-{ 0x8c95,	16,	{0x10, 0xe5, 0x58, 0x94, 0x00, 0x40, 0x06, 0x75, 0x58, 0x00, 0x75, 0x59, 0x10, 0xd3, 0xe5, 0x57} },
-{ 0x8ca5,	16,	{0x95, 0x59, 0xe5, 0x56, 0x95, 0x58, 0x40, 0x68, 0xae, 0x58, 0xaf, 0x59, 0x85, 0x55, 0x82, 0x85} },
-{ 0x8cb5,	16,	{0x54, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x56, 0xf5, 0x57, 0x80} },
-{ 0x8cc5,	16,	{0x4f, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f} },
-{ 0x8cd5,	16,	{0xf5, 0x59, 0xe4, 0x9e, 0xf5, 0x58, 0x45, 0x59, 0x60, 0x0b, 0xd3, 0xe5, 0x59, 0x94, 0x40, 0xe5} },
-{ 0x8ce5,	16,	{0x58, 0x94, 0x00, 0x40, 0x06, 0x75, 0x58, 0x00, 0x75, 0x59, 0x40, 0xd3, 0xe5, 0x57, 0x95, 0x59} },
-{ 0x8cf5,	16,	{0xe5, 0x56, 0x95, 0x58, 0x40, 0x17, 0xae, 0x58, 0xaf, 0x59, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83} },
-{ 0x8d05,	16,	{0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x56, 0xf5, 0x57, 0x7f, 0x01, 0x22} },
-{ 0x8d15,	16,	{0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xe0, 0x24, 0x9e, 0x70, 0x03, 0x02, 0x8d, 0xd5, 0x24, 0xf9} },
-{ 0x8d25,	16,	{0x60, 0x58, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8e, 0x25, 0x24, 0x14, 0x60, 0x03, 0x02, 0x8e, 0x69} },
-{ 0x8d35,	16,	{0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xd3, 0x94, 0xff, 0xee} },
-{ 0x8d45,	16,	{0x94, 0x00, 0x40, 0x03, 0x02, 0x8e, 0x69, 0x90, 0x01, 0x75, 0xef, 0xf0, 0xe5, 0x57, 0x15, 0x57} },
-{ 0x8d55,	16,	{0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e, 0x70, 0x03, 0x02, 0x8e, 0x69, 0x90, 0x01, 0x75, 0xe0} },
-{ 0x8d65,	16,	{0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9f} },
-{ 0x8d75,	16,	{0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83} },
-{ 0x8d85,	16,	{0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x80, 0xee, 0x94, 0x00, 0x50, 0x03, 0x02, 0x8e} },
-{ 0x8d95,	16,	{0x69, 0xd3, 0xef, 0x94, 0xff, 0xee, 0x94, 0x00, 0x40, 0x03, 0x02, 0x8e, 0x69, 0x90, 0x01, 0x76} },
-{ 0x8da5,	16,	{0xef, 0xf0, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e, 0x70, 0x03, 0x02} },
-{ 0x8db5,	16,	{0x8e, 0x69, 0x90, 0x01, 0x76, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a} },
-{ 0x8dc5,	16,	{0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9f, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2} },
-{ 0x8dd5,	16,	{0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x20, 0xee} },
-{ 0x8de5,	16,	{0x94, 0x00, 0x50, 0x03, 0x02, 0x8e, 0x69, 0xd3, 0xef, 0x94, 0x2f, 0xee, 0x94, 0x00, 0x50, 0x74} },
-{ 0x8df5,	16,	{0x90, 0x01, 0x77, 0xef, 0xf0, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e} },
-{ 0x8e05,	16,	{0x60, 0x62, 0x90, 0x01, 0x77, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a} },
-{ 0x8e15,	16,	{0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9f, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd5} },
-{ 0x8e25,	16,	{0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x01, 0x78, 0xcf, 0xf0} },
-{ 0x8e35,	16,	{0xa3, 0xef, 0xf0, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0x4e, 0x60, 0x24} },
-{ 0x8e45,	16,	{0x90, 0x01, 0x78, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9f, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0} },
-{ 0x8e55,	16,	{0xff, 0x90, 0x01, 0x7a, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9f, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83} },
-{ 0x8e65,	16,	{0xef, 0xf0, 0x80, 0xcf, 0x7e, 0x01, 0x7f, 0x35, 0x85, 0x55, 0x82, 0x85, 0x54, 0x83, 0xa3, 0xa3} },
-{ 0x8e75,	11,	{0xa3, 0xe0, 0xa3, 0xe0, 0x04, 0xfd, 0x12, 0x8e, 0xb4, 0x7f, 0x00} },
-{ 0x8e80,	1,	{0x22} },
-{ 0x8e81,	16,	{0x8e, 0x5f, 0x8f, 0x60, 0x8c, 0x61, 0x8d, 0x62, 0xaf, 0x03, 0x1b, 0xef, 0x60, 0x24, 0x05, 0x60} },
-{ 0x8e91,	16,	{0xe5, 0x60, 0xae, 0x5f, 0x70, 0x02, 0x05, 0x5f, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05} },
-{ 0x8ea1,	16,	{0x62, 0xe5, 0x62, 0xac, 0x61, 0x70, 0x02, 0x05, 0x61, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
-{ 0x8eb1,	3,	{0x80, 0xd6, 0x22} },
-{ 0x8eb4,	6,	{0x8d, 0x5a, 0xab, 0x07, 0xaa, 0x06} },
-{ 0x8eba,	16,	{0x75, 0x5e, 0x40, 0x75, 0x5d, 0x0d, 0x75, 0x5c, 0x03, 0x75, 0x5b, 0x00, 0x90, 0x7f, 0xc2, 0xe0} },
-{ 0x8eca,	16,	{0x20, 0xe1, 0xf9, 0xaf, 0x5e, 0xae, 0x5d, 0xad, 0x5c, 0xac, 0x5b, 0xec, 0x4d, 0x4e, 0x4f, 0x70} },
-{ 0x8eda,	16,	{0x08, 0x90, 0x7f, 0xc2, 0x74, 0x02, 0xf0, 0x80, 0xd7, 0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x16} },
-{ 0x8eea,	16,	{0xaf, 0x03, 0xae, 0x02, 0x7c, 0x7b, 0x7d, 0x80, 0xab, 0x5a, 0x12, 0x8e, 0x81, 0x90, 0x7f, 0xc3} },
-{ 0x8efa,	8,	{0xe5, 0x5a, 0xf0, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
-{ 0x8f02,	1,	{0x22} },
-{ 0x8f03,	16,	{0x90, 0x01, 0x84, 0x74, 0x0b, 0xf0, 0x90, 0x20, 0x70, 0xe0, 0x54, 0xf0, 0xff, 0xc4, 0x54, 0x0f} },
-{ 0x8f13,	16,	{0x90, 0x01, 0x85, 0xf0, 0x90, 0x95, 0xbf, 0xe4, 0x93, 0x90, 0x01, 0x86, 0xf0, 0x90, 0x95, 0xc0} },
-{ 0x8f23,	16,	{0xe4, 0x93, 0x90, 0x01, 0x87, 0xf0, 0xe4, 0x90, 0x01, 0x7c, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
-{ 0x8f33,	16,	{0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x88, 0xf0, 0x7e} },
-{ 0x8f43,	16,	{0x01, 0x7f, 0x7c, 0x12, 0x10, 0x2c, 0x7e, 0x01, 0x7f, 0x84, 0x7d, 0x14, 0x12, 0x8e, 0xb4, 0x7f} },
-{ 0x8f53,	1,	{0x00} },
-{ 0x8f54,	1,	{0x22} },
-{ 0x8f55,	16,	{0x7e, 0x7b, 0x7f, 0x40, 0x75, 0x4b, 0x7b, 0x75, 0x4c, 0x40, 0x90, 0x7f, 0xd3, 0xe0, 0xff, 0x85} },
-{ 0x8f65,	16,	{0x4b, 0x4e, 0x85, 0x4c, 0x4f, 0xe5, 0x4f, 0x24, 0x01, 0xf5, 0x53, 0xe4, 0x35, 0x4e, 0xf5, 0x52} },
-{ 0x8f75,	16,	{0xe4, 0xf5, 0x4d, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xe0, 0xfe, 0x14, 0xb4, 0x0c, 0x00, 0x50} },
-{ 0x8f85,	16,	{0x5b, 0x90, 0x8f, 0x8d, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x8f, 0xb1, 0x02, 0x8f, 0xb1, 0x02, 0x8f} },
-{ 0x8f95,	16,	{0xbb, 0x02, 0x8f, 0xc5, 0x02, 0x8f, 0xc5, 0x02, 0x8f, 0xc5, 0x02, 0x8f, 0xd9, 0x02, 0x8f, 0xb1} },
-{ 0x8fa5,	16,	{0x02, 0x8f, 0xcf, 0x02, 0x8f, 0xb1, 0x02, 0x8f, 0xe1, 0x02, 0x8f, 0xb1, 0xef, 0x64, 0x02, 0x60} },
-{ 0x8fb5,	16,	{0x2b, 0x75, 0x4d, 0xff, 0x80, 0x26, 0xef, 0x64, 0x0e, 0x60, 0x21, 0x75, 0x4d, 0xff, 0x80, 0x1c} },
-{ 0x8fc5,	16,	{0xef, 0x64, 0x03, 0x60, 0x17, 0x75, 0x4d, 0xff, 0x80, 0x12, 0xef, 0x64, 0x03, 0x60, 0x0d, 0x75} },
-{ 0x8fd5,	16,	{0x4d, 0xff, 0x80, 0x08, 0xef, 0x64, 0x06, 0x60, 0x03, 0x75, 0x4d, 0xff, 0xe5, 0x4d, 0x60, 0x15} },
-{ 0x8fe5,	16,	{0x90, 0x01, 0x98, 0x74, 0x11, 0xf0, 0xa3, 0xee, 0xf0, 0x7e, 0x01, 0x7f, 0x98, 0x7d, 0x02, 0x12} },
-{ 0x8ff5,	16,	{0x8e, 0xb4, 0xaf, 0x4d, 0x22, 0xe4, 0xf5, 0x4d, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xe0, 0x14} },
-{ 0x9005,	16,	{0xb4, 0x0f, 0x00, 0x40, 0x03, 0x02, 0x91, 0x23, 0x90, 0x90, 0x14, 0xf8, 0x28, 0x28, 0x73, 0x02} },
-{ 0x9015,	16,	{0x90, 0x41, 0x02, 0x90, 0x4d, 0x02, 0x90, 0x59, 0x02, 0x90, 0xa7, 0x02, 0x90, 0xb2, 0x02, 0x90} },
-{ 0x9025,	16,	{0xbd, 0x02, 0x90, 0xc8, 0x02, 0x90, 0xd3, 0x02, 0x90, 0xde, 0x02, 0x90, 0xe9, 0x02, 0x90, 0xf4} },
-{ 0x9035,	16,	{0x02, 0x90, 0xfb, 0x02, 0x91, 0x23, 0x02, 0x91, 0x06, 0x02, 0x91, 0x11, 0xaf, 0x53, 0xae, 0x52} },
-{ 0x9045,	16,	{0x12, 0x83, 0xb7, 0x8f, 0x4d, 0x02, 0x91, 0x26, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x84, 0x95, 0x8f} },
-{ 0x9055,	16,	{0x4d, 0x02, 0x91, 0x26, 0x85, 0x52, 0x50, 0x85, 0x53, 0x51, 0xe5, 0x51, 0x24, 0x01, 0xff, 0xe4} },
-{ 0x9065,	16,	{0x35, 0x50, 0xfe, 0x12, 0x85, 0x2f, 0xaf, 0x51, 0xae, 0x50, 0x12, 0x85, 0xc2, 0x8f, 0x4d, 0xef} },
-{ 0x9075,	16,	{0x64, 0x01, 0x60, 0x03, 0x02, 0x91, 0x26, 0xaf, 0x51, 0xae, 0x50, 0x12, 0x86, 0x17, 0x8f, 0x4d} },
-{ 0x9085,	16,	{0xe5, 0x4d, 0x70, 0x03, 0x02, 0x91, 0x26, 0x85, 0x51, 0x82, 0x85, 0x50, 0x83, 0xe0, 0x75, 0xf0} },
-{ 0x9095,	16,	{0x0d, 0xa4, 0x24, 0xf4, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xaf, 0x82, 0xfe, 0x12, 0x86, 0x17, 0x02} },
-{ 0x90a5,	16,	{0x91, 0x26, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x8a, 0x2a, 0x8f, 0x4d, 0x80, 0x74, 0xaf, 0x53, 0xae} },
-{ 0x90b5,	16,	{0x52, 0x12, 0x8a, 0x73, 0x8f, 0x4d, 0x80, 0x69, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x8a, 0xbc, 0x8f} },
-{ 0x90c5,	16,	{0x4d, 0x80, 0x5e, 0xaf, 0x4c, 0xae, 0x4b, 0x12, 0x8b, 0xe5, 0x8f, 0x4d, 0x80, 0x53, 0xaf, 0x53} },
-{ 0x90d5,	16,	{0xae, 0x52, 0x12, 0x89, 0x5b, 0x8f, 0x4d, 0x80, 0x48, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x1a, 0xf1} },
-{ 0x90e5,	16,	{0x8f, 0x4d, 0x80, 0x3d, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x89, 0xe6, 0x8f, 0x4d, 0x80, 0x32, 0x12} },
-{ 0x90f5,	16,	{0x8f, 0x03, 0x8f, 0x4d, 0x80, 0x2b, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x8b, 0x01, 0x8f, 0x4d, 0x80} },
-{ 0x9105,	16,	{0x20, 0xaf, 0x53, 0xae, 0x52, 0x12, 0x8b, 0x22, 0x8f, 0x4d, 0x80, 0x15, 0xaf, 0x4c, 0xae, 0x4b} },
-{ 0x9115,	16,	{0x7c, 0x02, 0x7d, 0xaf, 0x7b, 0x40, 0x12, 0x8e, 0x81, 0xe4, 0xf5, 0x4d, 0x80, 0x03, 0x75, 0x4d} },
-{ 0x9125,	16,	{0xff, 0xe5, 0x4d, 0x60, 0x1d, 0x90, 0x01, 0x98, 0x74, 0x11, 0xf0, 0x85, 0x4f, 0x82, 0x85, 0x4e} },
-{ 0x9135,	16,	{0x83, 0xe0, 0x90, 0x01, 0x99, 0xf0, 0x7e, 0x01, 0x7f, 0x98, 0x7d, 0x02, 0x12, 0x8e, 0xb4, 0xaf} },
-{ 0x9145,	16,	{0x4d, 0x22, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xe0, 0xff, 0x14, 0x24, 0xfa, 0x50, 0x04, 0x24} },
-{ 0x9155,	16,	{0xfe, 0x70, 0x1f, 0x90, 0x01, 0x98, 0x74, 0x10, 0xf0, 0xa3, 0xef, 0xf0, 0x85, 0x53, 0x82, 0x85} },
-{ 0x9165,	16,	{0x52, 0x83, 0xe0, 0x90, 0x01, 0x9a, 0xf0, 0x7e, 0x01, 0x7f, 0x98, 0x7d, 0x03, 0x12, 0x8e, 0xb4} },
-{ 0x9175,	4,	{0x8f, 0x4d, 0xaf, 0x4d} },
-{ 0x9179,	1,	{0x22} },
-{ 0x917a,	8,	{0x8f, 0x4e, 0x8e, 0x4d, 0x8d, 0x4c, 0x8c, 0x4b} },
-{ 0x9182,	16,	{0x75, 0x55, 0x01, 0x75, 0x56, 0x9c, 0xe4, 0xf5, 0x54, 0xaf, 0x50, 0x15, 0x50, 0xef, 0x70, 0x03} },
-{ 0x9192,	16,	{0x02, 0x92, 0x18, 0xaf, 0x4f, 0xe4, 0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xaf, 0x4e} },
-{ 0x91a2,	16,	{0xae, 0x4d, 0xad, 0x4c, 0xac, 0x4b, 0x12, 0xa0, 0x2e, 0xaf, 0x03, 0x8f, 0x53, 0xaf, 0x4e, 0xae} },
-{ 0x91b2,	16,	{0x4d, 0xad, 0x4c, 0xac, 0x4b, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x4f, 0xe4} },
-{ 0x91c2,	16,	{0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04} },
-{ 0x91d2,	16,	{0x12, 0xa0, 0x2e, 0x8f, 0x4e, 0x8e, 0x4d, 0x8d, 0x4c, 0x8c, 0x4b, 0xe5, 0x53, 0x24, 0x30, 0xf5} },
-{ 0x91e2,	16,	{0x53, 0xd3, 0x94, 0x39, 0x40, 0x06, 0x74, 0x07, 0x25, 0x53, 0xf5, 0x53, 0x05, 0x56, 0xe5, 0x56} },
-{ 0x91f2,	16,	{0xae, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x05, 0x56, 0xe5} },
-{ 0x9202,	16,	{0x56, 0xae, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe5, 0x53, 0xf0, 0x05} },
-{ 0x9212,	16,	{0x54, 0x05, 0x54, 0x02, 0x91, 0x8b, 0xe5, 0x56, 0x15, 0x56, 0x70, 0x02, 0x15, 0x55, 0xaf, 0x54} },
-{ 0x9222,	16,	{0x15, 0x54, 0xef, 0x60, 0x23, 0xe5, 0x56, 0x15, 0x56, 0xae, 0x55, 0x70, 0x02, 0x15, 0x55, 0xf5} },
-{ 0x9232,	16,	{0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05, 0x52, 0xe5, 0x52, 0xac, 0x51, 0x70, 0x02, 0x05, 0x51, 0x14} },
-{ 0x9242,	8,	{0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x80, 0xd6} },
-{ 0x924a,	1,	{0x22} },
-{ 0x924b,	16,	{0xaa, 0x07, 0xa9, 0x05, 0x90, 0x01, 0xc9, 0xe0, 0xc3, 0x94, 0x40, 0x50, 0x61, 0xac, 0x02, 0x74} },
-{ 0x925b,	16,	{0x01, 0x7e, 0x00, 0xa8, 0x04, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff} },
-{ 0x926b,	16,	{0xe4, 0xef, 0x55, 0x30, 0x60, 0x45, 0xea, 0x04, 0xff, 0x90, 0x01, 0xc2, 0xe0, 0xfc, 0xa3, 0xe0} },
-{ 0x927b,	16,	{0xfd, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0xa3, 0xe9, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} },
-{ 0x928b,	16,	{0xeb, 0xf0, 0x90, 0x01, 0xc2, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9f, 0x8e, 0xfc, 0xd3, 0xe5, 0xf0} },
-{ 0x929b,	16,	{0x94, 0x87, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0xc2, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0xca} },
-{ 0x92ab,	16,	{0xf0, 0xc2, 0xaf, 0x90, 0x01, 0xc9, 0xe0, 0x04, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
-{ 0x92bb,	1,	{0x22} },
-{ 0x92bc,	16,	{0x90, 0x01, 0xc9, 0xe0, 0xd3, 0x94, 0x00, 0x40, 0x55, 0x90, 0x01, 0xbe, 0xe0, 0xfc, 0xa3, 0xe0} },
-{ 0x92cc,	16,	{0xaa, 0x04, 0xf9, 0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0xaa, 0x06, 0xa9, 0x07, 0xa8} },
-{ 0x92dc,	16,	{0x01, 0xac, 0x02, 0xad, 0x03, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x03, 0x12} },
-{ 0x92ec,	16,	{0x9f, 0x1f, 0x90, 0x01, 0xbe, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9f, 0x8e, 0xfc, 0xd3, 0xe5, 0xf0} },
-{ 0x92fc,	16,	{0x94, 0x87, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0xbe, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0xca} },
-{ 0x930c,	16,	{0xf0, 0xc2, 0xaf, 0x90, 0x01, 0xc9, 0xe0, 0x14, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
-{ 0x931c,	1,	{0x22} },
-{ 0x931d,	16,	{0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x73, 0x7e, 0x7b, 0x7f, 0x80, 0x75, 0x50, 0x7b, 0x75, 0x51} },
-{ 0x932d,	16,	{0x80, 0xe5, 0x51, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x50, 0xa9, 0x07, 0x7b, 0x01, 0x8b, 0x52, 0xf5} },
-{ 0x933d,	16,	{0x53, 0x89, 0x54, 0xfe, 0x12, 0x92, 0xbc, 0xef, 0x60, 0x50, 0xab, 0x52, 0xaa, 0x53, 0xa9, 0x54} },
-{ 0x934d,	16,	{0x12, 0x9f, 0x48, 0x14, 0xff, 0x90, 0x00, 0x01, 0x12, 0x9f, 0x61, 0xb4, 0x02, 0x16, 0xc2, 0xaf} },
-{ 0x935d,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x44} },
-{ 0x936d,	16,	{0x04, 0xf0, 0xd2, 0xaf, 0x74, 0x01, 0x7e, 0x00, 0xa8, 0x07, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce} },
-{ 0x937d,	16,	{0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe4, 0xef, 0x55, 0x30, 0x60, 0x0f, 0x85, 0x51, 0x82, 0x85, 0x50} },
-{ 0x938d,	10,	{0x83, 0x74, 0x0d, 0xf0, 0x90, 0x7f, 0xc3, 0x74, 0x04, 0xf0} },
-{ 0x9397,	1,	{0x22} },
-{ 0x9398,	16,	{0x12, 0x93, 0x1d, 0xe4, 0xf5, 0x4b, 0x74, 0x36, 0x25, 0x4b, 0xf8, 0xe6, 0x54, 0xf0, 0xf5, 0x4c} },
-{ 0x93a8,	16,	{0x74, 0xc5, 0x25, 0x4b, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe0, 0x65, 0x4c, 0xff, 0xc4} },
-{ 0x93b8,	16,	{0x54, 0x0f, 0xf5, 0x4d, 0x60, 0x22, 0x74, 0xc5, 0x25, 0x4b, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5} },
-{ 0x93c8,	16,	{0x83, 0xe5, 0x4c, 0xf0, 0xaf, 0x4b, 0x7d, 0x01, 0xe5, 0x4c, 0x45, 0x4d, 0xfb, 0x12, 0x92, 0x4b} },
-{ 0x93d8,	16,	{0xef, 0x70, 0x05, 0x12, 0x93, 0x1d, 0x80, 0xec, 0x05, 0x4b, 0xe5, 0x4b, 0xc3, 0x94, 0x04, 0x40} },
-{ 0x93e8,	16,	{0xb5, 0x12, 0x93, 0x1d, 0xe5, 0x3a, 0x60, 0x48, 0xe4, 0xf5, 0x4b, 0xaf, 0x4b, 0x74, 0x01, 0xa8} },
-{ 0x93f8,	16,	{0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4c, 0x55, 0x3a, 0x60, 0x29, 0xe5, 0x4b} },
-{ 0x9408,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x30, 0xe6} },
-{ 0x9418,	16,	{0x16, 0xaf, 0x4b, 0x7d, 0x04, 0x7b, 0x80, 0x12, 0x92, 0x4b, 0xef, 0x70, 0x05, 0x12, 0x93, 0x1d} },
-{ 0x9428,	16,	{0x80, 0xef, 0xe5, 0x4c, 0xf4, 0x52, 0x3a, 0x05, 0x4b, 0xe5, 0x4b, 0xc3, 0x94, 0x04, 0x40, 0xbb} },
-{ 0x9438,	16,	{0x90, 0x03, 0x00, 0xe0, 0x60, 0x03, 0x02, 0x95, 0x05, 0x74, 0x19, 0xf0, 0x7f, 0x02, 0x12, 0x81} },
-{ 0x9448,	16,	{0xd9, 0x8e, 0x4e, 0x8f, 0x4f, 0xc3, 0xe5, 0x4e, 0x64, 0x80, 0x94, 0x80, 0x40, 0xee, 0x90, 0x01} },
-{ 0x9458,	16,	{0xbc, 0xe0, 0x65, 0x4f, 0xf0, 0x60, 0x37, 0xe4, 0xf5, 0x4b, 0xaf, 0x4b, 0x74, 0x01, 0xa8, 0x07} },
-{ 0x9468,	16,	{0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4c, 0x90, 0x01, 0xbc, 0xe0, 0x55, 0x4c, 0x60} },
-{ 0x9478,	16,	{0x14, 0xaf, 0x4b, 0x7d, 0x08, 0xe5, 0x4c, 0x55, 0x4f, 0xfb, 0x12, 0x92, 0x4b, 0xef, 0x70, 0x05} },
-{ 0x9488,	16,	{0x12, 0x93, 0x1d, 0x80, 0xec, 0x05, 0x4b, 0xe5, 0x4b, 0xc3, 0x94, 0x04, 0x40, 0xcc, 0x90, 0x01} },
-{ 0x9498,	16,	{0xbc, 0xe5, 0x4f, 0xf0, 0xe4, 0xf5, 0x4b, 0xc2, 0xaf, 0x74, 0x32, 0x25, 0x4b, 0xf8, 0xe6, 0xf5} },
-{ 0x94a8,	16,	{0x4c, 0xe4, 0xf6, 0xd2, 0xaf, 0x53, 0x4c, 0x1e, 0xe5, 0x4c, 0x60, 0x11, 0xaf, 0x4b, 0x7d, 0x02} },
-{ 0x94b8,	16,	{0xab, 0x4c, 0x12, 0x92, 0x4b, 0xef, 0x70, 0x05, 0x12, 0x93, 0x1d, 0x80, 0xef, 0x74, 0x2c, 0x25} },
-{ 0x94c8,	16,	{0x4b, 0xf8, 0xe6, 0xf5, 0x4c, 0x74, 0xfc, 0x25, 0x4b, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} },
-{ 0x94d8,	16,	{0xe0, 0x65, 0x4c, 0x60, 0x11, 0xaf, 0x4b, 0x7d, 0x04, 0xab, 0x4c, 0x12, 0x92, 0x4b, 0xef, 0x70} },
-{ 0x94e8,	16,	{0x05, 0x12, 0x93, 0x1d, 0x80, 0xef, 0x74, 0xfc, 0x25, 0x4b, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5} },
-{ 0x94f8,	16,	{0x83, 0xe5, 0x4c, 0xf0, 0x05, 0x4b, 0xe5, 0x4b, 0xc3, 0x94, 0x04, 0x40, 0x9a, 0x12, 0x93, 0x1d} },
-{ 0x9508,	1,	{0x22} },
-{ 0x9509,	12,	{0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x62, 0x02, 0x95, 0x50} },
-{ 0x9515,	16,	{0x02, 0x05, 0xad, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
-{ 0x9525,	16,	{0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
-{ 0x9535,	16,	{0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
-{ 0x9545,	16,	{0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x95, 0x95, 0xe4, 0x7e} },
-{ 0x9555,	16,	{0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
-{ 0x9565,	16,	{0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
-{ 0x9575,	16,	{0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
-{ 0x9585,	16,	{0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
-{ 0x9595,	16,	{0x60, 0x24, 0x02, 0x8a, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x81, 0x82, 0x84, 0x88} },
-{ 0x95a5,	16,	{0x90, 0xa0, 0xc0, 0xc1, 0xc2, 0xc4, 0xc8, 0xd0, 0xe0, 0xe1, 0xe2, 0xe4, 0xe8, 0xf0, 0xf1, 0xf2} },
-{ 0x95b5,	8,	{0xf4, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xfe, 0xff} },
-{ 0x95bd,	1,	{0x00} },
-{ 0x95be,	3,	{0x00, 0x03, 0x1d} },
-{ 0x95c1,	8,	{0x8b, 0x54, 0x8a, 0x55, 0x89, 0x56, 0x8d, 0x57} },
-{ 0x95c9,	16,	{0xe4, 0xf5, 0x58, 0xf5, 0x59, 0xaf, 0x57, 0x15, 0x57, 0xef, 0x60, 0x36, 0xab, 0x54, 0x05, 0x56} },
-{ 0x95d9,	16,	{0xe5, 0x56, 0xaa, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf9, 0x12, 0x9f, 0x48, 0xff, 0xe5, 0x58} },
-{ 0x95e9,	16,	{0xe5, 0x59, 0x6f, 0x25, 0xe0, 0xff, 0xe4, 0x33, 0xfe, 0x74, 0xa2, 0x2f, 0xf5, 0x82, 0xee, 0x34} },
-{ 0x95f9,	16,	{0x9b, 0xf5, 0x83, 0xe5, 0x58, 0xff, 0xe4, 0x93, 0xf5, 0x58, 0x74, 0x01, 0x93, 0x6f, 0xf5, 0x59} },
-{ 0x9609,	6,	{0x80, 0xc3, 0xae, 0x58, 0xaf, 0x59} },
-{ 0x960f,	1,	{0x22} },
-{ 0x9610,	11,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18} },
-{ 0x961b,	16,	{0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xfe, 0x30, 0xe0, 0x05, 0x90, 0x20, 0x02, 0xe0, 0xff, 0xee} },
-{ 0x962b,	16,	{0x30, 0xe1, 0x05, 0x90, 0x20, 0x0a, 0xe0, 0xff, 0xee, 0x30, 0xe2, 0x05, 0x90, 0x20, 0x12, 0xe0} },
-{ 0x963b,	16,	{0xff, 0xee, 0x30, 0xe3, 0x05, 0x90, 0x20, 0x1a, 0xe0, 0xff, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x1e} },
-{ 0x964b,	10,	{0x04, 0xe4, 0xf0, 0x80, 0x05, 0x90, 0x01, 0xc4, 0xee, 0xf0} },
-{ 0x9655,	9,	{0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
-{ 0x965e,	2,	{0xa9, 0x03} },
-{ 0x9660,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xe5} },
-{ 0x9670,	16,	{0x57, 0x45, 0x58, 0xf5, 0x59, 0xe9, 0x60, 0x14, 0x8a, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82} },
-{ 0x9680,	16,	{0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x4d, 0xf0, 0xe4, 0xfe, 0x80, 0x13, 0xeb, 0x24, 0x04, 0xf5} },
-{ 0x9690,	16,	{0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0xff, 0xed, 0xf4, 0xfc, 0xef, 0x5c, 0xf0, 0xae, 0x59, 0xeb} },
-{ 0x96a0,	16,	{0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0x55, 0x59, 0xfc, 0xb5, 0x06, 0x03, 0xaf} },
-{ 0x96b0,	16,	{0x05, 0x22, 0xe5, 0x57, 0x5c, 0xfe, 0xe5, 0x58, 0x5c, 0xfd, 0xe9, 0x60, 0x16, 0xee, 0x70, 0x04} },
-{ 0x96c0,	16,	{0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xae, 0x07, 0xed, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f} },
-{ 0x96d0,	16,	{0x00, 0xad, 0x07, 0xee, 0x60, 0x03, 0xaf, 0x57, 0x22, 0xed, 0x60, 0x03, 0xaf, 0x58, 0x22, 0x7f} },
-{ 0x96e0,	1,	{0x00} },
-{ 0x96e1,	1,	{0x22} },
-{ 0x96e2,	16,	{0x75, 0x50, 0x02, 0x75, 0x51, 0xb0, 0x90, 0x03, 0x35, 0x74, 0x0f, 0xf0, 0x85, 0x51, 0x82, 0x85} },
-{ 0x96f2,	16,	{0x50, 0x83, 0xe0, 0xff, 0x90, 0x03, 0x36, 0xf0, 0x85, 0x51, 0x82, 0x85, 0x50, 0x83, 0xa3, 0xe0} },
-{ 0x9702,	16,	{0x90, 0x03, 0x37, 0xf0, 0xa3, 0x74, 0xff, 0xf0, 0x75, 0x52, 0x03, 0x75, 0x53, 0x39, 0xef, 0x14} },
-{ 0x9712,	16,	{0xb4, 0x0b, 0x00, 0x40, 0x03, 0x02, 0x9b, 0x6a, 0x90, 0x97, 0x21, 0xf8, 0x28, 0x28, 0x73, 0x02} },
-{ 0x9722,	16,	{0x97, 0x42, 0x02, 0x97, 0xe1, 0x02, 0x98, 0xe6, 0x02, 0x99, 0x06, 0x02, 0x99, 0x06, 0x02, 0x99} },
-{ 0x9732,	16,	{0xa1, 0x02, 0x99, 0xdc, 0x02, 0x9a, 0x01, 0x02, 0x9a, 0xbf, 0x02, 0x9a, 0xef, 0x02, 0x9b, 0x1b} },
-{ 0x9742,	16,	{0xe4, 0xf5, 0x4b, 0xe5, 0x4b, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20} },
-{ 0x9752,	16,	{0xaf, 0x82, 0xf5, 0x4e, 0x8f, 0x4f, 0xe4, 0xff, 0xe4, 0xfe, 0xef, 0x60, 0x10, 0x74, 0x8a, 0x2e} },
-{ 0x9762,	16,	{0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf4, 0xf5, 0x4c, 0x80, 0x0d, 0x74, 0x8a, 0x2e} },
-{ 0x9772,	16,	{0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf5, 0x4c, 0xe5, 0x4f, 0x24, 0x07, 0xf5, 0x82} },
-{ 0x9782,	16,	{0xe4, 0x35, 0x4e, 0xf5, 0x83, 0xe5, 0x4c, 0xf0, 0xe0, 0xf5, 0x4d, 0x65, 0x4c, 0x60, 0x38, 0xe4} },
-{ 0x9792,	16,	{0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4b, 0x04, 0xfd, 0x05, 0x53, 0xe5, 0x53, 0xaa, 0x52, 0x70, 0x02} },
-{ 0x97a2,	16,	{0x05, 0x52, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xed, 0xf0, 0x05, 0x53, 0xe5, 0x53, 0xac, 0x52, 0x70} },
-{ 0x97b2,	16,	{0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe5, 0x4c, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52} },
-{ 0x97c2,	16,	{0x83, 0xe5, 0x4d, 0xf0, 0x02, 0x9b, 0x70, 0x0e, 0xbe, 0x24, 0x8f, 0x0f, 0xef, 0x64, 0x02, 0x70} },
-{ 0x97d2,	16,	{0x87, 0x05, 0x4b, 0xe5, 0x4b, 0x64, 0x04, 0x60, 0x03, 0x02, 0x97, 0x45, 0x02, 0x9b, 0x70, 0xe4} },
-{ 0x97e2,	16,	{0xf5, 0x4b, 0xaf, 0x4b, 0xe4, 0xfd, 0x12, 0x82, 0xa8, 0x05, 0x4b, 0xe5, 0x4b, 0xd3, 0x94, 0x03} },
-{ 0x97f2,	16,	{0x40, 0xf0, 0x90, 0x00, 0x04, 0x74, 0x96, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xe4, 0xf5, 0x4d, 0x7e} },
-{ 0x9802,	16,	{0x20, 0x7f, 0x00, 0x75, 0x4e, 0x20, 0x75, 0x4f, 0x00, 0xf5, 0x4b, 0xaf, 0x4b, 0x74, 0x01, 0xa8} },
-{ 0x9812,	16,	{0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4c, 0x90, 0x01, 0xc4, 0xf0, 0x90, 0x01} },
-{ 0x9822,	16,	{0xc0, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xa3, 0x74, 0x02} },
-{ 0x9832,	16,	{0xf0, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x4c, 0x34, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0} },
-{ 0x9842,	16,	{0x70, 0xef, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4b, 0x04, 0xff, 0x05, 0x53, 0xe5, 0x53, 0xac, 0x52} },
-{ 0x9852,	16,	{0x70, 0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52} },
-{ 0x9862,	16,	{0x83, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x01, 0xc4, 0xf0, 0x75, 0x4d, 0xff, 0x90, 0x01, 0xc4, 0xe0} },
-{ 0x9872,	16,	{0xff, 0x60, 0x37, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4b, 0x04, 0xfe, 0x05, 0x53, 0xe5, 0x53} },
-{ 0x9882,	16,	{0xac, 0x52, 0x70, 0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xee, 0xf0, 0x05, 0x53, 0xe5} },
-{ 0x9892,	16,	{0x53, 0xac, 0x52, 0x70, 0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x53} },
-{ 0x98a2,	16,	{0x82, 0x85, 0x52, 0x83, 0xe5, 0x4c, 0xf0, 0x75, 0x4d, 0xff, 0xe5, 0x4d, 0x70, 0x16, 0x74, 0x08} },
-{ 0x98b2,	16,	{0x25, 0x4f, 0xf5, 0x4f, 0xe4, 0x35, 0x4e, 0xf5, 0x4e, 0x05, 0x4b, 0xe5, 0x4b, 0x64, 0x04, 0x60} },
-{ 0x98c2,	16,	{0x03, 0x02, 0x98, 0x0d, 0xe4, 0xf5, 0x4b, 0xaf, 0x4b, 0x7d, 0x01, 0x12, 0x82, 0xa8, 0x05, 0x4b} },
-{ 0x98d2,	16,	{0xe5, 0x4b, 0xd3, 0x94, 0x03, 0x40, 0xf0, 0x90, 0x00, 0x04, 0x74, 0x13, 0xf0, 0xa3, 0x74, 0x12} },
-{ 0x98e2,	16,	{0xf0, 0x02, 0x9b, 0x70, 0x85, 0x51, 0x82, 0x85, 0x50, 0x83, 0xa3, 0xe0, 0x14, 0xff, 0x74, 0x01} },
-{ 0x98f2,	16,	{0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x90, 0x02, 0xf7, 0xf0, 0x90, 0x01, 0xc4} },
-{ 0x9902,	16,	{0xf0, 0x02, 0x9b, 0x70, 0x90, 0x01, 0xc0, 0x74, 0x03, 0xf0, 0xa3, 0x74, 0xe8, 0xf0, 0xe4, 0xf5} },
-{ 0x9912,	16,	{0x4d, 0x90, 0x02, 0xf7, 0xe0, 0xff, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x07, 0x19, 0x90, 0x01, 0xc0} },
-{ 0x9922,	16,	{0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xea, 0x90, 0x03, 0x38, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52} },
-{ 0x9932,	16,	{0x83, 0x74, 0xff, 0xf0, 0xf5, 0x4d, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x9b, 0x70, 0x90, 0x01, 0xc0} },
-{ 0x9942,	16,	{0xf0, 0xa3, 0x74, 0x96, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xf6, 0x7f} },
-{ 0x9952,	16,	{0x02, 0x12, 0x81, 0xd9, 0xc3, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xef, 0x54, 0x0f, 0xf5} },
-{ 0x9962,	16,	{0x4d, 0x90, 0x02, 0xf7, 0xe0, 0x55, 0x4d, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x8f} },
-{ 0x9972,	16,	{0x4c, 0x85, 0x51, 0x82, 0x85, 0x50, 0x83, 0xe0, 0xb4, 0x05, 0x0c, 0xe5, 0x4c, 0x70, 0x04, 0x7f} },
-{ 0x9982,	16,	{0x01, 0x80, 0x02, 0x7f, 0x00, 0x8f, 0x4c, 0xe5, 0x4c, 0x70, 0x03, 0x02, 0x9b, 0x70, 0xe4, 0x90} },
-{ 0x9992,	16,	{0x03, 0x38, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52, 0x83, 0xe5, 0x4d, 0xf0, 0x02, 0x9b, 0x70, 0xe4} },
-{ 0x99a2,	16,	{0xff, 0xfd, 0x12, 0x82, 0xa8, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x4e, 0x20, 0x75, 0x4f, 0x00, 0x85} },
-{ 0x99b2,	16,	{0x4f, 0x82, 0x85, 0x4e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85, 0x4f, 0x82, 0x85} },
-{ 0x99c2,	16,	{0x4e, 0x83, 0x74, 0x01, 0xf0, 0xa3, 0xe4, 0xf0, 0x85, 0x4f, 0x82, 0x85, 0x4e, 0x83, 0xa3, 0xa3} },
-{ 0x99d2,	16,	{0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0xd2, 0x04, 0x02, 0x9b, 0x70, 0xc2, 0x04, 0x7e, 0x20, 0x7f, 0x00} },
-{ 0x99e2,	16,	{0x75, 0x4e, 0x20, 0x75, 0x4f, 0x00, 0xe5, 0x4f, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x4e, 0xf5} },
-{ 0x99f2,	16,	{0x83, 0xe0, 0x30, 0xe6, 0xf1, 0xe4, 0xff, 0x7d, 0x01, 0x12, 0x82, 0xa8, 0x02, 0x9b, 0x70, 0xe4} },
-{ 0x9a02,	16,	{0xf5, 0x4d, 0xf5, 0x4b, 0xaf, 0x4b, 0xe4, 0xfd, 0x12, 0x82, 0xa8, 0xe5, 0x4b, 0x75, 0xf0, 0x08} },
-{ 0x9a12,	16,	{0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x4e, 0x8f, 0x4f, 0xf5, 0x83} },
-{ 0x9a22,	16,	{0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf} },
-{ 0x9a32,	16,	{0x4b, 0x7d, 0x01, 0x7b, 0x01, 0x75, 0x57, 0x80, 0x75, 0x58, 0x40, 0x12, 0x96, 0x5e, 0x8f, 0x4d} },
-{ 0x9a42,	16,	{0xe5, 0x4d, 0x70, 0x11, 0xaf, 0x4b, 0x7d, 0x02, 0x7b, 0x01, 0x75, 0x57, 0x10, 0x75, 0x58, 0x20} },
-{ 0x9a52,	16,	{0x12, 0x96, 0x5e, 0x8f, 0x4d, 0xe5, 0x4d, 0x70, 0x10, 0xaf, 0x4b, 0x7d, 0x01, 0xfb, 0x75, 0x57} },
-{ 0x9a62,	16,	{0x80, 0x75, 0x58, 0x40, 0x12, 0x96, 0x5e, 0x8f, 0x4d, 0xe5, 0x4d, 0x70, 0x10, 0xaf, 0x4b, 0x7d} },
-{ 0x9a72,	16,	{0x02, 0xfb, 0x75, 0x57, 0x10, 0x75, 0x58, 0x20, 0x12, 0x96, 0x5e, 0x8f, 0x4d, 0xaf, 0x4b, 0x7d} },
-{ 0x9a82,	16,	{0x01, 0x12, 0x82, 0xa8, 0xe5, 0x4d, 0x60, 0x26, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4b, 0x04} },
-{ 0x9a92,	16,	{0xff, 0x05, 0x53, 0xe5, 0x53, 0xac, 0x52, 0x70, 0x02, 0x05, 0x52, 0x14, 0xf5, 0x82, 0x8c, 0x83} },
-{ 0x9aa2,	16,	{0xef, 0xf0, 0x85, 0x53, 0x82, 0x85, 0x52, 0x83, 0xe5, 0x4d, 0xf0, 0x02, 0x9b, 0x70, 0x05, 0x4b} },
-{ 0x9ab2,	16,	{0xe5, 0x4b, 0xd3, 0x94, 0x03, 0x50, 0x03, 0x02, 0x9a, 0x06, 0x02, 0x9b, 0x70, 0xe4, 0x90, 0x03} },
-{ 0x9ac2,	16,	{0x59, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74} },
-{ 0x9ad2,	16,	{0x9b, 0xf0, 0xa3, 0x74, 0x92, 0xf0, 0x7e, 0x03, 0x7f, 0x59, 0x12, 0x19, 0xc1, 0xef, 0x64, 0x08} },
-{ 0x9ae2,	16,	{0x70, 0x03, 0x02, 0x9b, 0x70, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x02, 0x9b, 0x70, 0xe4, 0x90, 0x03} },
-{ 0x9af2,	16,	{0x59, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0xe5} },
-{ 0x9b02,	16,	{0x52, 0xf0, 0xa3, 0xe5, 0x53, 0xf0, 0x7e, 0x03, 0x7f, 0x59, 0x12, 0x10, 0x2c, 0xef, 0x64, 0x08} },
-{ 0x9b12,	16,	{0x60, 0x5c, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x80, 0x55, 0xe5, 0x51, 0x24, 0x02, 0xff, 0xe4, 0x35} },
-{ 0x9b22,	16,	{0x50, 0xfa, 0xa9, 0x07, 0x7b, 0x01, 0x7d, 0x10, 0x12, 0x95, 0xc1, 0xef, 0x4e, 0x70, 0x32, 0x90} },
-{ 0x9b32,	16,	{0x03, 0x59, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xe5} },
-{ 0x9b42,	16,	{0x51, 0x24, 0x02, 0x90, 0x03, 0x60, 0xf0, 0xe4, 0x35, 0x50, 0x90, 0x03, 0x5f, 0xf0, 0x7e, 0x03} },
-{ 0x9b52,	16,	{0x7f, 0x59, 0x12, 0x19, 0xc1, 0xef, 0x64, 0x08, 0x60, 0x14, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x80} },
-{ 0x9b62,	16,	{0x0d, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x80, 0x06, 0x90, 0x03, 0x38, 0x74, 0x01, 0xf0, 0x90, 0x01} },
-{ 0x9b72,	16,	{0xc0, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70} },
-{ 0x9b82,	15,	{0xf6, 0x7e, 0x03, 0x7f, 0x35, 0x7d, 0x24, 0x12, 0x8e, 0xb4, 0xe4, 0x90, 0x02, 0xaf, 0xf0} },
-{ 0x9b91,	1,	{0x22} },
-{ 0x9b92,	16,	{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f} },
-{ 0x9ba2,	16,	{0x00, 0x00, 0xc0, 0xc1, 0xc1, 0x81, 0x01, 0x40, 0xc3, 0x01, 0x03, 0xc0, 0x02, 0x80, 0xc2, 0x41} },
-{ 0x9bb2,	16,	{0xc6, 0x01, 0x06, 0xc0, 0x07, 0x80, 0xc7, 0x41, 0x05, 0x00, 0xc5, 0xc1, 0xc4, 0x81, 0x04, 0x40} },
-{ 0x9bc2,	16,	{0xcc, 0x01, 0x0c, 0xc0, 0x0d, 0x80, 0xcd, 0x41, 0x0f, 0x00, 0xcf, 0xc1, 0xce, 0x81, 0x0e, 0x40} },
-{ 0x9bd2,	16,	{0x0a, 0x00, 0xca, 0xc1, 0xcb, 0x81, 0x0b, 0x40, 0xc9, 0x01, 0x09, 0xc0, 0x08, 0x80, 0xc8, 0x41} },
-{ 0x9be2,	16,	{0xd8, 0x01, 0x18, 0xc0, 0x19, 0x80, 0xd9, 0x41, 0x1b, 0x00, 0xdb, 0xc1, 0xda, 0x81, 0x1a, 0x40} },
-{ 0x9bf2,	16,	{0x1e, 0x00, 0xde, 0xc1, 0xdf, 0x81, 0x1f, 0x40, 0xdd, 0x01, 0x1d, 0xc0, 0x1c, 0x80, 0xdc, 0x41} },
-{ 0x9c02,	16,	{0x14, 0x00, 0xd4, 0xc1, 0xd5, 0x81, 0x15, 0x40, 0xd7, 0x01, 0x17, 0xc0, 0x16, 0x80, 0xd6, 0x41} },
-{ 0x9c12,	16,	{0xd2, 0x01, 0x12, 0xc0, 0x13, 0x80, 0xd3, 0x41, 0x11, 0x00, 0xd1, 0xc1, 0xd0, 0x81, 0x10, 0x40} },
-{ 0x9c22,	16,	{0xf0, 0x01, 0x30, 0xc0, 0x31, 0x80, 0xf1, 0x41, 0x33, 0x00, 0xf3, 0xc1, 0xf2, 0x81, 0x32, 0x40} },
-{ 0x9c32,	16,	{0x36, 0x00, 0xf6, 0xc1, 0xf7, 0x81, 0x37, 0x40, 0xf5, 0x01, 0x35, 0xc0, 0x34, 0x80, 0xf4, 0x41} },
-{ 0x9c42,	16,	{0x3c, 0x00, 0xfc, 0xc1, 0xfd, 0x81, 0x3d, 0x40, 0xff, 0x01, 0x3f, 0xc0, 0x3e, 0x80, 0xfe, 0x41} },
-{ 0x9c52,	16,	{0xfa, 0x01, 0x3a, 0xc0, 0x3b, 0x80, 0xfb, 0x41, 0x39, 0x00, 0xf9, 0xc1, 0xf8, 0x81, 0x38, 0x40} },
-{ 0x9c62,	16,	{0x28, 0x00, 0xe8, 0xc1, 0xe9, 0x81, 0x29, 0x40, 0xeb, 0x01, 0x2b, 0xc0, 0x2a, 0x80, 0xea, 0x41} },
-{ 0x9c72,	16,	{0xee, 0x01, 0x2e, 0xc0, 0x2f, 0x80, 0xef, 0x41, 0x2d, 0x00, 0xed, 0xc1, 0xec, 0x81, 0x2c, 0x40} },
-{ 0x9c82,	16,	{0xe4, 0x01, 0x24, 0xc0, 0x25, 0x80, 0xe5, 0x41, 0x27, 0x00, 0xe7, 0xc1, 0xe6, 0x81, 0x26, 0x40} },
-{ 0x9c92,	16,	{0x22, 0x00, 0xe2, 0xc1, 0xe3, 0x81, 0x23, 0x40, 0xe1, 0x01, 0x21, 0xc0, 0x20, 0x80, 0xe0, 0x41} },
-{ 0x9ca2,	16,	{0xa0, 0x01, 0x60, 0xc0, 0x61, 0x80, 0xa1, 0x41, 0x63, 0x00, 0xa3, 0xc1, 0xa2, 0x81, 0x62, 0x40} },
-{ 0x9cb2,	16,	{0x66, 0x00, 0xa6, 0xc1, 0xa7, 0x81, 0x67, 0x40, 0xa5, 0x01, 0x65, 0xc0, 0x64, 0x80, 0xa4, 0x41} },
-{ 0x9cc2,	16,	{0x6c, 0x00, 0xac, 0xc1, 0xad, 0x81, 0x6d, 0x40, 0xaf, 0x01, 0x6f, 0xc0, 0x6e, 0x80, 0xae, 0x41} },
-{ 0x9cd2,	16,	{0xaa, 0x01, 0x6a, 0xc0, 0x6b, 0x80, 0xab, 0x41, 0x69, 0x00, 0xa9, 0xc1, 0xa8, 0x81, 0x68, 0x40} },
-{ 0x9ce2,	16,	{0x78, 0x00, 0xb8, 0xc1, 0xb9, 0x81, 0x79, 0x40, 0xbb, 0x01, 0x7b, 0xc0, 0x7a, 0x80, 0xba, 0x41} },
-{ 0x9cf2,	16,	{0xbe, 0x01, 0x7e, 0xc0, 0x7f, 0x80, 0xbf, 0x41, 0x7d, 0x00, 0xbd, 0xc1, 0xbc, 0x81, 0x7c, 0x40} },
-{ 0x9d02,	16,	{0xb4, 0x01, 0x74, 0xc0, 0x75, 0x80, 0xb5, 0x41, 0x77, 0x00, 0xb7, 0xc1, 0xb6, 0x81, 0x76, 0x40} },
-{ 0x9d12,	16,	{0x72, 0x00, 0xb2, 0xc1, 0xb3, 0x81, 0x73, 0x40, 0xb1, 0x01, 0x71, 0xc0, 0x70, 0x80, 0xb0, 0x41} },
-{ 0x9d22,	16,	{0x50, 0x00, 0x90, 0xc1, 0x91, 0x81, 0x51, 0x40, 0x93, 0x01, 0x53, 0xc0, 0x52, 0x80, 0x92, 0x41} },
-{ 0x9d32,	16,	{0x96, 0x01, 0x56, 0xc0, 0x57, 0x80, 0x97, 0x41, 0x55, 0x00, 0x95, 0xc1, 0x94, 0x81, 0x54, 0x40} },
-{ 0x9d42,	16,	{0x9c, 0x01, 0x5c, 0xc0, 0x5d, 0x80, 0x9d, 0x41, 0x5f, 0x00, 0x9f, 0xc1, 0x9e, 0x81, 0x5e, 0x40} },
-{ 0x9d52,	16,	{0x5a, 0x00, 0x9a, 0xc1, 0x9b, 0x81, 0x5b, 0x40, 0x99, 0x01, 0x59, 0xc0, 0x58, 0x80, 0x98, 0x41} },
-{ 0x9d62,	16,	{0x88, 0x01, 0x48, 0xc0, 0x49, 0x80, 0x89, 0x41, 0x4b, 0x00, 0x8b, 0xc1, 0x8a, 0x81, 0x4a, 0x40} },
-{ 0x9d72,	16,	{0x4e, 0x00, 0x8e, 0xc1, 0x8f, 0x81, 0x4f, 0x40, 0x8d, 0x01, 0x4d, 0xc0, 0x4c, 0x80, 0x8c, 0x41} },
-{ 0x9d82,	16,	{0x44, 0x00, 0x84, 0xc1, 0x85, 0x81, 0x45, 0x40, 0x87, 0x01, 0x47, 0xc0, 0x46, 0x80, 0x86, 0x41} },
-{ 0x9d92,	16,	{0x82, 0x01, 0x42, 0xc0, 0x43, 0x80, 0x83, 0x41, 0x41, 0x00, 0x81, 0xc1, 0x80, 0x81, 0x40, 0x40} },
-{ 0x9da2,	16,	{0xe4, 0xff, 0x74, 0xf8, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02} },
-{ 0x9db2,	16,	{0x9e, 0x45, 0x74, 0x36, 0x2f, 0xf8, 0xe6, 0x20, 0xe5, 0x03, 0x02, 0x9e, 0x45, 0xef, 0x75, 0xf0} },
-{ 0x9dc2,	16,	{0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xad, 0x82, 0xfc, 0xf5, 0x83, 0xe5, 0x82} },
-{ 0x9dd2,	16,	{0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0x60, 0x64, 0x60, 0x70, 0x63} },
-{ 0x9de2,	16,	{0xef, 0x25, 0xe0, 0x24, 0xef, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01} },
-{ 0x9df2,	16,	{0x12, 0x9f, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0, 0x8d, 0x82, 0x8c, 0x83, 0xf0, 0x74, 0xf8} },
-{ 0x9e02,	16,	{0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x14, 0xf0, 0x70, 0x36, 0xef, 0x25, 0xe0} },
-{ 0x9e12,	16,	{0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0xef, 0x25, 0xe0, 0xfe, 0xc3} },
-{ 0x9e22,	16,	{0x74, 0x0c, 0x9e, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xad} },
-{ 0x9e32,	16,	{0x82, 0xfc, 0xef, 0x25, 0xe0, 0x24, 0xef, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xec, 0xf0} },
-{ 0x9e42,	12,	{0xa3, 0xed, 0xf0, 0x0f, 0xef, 0x64, 0x04, 0x60, 0x03, 0x02, 0x9d, 0xa4} },
-{ 0x9e4e,	1,	{0x22} },
-{ 0x9e4f,	16,	{0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e} },
-{ 0x9e5f,	16,	{0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08} },
-{ 0x9e6f,	16,	{0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83} },
-{ 0x9e7f,	16,	{0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08} },
-{ 0x9e8f,	16,	{0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c} },
-{ 0x9e9f,	16,	{0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10} },
-{ 0x9eaf,	16,	{0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33} },
-{ 0x9ebf,	16,	{0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83} },
-{ 0x9ecf,	16,	{0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80} },
-{ 0x9edf,	16,	{0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0} },
-{ 0x9eef,	16,	{0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc} },
-{ 0x9eff,	16,	{0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde} },
-{ 0x9f0f,	16,	{0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc} },
-{ 0x9f1f,	16,	{0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xc2, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4} },
-{ 0x9f2f,	16,	{0x04, 0x00, 0x50, 0xb8, 0x23, 0x23, 0x45, 0x82, 0xf5, 0x82, 0xef, 0x4e, 0x60, 0xae, 0xef, 0x60} },
-{ 0x9f3f,	9,	{0x01, 0x0e, 0xe5, 0x82, 0x23, 0x90, 0x9e, 0x9f, 0x73} },
-{ 0x9f48,	16,	{0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
-{ 0x9f58,	9,	{0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
-{ 0x9f61,	16,	{0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
-{ 0x9f71,	16,	{0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
-{ 0x9f81,	13,	{0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
-{ 0x9f8e,	16,	{0xc5, 0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02} },
-{ 0x9f9e,	6,	{0x15, 0x83, 0xe0, 0x38, 0xf0, 0x22} },
-{ 0x9fa4,	16,	{0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83} },
-{ 0x9fb4,	6,	{0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22} },
-{ 0x9fba,	16,	{0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} },
-{ 0x9fca,	16,	{0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} },
-{ 0x9fda,	16,	{0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} },
-{ 0x9fea,	8,	{0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} },
-{ 0x9ff2,	16,	{0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc} },
-{ 0xa002,	16,	{0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40} },
-{ 0xa012,	16,	{0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6} },
-{ 0xa022,	16,	{0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9} },
-{ 0xa032,	16,	{0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb} },
-{ 0xa042,	16,	{0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb} },
-{ 0xa052,	16,	{0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9} },
-{ 0xa062,	16,	{0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc} },
-{ 0xa072,	16,	{0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a} },
-{ 0xa082,	16,	{0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f} },
-{ 0xa092,	16,	{0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07} },
-{ 0xa0a2,	16,	{0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8} },
-{ 0xa0b2,	14,	{0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22} },
-{ 0xa0c0,	16,	{0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} },
-{ 0xa0d0,	1,	{0x22} },
-{ 0xa0d1,	16,	{0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef, 0x13, 0xff} },
-{ 0xa0e1,	3,	{0xd8, 0xf1, 0x22} },
-{ 0xa0e4,	16,	{0x08, 0x08, 0x08, 0xe6, 0xcf, 0x2f, 0xf6, 0x18, 0xe6, 0xce, 0x3e, 0xf6, 0x18, 0xe6, 0xcd, 0x3d} },
-{ 0xa0f4,	7,	{0xf6, 0x18, 0xe6, 0xcc, 0x3c, 0xf6, 0x22} },
-{ 0xa0fb,	12,	{0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} },
-{ 0xa107,	16,	{0xa8, 0x82, 0x85, 0x83, 0xf0, 0xd0, 0x83, 0xd0, 0x82, 0x12, 0xa1, 0x1e, 0x12, 0xa1, 0x1e, 0x12} },
-{ 0xa117,	16,	{0xa1, 0x1e, 0x12, 0xa1, 0x1e, 0xe4, 0x73, 0xe4, 0x93, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83} },
-{ 0xa127,	16,	{0xc8, 0xc5, 0x82, 0xc8, 0xf0, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83, 0xc8, 0xc5, 0x82, 0xc8} },
-{ 0xa137,	1,	{0x22} },
+{ 0x82a8,	2,	{0xae, 0x07} },
+{ 0x82aa,	16,	{0x7c, 0x02, 0xec, 0x14, 0x60, 0x15, 0x14, 0x70, 0x1e, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0} },
+{ 0x82ba,	16,	{0xee, 0x25, 0xe0, 0x44, 0x40, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xa6, 0xed, 0xf0} },
+{ 0x82ca,	16,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xfb, 0x30, 0xe0, 0xf8, 0xbc} },
+{ 0x82da,	16,	{0x02, 0x0a, 0x20, 0xe1, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22, 0xeb, 0x30, 0xe2, 0x0a} },
+{ 0x82ea,	14,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xdc, 0xb6, 0x7f, 0x08} },
+{ 0x82f8,	1,	{0x22} },
+{ 0x82f9,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xf5} },
+{ 0x8309,	16,	{0x83, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x5f, 0x74, 0xbf} },
+{ 0x8319,	16,	{0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x44, 0x10, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3} },
+{ 0x8329,	16,	{0xa3, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xf0, 0xf9, 0xed, 0x60, 0x1d, 0x74, 0x01} },
+{ 0x8339,	16,	{0x7e, 0x00, 0xa8, 0x07, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe4} },
+{ 0x8349,	16,	{0xef, 0x55, 0x3c, 0x60, 0x04, 0x79, 0x09, 0x80, 0x02, 0x79, 0x0d, 0x8b, 0x82, 0x8a, 0x83, 0xa3} },
+{ 0x8359,	16,	{0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x54, 0xef, 0xf0, 0x8b} },
+{ 0x8369,	16,	{0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe5, 0x5f, 0xf0, 0xae, 0x02, 0xaf, 0x03, 0x8f, 0x82, 0x8e} },
+{ 0x8379,	4,	{0x83, 0xa3, 0xe9, 0xf0} },
+{ 0x837d,	1,	{0x22} },
+{ 0x837e,	4,	{0x8f, 0x5f, 0x8d, 0x60} },
+{ 0x8382,	16,	{0xe4, 0xf5, 0x61, 0x74, 0x3d, 0x2f, 0xf8, 0x76, 0x08, 0xe5, 0x5f, 0x75, 0xf0, 0x0d, 0xa4, 0x24} },
+{ 0x8392,	16,	{0x02, 0xf5, 0x82, 0xe4, 0x34, 0x03, 0xf5, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} },
+{ 0x83a2,	16,	{0xa3, 0xe0, 0xff, 0x7b, 0x80, 0x7a, 0x25, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0xa1, 0xb7, 0x50} },
+{ 0x83b2,	16,	{0x3c, 0xe5, 0x5f, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34, 0x03, 0xf5, 0x83} },
+{ 0x83c2,	16,	{0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x96, 0x78} },
+{ 0x83d2,	16,	{0x00, 0xc3, 0x12, 0xa1, 0xb7, 0x40, 0x0c, 0x75, 0x61, 0x40, 0x74, 0x3d, 0x25, 0x5f, 0xf8, 0x76} },
+{ 0x83e2,	16,	{0x10, 0x80, 0x0a, 0x75, 0x61, 0x80, 0x74, 0x3d, 0x25, 0x5f, 0xf8, 0x76, 0x38, 0xe5, 0x61, 0x45} },
+{ 0x83f2,	16,	{0x60, 0x44, 0x01, 0xff, 0xe5, 0x5f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x8402,	5,	{0x20, 0xf5, 0x83, 0xef, 0xf0} },
+{ 0x8407,	1,	{0x22} },
+{ 0x8408,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x55, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22} },
+{ 0x8418,	16,	{0xe5, 0x55, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5} },
+{ 0x8428,	16,	{0x56, 0x8f, 0x57, 0xe5, 0x55, 0x25, 0xe0, 0x24, 0xc6, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} },
+{ 0x8438,	16,	{0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x55, 0x25, 0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} },
+{ 0x8448,	16,	{0x83, 0xe4, 0xf0, 0x74, 0x22, 0x25, 0x55, 0xf8, 0xe4, 0xf6, 0xe5, 0x57, 0x24, 0x04, 0xf5, 0x82} },
+{ 0x8458,	16,	{0xe4, 0x35, 0x56, 0xf5, 0x83, 0xe0, 0x44, 0x03, 0xf0, 0xaf, 0x55, 0x7d, 0x06, 0x12, 0x83, 0x7e} },
+{ 0x8468,	16,	{0xaf, 0x55, 0x7d, 0x01, 0x12, 0x82, 0xf9, 0x85, 0x57, 0x82, 0x85, 0x56, 0x83, 0xa3, 0xa3, 0xe0} },
+{ 0x8478,	16,	{0x20, 0xe0, 0x22, 0xe0, 0xff, 0xe5, 0x57, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x56, 0xf5, 0x83} },
+{ 0x8488,	16,	{0xe0, 0xe5, 0x57, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x56, 0xf5, 0x83, 0xe0, 0xff, 0xaf, 0x55} },
+{ 0x8498,	16,	{0x7d, 0x06, 0x12, 0x83, 0x7e, 0x74, 0xf8, 0x25, 0x55, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} },
+{ 0x84a8,	16,	{0xe4, 0xf0, 0xe5, 0x55, 0x25, 0xe0, 0xff, 0xc3, 0x74, 0x0c, 0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24} },
+{ 0x84b8,	16,	{0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82, 0xfe, 0xe5, 0x55, 0x25, 0xe0, 0x24, 0xef} },
+{ 0x84c8,	16,	{0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0xaf, 0x55, 0x74, 0x01} },
+{ 0x84d8,	13,	{0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x31, 0x7f, 0x00} },
+{ 0x84e5,	1,	{0x22} },
+{ 0x84e6,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x55, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22} },
+{ 0x84f6,	16,	{0xaf, 0x55, 0xe4, 0xfd, 0x12, 0x82, 0xf9, 0x74, 0xf8, 0x25, 0x55, 0xf5, 0x82, 0xe4, 0x34, 0x02} },
+{ 0x8506,	16,	{0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x55, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x8516,	16,	{0x20, 0xaf, 0x82, 0xf5, 0x57, 0x8f, 0x58, 0xf5, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82, 0xe4} },
+{ 0x8526,	16,	{0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf, 0x55, 0x7d, 0x06, 0x12, 0x83, 0x7e, 0xe5} },
+{ 0x8536,	16,	{0x58, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x57, 0xf5, 0x83, 0xe0, 0x30, 0xe0, 0x09, 0x85, 0x58} },
+{ 0x8546,	16,	{0x82, 0x85, 0x57, 0x83, 0xe0, 0xf5, 0x56, 0xaf, 0x55, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02} },
+{ 0x8556,	16,	{0xc3, 0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x31, 0xe5, 0x55, 0x25, 0xe0, 0x24, 0xc6, 0xf5, 0x82, 0xe4} },
+{ 0x8566,	16,	{0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x20, 0xe1, 0x0f, 0xe5, 0x55, 0x25, 0xe0, 0x24, 0xc7, 0xf5, 0x82} },
+{ 0x8576,	9,	{0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x7f, 0x00} },
+{ 0x857f,	1,	{0x22} },
+{ 0x8580,	4,	{0x8e, 0x55, 0x8f, 0x56} },
+{ 0x8584,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x57, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22} },
+{ 0x8594,	16,	{0xe5, 0x57, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0} },
+{ 0x85a4,	16,	{0x54, 0x03, 0x70, 0x24, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0x30, 0xe0, 0x07, 0xaf} },
+{ 0x85b4,	16,	{0x57, 0x7d, 0x02, 0x12, 0x83, 0x7e, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0x30, 0xe1} },
+{ 0x85c4,	10,	{0x07, 0xaf, 0x57, 0x7d, 0x04, 0x12, 0x83, 0x7e, 0x7f, 0x00} },
+{ 0x85ce,	1,	{0x22} },
+{ 0x85cf,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0xa3, 0xa3, 0xa3, 0xe0, 0xfc, 0xed} },
+{ 0x85df,	16,	{0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xc0, 0x83, 0xc0} },
+{ 0x85ef,	16,	{0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0} },
+{ 0x85ff,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0xe0, 0xfd, 0xec, 0x6d, 0xd0} },
+{ 0x860f,	16,	{0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f} },
+{ 0x861f,	16,	{0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82} },
+{ 0x862f,	16,	{0x8e, 0x83, 0xa3, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0} },
+{ 0x863f,	16,	{0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0} },
+{ 0x864f,	16,	{0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xff, 0xed, 0x6f, 0xd0, 0x82, 0xd0} },
+{ 0x865f,	3,	{0x83, 0xf0, 0x22} },
+{ 0x8662,	4,	{0xad, 0x07, 0xac, 0x06} },
+{ 0x8666,	16,	{0x79, 0x0d, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff} },
+{ 0x8676,	16,	{0x22, 0x8c, 0x55, 0x8d, 0x56, 0xee, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x8686,	16,	{0x03, 0xaf, 0x82, 0xfe, 0xad, 0x01, 0x19, 0xed, 0x60, 0x24, 0x0f, 0xef, 0xac, 0x06, 0x70, 0x01} },
+{ 0x8696,	16,	{0x0e, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe0, 0xfd, 0x05, 0x56, 0xe5, 0x56, 0xaa, 0x55, 0x70, 0x02} },
+{ 0x86a6,	16,	{0x05, 0x55, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xe0, 0x6d, 0x60, 0xd9, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
+{ 0x86b6,	1,	{0x22} },
+{ 0x86b7,	4,	{0x8e, 0x55, 0x8f, 0x56} },
+{ 0x86bb,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x5c, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22} },
+{ 0x86cb,	16,	{0xe5, 0x5c, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5} },
+{ 0x86db,	16,	{0x5d, 0x8f, 0x5e, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3} },
+{ 0x86eb,	16,	{0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x08, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xd3, 0x12, 0xa1} },
+{ 0x86fb,	16,	{0xb7, 0x40, 0x10, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0x12, 0xa1, 0xfe, 0x00, 0x00, 0x00} },
+{ 0x870b,	16,	{0x08, 0x80, 0x2e, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3} },
+{ 0x871b,	16,	{0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x08, 0x79, 0x07, 0x78, 0x00, 0xc3, 0x12, 0xa1} },
+{ 0x872b,	16,	{0xb7, 0x50, 0x0e, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0x12, 0xa1, 0xfe, 0x00, 0x07, 0x08} },
+{ 0x873b,	16,	{0x00, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa} },
+{ 0x874b,	16,	{0xa3, 0xe0, 0xfb, 0x7f, 0x00, 0x7e, 0x50, 0x7d, 0x46, 0x7c, 0x00, 0x12, 0xa1, 0x25, 0x8f, 0x5a} },
+{ 0x875b,	16,	{0x8e, 0x59, 0x8d, 0x58, 0x8c, 0x57, 0x7b, 0x0a, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0x12, 0xa1} },
+{ 0x876b,	16,	{0x25, 0xaf, 0x03, 0x8f, 0x5b, 0xaf, 0x5a, 0xae, 0x59, 0xad, 0x58, 0xac, 0x57, 0x7b, 0x0a, 0x7a} },
+{ 0x877b,	16,	{0x00, 0x79, 0x00, 0x78, 0x00, 0x12, 0xa1, 0x25, 0x8f, 0x5a, 0x8e, 0x59, 0x8d, 0x58, 0x8c, 0x57} },
+{ 0x878b,	16,	{0xe5, 0x5b, 0xc3, 0x94, 0x05, 0x40, 0x15, 0xe5, 0x5a, 0x24, 0x01, 0xf5, 0x5a, 0xe4, 0x35, 0x59} },
+{ 0x879b,	16,	{0xf5, 0x59, 0xe4, 0x35, 0x58, 0xf5, 0x58, 0xe4, 0x35, 0x57, 0xf5, 0x57, 0x85, 0x5e, 0x82, 0x85} },
+{ 0x87ab,	16,	{0x5d, 0x83, 0xa3, 0xe4, 0xf0, 0x85, 0x5e, 0x82, 0x85, 0x5d, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44} },
+{ 0x87bb,	16,	{0x80, 0xf0, 0x85, 0x5e, 0x82, 0x85, 0x5d, 0x83, 0xe5, 0x5a, 0xf0, 0xaf, 0x5a, 0xae, 0x59, 0xad} },
+{ 0x87cb,	16,	{0x58, 0xac, 0x57, 0x78, 0x08, 0x12, 0xa1, 0xc8, 0x85, 0x5e, 0x82, 0x85, 0x5d, 0x83, 0xa3, 0xef} },
+{ 0x87db,	16,	{0xf0, 0x85, 0x5e, 0x82, 0x85, 0x5d, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0xe4, 0xf5} },
+{ 0x87eb,	16,	{0x5b, 0xe5, 0x56, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0xff, 0xb4, 0x62} },
+{ 0x87fb,	16,	{0x05, 0x43, 0x5b, 0x0a, 0x80, 0x1a, 0xef, 0xb4, 0x72, 0x05, 0x43, 0x5b, 0x08, 0x80, 0x11, 0xef} },
+{ 0x880b,	16,	{0xb4, 0x74, 0x05, 0x43, 0x5b, 0x02, 0x80, 0x08, 0xef, 0x64, 0x6e, 0x60, 0x03, 0x7f, 0xff, 0x22} },
+{ 0x881b,	16,	{0xe5, 0x56, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0xff, 0x30, 0xe3, 0x03} },
+{ 0x882b,	16,	{0x43, 0x5b, 0x80, 0xef, 0x30, 0xe7, 0x12, 0x43, 0x5b, 0x40, 0xe5, 0x5e, 0x24, 0x04, 0xf5, 0x82} },
+{ 0x883b,	16,	{0xe4, 0x35, 0x5d, 0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x56, 0x24, 0x0b, 0xf5, 0x82, 0xe4} },
+{ 0x884b,	16,	{0x35, 0x55, 0xf5, 0x83, 0xe0, 0xff, 0x20, 0xe1, 0x03, 0x30, 0xe4, 0x23, 0xaf, 0x5c, 0x74, 0x01} },
+{ 0x885b,	16,	{0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x3c, 0xe5, 0x5e, 0x24, 0x04, 0xf5} },
+{ 0x886b,	16,	{0x82, 0xe4, 0x35, 0x5d, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0xe4, 0xf5, 0x5b, 0x80, 0x10, 0xaf} },
+{ 0x887b,	16,	{0x5c, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x3c, 0x85} },
+{ 0x888b,	16,	{0x5e, 0x82, 0x85, 0x5d, 0x83, 0xa3, 0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x85, 0x5e, 0x82, 0x85, 0x5d} },
+{ 0x889b,	16,	{0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5b, 0xf0, 0xe5, 0x56, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x88ab,	16,	{0x55, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x5e, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x5d, 0xf5, 0x83} },
+{ 0x88bb,	16,	{0xef, 0xf0, 0xe5, 0x56, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0xff, 0xe5} },
+{ 0x88cb,	16,	{0x5e, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x5d, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x56, 0x24, 0x09} },
+{ 0x88db,	16,	{0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x5e, 0x24, 0x06, 0xf5, 0x82, 0xe4} },
+{ 0x88eb,	16,	{0x35, 0x5d, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x56, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5} },
+{ 0x88fb,	16,	{0x83, 0xe0, 0xff, 0xe5, 0x5e, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x5d, 0xf5, 0x83, 0xef, 0xf0} },
+{ 0x890b,	16,	{0x85, 0x5e, 0x82, 0x85, 0x5d, 0x83, 0xa3, 0xa3, 0xa3, 0xe4, 0xf0, 0x85, 0x5e, 0x82, 0x85, 0x5d} },
+{ 0x891b,	16,	{0x83, 0xa3, 0xa3, 0xf0, 0xaf, 0x5c, 0x7d, 0x06, 0x12, 0x83, 0x7e, 0x75, 0x5b, 0x08, 0xe5, 0x56} },
+{ 0x892b,	16,	{0x24, 0x0c, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0x43, 0x5b, 0x10, 0xe5} },
+{ 0x893b,	16,	{0x5e, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x5d, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x45, 0x5b, 0xf0} },
+{ 0x894b,	16,	{0xe5, 0x56, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0xfe, 0xc3, 0x94, 0x05} },
+{ 0x895b,	16,	{0x40, 0x06, 0xee, 0xd3, 0x94, 0x08, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xe5, 0x56, 0x24, 0x06, 0xf5} },
+{ 0x896b,	16,	{0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0, 0xfd, 0xc3, 0x94, 0x01, 0x40, 0x06, 0xed, 0xd3, 0x94} },
+{ 0x897b,	16,	{0x02, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xed, 0x14, 0xff, 0x25, 0xe0, 0x25, 0xe0, 0xff, 0xee, 0x24} },
+{ 0x898b,	16,	{0xfb, 0x4f, 0xf5, 0x5b, 0xe5, 0x56, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x55, 0xf5, 0x83, 0xe0} },
+{ 0x899b,	16,	{0x24, 0xd0, 0x60, 0x18, 0x14, 0x60, 0x1a, 0x24, 0xc3, 0x60, 0x1e, 0x14, 0x60, 0x09, 0x24, 0x0a} },
+{ 0x89ab,	16,	{0x70, 0x14, 0x43, 0x5b, 0x18, 0x80, 0x12, 0x43, 0x5b, 0x08, 0x80, 0x0d, 0x43, 0x5b, 0x38, 0x80} },
+{ 0x89bb,	16,	{0x08, 0x43, 0x5b, 0x28, 0x80, 0x03, 0x7f, 0xff, 0x22, 0x85, 0x5e, 0x82, 0x85, 0x5d, 0x83, 0xa3} },
+{ 0x89cb,	16,	{0xa3, 0xa3, 0xe5, 0x5b, 0xf0, 0xaf, 0x5c, 0x7d, 0x01, 0x12, 0x82, 0xf9, 0xaa, 0x55, 0xa9, 0x56} },
+{ 0x89db,	16,	{0x7b, 0x01, 0xc0, 0x01, 0xe5, 0x5c, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x01, 0xf9, 0x74, 0x03, 0x35} },
+{ 0x89eb,	15,	{0xf0, 0xa8, 0x01, 0xfc, 0xd0, 0x01, 0x7e, 0x00, 0x7f, 0x0d, 0x12, 0xa0, 0x16, 0x7f, 0x00} },
+{ 0x89fa,	1,	{0x22} },
+{ 0x89fb,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
+{ 0x8a0b,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xad, 0x82, 0xfc, 0x90, 0x01} },
+{ 0x8a1b,	16,	{0x2c, 0x74, 0x08, 0xf0, 0xee, 0x04, 0xa3, 0xf0, 0xe4, 0xa3, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xe5} },
+{ 0x8a2b,	16,	{0x82, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x90, 0x01, 0x2f, 0xf0, 0x8d} },
+{ 0x8a3b,	16,	{0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54} },
+{ 0x8a4b,	16,	{0x1e, 0x90, 0x01, 0x30, 0xf0, 0x74, 0x2c, 0x2e, 0xf8, 0xe6, 0xa3, 0xf0, 0xaf, 0x06, 0x74, 0x01} },
+{ 0x8a5b,	16,	{0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x55, 0xe5, 0x30, 0xc3, 0x94, 0x01} },
+{ 0x8a6b,	16,	{0x40, 0x0d, 0x90, 0x20, 0x78, 0xe0, 0x54, 0x0f, 0x75, 0x56, 0x00, 0xf5, 0x57, 0x80, 0x09, 0x7f} },
+{ 0x8a7b,	16,	{0x02, 0x12, 0x81, 0xd9, 0x8e, 0x56, 0x8f, 0x57, 0xc3, 0xe5, 0x56, 0x64, 0x80, 0x94, 0x80, 0x40} },
+{ 0x8a8b,	16,	{0xda, 0xe5, 0x55, 0x55, 0x57, 0x90, 0x01, 0x32, 0xf0, 0x7e, 0x01, 0x7f, 0x2c, 0x7d, 0x07, 0x12} },
+{ 0x8a9b,	4,	{0x8f, 0x6e, 0x7f, 0x00} },
+{ 0x8a9f,	1,	{0x22} },
+{ 0x8aa0,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
+{ 0x8ab0,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0x90, 0x01} },
+{ 0x8ac0,	16,	{0x33, 0x74, 0x0a, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x8ad0,	16,	{0x83, 0xf5, 0x83, 0xe0, 0x90, 0x01, 0x34, 0xf0, 0x7e, 0x01, 0x7f, 0x33, 0x7d, 0x02, 0x12, 0x8f} },
+{ 0x8ae0,	3,	{0x6e, 0x7f, 0x00} },
+{ 0x8ae3,	1,	{0x22} },
+{ 0x8ae4,	4,	{0xad, 0x07, 0xac, 0x06} },
+{ 0x8ae8,	16,	{0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
+{ 0x8af8,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0x8d, 0x82} },
+{ 0x8b08,	16,	{0x8c, 0x83, 0xa3, 0xe0, 0x60, 0x0f, 0xef, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0} },
+{ 0x8b18,	16,	{0x44, 0x02, 0xf0, 0x80, 0x0d, 0xef, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54} },
+{ 0x8b28,	4,	{0xfd, 0xf0, 0x7f, 0x00} },
+{ 0x8b2c,	1,	{0x22} },
+{ 0x8b2d,	4,	{0xad, 0x07, 0xac, 0x06} },
+{ 0x8b31,	16,	{0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
+{ 0x8b41,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0x8d, 0x82} },
+{ 0x8b51,	16,	{0x8c, 0x83, 0xa3, 0xe0, 0x60, 0x0f, 0xef, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0} },
+{ 0x8b61,	16,	{0x44, 0x01, 0xf0, 0x80, 0x0d, 0xef, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54} },
+{ 0x8b71,	4,	{0xfe, 0xf0, 0x7f, 0x00} },
+{ 0x8b75,	1,	{0x22} },
+{ 0x8b76,	4,	{0xad, 0x07, 0xac, 0x06} },
+{ 0x8b7a,	16,	{0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xee} },
+{ 0x8b8a,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0x8d, 0x82} },
+{ 0x8b9a,	16,	{0x8c, 0x83, 0xa3, 0xe0, 0x60, 0x0d, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x40} },
+{ 0x8baa,	16,	{0xf0, 0x80, 0x0b, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x00} },
+{ 0x8bba,	1,	{0x22} },
+{ 0x8bbb,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xfe, 0xc3, 0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xaf} },
+{ 0x8bcb,	16,	{0x06, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x3b, 0x7f, 0x00} },
+{ 0x8bdb,	1,	{0x22} },
+{ 0x8bdc,	4,	{0x8e, 0x55, 0x8f, 0x56} },
+{ 0x8be0,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0, 0xf5, 0x5a, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xd3} },
+{ 0x8bf0,	16,	{0x94, 0x04, 0x40, 0x03, 0x7f, 0xff, 0x22, 0xe5, 0x57, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x1f} },
+{ 0x8c00,	16,	{0x14, 0x60, 0x28, 0x24, 0x03, 0x70, 0x2e, 0x7e, 0x7e, 0x7f, 0x80, 0x75, 0x58, 0x7e, 0x75, 0x59} },
+{ 0x8c10,	16,	{0x80, 0x80, 0x22, 0x7e, 0x7e, 0x7f, 0x00, 0x75, 0x58, 0x7e, 0x75, 0x59, 0x00, 0x80, 0x16, 0x7e} },
+{ 0x8c20,	16,	{0x7d, 0x7f, 0x80, 0x75, 0x58, 0x7d, 0x75, 0x59, 0x80, 0x80, 0x0a, 0x7e, 0x7d, 0x7f, 0x00, 0x75} },
+{ 0x8c30,	16,	{0x58, 0x7d, 0x75, 0x59, 0x00, 0xe5, 0x5a, 0x70, 0x1b, 0x85, 0x59, 0x82, 0x85, 0x58, 0x83, 0x74} },
+{ 0x8c40,	16,	{0xff, 0xf0, 0xe5, 0x57, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74} },
+{ 0x8c50,	16,	{0x01, 0xf0, 0x80, 0x48, 0xe5, 0x56, 0x24, 0x02, 0xff, 0xe4, 0x35, 0x55, 0xfe, 0xe5, 0x5a, 0x60} },
+{ 0x8c60,	16,	{0x23, 0x0f, 0xef, 0xac, 0x06, 0x70, 0x01, 0x0e, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe0, 0xfd, 0x05} },
+{ 0x8c70,	16,	{0x59, 0xe5, 0x59, 0xaa, 0x58, 0x70, 0x02, 0x05, 0x58, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xed, 0xf0} },
+{ 0x8c80,	16,	{0x15, 0x5a, 0x80, 0xd9, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xff, 0xe5, 0x57, 0x25} },
+{ 0x8c90,	14,	{0xe0, 0x24, 0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x7f, 0x00} },
+{ 0x8c9e,	1,	{0x22} },
+{ 0x8c9f,	16,	{0xef, 0x24, 0x05, 0xf5, 0x56, 0xe4, 0x3e, 0xf5, 0x55, 0x90, 0x01, 0x35, 0x74, 0x07, 0xf0, 0x90} },
+{ 0x8caf,	16,	{0x01, 0x7a, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x36, 0xf0, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3} },
+{ 0x8cbf,	16,	{0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0x8e, 0x57, 0xf5, 0x58, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83} },
+{ 0x8ccf,	16,	{0xe0, 0x24, 0x9e, 0x60, 0x61, 0x24, 0xf9, 0x60, 0x0e, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8d, 0x80} },
+{ 0x8cdf,	16,	{0x24, 0x14, 0x60, 0x03, 0x02, 0x8d, 0xcc, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xfe} },
+{ 0x8cef,	16,	{0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f, 0xf5, 0x5a, 0x74, 0x01, 0x9e, 0xf5, 0x59, 0xd3, 0xe5, 0x5a} },
+{ 0x8cff,	16,	{0x94, 0x40, 0xe5, 0x59, 0x94, 0x00, 0x40, 0x06, 0x75, 0x59, 0x00, 0x75, 0x5a, 0x40, 0xd3, 0xe5} },
+{ 0x8d0f,	16,	{0x58, 0x95, 0x5a, 0xe5, 0x57, 0x95, 0x59, 0x50, 0x03, 0x02, 0x8d, 0xcf, 0xae, 0x59, 0xaf, 0x5a} },
+{ 0x8d1f,	16,	{0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e} },
+{ 0x8d2f,	16,	{0x57, 0xf5, 0x58, 0x02, 0x8d, 0xcf, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xfe, 0xa3} },
+{ 0x8d3f,	16,	{0xe0, 0xff, 0xc3, 0x74, 0x30, 0x9f, 0xf5, 0x5a, 0xe4, 0x9e, 0xf5, 0x59, 0xd3, 0xe5, 0x5a, 0x94} },
+{ 0x8d4f,	16,	{0x10, 0xe5, 0x59, 0x94, 0x00, 0x40, 0x06, 0x75, 0x59, 0x00, 0x75, 0x5a, 0x10, 0xd3, 0xe5, 0x58} },
+{ 0x8d5f,	16,	{0x95, 0x5a, 0xe5, 0x57, 0x95, 0x59, 0x40, 0x68, 0xae, 0x59, 0xaf, 0x5a, 0x85, 0x56, 0x82, 0x85} },
+{ 0x8d6f,	16,	{0x55, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x57, 0xf5, 0x58, 0x80} },
+{ 0x8d7f,	16,	{0x4f, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f} },
+{ 0x8d8f,	16,	{0xf5, 0x5a, 0xe4, 0x9e, 0xf5, 0x59, 0x45, 0x5a, 0x60, 0x0b, 0xd3, 0xe5, 0x5a, 0x94, 0x40, 0xe5} },
+{ 0x8d9f,	16,	{0x59, 0x94, 0x00, 0x40, 0x06, 0x75, 0x59, 0x00, 0x75, 0x5a, 0x40, 0xd3, 0xe5, 0x58, 0x95, 0x5a} },
+{ 0x8daf,	16,	{0xe5, 0x57, 0x95, 0x59, 0x40, 0x17, 0xae, 0x59, 0xaf, 0x5a, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83} },
+{ 0x8dbf,	16,	{0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x57, 0xf5, 0x58, 0x7f, 0x01, 0x22} },
+{ 0x8dcf,	16,	{0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xe0, 0x24, 0x9e, 0x70, 0x03, 0x02, 0x8e, 0x8f, 0x24, 0xf9} },
+{ 0x8ddf,	16,	{0x60, 0x58, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8e, 0xdf, 0x24, 0x14, 0x60, 0x03, 0x02, 0x8f, 0x23} },
+{ 0x8def,	16,	{0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xd3, 0x94, 0xff, 0xee} },
+{ 0x8dff,	16,	{0x94, 0x00, 0x40, 0x03, 0x02, 0x8f, 0x23, 0x90, 0x01, 0x75, 0xef, 0xf0, 0xe5, 0x58, 0x15, 0x58} },
+{ 0x8e0f,	16,	{0xae, 0x57, 0x70, 0x02, 0x15, 0x57, 0x4e, 0x70, 0x03, 0x02, 0x8f, 0x23, 0x90, 0x01, 0x75, 0xe0} },
+{ 0x8e1f,	16,	{0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0xa0} },
+{ 0x8e2f,	16,	{0x9b, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83} },
+{ 0x8e3f,	16,	{0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x80, 0xee, 0x94, 0x00, 0x50, 0x03, 0x02, 0x8f} },
+{ 0x8e4f,	16,	{0x23, 0xd3, 0xef, 0x94, 0xff, 0xee, 0x94, 0x00, 0x40, 0x03, 0x02, 0x8f, 0x23, 0x90, 0x01, 0x76} },
+{ 0x8e5f,	16,	{0xef, 0xf0, 0xe5, 0x58, 0x15, 0x58, 0xae, 0x57, 0x70, 0x02, 0x15, 0x57, 0x4e, 0x70, 0x03, 0x02} },
+{ 0x8e6f,	16,	{0x8f, 0x23, 0x90, 0x01, 0x76, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a} },
+{ 0x8e7f,	16,	{0xe4, 0x75, 0xf0, 0x01, 0x12, 0xa0, 0x9b, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2} },
+{ 0x8e8f,	16,	{0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x20, 0xee} },
+{ 0x8e9f,	16,	{0x94, 0x00, 0x50, 0x03, 0x02, 0x8f, 0x23, 0xd3, 0xef, 0x94, 0x2f, 0xee, 0x94, 0x00, 0x50, 0x74} },
+{ 0x8eaf,	16,	{0x90, 0x01, 0x77, 0xef, 0xf0, 0xe5, 0x58, 0x15, 0x58, 0xae, 0x57, 0x70, 0x02, 0x15, 0x57, 0x4e} },
+{ 0x8ebf,	16,	{0x60, 0x62, 0x90, 0x01, 0x77, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x7a} },
+{ 0x8ecf,	16,	{0xe4, 0x75, 0xf0, 0x01, 0x12, 0xa0, 0x9b, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd5} },
+{ 0x8edf,	16,	{0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x01, 0x78, 0xcf, 0xf0} },
+{ 0x8eef,	16,	{0xa3, 0xef, 0xf0, 0xe5, 0x58, 0x15, 0x58, 0xae, 0x57, 0x70, 0x02, 0x15, 0x57, 0x4e, 0x60, 0x24} },
+{ 0x8eff,	16,	{0x90, 0x01, 0x78, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0xa0, 0x9b, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0} },
+{ 0x8f0f,	16,	{0xff, 0x90, 0x01, 0x7a, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0xa0, 0x9b, 0x85, 0xf0, 0x82, 0xf5, 0x83} },
+{ 0x8f1f,	16,	{0xef, 0xf0, 0x80, 0xcf, 0x7e, 0x01, 0x7f, 0x35, 0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xa3, 0xa3} },
+{ 0x8f2f,	11,	{0xa3, 0xe0, 0xa3, 0xe0, 0x04, 0xfd, 0x12, 0x8f, 0x6e, 0x7f, 0x00} },
+{ 0x8f3a,	1,	{0x22} },
+{ 0x8f3b,	16,	{0x8e, 0x60, 0x8f, 0x61, 0x8c, 0x62, 0x8d, 0x63, 0xaf, 0x03, 0x1b, 0xef, 0x60, 0x24, 0x05, 0x61} },
+{ 0x8f4b,	16,	{0xe5, 0x61, 0xae, 0x60, 0x70, 0x02, 0x05, 0x60, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05} },
+{ 0x8f5b,	16,	{0x63, 0xe5, 0x63, 0xac, 0x62, 0x70, 0x02, 0x05, 0x62, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
+{ 0x8f6b,	3,	{0x80, 0xd6, 0x22} },
+{ 0x8f6e,	6,	{0x8d, 0x5b, 0xab, 0x07, 0xaa, 0x06} },
+{ 0x8f74,	16,	{0x75, 0x5f, 0x40, 0x75, 0x5e, 0x0d, 0x75, 0x5d, 0x03, 0x75, 0x5c, 0x00, 0x90, 0x7f, 0xc2, 0xe0} },
+{ 0x8f84,	16,	{0x20, 0xe1, 0xf9, 0xaf, 0x5f, 0xae, 0x5e, 0xad, 0x5d, 0xac, 0x5c, 0xec, 0x4d, 0x4e, 0x4f, 0x70} },
+{ 0x8f94,	16,	{0x08, 0x90, 0x7f, 0xc2, 0x74, 0x02, 0xf0, 0x80, 0xd7, 0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x16} },
+{ 0x8fa4,	16,	{0xaf, 0x03, 0xae, 0x02, 0x7c, 0x7b, 0x7d, 0x80, 0xab, 0x5b, 0x12, 0x8f, 0x3b, 0x90, 0x7f, 0xc3} },
+{ 0x8fb4,	8,	{0xe5, 0x5b, 0xf0, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
+{ 0x8fbc,	1,	{0x22} },
+{ 0x8fbd,	16,	{0x90, 0x01, 0x84, 0x74, 0x0b, 0xf0, 0xa3, 0xe5, 0x30, 0xf0, 0x90, 0x0a, 0xf1, 0xe4, 0x93, 0x90} },
+{ 0x8fcd,	16,	{0x01, 0x86, 0xf0, 0x90, 0x0a, 0xf2, 0xe4, 0x93, 0x90, 0x01, 0x87, 0xf0, 0xe4, 0x90, 0x01, 0x7c} },
+{ 0x8fdd,	16,	{0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x01} },
+{ 0x8fed,	16,	{0xf0, 0xa3, 0x74, 0x88, 0xf0, 0x7e, 0x01, 0x7f, 0x7c, 0x12, 0x19, 0xc1, 0x7e, 0x01, 0x7f, 0x84} },
+{ 0x8ffd,	7,	{0x7d, 0x14, 0x12, 0x8f, 0x6e, 0x7f, 0x00} },
+{ 0x9004,	1,	{0x22} },
+{ 0x9005,	16,	{0x7e, 0x7b, 0x7f, 0x40, 0x75, 0x4c, 0x7b, 0x75, 0x4d, 0x40, 0x90, 0x7f, 0xd3, 0xe0, 0xff, 0x85} },
+{ 0x9015,	16,	{0x4c, 0x4f, 0x85, 0x4d, 0x50, 0xe5, 0x50, 0x24, 0x01, 0xf5, 0x54, 0xe4, 0x35, 0x4f, 0xf5, 0x53} },
+{ 0x9025,	16,	{0xe4, 0xf5, 0x4e, 0x85, 0x50, 0x82, 0x85, 0x4f, 0x83, 0xe0, 0xfe, 0x14, 0xb4, 0x0c, 0x00, 0x50} },
+{ 0x9035,	16,	{0x5b, 0x90, 0x90, 0x3d, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x90, 0x61, 0x02, 0x90, 0x61, 0x02, 0x90} },
+{ 0x9045,	16,	{0x6b, 0x02, 0x90, 0x75, 0x02, 0x90, 0x75, 0x02, 0x90, 0x75, 0x02, 0x90, 0x89, 0x02, 0x90, 0x61} },
+{ 0x9055,	16,	{0x02, 0x90, 0x7f, 0x02, 0x90, 0x61, 0x02, 0x90, 0x91, 0x02, 0x90, 0x61, 0xef, 0x64, 0x02, 0x60} },
+{ 0x9065,	16,	{0x2b, 0x75, 0x4e, 0xff, 0x80, 0x26, 0xef, 0x64, 0x0e, 0x60, 0x21, 0x75, 0x4e, 0xff, 0x80, 0x1c} },
+{ 0x9075,	16,	{0xef, 0x64, 0x03, 0x60, 0x17, 0x75, 0x4e, 0xff, 0x80, 0x12, 0xef, 0x64, 0x03, 0x60, 0x0d, 0x75} },
+{ 0x9085,	16,	{0x4e, 0xff, 0x80, 0x08, 0xef, 0x64, 0x06, 0x60, 0x03, 0x75, 0x4e, 0xff, 0xe5, 0x4e, 0x60, 0x15} },
+{ 0x9095,	16,	{0x90, 0x01, 0x98, 0x74, 0x11, 0xf0, 0xa3, 0xee, 0xf0, 0x7e, 0x01, 0x7f, 0x98, 0x7d, 0x02, 0x12} },
+{ 0x90a5,	16,	{0x8f, 0x6e, 0xaf, 0x4e, 0x22, 0xe4, 0xf5, 0x4e, 0x85, 0x50, 0x82, 0x85, 0x4f, 0x83, 0xe0, 0x14} },
+{ 0x90b5,	16,	{0xb4, 0x0f, 0x00, 0x40, 0x03, 0x02, 0x91, 0xd3, 0x90, 0x90, 0xc4, 0xf8, 0x28, 0x28, 0x73, 0x02} },
+{ 0x90c5,	16,	{0x90, 0xf1, 0x02, 0x90, 0xfd, 0x02, 0x91, 0x09, 0x02, 0x91, 0x57, 0x02, 0x91, 0x62, 0x02, 0x91} },
+{ 0x90d5,	16,	{0x6d, 0x02, 0x91, 0x78, 0x02, 0x91, 0x83, 0x02, 0x91, 0x8e, 0x02, 0x91, 0x99, 0x02, 0x91, 0xa4} },
+{ 0x90e5,	16,	{0x02, 0x91, 0xab, 0x02, 0x91, 0xd3, 0x02, 0x91, 0xb6, 0x02, 0x91, 0xc1, 0xaf, 0x54, 0xae, 0x53} },
+{ 0x90f5,	16,	{0x12, 0x84, 0x08, 0x8f, 0x4e, 0x02, 0x91, 0xd6, 0xaf, 0x54, 0xae, 0x53, 0x12, 0x84, 0xe6, 0x8f} },
+{ 0x9105,	16,	{0x4e, 0x02, 0x91, 0xd6, 0x85, 0x53, 0x51, 0x85, 0x54, 0x52, 0xe5, 0x52, 0x24, 0x01, 0xff, 0xe4} },
+{ 0x9115,	16,	{0x35, 0x51, 0xfe, 0x12, 0x85, 0xcf, 0xaf, 0x52, 0xae, 0x51, 0x12, 0x86, 0x62, 0x8f, 0x4e, 0xef} },
+{ 0x9125,	16,	{0x64, 0x01, 0x60, 0x03, 0x02, 0x91, 0xd6, 0xaf, 0x52, 0xae, 0x51, 0x12, 0x86, 0xb7, 0x8f, 0x4e} },
+{ 0x9135,	16,	{0xe5, 0x4e, 0x70, 0x03, 0x02, 0x91, 0xd6, 0x85, 0x52, 0x82, 0x85, 0x51, 0x83, 0xe0, 0x75, 0xf0} },
+{ 0x9145,	16,	{0x0d, 0xa4, 0x24, 0xf4, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xaf, 0x82, 0xfe, 0x12, 0x86, 0xb7, 0x02} },
+{ 0x9155,	16,	{0x91, 0xd6, 0xaf, 0x54, 0xae, 0x53, 0x12, 0x8a, 0xe4, 0x8f, 0x4e, 0x80, 0x74, 0xaf, 0x54, 0xae} },
+{ 0x9165,	16,	{0x53, 0x12, 0x8b, 0x2d, 0x8f, 0x4e, 0x80, 0x69, 0xaf, 0x54, 0xae, 0x53, 0x12, 0x8b, 0x76, 0x8f} },
+{ 0x9175,	16,	{0x4e, 0x80, 0x5e, 0xaf, 0x4d, 0xae, 0x4c, 0x12, 0x8c, 0x9f, 0x8f, 0x4e, 0x80, 0x53, 0xaf, 0x54} },
+{ 0x9185,	16,	{0xae, 0x53, 0x12, 0x89, 0xfb, 0x8f, 0x4e, 0x80, 0x48, 0xaf, 0x54, 0xae, 0x53, 0x12, 0x85, 0x80} },
+{ 0x9195,	16,	{0x8f, 0x4e, 0x80, 0x3d, 0xaf, 0x54, 0xae, 0x53, 0x12, 0x8a, 0xa0, 0x8f, 0x4e, 0x80, 0x32, 0x12} },
+{ 0x91a5,	16,	{0x8f, 0xbd, 0x8f, 0x4e, 0x80, 0x2b, 0xaf, 0x54, 0xae, 0x53, 0x12, 0x8b, 0xbb, 0x8f, 0x4e, 0x80} },
+{ 0x91b5,	16,	{0x20, 0xaf, 0x54, 0xae, 0x53, 0x12, 0x8b, 0xdc, 0x8f, 0x4e, 0x80, 0x15, 0xaf, 0x4d, 0xae, 0x4c} },
+{ 0x91c5,	16,	{0x7c, 0x02, 0x7d, 0xaf, 0x7b, 0x40, 0x12, 0x8f, 0x3b, 0xe4, 0xf5, 0x4e, 0x80, 0x03, 0x75, 0x4e} },
+{ 0x91d5,	16,	{0xff, 0xe5, 0x4e, 0x60, 0x1d, 0x90, 0x01, 0x98, 0x74, 0x11, 0xf0, 0x85, 0x50, 0x82, 0x85, 0x4f} },
+{ 0x91e5,	16,	{0x83, 0xe0, 0x90, 0x01, 0x99, 0xf0, 0x7e, 0x01, 0x7f, 0x98, 0x7d, 0x02, 0x12, 0x8f, 0x6e, 0xaf} },
+{ 0x91f5,	16,	{0x4e, 0x22, 0x85, 0x50, 0x82, 0x85, 0x4f, 0x83, 0xe0, 0xff, 0x14, 0x24, 0xfa, 0x50, 0x04, 0x24} },
+{ 0x9205,	16,	{0xfe, 0x70, 0x1f, 0x90, 0x01, 0x98, 0x74, 0x10, 0xf0, 0xa3, 0xef, 0xf0, 0x85, 0x54, 0x82, 0x85} },
+{ 0x9215,	16,	{0x53, 0x83, 0xe0, 0x90, 0x01, 0x9a, 0xf0, 0x7e, 0x01, 0x7f, 0x98, 0x7d, 0x03, 0x12, 0x8f, 0x6e} },
+{ 0x9225,	4,	{0x8f, 0x4e, 0xaf, 0x4e} },
+{ 0x9229,	1,	{0x22} },
+{ 0x922a,	8,	{0x8f, 0x4f, 0x8e, 0x4e, 0x8d, 0x4d, 0x8c, 0x4c} },
+{ 0x9232,	16,	{0x75, 0x56, 0x01, 0x75, 0x57, 0x9c, 0xe4, 0xf5, 0x55, 0xaf, 0x51, 0x15, 0x51, 0xef, 0x70, 0x03} },
+{ 0x9242,	16,	{0x02, 0x92, 0xc8, 0xaf, 0x50, 0xe4, 0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xaf, 0x4f} },
+{ 0x9252,	16,	{0xae, 0x4e, 0xad, 0x4d, 0xac, 0x4c, 0x12, 0xa1, 0x25, 0xaf, 0x03, 0x8f, 0x54, 0xaf, 0x4f, 0xae} },
+{ 0x9262,	16,	{0x4e, 0xad, 0x4d, 0xac, 0x4c, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x50, 0xe4} },
+{ 0x9272,	16,	{0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04} },
+{ 0x9282,	16,	{0x12, 0xa1, 0x25, 0x8f, 0x4f, 0x8e, 0x4e, 0x8d, 0x4d, 0x8c, 0x4c, 0xe5, 0x54, 0x24, 0x30, 0xf5} },
+{ 0x9292,	16,	{0x54, 0xd3, 0x94, 0x39, 0x40, 0x06, 0x74, 0x07, 0x25, 0x54, 0xf5, 0x54, 0x05, 0x57, 0xe5, 0x57} },
+{ 0x92a2,	16,	{0xae, 0x56, 0x70, 0x02, 0x05, 0x56, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x05, 0x57, 0xe5} },
+{ 0x92b2,	16,	{0x57, 0xae, 0x56, 0x70, 0x02, 0x05, 0x56, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe5, 0x54, 0xf0, 0x05} },
+{ 0x92c2,	16,	{0x55, 0x05, 0x55, 0x02, 0x92, 0x3b, 0xe5, 0x57, 0x15, 0x57, 0x70, 0x02, 0x15, 0x56, 0xaf, 0x55} },
+{ 0x92d2,	16,	{0x15, 0x55, 0xef, 0x60, 0x23, 0xe5, 0x57, 0x15, 0x57, 0xae, 0x56, 0x70, 0x02, 0x15, 0x56, 0xf5} },
+{ 0x92e2,	16,	{0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05, 0x53, 0xe5, 0x53, 0xac, 0x52, 0x70, 0x02, 0x05, 0x52, 0x14} },
+{ 0x92f2,	8,	{0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x80, 0xd6} },
+{ 0x92fa,	1,	{0x22} },
+{ 0x92fb,	16,	{0xe4, 0x90, 0x01, 0xc9, 0xf0, 0x7e, 0x01, 0x7f, 0xca, 0x90, 0x01, 0xbe, 0xee, 0xf0, 0xa3, 0xef} },
+{ 0x930b,	10,	{0xf0, 0x90, 0x01, 0xc2, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} },
+{ 0x9315,	16,	{0xaa, 0x07, 0xa9, 0x05, 0x90, 0x01, 0xc9, 0xe0, 0xc3, 0x94, 0x40, 0x50, 0x61, 0xac, 0x02, 0x74} },
+{ 0x9325,	16,	{0x01, 0x7e, 0x00, 0xa8, 0x04, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff} },
+{ 0x9335,	16,	{0xe4, 0xef, 0x55, 0x31, 0x60, 0x45, 0xea, 0x04, 0xff, 0x90, 0x01, 0xc2, 0xe0, 0xfc, 0xa3, 0xe0} },
+{ 0x9345,	16,	{0xfd, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0xa3, 0xe9, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} },
+{ 0x9355,	16,	{0xeb, 0xf0, 0x90, 0x01, 0xc2, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0xa0, 0x85, 0xfc, 0xd3, 0xe5, 0xf0} },
+{ 0x9365,	16,	{0x94, 0x87, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0xc2, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0xca} },
+{ 0x9375,	16,	{0xf0, 0xc2, 0xaf, 0x90, 0x01, 0xc9, 0xe0, 0x04, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
+{ 0x9385,	1,	{0x22} },
+{ 0x9386,	16,	{0x90, 0x01, 0xc9, 0xe0, 0xd3, 0x94, 0x00, 0x40, 0x55, 0x90, 0x01, 0xbe, 0xe0, 0xfc, 0xa3, 0xe0} },
+{ 0x9396,	16,	{0xaa, 0x04, 0xf9, 0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0xaa, 0x06, 0xa9, 0x07, 0xa8} },
+{ 0x93a6,	16,	{0x01, 0xac, 0x02, 0xad, 0x03, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x03, 0x12} },
+{ 0x93b6,	16,	{0xa0, 0x16, 0x90, 0x01, 0xbe, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0xa0, 0x85, 0xfc, 0xd3, 0xe5, 0xf0} },
+{ 0x93c6,	16,	{0x94, 0x87, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0xbe, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0xca} },
+{ 0x93d6,	16,	{0xf0, 0xc2, 0xaf, 0x90, 0x01, 0xc9, 0xe0, 0x14, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
+{ 0x93e6,	1,	{0x22} },
+{ 0x93e7,	16,	{0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x73, 0x7e, 0x7b, 0x7f, 0x80, 0x75, 0x51, 0x7b, 0x75, 0x52} },
+{ 0x93f7,	16,	{0x80, 0xe5, 0x52, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x51, 0xa9, 0x07, 0x7b, 0x01, 0x8b, 0x53, 0xf5} },
+{ 0x9407,	16,	{0x54, 0x89, 0x55, 0xfe, 0x12, 0x93, 0x86, 0xef, 0x60, 0x50, 0xab, 0x53, 0xaa, 0x54, 0xa9, 0x55} },
+{ 0x9417,	16,	{0x12, 0xa0, 0x3f, 0x14, 0xff, 0x90, 0x00, 0x01, 0x12, 0xa0, 0x58, 0xb4, 0x02, 0x16, 0xc2, 0xaf} },
+{ 0x9427,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x44} },
+{ 0x9437,	16,	{0x04, 0xf0, 0xd2, 0xaf, 0x74, 0x01, 0x7e, 0x00, 0xa8, 0x07, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce} },
+{ 0x9447,	16,	{0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe4, 0xef, 0x55, 0x31, 0x60, 0x0f, 0x85, 0x52, 0x82, 0x85, 0x51} },
+{ 0x9457,	10,	{0x83, 0x74, 0x0d, 0xf0, 0x90, 0x7f, 0xc3, 0x74, 0x04, 0xf0} },
+{ 0x9461,	1,	{0x22} },
+{ 0x9462,	16,	{0x12, 0x93, 0xe7, 0xe4, 0xf5, 0x4c, 0x74, 0x37, 0x25, 0x4c, 0xf8, 0xe6, 0x54, 0xf0, 0xf5, 0x4d} },
+{ 0x9472,	16,	{0x74, 0xc5, 0x25, 0x4c, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe0, 0x65, 0x4d, 0xff, 0xc4} },
+{ 0x9482,	16,	{0x54, 0x0f, 0xf5, 0x4e, 0x60, 0x22, 0x74, 0xc5, 0x25, 0x4c, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5} },
+{ 0x9492,	16,	{0x83, 0xe5, 0x4d, 0xf0, 0xaf, 0x4c, 0x7d, 0x01, 0xe5, 0x4d, 0x45, 0x4e, 0xfb, 0x12, 0x93, 0x15} },
+{ 0x94a2,	16,	{0xef, 0x70, 0x05, 0x12, 0x93, 0xe7, 0x80, 0xec, 0x05, 0x4c, 0xe5, 0x4c, 0xc3, 0x94, 0x04, 0x40} },
+{ 0x94b2,	16,	{0xb5, 0x12, 0x93, 0xe7, 0xe5, 0x3b, 0x60, 0x48, 0xe4, 0xf5, 0x4c, 0xaf, 0x4c, 0x74, 0x01, 0xa8} },
+{ 0x94c2,	16,	{0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4d, 0x55, 0x3b, 0x60, 0x29, 0xe5, 0x4c} },
+{ 0x94d2,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x30, 0xe6} },
+{ 0x94e2,	16,	{0x16, 0xaf, 0x4c, 0x7d, 0x04, 0x7b, 0x80, 0x12, 0x93, 0x15, 0xef, 0x70, 0x05, 0x12, 0x93, 0xe7} },
+{ 0x94f2,	16,	{0x80, 0xef, 0xe5, 0x4d, 0xf4, 0x52, 0x3b, 0x05, 0x4c, 0xe5, 0x4c, 0xc3, 0x94, 0x04, 0x40, 0xbb} },
+{ 0x9502,	16,	{0x90, 0x03, 0x00, 0xe0, 0x60, 0x03, 0x02, 0x95, 0xe3, 0x74, 0x19, 0xf0, 0xe5, 0x30, 0xc3, 0x94} },
+{ 0x9512,	16,	{0x01, 0x40, 0x0d, 0x90, 0x20, 0x78, 0xe0, 0x54, 0x0f, 0x75, 0x4f, 0x00, 0xf5, 0x50, 0x80, 0x09} },
+{ 0x9522,	16,	{0x7f, 0x02, 0x12, 0x81, 0xd9, 0x8e, 0x4f, 0x8f, 0x50, 0xc3, 0xe5, 0x4f, 0x64, 0x80, 0x94, 0x80} },
+{ 0x9532,	16,	{0x40, 0xda, 0x90, 0x01, 0xbc, 0xe0, 0x65, 0x50, 0xf0, 0x60, 0x37, 0xe4, 0xf5, 0x4c, 0xaf, 0x4c} },
+{ 0x9542,	16,	{0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4d, 0x90, 0x01, 0xbc} },
+{ 0x9552,	16,	{0xe0, 0x55, 0x4d, 0x60, 0x14, 0xaf, 0x4c, 0x7d, 0x08, 0xe5, 0x4d, 0x55, 0x50, 0xfb, 0x12, 0x93} },
+{ 0x9562,	16,	{0x15, 0xef, 0x70, 0x05, 0x12, 0x93, 0xe7, 0x80, 0xec, 0x05, 0x4c, 0xe5, 0x4c, 0xc3, 0x94, 0x04} },
+{ 0x9572,	16,	{0x40, 0xcc, 0x90, 0x01, 0xbc, 0xe5, 0x50, 0xf0, 0xe4, 0xf5, 0x4c, 0xc2, 0xaf, 0x74, 0x33, 0x25} },
+{ 0x9582,	16,	{0x4c, 0xf8, 0xe6, 0xf5, 0x4d, 0xe4, 0xf6, 0xd2, 0xaf, 0x53, 0x4d, 0x1e, 0xe5, 0x4d, 0x60, 0x11} },
+{ 0x9592,	16,	{0xaf, 0x4c, 0x7d, 0x02, 0xab, 0x4d, 0x12, 0x93, 0x15, 0xef, 0x70, 0x05, 0x12, 0x93, 0xe7, 0x80} },
+{ 0x95a2,	16,	{0xef, 0x74, 0x2c, 0x25, 0x4c, 0xf8, 0xe6, 0xf5, 0x4d, 0x74, 0xfc, 0x25, 0x4c, 0xf5, 0x82, 0xe4} },
+{ 0x95b2,	16,	{0x34, 0x02, 0xf5, 0x83, 0xe0, 0x65, 0x4d, 0x60, 0x11, 0xaf, 0x4c, 0x7d, 0x04, 0xab, 0x4d, 0x12} },
+{ 0x95c2,	16,	{0x93, 0x15, 0xef, 0x70, 0x05, 0x12, 0x93, 0xe7, 0x80, 0xef, 0x74, 0xfc, 0x25, 0x4c, 0xf5, 0x82} },
+{ 0x95d2,	16,	{0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe5, 0x4d, 0xf0, 0x05, 0x4c, 0xe5, 0x4c, 0xc3, 0x94, 0x04, 0x40} },
+{ 0x95e2,	4,	{0x9a, 0x12, 0x93, 0xe7} },
+{ 0x95e6,	1,	{0x22} },
+{ 0x95e7,	12,	{0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x63, 0x02, 0x96, 0x2e} },
+{ 0x95f3,	16,	{0x02, 0x05, 0xad, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
+{ 0x9603,	16,	{0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
+{ 0x9613,	16,	{0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
+{ 0x9623,	16,	{0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x96, 0x73, 0xe4, 0x7e} },
+{ 0x9633,	16,	{0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
+{ 0x9643,	16,	{0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
+{ 0x9653,	16,	{0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
+{ 0x9663,	16,	{0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
+{ 0x9673,	16,	{0x60, 0x24, 0x02, 0x8a, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x81, 0x82, 0x84, 0x88} },
+{ 0x9683,	16,	{0x90, 0xa0, 0xc0, 0xc1, 0xc2, 0xc4, 0xc8, 0xd0, 0xe0, 0xe1, 0xe2, 0xe4, 0xe8, 0xf0, 0xf1, 0xf2} },
+{ 0x9693,	8,	{0xf4, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xfe, 0xff} },
+{ 0x969b,	1,	{0x00} },
+{ 0x969c,	8,	{0x8b, 0x57, 0x8a, 0x58, 0x89, 0x59, 0x8d, 0x5a} },
+{ 0x96a4,	16,	{0xe4, 0xf5, 0x5b, 0xf5, 0x5c, 0xaf, 0x5a, 0x15, 0x5a, 0xef, 0x60, 0x36, 0xab, 0x57, 0x05, 0x59} },
+{ 0x96b4,	16,	{0xe5, 0x59, 0xaa, 0x58, 0x70, 0x02, 0x05, 0x58, 0x14, 0xf9, 0x12, 0xa0, 0x3f, 0xff, 0xe5, 0x5b} },
+{ 0x96c4,	16,	{0xe5, 0x5c, 0x6f, 0x25, 0xe0, 0xff, 0xe4, 0x33, 0xfe, 0x74, 0x99, 0x2f, 0xf5, 0x82, 0xee, 0x34} },
+{ 0x96d4,	16,	{0x9c, 0xf5, 0x83, 0xe5, 0x5b, 0xff, 0xe4, 0x93, 0xf5, 0x5b, 0x74, 0x01, 0x93, 0x6f, 0xf5, 0x5c} },
+{ 0x96e4,	6,	{0x80, 0xc3, 0xae, 0x5b, 0xaf, 0x5c} },
+{ 0x96ea,	1,	{0x22} },
+{ 0x96eb,	11,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18} },
+{ 0x96f6,	16,	{0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xfe, 0x30, 0xe0, 0x05, 0x90, 0x20, 0x02, 0xe0, 0xff, 0xee} },
+{ 0x9706,	16,	{0x30, 0xe1, 0x05, 0x90, 0x20, 0x0a, 0xe0, 0xff, 0xee, 0x30, 0xe2, 0x05, 0x90, 0x20, 0x12, 0xe0} },
+{ 0x9716,	16,	{0xff, 0xee, 0x30, 0xe3, 0x05, 0x90, 0x20, 0x1a, 0xe0, 0xff, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x1e} },
+{ 0x9726,	10,	{0x04, 0xe4, 0xf0, 0x80, 0x05, 0x90, 0x01, 0xc4, 0xee, 0xf0} },
+{ 0x9730,	9,	{0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x9739,	2,	{0xa9, 0x03} },
+{ 0x973b,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xe5} },
+{ 0x974b,	16,	{0x5a, 0x45, 0x5b, 0xf5, 0x5c, 0xe9, 0x60, 0x14, 0x8a, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82} },
+{ 0x975b,	16,	{0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x4d, 0xf0, 0xe4, 0xfe, 0x80, 0x13, 0xeb, 0x24, 0x04, 0xf5} },
+{ 0x976b,	16,	{0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0xff, 0xed, 0xf4, 0xfc, 0xef, 0x5c, 0xf0, 0xae, 0x5c, 0xeb} },
+{ 0x977b,	16,	{0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0x55, 0x5c, 0xfc, 0xb5, 0x06, 0x03, 0xaf} },
+{ 0x978b,	16,	{0x05, 0x22, 0xe5, 0x5a, 0x5c, 0xfe, 0xe5, 0x5b, 0x5c, 0xfd, 0xe9, 0x60, 0x16, 0xee, 0x70, 0x04} },
+{ 0x979b,	16,	{0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xae, 0x07, 0xed, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f} },
+{ 0x97ab,	16,	{0x00, 0xad, 0x07, 0xee, 0x60, 0x03, 0xaf, 0x5a, 0x22, 0xed, 0x60, 0x03, 0xaf, 0x5b, 0x22, 0x7f} },
+{ 0x97bb,	1,	{0x00} },
+{ 0x97bc,	1,	{0x22} },
+{ 0x97bd,	16,	{0x75, 0x53, 0x02, 0x75, 0x54, 0xb0, 0x90, 0x03, 0x35, 0x74, 0x0f, 0xf0, 0x85, 0x54, 0x82, 0x85} },
+{ 0x97cd,	16,	{0x53, 0x83, 0xa3, 0xe0, 0xff, 0x90, 0x03, 0x37, 0xf0, 0x85, 0x54, 0x82, 0x85, 0x53, 0x83, 0xe0} },
+{ 0x97dd,	16,	{0x90, 0x03, 0x36, 0xf0, 0x90, 0x03, 0x38, 0x74, 0xff, 0xf0, 0x75, 0x55, 0x03, 0x75, 0x56, 0x39} },
+{ 0x97ed,	16,	{0xef, 0x14, 0xb4, 0x0b, 0x00, 0x40, 0x03, 0x02, 0x9c, 0x61, 0x90, 0x97, 0xfe, 0xf8, 0x28, 0x28} },
+{ 0x97fd,	16,	{0x73, 0x02, 0x98, 0x1f, 0x02, 0x98, 0xbe, 0x02, 0x99, 0xc3, 0x02, 0x99, 0xe2, 0x02, 0x99, 0xe2} },
+{ 0x980d,	16,	{0x02, 0x9a, 0x98, 0x02, 0x9a, 0xd3, 0x02, 0x9a, 0xf8, 0x02, 0x9b, 0xb6, 0x02, 0x9b, 0xe6, 0x02} },
+{ 0x981d,	16,	{0x9c, 0x12, 0xe4, 0xf5, 0x4c, 0xe5, 0x4c, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4} },
+{ 0x982d,	16,	{0x34, 0x20, 0xaf, 0x82, 0xf5, 0x51, 0x8f, 0x52, 0xe4, 0xff, 0xe4, 0xfe, 0xef, 0x60, 0x10, 0x74} },
+{ 0x983d,	16,	{0x8a, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf4, 0xf5, 0x4d, 0x80, 0x0d, 0x74} },
+{ 0x984d,	16,	{0x8a, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf5, 0x4d, 0xe5, 0x52, 0x24, 0x07} },
+{ 0x985d,	16,	{0xf5, 0x82, 0xe4, 0x35, 0x51, 0xf5, 0x83, 0xe5, 0x4d, 0xf0, 0xe0, 0xf5, 0x4e, 0x65, 0x4d, 0x60} },
+{ 0x986d,	16,	{0x38, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4c, 0x04, 0xfd, 0x05, 0x56, 0xe5, 0x56, 0xaa, 0x55} },
+{ 0x987d,	16,	{0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8a, 0x83, 0xed, 0xf0, 0x05, 0x56, 0xe5, 0x56, 0xac} },
+{ 0x988d,	16,	{0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xe5, 0x4d, 0xf0, 0x85, 0x56, 0x82} },
+{ 0x989d,	16,	{0x85, 0x55, 0x83, 0xe5, 0x4e, 0xf0, 0x02, 0x9c, 0x67, 0x0e, 0xbe, 0x24, 0x8f, 0x0f, 0xef, 0x64} },
+{ 0x98ad,	16,	{0x02, 0x70, 0x87, 0x05, 0x4c, 0xe5, 0x4c, 0x64, 0x04, 0x60, 0x03, 0x02, 0x98, 0x22, 0x02, 0x9c} },
+{ 0x98bd,	16,	{0x67, 0xe4, 0xf5, 0x4c, 0xaf, 0x4c, 0xe4, 0xfd, 0x12, 0x82, 0xf9, 0x05, 0x4c, 0xe5, 0x4c, 0xd3} },
+{ 0x98cd,	16,	{0x94, 0x03, 0x40, 0xf0, 0x90, 0x00, 0x04, 0x74, 0x96, 0xf0, 0xa3, 0x74, 0xeb, 0xf0, 0xe4, 0xf5} },
+{ 0x98dd,	16,	{0x4e, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x51, 0x20, 0x75, 0x52, 0x00, 0xf5, 0x4c, 0xaf, 0x4c, 0x74} },
+{ 0x98ed,	16,	{0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x4d, 0x90, 0x01, 0xc4, 0xf0} },
+{ 0x98fd,	16,	{0x90, 0x01, 0xc0, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x85, 0x52, 0x82, 0x85, 0x51, 0x83, 0xa3} },
+{ 0x990d,	16,	{0x74, 0x02, 0xf0, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x4d, 0x34, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02} },
+{ 0x991d,	16,	{0xa3, 0xe0, 0x70, 0xef, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4c, 0x04, 0xff, 0x05, 0x56, 0xe5, 0x56} },
+{ 0x992d,	16,	{0xac, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x56, 0x82} },
+{ 0x993d,	16,	{0x85, 0x55, 0x83, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x01, 0xc4, 0xf0, 0x75, 0x4e, 0xff, 0x90, 0x01} },
+{ 0x994d,	16,	{0xc4, 0xe0, 0xff, 0x60, 0x37, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4c, 0x04, 0xfe, 0x05, 0x56} },
+{ 0x995d,	16,	{0xe5, 0x56, 0xac, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xee, 0xf0, 0x05} },
+{ 0x996d,	16,	{0x56, 0xe5, 0x56, 0xac, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
+{ 0x997d,	16,	{0x85, 0x56, 0x82, 0x85, 0x55, 0x83, 0xe5, 0x4d, 0xf0, 0x75, 0x4e, 0xff, 0xe5, 0x4e, 0x70, 0x16} },
+{ 0x998d,	16,	{0x74, 0x08, 0x25, 0x52, 0xf5, 0x52, 0xe4, 0x35, 0x51, 0xf5, 0x51, 0x05, 0x4c, 0xe5, 0x4c, 0x64} },
+{ 0x999d,	16,	{0x04, 0x60, 0x03, 0x02, 0x98, 0xea, 0xe4, 0xf5, 0x4c, 0xaf, 0x4c, 0x7d, 0x01, 0x12, 0x82, 0xf9} },
+{ 0x99ad,	16,	{0x05, 0x4c, 0xe5, 0x4c, 0xd3, 0x94, 0x03, 0x40, 0xf0, 0x90, 0x00, 0x04, 0x74, 0x13, 0xf0, 0xa3} },
+{ 0x99bd,	16,	{0x74, 0x12, 0xf0, 0x02, 0x9c, 0x67, 0x85, 0x54, 0x82, 0x85, 0x53, 0x83, 0xe0, 0x14, 0xff, 0x74} },
+{ 0x99cd,	16,	{0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x90, 0x02, 0xf7, 0xf0, 0x90, 0x01} },
+{ 0x99dd,	16,	{0xc4, 0xf0, 0x02, 0x9c, 0x67, 0x90, 0x01, 0xc0, 0x74, 0x03, 0xf0, 0xa3, 0x74, 0xe8, 0xf0, 0xe4} },
+{ 0x99ed,	16,	{0xf5, 0x4e, 0x90, 0x02, 0xf7, 0xe0, 0xff, 0x90, 0x01, 0xc4, 0xe0, 0xb5, 0x07, 0x19, 0x90, 0x01} },
+{ 0x99fd,	16,	{0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xea, 0x90, 0x03, 0x38, 0xf0, 0x85, 0x56, 0x82, 0x85} },
+{ 0x9a0d,	16,	{0x55, 0x83, 0x74, 0xff, 0xf0, 0xf5, 0x4e, 0xe5, 0x4e, 0x60, 0x03, 0x02, 0x9c, 0x67, 0x90, 0x01} },
+{ 0x9a1d,	16,	{0xc0, 0xf0, 0xa3, 0x74, 0x96, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xf6} },
+{ 0x9a2d,	16,	{0xe5, 0x30, 0xc3, 0x94, 0x01, 0x40, 0x0d, 0x90, 0x20, 0x78, 0xe0, 0x54, 0x0f, 0x75, 0x4f, 0x00} },
+{ 0x9a3d,	16,	{0xf5, 0x50, 0x80, 0x09, 0x7f, 0x02, 0x12, 0x81, 0xd9, 0x8e, 0x4f, 0x8f, 0x50, 0xc3, 0xe5, 0x4f} },
+{ 0x9a4d,	16,	{0x64, 0x80, 0x94, 0x80, 0x40, 0xda, 0xe5, 0x50, 0x54, 0x0f, 0xf5, 0x4e, 0x90, 0x02, 0xf7, 0xe0} },
+{ 0x9a5d,	16,	{0x55, 0x4e, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x8f, 0x4d, 0x85, 0x54, 0x82, 0x85} },
+{ 0x9a6d,	16,	{0x53, 0x83, 0xa3, 0xe0, 0xb4, 0x05, 0x0c, 0xe5, 0x4d, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f} },
+{ 0x9a7d,	16,	{0x00, 0x8f, 0x4d, 0xe5, 0x4d, 0x70, 0x03, 0x02, 0x9c, 0x67, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x85} },
+{ 0x9a8d,	16,	{0x56, 0x82, 0x85, 0x55, 0x83, 0xe5, 0x4e, 0xf0, 0x02, 0x9c, 0x67, 0xe4, 0xff, 0xfd, 0x12, 0x82} },
+{ 0x9a9d,	16,	{0xf9, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x51, 0x20, 0x75, 0x52, 0x00, 0x85, 0x52, 0x82, 0x85, 0x51} },
+{ 0x9aad,	16,	{0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85, 0x52, 0x82, 0x85, 0x51, 0x83, 0x74, 0x01} },
+{ 0x9abd,	16,	{0xf0, 0xa3, 0xe4, 0xf0, 0x85, 0x52, 0x82, 0x85, 0x51, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0x7f} },
+{ 0x9acd,	16,	{0xf0, 0xd2, 0x04, 0x02, 0x9c, 0x67, 0xc2, 0x04, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x51, 0x20, 0x75} },
+{ 0x9add,	16,	{0x52, 0x00, 0xe5, 0x52, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x51, 0xf5, 0x83, 0xe0, 0x30, 0xe6} },
+{ 0x9aed,	16,	{0xf1, 0xe4, 0xff, 0x7d, 0x01, 0x12, 0x82, 0xf9, 0x02, 0x9c, 0x67, 0xe4, 0xf5, 0x4e, 0xf5, 0x4c} },
+{ 0x9afd,	16,	{0xaf, 0x4c, 0xe4, 0xfd, 0x12, 0x82, 0xf9, 0xe5, 0x4c, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5} },
+{ 0x9b0d,	16,	{0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x51, 0x8f, 0x52, 0xf5, 0x83, 0xe5, 0x82, 0x24, 0x04} },
+{ 0x9b1d,	16,	{0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf, 0x4c, 0x7d, 0x01, 0x7b} },
+{ 0x9b2d,	16,	{0x01, 0x75, 0x5a, 0x80, 0x75, 0x5b, 0x40, 0x12, 0x97, 0x39, 0x8f, 0x4e, 0xe5, 0x4e, 0x70, 0x11} },
+{ 0x9b3d,	16,	{0xaf, 0x4c, 0x7d, 0x02, 0x7b, 0x01, 0x75, 0x5a, 0x10, 0x75, 0x5b, 0x20, 0x12, 0x97, 0x39, 0x8f} },
+{ 0x9b4d,	16,	{0x4e, 0xe5, 0x4e, 0x70, 0x10, 0xaf, 0x4c, 0x7d, 0x01, 0xfb, 0x75, 0x5a, 0x80, 0x75, 0x5b, 0x40} },
+{ 0x9b5d,	16,	{0x12, 0x97, 0x39, 0x8f, 0x4e, 0xe5, 0x4e, 0x70, 0x10, 0xaf, 0x4c, 0x7d, 0x02, 0xfb, 0x75, 0x5a} },
+{ 0x9b6d,	16,	{0x10, 0x75, 0x5b, 0x20, 0x12, 0x97, 0x39, 0x8f, 0x4e, 0xaf, 0x4c, 0x7d, 0x01, 0x12, 0x82, 0xf9} },
+{ 0x9b7d,	16,	{0xe5, 0x4e, 0x60, 0x26, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0xe5, 0x4c, 0x04, 0xff, 0x05, 0x56, 0xe5} },
+{ 0x9b8d,	16,	{0x56, 0xac, 0x55, 0x70, 0x02, 0x05, 0x55, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x56} },
+{ 0x9b9d,	16,	{0x82, 0x85, 0x55, 0x83, 0xe5, 0x4e, 0xf0, 0x02, 0x9c, 0x67, 0x05, 0x4c, 0xe5, 0x4c, 0xd3, 0x94} },
+{ 0x9bad,	16,	{0x03, 0x50, 0x03, 0x02, 0x9a, 0xfd, 0x02, 0x9c, 0x67, 0xe4, 0x90, 0x03, 0x59, 0xf0, 0xa3, 0xf0} },
+{ 0x9bbd,	16,	{0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x9c, 0xf0, 0xa3, 0x74} },
+{ 0x9bcd,	16,	{0x89, 0xf0, 0x7e, 0x03, 0x7f, 0x59, 0x12, 0x10, 0xcc, 0xef, 0x64, 0x08, 0x70, 0x03, 0x02, 0x9c} },
+{ 0x9bdd,	16,	{0x67, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x02, 0x9c, 0x67, 0xe4, 0x90, 0x03, 0x59, 0xf0, 0xa3, 0xf0} },
+{ 0x9bed,	16,	{0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0xe5, 0x55, 0xf0, 0xa3, 0xe5} },
+{ 0x9bfd,	16,	{0x56, 0xf0, 0x7e, 0x03, 0x7f, 0x59, 0x12, 0x19, 0xc1, 0xef, 0x64, 0x08, 0x60, 0x5c, 0xe4, 0x90} },
+{ 0x9c0d,	16,	{0x03, 0x38, 0xf0, 0x80, 0x55, 0xe5, 0x54, 0x24, 0x02, 0xff, 0xe4, 0x35, 0x53, 0xfa, 0xa9, 0x07} },
+{ 0x9c1d,	16,	{0x7b, 0x01, 0x7d, 0x10, 0x12, 0x96, 0x9c, 0xef, 0x4e, 0x70, 0x32, 0x90, 0x03, 0x59, 0xf0, 0xa3} },
+{ 0x9c2d,	16,	{0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xe5, 0x54, 0x24, 0x02, 0x90} },
+{ 0x9c3d,	16,	{0x03, 0x60, 0xf0, 0xe4, 0x35, 0x53, 0x90, 0x03, 0x5f, 0xf0, 0x7e, 0x03, 0x7f, 0x59, 0x12, 0x10} },
+{ 0x9c4d,	16,	{0xcc, 0xef, 0x64, 0x08, 0x60, 0x14, 0xe4, 0x90, 0x03, 0x38, 0xf0, 0x80, 0x0d, 0xe4, 0x90, 0x03} },
+{ 0x9c5d,	16,	{0x38, 0xf0, 0x80, 0x06, 0x90, 0x03, 0x38, 0x74, 0x01, 0xf0, 0x90, 0x01, 0xc0, 0xe4, 0xf0, 0xa3} },
+{ 0x9c6d,	16,	{0x74, 0x0a, 0xf0, 0x90, 0x01, 0xc0, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xf6, 0x7e, 0x03, 0x7f} },
+{ 0x9c7d,	11,	{0x35, 0x7d, 0x24, 0x12, 0x8f, 0x6e, 0xe4, 0x90, 0x02, 0xaf, 0xf0} },
+{ 0x9c88,	1,	{0x22} },
+{ 0x9c89,	16,	{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f} },
+{ 0x9c99,	16,	{0x00, 0x00, 0xc0, 0xc1, 0xc1, 0x81, 0x01, 0x40, 0xc3, 0x01, 0x03, 0xc0, 0x02, 0x80, 0xc2, 0x41} },
+{ 0x9ca9,	16,	{0xc6, 0x01, 0x06, 0xc0, 0x07, 0x80, 0xc7, 0x41, 0x05, 0x00, 0xc5, 0xc1, 0xc4, 0x81, 0x04, 0x40} },
+{ 0x9cb9,	16,	{0xcc, 0x01, 0x0c, 0xc0, 0x0d, 0x80, 0xcd, 0x41, 0x0f, 0x00, 0xcf, 0xc1, 0xce, 0x81, 0x0e, 0x40} },
+{ 0x9cc9,	16,	{0x0a, 0x00, 0xca, 0xc1, 0xcb, 0x81, 0x0b, 0x40, 0xc9, 0x01, 0x09, 0xc0, 0x08, 0x80, 0xc8, 0x41} },
+{ 0x9cd9,	16,	{0xd8, 0x01, 0x18, 0xc0, 0x19, 0x80, 0xd9, 0x41, 0x1b, 0x00, 0xdb, 0xc1, 0xda, 0x81, 0x1a, 0x40} },
+{ 0x9ce9,	16,	{0x1e, 0x00, 0xde, 0xc1, 0xdf, 0x81, 0x1f, 0x40, 0xdd, 0x01, 0x1d, 0xc0, 0x1c, 0x80, 0xdc, 0x41} },
+{ 0x9cf9,	16,	{0x14, 0x00, 0xd4, 0xc1, 0xd5, 0x81, 0x15, 0x40, 0xd7, 0x01, 0x17, 0xc0, 0x16, 0x80, 0xd6, 0x41} },
+{ 0x9d09,	16,	{0xd2, 0x01, 0x12, 0xc0, 0x13, 0x80, 0xd3, 0x41, 0x11, 0x00, 0xd1, 0xc1, 0xd0, 0x81, 0x10, 0x40} },
+{ 0x9d19,	16,	{0xf0, 0x01, 0x30, 0xc0, 0x31, 0x80, 0xf1, 0x41, 0x33, 0x00, 0xf3, 0xc1, 0xf2, 0x81, 0x32, 0x40} },
+{ 0x9d29,	16,	{0x36, 0x00, 0xf6, 0xc1, 0xf7, 0x81, 0x37, 0x40, 0xf5, 0x01, 0x35, 0xc0, 0x34, 0x80, 0xf4, 0x41} },
+{ 0x9d39,	16,	{0x3c, 0x00, 0xfc, 0xc1, 0xfd, 0x81, 0x3d, 0x40, 0xff, 0x01, 0x3f, 0xc0, 0x3e, 0x80, 0xfe, 0x41} },
+{ 0x9d49,	16,	{0xfa, 0x01, 0x3a, 0xc0, 0x3b, 0x80, 0xfb, 0x41, 0x39, 0x00, 0xf9, 0xc1, 0xf8, 0x81, 0x38, 0x40} },
+{ 0x9d59,	16,	{0x28, 0x00, 0xe8, 0xc1, 0xe9, 0x81, 0x29, 0x40, 0xeb, 0x01, 0x2b, 0xc0, 0x2a, 0x80, 0xea, 0x41} },
+{ 0x9d69,	16,	{0xee, 0x01, 0x2e, 0xc0, 0x2f, 0x80, 0xef, 0x41, 0x2d, 0x00, 0xed, 0xc1, 0xec, 0x81, 0x2c, 0x40} },
+{ 0x9d79,	16,	{0xe4, 0x01, 0x24, 0xc0, 0x25, 0x80, 0xe5, 0x41, 0x27, 0x00, 0xe7, 0xc1, 0xe6, 0x81, 0x26, 0x40} },
+{ 0x9d89,	16,	{0x22, 0x00, 0xe2, 0xc1, 0xe3, 0x81, 0x23, 0x40, 0xe1, 0x01, 0x21, 0xc0, 0x20, 0x80, 0xe0, 0x41} },
+{ 0x9d99,	16,	{0xa0, 0x01, 0x60, 0xc0, 0x61, 0x80, 0xa1, 0x41, 0x63, 0x00, 0xa3, 0xc1, 0xa2, 0x81, 0x62, 0x40} },
+{ 0x9da9,	16,	{0x66, 0x00, 0xa6, 0xc1, 0xa7, 0x81, 0x67, 0x40, 0xa5, 0x01, 0x65, 0xc0, 0x64, 0x80, 0xa4, 0x41} },
+{ 0x9db9,	16,	{0x6c, 0x00, 0xac, 0xc1, 0xad, 0x81, 0x6d, 0x40, 0xaf, 0x01, 0x6f, 0xc0, 0x6e, 0x80, 0xae, 0x41} },
+{ 0x9dc9,	16,	{0xaa, 0x01, 0x6a, 0xc0, 0x6b, 0x80, 0xab, 0x41, 0x69, 0x00, 0xa9, 0xc1, 0xa8, 0x81, 0x68, 0x40} },
+{ 0x9dd9,	16,	{0x78, 0x00, 0xb8, 0xc1, 0xb9, 0x81, 0x79, 0x40, 0xbb, 0x01, 0x7b, 0xc0, 0x7a, 0x80, 0xba, 0x41} },
+{ 0x9de9,	16,	{0xbe, 0x01, 0x7e, 0xc0, 0x7f, 0x80, 0xbf, 0x41, 0x7d, 0x00, 0xbd, 0xc1, 0xbc, 0x81, 0x7c, 0x40} },
+{ 0x9df9,	16,	{0xb4, 0x01, 0x74, 0xc0, 0x75, 0x80, 0xb5, 0x41, 0x77, 0x00, 0xb7, 0xc1, 0xb6, 0x81, 0x76, 0x40} },
+{ 0x9e09,	16,	{0x72, 0x00, 0xb2, 0xc1, 0xb3, 0x81, 0x73, 0x40, 0xb1, 0x01, 0x71, 0xc0, 0x70, 0x80, 0xb0, 0x41} },
+{ 0x9e19,	16,	{0x50, 0x00, 0x90, 0xc1, 0x91, 0x81, 0x51, 0x40, 0x93, 0x01, 0x53, 0xc0, 0x52, 0x80, 0x92, 0x41} },
+{ 0x9e29,	16,	{0x96, 0x01, 0x56, 0xc0, 0x57, 0x80, 0x97, 0x41, 0x55, 0x00, 0x95, 0xc1, 0x94, 0x81, 0x54, 0x40} },
+{ 0x9e39,	16,	{0x9c, 0x01, 0x5c, 0xc0, 0x5d, 0x80, 0x9d, 0x41, 0x5f, 0x00, 0x9f, 0xc1, 0x9e, 0x81, 0x5e, 0x40} },
+{ 0x9e49,	16,	{0x5a, 0x00, 0x9a, 0xc1, 0x9b, 0x81, 0x5b, 0x40, 0x99, 0x01, 0x59, 0xc0, 0x58, 0x80, 0x98, 0x41} },
+{ 0x9e59,	16,	{0x88, 0x01, 0x48, 0xc0, 0x49, 0x80, 0x89, 0x41, 0x4b, 0x00, 0x8b, 0xc1, 0x8a, 0x81, 0x4a, 0x40} },
+{ 0x9e69,	16,	{0x4e, 0x00, 0x8e, 0xc1, 0x8f, 0x81, 0x4f, 0x40, 0x8d, 0x01, 0x4d, 0xc0, 0x4c, 0x80, 0x8c, 0x41} },
+{ 0x9e79,	16,	{0x44, 0x00, 0x84, 0xc1, 0x85, 0x81, 0x45, 0x40, 0x87, 0x01, 0x47, 0xc0, 0x46, 0x80, 0x86, 0x41} },
+{ 0x9e89,	16,	{0x82, 0x01, 0x42, 0xc0, 0x43, 0x80, 0x83, 0x41, 0x41, 0x00, 0x81, 0xc1, 0x80, 0x81, 0x40, 0x40} },
+{ 0x9e99,	16,	{0xe4, 0xff, 0x74, 0xf8, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02} },
+{ 0x9ea9,	16,	{0x9f, 0x3c, 0x74, 0x37, 0x2f, 0xf8, 0xe6, 0x20, 0xe5, 0x03, 0x02, 0x9f, 0x3c, 0xef, 0x75, 0xf0} },
+{ 0x9eb9,	16,	{0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xad, 0x82, 0xfc, 0xf5, 0x83, 0xe5, 0x82} },
+{ 0x9ec9,	16,	{0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0x60, 0x64, 0x60, 0x70, 0x63} },
+{ 0x9ed9,	16,	{0xef, 0x25, 0xe0, 0x24, 0xef, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01} },
+{ 0x9ee9,	16,	{0x12, 0xa0, 0x9b, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0, 0x8d, 0x82, 0x8c, 0x83, 0xf0, 0x74, 0xf8} },
+{ 0x9ef9,	16,	{0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x14, 0xf0, 0x70, 0x36, 0xef, 0x25, 0xe0} },
+{ 0x9f09,	16,	{0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0xef, 0x25, 0xe0, 0xfe, 0xc3} },
+{ 0x9f19,	16,	{0x74, 0x0c, 0x9e, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xad} },
+{ 0x9f29,	16,	{0x82, 0xfc, 0xef, 0x25, 0xe0, 0x24, 0xef, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xec, 0xf0} },
+{ 0x9f39,	12,	{0xa3, 0xed, 0xf0, 0x0f, 0xef, 0x64, 0x04, 0x60, 0x03, 0x02, 0x9e, 0x9b} },
+{ 0x9f45,	1,	{0x22} },
+{ 0x9f46,	16,	{0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e} },
+{ 0x9f56,	16,	{0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08} },
+{ 0x9f66,	16,	{0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83} },
+{ 0x9f76,	16,	{0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08} },
+{ 0x9f86,	16,	{0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c} },
+{ 0x9f96,	16,	{0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10} },
+{ 0x9fa6,	16,	{0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33} },
+{ 0x9fb6,	16,	{0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83} },
+{ 0x9fc6,	16,	{0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80} },
+{ 0x9fd6,	16,	{0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0} },
+{ 0x9fe6,	16,	{0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc} },
+{ 0x9ff6,	16,	{0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde} },
+{ 0xa006,	16,	{0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc} },
+{ 0xa016,	16,	{0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xc2, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4} },
+{ 0xa026,	16,	{0x04, 0x00, 0x50, 0xb8, 0x23, 0x23, 0x45, 0x82, 0xf5, 0x82, 0xef, 0x4e, 0x60, 0xae, 0xef, 0x60} },
+{ 0xa036,	9,	{0x01, 0x0e, 0xe5, 0x82, 0x23, 0x90, 0x9f, 0x96, 0x73} },
+{ 0xa03f,	16,	{0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
+{ 0xa04f,	9,	{0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
+{ 0xa058,	16,	{0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
+{ 0xa068,	16,	{0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
+{ 0xa078,	13,	{0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
+{ 0xa085,	16,	{0xc5, 0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02} },
+{ 0xa095,	6,	{0x15, 0x83, 0xe0, 0x38, 0xf0, 0x22} },
+{ 0xa09b,	16,	{0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83} },
+{ 0xa0ab,	6,	{0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22} },
+{ 0xa0b1,	16,	{0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} },
+{ 0xa0c1,	16,	{0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} },
+{ 0xa0d1,	16,	{0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} },
+{ 0xa0e1,	8,	{0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} },
+{ 0xa0e9,	16,	{0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc} },
+{ 0xa0f9,	16,	{0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40} },
+{ 0xa109,	16,	{0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6} },
+{ 0xa119,	16,	{0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9} },
+{ 0xa129,	16,	{0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb} },
+{ 0xa139,	16,	{0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb} },
+{ 0xa149,	16,	{0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9} },
+{ 0xa159,	16,	{0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc} },
+{ 0xa169,	16,	{0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a} },
+{ 0xa179,	16,	{0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f} },
+{ 0xa189,	16,	{0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07} },
+{ 0xa199,	16,	{0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8} },
+{ 0xa1a9,	14,	{0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22} },
+{ 0xa1b7,	16,	{0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} },
+{ 0xa1c7,	1,	{0x22} },
+{ 0xa1c8,	16,	{0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef, 0x13, 0xff} },
+{ 0xa1d8,	3,	{0xd8, 0xf1, 0x22} },
+{ 0xa1db,	16,	{0x08, 0x08, 0x08, 0xe6, 0xcf, 0x2f, 0xf6, 0x18, 0xe6, 0xce, 0x3e, 0xf6, 0x18, 0xe6, 0xcd, 0x3d} },
+{ 0xa1eb,	7,	{0xf6, 0x18, 0xe6, 0xcc, 0x3c, 0xf6, 0x22} },
+{ 0xa1f2,	12,	{0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} },
+{ 0xa1fe,	16,	{0xa8, 0x82, 0x85, 0x83, 0xf0, 0xd0, 0x83, 0xd0, 0x82, 0x12, 0xa2, 0x15, 0x12, 0xa2, 0x15, 0x12} },
+{ 0xa20e,	16,	{0xa2, 0x15, 0x12, 0xa2, 0x15, 0xe4, 0x73, 0xe4, 0x93, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83} },
+{ 0xa21e,	16,	{0xc8, 0xc5, 0x82, 0xc8, 0xf0, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83, 0xc8, 0xc5, 0x82, 0xc8} },
+{ 0xa22e,	1,	{0x22} },
 { 0xffff,	0,	{0x00} }
 };
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c
--- v2.5.0/linux/drivers/usb/storage/scsiglue.c	Sun Nov 11 10:01:32 2001
+++ linux/drivers/usb/storage/scsiglue.c	Wed Nov 28 10:22:27 2001
@@ -388,7 +388,6 @@
 	present:		0,
 	unchecked_isa_dma:	FALSE,
 	use_clustering:		TRUE,
-	use_new_eh_code:	TRUE,
 	emulated:		TRUE
 };
 
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- v2.5.0/linux/drivers/usb/usb-ohci.c	Fri Nov  9 13:41:42 2001
+++ linux/drivers/usb/usb-ohci.c	Sat Dec  8 20:28:45 2001
@@ -485,7 +485,7 @@
 
 			/* implicitly requeued */
   			urb->actual_length = 0;
-  			urb->status = USB_ST_URB_PENDING;
+  			urb->status = -EINPROGRESS;
   			if (urb_priv->state != URB_DEL)
   				td_submit_urb (urb);
   			break;
@@ -502,7 +502,7 @@
 				urb->complete (urb);
 				spin_lock_irqsave (&usb_ed_lock, flags);
 				urb->actual_length = 0;
-  				urb->status = USB_ST_URB_PENDING;
+  				urb->status = -EINPROGRESS;
   				urb->start_frame = urb_priv->ed->last_iso + 1;
   				if (urb_priv->state != URB_DEL) {
   					for (i = 0; i < urb->number_of_packets; i++) {
@@ -673,7 +673,7 @@
 
 	urb->actual_length = 0;
 	urb->hcpriv = urb_priv;
-	urb->status = USB_ST_URB_PENDING;
+	urb->status = -EINPROGRESS;
 
 	/* link the ed into a chain if is not already */
 	if (ed->state != ED_OPER)
@@ -737,7 +737,7 @@
 	if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
 		return rh_unlink_urb (urb);
 
-	if (urb->hcpriv && (urb->status == USB_ST_URB_PENDING)) { 
+	if (urb->hcpriv && (urb->status == -EINPROGRESS)) { 
 		if (!ohci->disabled) {
 			urb_priv_t  * urb_priv;
 
@@ -777,11 +777,11 @@
 
 				/* wait until all TDs are deleted */
 				set_current_state(TASK_UNINTERRUPTIBLE);
-				while (timeout && (urb->status == USB_ST_URB_PENDING))
+				while (timeout && (urb->status == -EINPROGRESS))
 					timeout = schedule_timeout (timeout);
 				set_current_state(TASK_RUNNING);
 				remove_wait_queue (&unlink_wakeup, &wait); 
-				if (urb->status == USB_ST_URB_PENDING) {
+				if (urb->status == -EINPROGRESS) {
 					err ("unlink URB timeout");
 					return -ETIMEDOUT;
 				}
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/usb-ohci.h linux/drivers/usb/usb-ohci.h
--- v2.5.0/linux/drivers/usb/usb-ohci.h	Wed Oct 24 08:26:12 2001
+++ linux/drivers/usb/usb-ohci.h	Sat Dec  8 20:28:45 2001
@@ -11,22 +11,22 @@
 static int cc_to_error[16] = { 
 
 /* mapping of the OHCI CC status to error codes */ 
-	/* No  Error  */               USB_ST_NOERROR,
-	/* CRC Error  */               USB_ST_CRC,
-	/* Bit Stuff  */               USB_ST_BITSTUFF,
-	/* Data Togg  */               USB_ST_CRC,
-	/* Stall      */               USB_ST_STALL,
-	/* DevNotResp */               USB_ST_NORESPONSE,
-	/* PIDCheck   */               USB_ST_BITSTUFF,
-	/* UnExpPID   */               USB_ST_BITSTUFF,
-	/* DataOver   */               USB_ST_DATAOVERRUN,
-	/* DataUnder  */               USB_ST_DATAUNDERRUN,
-	/* reservd    */               USB_ST_NORESPONSE,
-	/* reservd    */               USB_ST_NORESPONSE,
-	/* BufferOver */               USB_ST_BUFFEROVERRUN,
-	/* BuffUnder  */               USB_ST_BUFFERUNDERRUN,
-	/* Not Access */               USB_ST_NORESPONSE,
-	/* Not Access */               USB_ST_NORESPONSE 
+	/* No  Error  */	0,
+	/* CRC Error  */	-EILSEQ,
+	/* Bit Stuff  */	-EPROTO,
+	/* Data Togg  */	-EILSEQ,
+	/* Stall      */	-EPIPE,
+	/* DevNotResp */	-ETIMEDOUT,
+	/* PIDCheck   */	-EPROTO,
+	/* UnExpPID   */	-EPROTO,
+	/* DataOver   */	-EOVERFLOW,
+	/* DataUnder  */	-EREMOTEIO,
+	/* reservd    */	-ETIMEDOUT,
+	/* reservd    */	-ETIMEDOUT,
+	/* BufferOver */	-ECOMM,
+	/* BuffUnder  */	-ENOSR,
+	/* Not Access */	-ETIMEDOUT,
+	/* Not Access */	-ETIMEDOUT 
 };
 
 #include <linux/config.h>
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.5.0/linux/drivers/usb/usb.c	Wed Nov 21 09:59:11 2001
+++ linux/drivers/usb/usb.c	Sat Dec  8 20:28:45 2001
@@ -7,7 +7,8 @@
  * (C) Copyright Gregory P. Smith 1999
  * (C) Copyright Deti Fliegl 1999 (new USB architecture)
  * (C) Copyright Randy Dunlap 2000
- * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
+ * (C) Copyright David Brownell 2000-2001 (kernel hotplug, usb_device_id,
+ 	more docs, etc)
  * (C) Copyright Yggdrasil Computing, Inc. 2000
  *     (usb_device_id matching changes by Adam J. Richter)
  *
@@ -105,8 +106,8 @@
  *	Goes through all unclaimed USB interfaces, and offers them to all
  *	registered USB drivers through the 'probe' function.
  *	This will automatically be called after usb_register is called.
- *	It is called by some of the USB subsystems after one of their subdrivers
- *	are registered.
+ *	It is called by some of the subsystems layered over USB
+ *	after one of their subdrivers are registered.
  */
 void usb_scan_devices(void)
 {
@@ -193,6 +194,22 @@
 	up (&usb_bus_list_lock);
 }
 
+/**
+ * usb_ifnum_to_if - get the interface object with a given interface number
+ * @dev: the device whose current configuration is considered
+ * @ifnum: the desired interface
+ *
+ * This walks the device descriptor for the currently active configuration
+ * and returns a pointer to the interface with that particular interface
+ * number, or null.
+ *
+ * Note that configuration descriptors are not required to assign interface
+ * numbers sequentially, so that it would be incorrect to assume that
+ * the first interface in that descriptor corresponds to interface zero.
+ * This routine helps device drivers avoid such mistakes.
+ * However, you should make sure that you do the right thing with any
+ * alternate settings available for this interfaces.
+ */
 struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
 {
 	int i;
@@ -204,6 +221,20 @@
 	return NULL;
 }
 
+/**
+ * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
+ * @dev: the device whose current configuration is considered
+ * @epnum: the desired endpoint
+ *
+ * This walks the device descriptor for the currently active configuration,
+ * and returns a pointer to the endpoint with that particular endpoint
+ * number, or null.
+ *
+ * Note that interface descriptors are not required to assign endpont
+ * numbers sequentially, so that it would be incorrect to assume that
+ * the first endpoint in that descriptor corresponds to interface zero.
+ * This routine helps device drivers avoid such mistakes.
+ */
 struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
 {
 	int i, j, k;
@@ -261,7 +292,7 @@
  * bustime is from calc_bus_time(), but converted to microseconds.
  *
  * returns <bustime in us> if successful,
- * or USB_ST_BANDWIDTH_ERROR if bandwidth request fails.
+ * or -ENOSPC if bandwidth request fails.
  *
  * FIXME:
  * This initial implementation does not use Endpoint.bInterval
@@ -302,7 +333,7 @@
 
 	if (!usb_bandwidth_option)	/* don't enforce it */
 		return (bustime);
-	return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? bustime : USB_ST_BANDWIDTH_ERROR;
+	return (new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ? bustime : -ENOSPC;
 }
 
 void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc)
@@ -356,7 +387,7 @@
 }
 
 /**
- *	usb_alloc_bus - creates a new USB host controller structure
+ *	usb_alloc_bus - creates a new USB host controller structure (usbcore-internal)
  *	@op: pointer to a struct usb_operations that this bus structure should use
  *
  *	Creates a USB host controller bus structure with the specified 
@@ -398,7 +429,7 @@
 }
 
 /**
- *	usb_free_bus - frees the memory used by a bus structure
+ *	usb_free_bus - frees the memory used by a bus structure (usbcore-internal)
  *	@bus: pointer to the bus to free
  *
  *	(For use only by USB Host Controller Drivers.)
@@ -412,10 +443,12 @@
 }
 
 /**
- *	usb_register_bus - registers the USB host controller with the usb core
+ *	usb_register_bus - registers the USB host controller with the usb core (usbcore-internal)
  *	@bus: pointer to the bus to register
  *
  *	(For use only by USB Host Controller Drivers.)
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
  */
 void usb_register_bus(struct usb_bus *bus)
 {
@@ -441,10 +474,12 @@
 }
 
 /**
- *	usb_deregister_bus - deregisters the USB host controller
+ *	usb_deregister_bus - deregisters the USB host controller (usbcore-internal)
  *	@bus: pointer to the bus to deregister
  *
  *	(For use only by USB Host Controller Drivers.)
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
  */
 void usb_deregister_bus(struct usb_bus *bus)
 {
@@ -493,27 +528,49 @@
 }
 
 
-/*
- * This is intended to be used by usb device drivers that need to
- * claim more than one interface on a device at once when probing
- * (audio and acm are good examples).  No device driver should have
- * to mess with the internal usb_interface or usb_device structure
- * members.
+/**
+ * usb_driver_claim_interface - bind a driver to an interface
+ * @driver: the driver to be bound
+ * @iface: the interface to which it will be bound
+ * @priv: driver data associated with that interface
+ *
+ * This is used by usb device drivers that need to claim more than one
+ * interface on a device when probing (audio and acm are current examples).
+ * No device driver should directly modify internal usb_interface or
+ * usb_device structure members.
+ *
+ * Few drivers should need to use this routine, since the most natural
+ * way to bind to an interface is to return the private data from
+ * the driver's probe() method.  Any driver that does use this must
+ * first be sure that no other driver has claimed the interface, by
+ * checking with usb_interface_claimed().
  */
 void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv)
 {
 	if (!iface || !driver)
 		return;
 
-	dbg("%s driver claimed interface %p", driver->name, iface);
+	// FIXME change API to report an error in this case
+	if (iface->driver)
+	    err ("%s driver booted %s off interface %p",
+	    	driver->name, iface->driver->name, iface);
+	else
+	    dbg("%s driver claimed interface %p", driver->name, iface);
 
 	iface->driver = driver;
 	iface->private_data = priv;
 } /* usb_driver_claim_interface() */
 
-/*
+/**
+ * usb_interface_claimed - returns true iff an interface is claimed
+ * @iface: the interface being checked
+ *
  * This should be used by drivers to check other interfaces to see if
- * they are available or not.
+ * they are available or not.  If another driver has claimed the interface,
+ * they may not claim it.  Otherwise it's OK to claim it using
+ * usb_driver_claim_interface().
+ *
+ * Returns true (nonzero) iff the interface is claimed, else false (zero).
  */
 int usb_interface_claimed(struct usb_interface *iface)
 {
@@ -523,8 +580,19 @@
 	return (iface->driver != NULL);
 } /* usb_interface_claimed() */
 
-/*
- * This should be used by drivers to release their claimed interfaces
+/**
+ * usb_driver_release_interface - unbind a driver from an interface
+ * @driver: the driver to be unbound
+ * @iface: the interface from which it will be unbound
+ * 
+ * This should be used by drivers to release their claimed interfaces.
+ * It is normally called in their disconnect() methods, and only for
+ * drivers that bound to more than one interface in their probe().
+ *
+ * When the USB subsystem disconnect()s a driver from some interface,
+ * it automatically invokes this method for that interface.  That
+ * means that even drivers that used usb_driver_claim_interface()
+ * usually won't need to call this.
  */
 void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
 {
@@ -923,9 +991,15 @@
 	}
 }
 
-/*
- * Only HC's should call usb_alloc_dev and usb_free_dev directly
- * Anybody may use usb_inc_dev_use or usb_dec_dev_use
+/**
+ * usb_alloc_dev - allocate a usb device structure (usbcore-internal)
+ * @parent: hub to which device is connected
+ * @bus: bus used to access the device
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
  */
 struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
 {
@@ -952,6 +1026,8 @@
 	return dev;
 }
 
+// usbcore-internal ...
+// but usb_dec_dev_use() is #defined to this, and that's public!!
 void usb_free_dev(struct usb_device *dev)
 {
 	if (atomic_dec_and_test(&dev->refcnt)) {
@@ -964,14 +1040,25 @@
 	}
 }
 
+/**
+ * usb_inc_dev_use - record another reference to a device
+ * @dev: the device being referenced
+ *
+ * Each live reference to a device should be refcounted.
+ *
+ * Device drivers should normally record such references in their
+ * open() methods.
+ * Drivers should then release them, using usb_dec_dev_use(), in their
+ * close() methods.
+ */
 void usb_inc_dev_use(struct usb_device *dev)
 {
 	atomic_inc(&dev->refcnt);
 }
 
-/* ------------------------------------------------------------------------------------- 
+/* ---------------------------------------------------------------------- 
  * New USB Core Functions
- * -------------------------------------------------------------------------------------*/
+ * ----------------------------------------------------------------------*/
 
 /**
  *	usb_alloc_urb - creates a new urb for a USB driver to use
@@ -1017,6 +1104,61 @@
 		kfree(urb);
 }
 /*-------------------------------------------------------------------*/
+
+/**
+ * usb_submit_urb - asynchronously issue a transfer request for an endpoint
+ * @urb: pointer to the urb describing the request
+ *
+ * This submits a transfer request, and transfers control of the URB
+ * describing that request to the USB subsystem.  Request completion will
+ * indicated later, asynchronously, by calling the completion handler.
+ * This call may be issued in interrupt context.
+ *
+ * The caller must have correctly initialized the URB before submitting
+ * it.  Macros such as FILL_BULK_URB() and FILL_CONTROL_URB() are
+ * available to ensure that most fields are correctly initialized, for
+ * the particular kind of transfer, although they will not initialize
+ * any transfer flags.
+ *
+ * Successful submissions return 0; otherwise this routine returns a
+ * negative error number.  If the submission is successful, the complete
+ * fuction of the urb will be called when the USB host driver is
+ * finished with the urb (either a successful transmission, or some
+ * error case.)
+ *
+ * Unreserved Bandwidth Transfers:
+ *
+ * Bulk or control requests complete only once.  When the completion
+ * function is called, control of the URB is returned to the device
+ * driver which issued the request.  The completion handler may then
+ * immediately free or reuse that URB.
+ *
+ * Bulk URBs will be queued if the USB_QUEUE_BULK transfer flag is set
+ * in the URB.  This can be used to maximize bandwidth utilization by
+ * letting the USB controller start work on the next URB without any
+ * delay to report completion (scheduling and processing an interrupt)
+ * and then submit that next request.
+ *
+ * For control endpoints, the synchronous usb_control_msg() call is
+ * often used (in non-interrupt context) instead of this call.
+ *
+ * Reserved Bandwidth Transfers:
+ *
+ * Periodic URBs (interrupt or isochronous) are completed repeatedly,
+ * until the original request is aborted.  When the completion callback
+ * indicates the URB has been unlinked (with a special status code),
+ * control of that URB returns to the device driver.  Otherwise, the
+ * completion handler does not control the URB, and should not change
+ * any of its fields.
+ *
+ * Note that isochronous URBs should be submitted in a "ring" data
+ * structure (using urb->next) to ensure that they are resubmitted
+ * appropriately.
+ *
+ * If the USB subsystem can't reserve sufficient bandwidth to perform
+ * the periodic request, and bandwidth reservation is being done for
+ * this controller, submitting such a periodic request will fail. 
+ */
 int usb_submit_urb(urb_t *urb)
 {
 	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
@@ -1026,6 +1168,31 @@
 }
 
 /*-------------------------------------------------------------------*/
+
+/**
+ * usb_unlink_urb - abort/cancel a transfer request for an endpoint
+ * @urb: pointer to urb describing a previously submitted request
+ *
+ * This routine cancels an in-progress request.  The requests's
+ * completion handler will be called with a status code indicating
+ * that the request has been canceled, and that control of the URB
+ * has been returned to that device driver.  This is the only way
+ * to stop an interrupt transfer, so long as the device is connected.
+ *
+ * When the USB_ASYNC_UNLINK transfer flag for the URB is clear, this
+ * request is synchronous.  Success is indicated by returning zero,
+ * at which time the urb will have been unlinked,
+ * and the completion function will see status -ENOENT.  Failure is
+ * indicated by any other return value.  This mode may not be used
+ * when unlinking an urb from an interrupt context, such as a bottom
+ * half or a completion handler,
+ *
+ * When the USB_ASYNC_UNLINK transfer flag for the URB is set, this
+ * request is asynchronous.  Success is indicated by returning -EINPROGRESS,
+ * at which time the urb will normally not have been unlinked,
+ * and the completion function will see status -ECONNRESET.  Failure is
+ * indicated by any other return value.
+ */
 int usb_unlink_urb(urb_t *urb)
 {
 	if (urb && urb->dev && urb->dev->bus && urb->dev->bus->op)
@@ -1034,12 +1201,14 @@
 		return -ENODEV;
 }
 /*-------------------------------------------------------------------*
- *                     COMPLETION HANDLERS                           *
+ *                         SYNCHRONOUS CALLS                         *
  *-------------------------------------------------------------------*/
 
-/*-------------------------------------------------------------------*
- * completion handler for compatibility wrappers (sync control/bulk) *
- *-------------------------------------------------------------------*/
+struct usb_api_data {
+	wait_queue_head_t wqh;
+	int done;
+};
+
 static void usb_api_blocking_completion(urb_t *urb)
 {
 	struct usb_api_data *awd = (struct usb_api_data *)urb->context;
@@ -1049,10 +1218,6 @@
 	wake_up(&awd->wqh);
 }
 
-/*-------------------------------------------------------------------*
- *                         COMPATIBILITY STUFF                       *
- *-------------------------------------------------------------------*/
-
 // Starts urb and waits for completion or timeout
 static int usb_start_wait_urb(urb_t *urb, int timeout, int* actual_length)
 { 
@@ -1145,7 +1310,7 @@
  *	This function sends a simple control message to a specified endpoint
  *	and waits for the message to complete, or timeout.
  *	
- *	If successful, it returns 0, othwise a negative error number.
+ *	If successful, it returns 0, otherwise a negative error number.
  *
  *	Don't use this function from within an interrupt context, like a
  *	bottom half handler.  If you need a asyncronous message, or need to send
@@ -1188,9 +1353,9 @@
  *	This function sends a simple bulk message to a specified endpoint
  *	and waits for the message to complete, or timeout.
  *	
- *	If successful, it returns 0, othwise a negative error number.
- *	The number of actual bytes transferred will be plaed in the 
- *	actual_timeout paramater.
+ *	If successful, it returns 0, otherwise a negative error number.
+ *	The number of actual bytes transferred will be stored in the 
+ *	actual_length paramater.
  *
  *	Don't use this function from within an interrupt context, like a
  *	bottom half handler.  If you need a asyncronous message, or need to
@@ -1214,16 +1379,19 @@
 	return usb_start_wait_urb(urb,timeout,actual_length);
 }
 
-/*
- * usb_get_current_frame_number()
+/**
+ * usb_get_current_frame_number - return current bus frame number
+ * @dev: the device whose bus is being queried
  *
- * returns the current frame number for the parent USB bus/controller
- * of the given USB device.
+ * Returns the current frame number for the USB host controller
+ * used with the given USB device.  This can be used when scheduling
+ * isochronous requests.
  */
-int usb_get_current_frame_number(struct usb_device *usb_dev)
+int usb_get_current_frame_number(struct usb_device *dev)
 {
-	return usb_dev->bus->op->get_frame_number (usb_dev);
+	return dev->bus->op->get_frame_number (dev);
 }
+
 /*-------------------------------------------------------------------*/
 
 static int usb_parse_endpoint(struct usb_endpoint_descriptor *endpoint, unsigned char *buffer, int size)
@@ -1556,6 +1724,8 @@
 	return size;
 }
 
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally on disconnect/destroy path
 void usb_destroy_configuration(struct usb_device *dev)
 {
 	int c, i, j, k;
@@ -1685,8 +1855,16 @@
 	return -1;
 }
 
-/*
+/**
+ * usb_disconnect - disconnect a device (usbcore-internal)
+ * @pdev: pointer to device being disconnected
+ *
  * Something got disconnected. Get rid of it, and all of its children.
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
  */
 void usb_disconnect(struct usb_device **pdev)
 {
@@ -1735,11 +1913,17 @@
 	usb_free_dev(dev);
 }
 
-/*
+/**
+ * usb_connect - connects a new device during enumeration (usbcore-internal)
+ * @dev: partially enumerated device
+ *
  * Connect a new USB device. This basically just initializes
  * the USB device information and sets up the topology - it's
  * up to the low-level driver to reset the port and actually
  * do the setup (the upper levels don't know how to do that).
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
  */
 void usb_connect(struct usb_device *dev)
 {
@@ -1747,6 +1931,9 @@
 	// FIXME needs locking for SMP!!
 	/* why? this is called only from the hub thread, 
 	 * which hopefully doesn't run on multiple CPU's simultaneously 8-)
+	 * ... it's also called from modprobe/rmmod/apmd threads as part
+	 * of virtual root hub init/reinit.  In the init case, the hub code 
+	 * won't have seen this, but not so for reinit ... 
 	 */
 	dev->descriptor.bMaxPacketSize0 = 8;  /* Start off at 8 bytes  */
 #ifndef DEVNUM_ROUND_ROBIN
@@ -1770,19 +1957,38 @@
  * These are the actual routines to send
  * and receive control messages.
  */
-#ifdef CONFIG_USB_LONG_TIMEOUT
-#define GET_TIMEOUT 4
-#else
-#define GET_TIMEOUT 3
-#endif
-#define SET_TIMEOUT 3
 
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally, for usb_new_device()
 int usb_set_address(struct usb_device *dev)
 {
 	return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
-		0, dev->devnum, 0, NULL, 0, HZ * GET_TIMEOUT);
+		// FIXME USB_CTRL_SET_TIMEOUT
+		0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT);
 }
 
+/**
+ * usb_get_descriptor - issues a generic GET_DESCRIPTOR request
+ * @dev: the device whose descriptor is being retrieved
+ * @type: the descriptor type (USB_DT_*)
+ * @index: the number of the descriptor
+ * @buf: where to put the descriptor
+ * @size: how big is "buf"?
+ *
+ * Gets a USB descriptor.  Convenience functions exist to simplify
+ * getting some types of descriptors.  Use
+ * usb_get_device_descriptor() for USB_DT_DEVICE,
+ * and usb_get_string() or usb_string() for USB_DT_STRING.
+ * Configuration descriptors (USB_DT_CONFIG) are part of the device
+ * structure, at least for the current configuration.
+ * In addition to a number of USB-standard descriptors, some
+ * devices also use class-specific or vendor-specific descriptors.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
 int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char index, void *buf, int size)
 {
 	int i = 5;
@@ -1791,30 +1997,64 @@
 	memset(buf,0,size);	// Make sure we parse really received data
 
 	while (i--) {
+		/* retries if the returned length was 0; flakey device */
 		if ((result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
-			(type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)) > 0 ||
-		     result == -EPIPE)
-			break;	/* retry if the returned length was 0; flaky device */
+				    USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+				    (type << 8) + index, 0, buf, size,
+				    HZ * USB_CTRL_GET_TIMEOUT)) > 0
+				|| result == -EPIPE)
+			break;
 	}
 	return result;
 }
 
-int usb_get_class_descriptor(struct usb_device *dev, int ifnum,
-		unsigned char type, unsigned char id, void *buf, int size)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
-		(type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);
-}
-
+/**
+ * usb_get_string - gets a string descriptor
+ * @dev: the device whose string descriptor is being retrieved
+ * @langid: code for language chosen (from string descriptor zero)
+ * @index: the number of the descriptor
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ *
+ * Retrieves a string, encoded using UTF-16LE (Unicode, 16 bits per character,
+ * in little-endian byte order).
+ * The usb_string() function will often be a convenient way to turn
+ * these strings into kernel-printable form.
+ *
+ * Strings may be referenced in device, configuration, interface, or other
+ * descriptors, and could also be used in vendor-specific ways.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
 int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size)
 {
 	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 		USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
-		(USB_DT_STRING << 8) + index, langid, buf, size, HZ * GET_TIMEOUT);
+		(USB_DT_STRING << 8) + index, langid, buf, size,
+		HZ * USB_CTRL_GET_TIMEOUT);
 }
 
+/**
+ * usb_get_device_descriptor - (re)reads the device descriptor
+ * @dev: the device whose device descriptor is being updated
+ *
+ * Updates the copy of the device descriptor stored in the device structure,
+ * which dedicates space for this purpose.  Note that several fields are
+ * converted to the host CPU's byte order:  the USB version (bcdUSB), and
+ * vendors product and version fields (idVendor, idProduct, and bcdDevice).
+ * That lets device drivers compare against non-byteswapped constants.
+ *
+ * There's normally no need to use this call, although some devices
+ * will change their descriptors after events like updating firmware.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
 int usb_get_device_descriptor(struct usb_device *dev)
 {
 	int ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor,
@@ -1828,39 +2068,37 @@
 	return ret;
 }
 
+/**
+ * usb_get_status - issues a GET_STATUS call
+ * @dev: the device whose status is being checked
+ * @type: USB_RECIP_*; for device, interface, or endpoint
+ * @target: zero (for device), else interface or endpoint number
+ * @data: pointer to two bytes of bitmap data
+ *
+ * Returns device, interface, or endpoint status.  Normally only of
+ * interest to see if the device is self powered, or has enabled the
+ * remote wakeup facility; or whether a bulk or interrupt endpoint
+ * is halted ("stalled").
+ *
+ * Bits in these status bitmaps are set using the SET_FEATURE request,
+ * and cleared using the CLEAR_FEATURE request.  The usb_clear_halt()
+ * function should be used to clear halt ("stall") status.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
 int usb_get_status(struct usb_device *dev, int type, int target, void *data)
 {
 	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2, HZ * GET_TIMEOUT);
+		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, data, 2,
+		HZ * USB_CTRL_GET_TIMEOUT);
 }
 
-int usb_get_protocol(struct usb_device *dev, int ifnum)
-{
-	unsigned char type;
-	int ret;
-
-	if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-	    USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-	    0, ifnum, &type, 1, HZ * GET_TIMEOUT)) < 0)
-		return ret;
-
-	return type;
-}
-
-int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol)
-{
-	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		protocol, ifnum, NULL, 0, HZ * SET_TIMEOUT);
-}
-
-int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id)
-{
-	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		(duration << 8) | report_id, ifnum, NULL, 0, HZ * SET_TIMEOUT);
-}
 
+// hub-only!! ... and only exported for reset/reinit path.
+// otherwise used internally, for config/altsetting reconfig.
 void usb_set_maxpacket(struct usb_device *dev)
 {
 	int i, b;
@@ -1890,9 +2128,26 @@
 	}
 }
 
-/*
- * endp: endpoint number in bits 0-3;
- *	direction flag in bit 7 (1 = IN, 0 = OUT)
+/**
+ * usb_clear_halt - tells device to clear endpoint halt/stall condition
+ * @dev: device whose endpoint is halted
+ * @pipe: endpoint "pipe" being cleared
+ *
+ * This is used to clear halt conditions for bulk and interrupt endpoints,
+ * as reported by URB completion status.  Endpoints that are halted are
+ * sometimes referred to as being "stalled".  Such endpoints are unable
+ * to transmit or receive data until the halt status is cleared.  Any URBs
+ * queued queued for such an endpoint should normally be unlinked before
+ * clearing the halt condition.
+ *
+ * Note that control and isochronous endpoints don't halt, although control
+ * endpoints report "protocol stall" (for unsupported requests) using the
+ * same status code used to report a true stall.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
  */
 int usb_clear_halt(struct usb_device *dev, int pipe)
 {
@@ -1907,7 +2162,8 @@
 */
 
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT);
+		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0,
+		HZ * USB_CTRL_SET_TIMEOUT);
 
 	/* don't clear if failed */
 	if (result < 0)
@@ -1921,7 +2177,8 @@
 
 	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
-		buffer, sizeof(status), HZ * SET_TIMEOUT);
+		// FIXME USB_CTRL_GET_TIMEOUT, yes?  why not usb_get_status() ?
+		buffer, sizeof(status), HZ * USB_CTRL_SET_TIMEOUT);
 
 	memcpy(&status, buffer, sizeof(status));
 	kfree(buffer);
@@ -1941,6 +2198,33 @@
 	return 0;
 }
 
+/**
+ * usb_set_interface - Makes a particular alternate setting be current
+ * @dev: the device whose interface is being updated
+ * @interface: the interface being updated
+ * @alternate: the setting being chosen.
+ *
+ * This is used to enable data transfers on interfaces that may not
+ * be enabled by default.  Not all devices support such configurability.
+ *
+ * Within any given configuration, each interface may have several
+ * alternative settings.  These are often used to control levels of
+ * bandwidth consumption.  For example, the default setting for a high
+ * speed interrupt endpoint may not send more than about 4KBytes per
+ * microframe, and isochronous endpoints may never be part of a an
+ * interface's default setting.  To access such bandwidth, alternate
+ * interface setting must be made current.
+ *
+ * Note that in the Linux USB subsystem, bandwidth associated with
+ * an endpoint in a given alternate setting is not reserved until an
+ * is submitted that needs that bandwidth.  Some other operating systems
+ * allocate bandwidth early, when a configuration is chosen.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
 int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 {
 	struct usb_interface *iface;
@@ -1964,6 +2248,35 @@
 	return 0;
 }
 
+/**
+ * usb_set_configuration - Makes a particular device setting be current
+ * @dev: the device whose configuration is being updated
+ * @configuration: the configuration being chosen.
+ *
+ * This is used to enable non-default device modes.  Not all devices
+ * support this kind of configurability.  By default, configuration
+ * zero is selected after enumeration; many devices only have a single
+ * configuration.
+ *
+ * USB devices may support one or more configurations, which affect
+ * power consumption and the functionality available.  For example,
+ * the default configuration is limited to using 100mA of bus power,
+ * so that when certain device functionality requires more power,
+ * and the device is bus powered, that functionality will be in some
+ * non-default device configuration.  Other device modes may also be
+ * reflected as configuration options, such as whether two ISDN
+ * channels are presented as independent 64Kb/s interfaces or as one
+ * bonded 128Kb/s interface.
+ *
+ * Note that USB has an additional level of device configurability,
+ * associated with interfaces.  That configurability is accessed using
+ * usb_set_interface().
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns zero on success, or else the status code returned by the
+ * underlying usb_control_msg() call.
+ */
 int usb_set_configuration(struct usb_device *dev, int configuration)
 {
 	int i, ret;
@@ -1981,7 +2294,8 @@
 	}
 
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-	    USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * SET_TIMEOUT)) < 0)
+			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
+			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
 		return ret;
 
 	dev->actconfig = cp;
@@ -1992,20 +2306,8 @@
 	return 0;
 }
 
-int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size)
-{
-	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		(type << 8) + id, ifnum, buf, size, HZ * GET_TIMEOUT);
-}
-
-int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type, unsigned char id, void *buf, int size)
-{
-	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		(type << 8) + id, ifnum, buf, size, HZ);
-}
-
+// hub-only!! ... and only in reset path, or usb_new_device()
+// (used by real hubs and virtual root hubs)
 int usb_get_configuration(struct usb_device *dev)
 {
 	int result;
@@ -2106,9 +2408,28 @@
 	return result;
 }
 
-/*
- * usb_string:
- *	returns string length (> 0) or error (< 0)
+/**
+ * usb_string - returns ISO 8859-1 version of a string descriptor
+ * @dev: the device whose string descriptor is being retrieved
+ * @index: the number of the descriptor
+ * @buf: where to put the string
+ * @size: how big is "buf"?
+ * 
+ * This converts the UTF-16LE encoded strings returned by devices, from
+ * usb_get_string_descriptor(), to null-terminated ISO-8859-1 encoded ones
+ * that are more usable in most kernel contexts.  Note that all characters
+ * in the chosen descriptor that can't be encoded using ISO-8859-1
+ * are converted to the question mark ("?") character, and this function
+ * chooses strings in the first language supported by the device.
+ *
+ * The ASCII (or, redundantly, "US-ASCII") character set is the seven-bit
+ * subset of ISO 8859-1. ISO-8859-1 is the eight-bit subset of Unicode,
+ * and is appropriate for use many uses of English and several other
+ * Western European languages.  (But it doesn't include the "Euro" symbol.)
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Returns length of the string (>= 0) or usb_control_msg status (< 0).
  */
 int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
 {
@@ -2155,7 +2476,7 @@
 		if (idx >= size)
 			break;
 		if (tbuf[u+1])			/* high byte */
-			buf[idx++] = '?';  /* non-ASCII character */
+			buf[idx++] = '?';  /* non ISO-8859-1 character */
 		else
 			buf[idx++] = tbuf[u];
 	}
@@ -2173,6 +2494,11 @@
  * get the ball rolling..
  *
  * Returns 0 for success, != 0 for error.
+ *
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Only hub drivers (including virtual root hub drivers for host
+ * controllers) should ever call this.
  */
 int usb_new_device(struct usb_device *dev)
 {
@@ -2388,33 +2714,28 @@
 EXPORT_SYMBOL(usb_claim_bandwidth);
 EXPORT_SYMBOL(usb_release_bandwidth);
 
-EXPORT_SYMBOL(usb_set_address);
-EXPORT_SYMBOL(usb_get_descriptor);
-EXPORT_SYMBOL(usb_get_class_descriptor);
 EXPORT_SYMBOL(__usb_get_extra_descriptor);
-EXPORT_SYMBOL(usb_get_device_descriptor);
-EXPORT_SYMBOL(usb_get_string);
-EXPORT_SYMBOL(usb_string);
-EXPORT_SYMBOL(usb_get_protocol);
-EXPORT_SYMBOL(usb_set_protocol);
-EXPORT_SYMBOL(usb_get_report);
-EXPORT_SYMBOL(usb_set_report);
-EXPORT_SYMBOL(usb_set_idle);
-EXPORT_SYMBOL(usb_clear_halt);
-EXPORT_SYMBOL(usb_set_interface);
-EXPORT_SYMBOL(usb_get_configuration);
-EXPORT_SYMBOL(usb_set_configuration);
-EXPORT_SYMBOL(usb_get_status);
 
 EXPORT_SYMBOL(usb_get_current_frame_number);
 
+// asynchronous request completion model
 EXPORT_SYMBOL(usb_alloc_urb);
 EXPORT_SYMBOL(usb_free_urb);
 EXPORT_SYMBOL(usb_submit_urb);
 EXPORT_SYMBOL(usb_unlink_urb);
 
+// synchronous request completion model
 EXPORT_SYMBOL(usb_control_msg);
 EXPORT_SYMBOL(usb_bulk_msg);
+// synchronous control message convenience routines
+EXPORT_SYMBOL(usb_get_descriptor);
+EXPORT_SYMBOL(usb_get_device_descriptor);
+EXPORT_SYMBOL(usb_get_status);
+EXPORT_SYMBOL(usb_get_string);
+EXPORT_SYMBOL(usb_string);
+EXPORT_SYMBOL(usb_clear_halt);
+EXPORT_SYMBOL(usb_set_configuration);
+EXPORT_SYMBOL(usb_set_interface);
 
 EXPORT_SYMBOL(usb_devfs_handle);
 MODULE_LICENSE("GPL");
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- v2.5.0/linux/drivers/usb/usbkbd.c	Fri Sep 14 14:04:07 2001
+++ linux/drivers/usb/usbkbd.c	Sat Dec  8 20:28:45 2001
@@ -35,6 +35,9 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 
+#define	_HID_BOOT_PROTOCOL
+#include "hid.h"
+
 /*
  * Version Information
  */
@@ -192,8 +195,8 @@
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
-	usb_set_protocol(dev, interface->bInterfaceNumber, 0);
-	usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
+	hid_set_protocol(dev, interface->bInterfaceNumber, 0);
+	hid_set_idle(dev, interface->bInterfaceNumber, 0, 0);
 
 	if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
 	memset(kbd, 0, sizeof(struct usb_kbd));
@@ -216,7 +219,7 @@
 		usb_kbd_irq, kbd, endpoint->bInterval);
 
 	kbd->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-	kbd->dr.request = USB_REQ_SET_REPORT;
+	kbd->dr.request = HID_REQ_SET_REPORT;
 	kbd->dr.value = 0x200;
 	kbd->dr.index = interface->bInterfaceNumber;
 	kbd->dr.length = 1;
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c
--- v2.5.0/linux/drivers/usb/usbmouse.c	Fri Sep 14 14:04:07 2001
+++ linux/drivers/usb/usbmouse.c	Sat Dec  8 20:28:45 2001
@@ -35,6 +35,9 @@
 #include <linux/init.h>
 #include <linux/usb.h>
 
+#define	_HID_BOOT_PROTOCOL
+#include "hid.h"
+
 /*
  * Version Information
  */
@@ -118,7 +121,7 @@
 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
 
-	usb_set_idle(dev, interface->bInterfaceNumber, 0, 0);
+	hid_set_idle(dev, interface->bInterfaceNumber, 0, 0);
 
 	if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
 	memset(mouse, 0, sizeof(struct usb_mouse));
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/usbnet.c linux/drivers/usb/usbnet.c
--- v2.5.0/linux/drivers/usb/usbnet.c	Wed Nov 21 09:51:08 2001
+++ linux/drivers/usb/usbnet.c	Sat Dec  8 20:25:02 2001
@@ -1535,7 +1535,7 @@
 	struct skb_data		*entry = (struct skb_data *) skb->cb;
 	struct usbnet		*dev = entry->dev;
 
-	if (urb->status == USB_ST_STALL) {
+	if (urb->status == -EPIPE) {
 		if (dev->ctrl_task.sync == 0) {
 			dev->ctrl_task.routine = tx_clear_halt;
 			dev->ctrl_task.data = dev;
@@ -1868,6 +1868,11 @@
 #ifdef	CONFIG_USB_AN2720
 {
 	USB_DEVICE (0x0547, 0x2720),	// AnchorChips defaults
+	driver_info:	(unsigned long) &an2720_info,
+},
+
+{
+	USB_DEVICE (0x0547, 0x2727),	// Xircom PGUNET
 	driver_info:	(unsigned long) &an2720_info,
 },
 #endif
diff -u --recursive --new-file v2.5.0/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c
--- v2.5.0/linux/drivers/usb/uss720.c	Sat Oct 20 19:13:11 2001
+++ linux/drivers/usb/uss720.c	Sat Dec  8 20:28:45 2001
@@ -193,7 +193,7 @@
 	struct parport *pp = (struct parport *)dev_id;
 	struct parport_uss720_private *priv = pp->private_data;	
 
-	if (usbstatus != USB_ST_NOERROR || len < 4 || !buffer)
+	if (usbstatus != 0 || len < 4 || !buffer)
 		return 1;
 	memcpy(priv->reg, buffer, 4);
 	/* if nAck interrupts are enabled and we have an interrupt, call the interrupt procedure */
diff -u --recursive --new-file v2.5.0/linux/drivers/video/modedb.c linux/drivers/video/modedb.c
--- v2.5.0/linux/drivers/video/modedb.c	Fri Mar  2 18:38:39 2001
+++ linux/drivers/video/modedb.c	Tue Nov 27 17:06:50 2001
@@ -14,9 +14,9 @@
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/fb.h>
-#include <linux/console_struct.h>
 #include <linux/sched.h>
 
+#include <video/fbcon.h>
 
 #undef DEBUG
 
@@ -256,29 +256,6 @@
 	}
     }
 }
-
-static int PROC_CONSOLE(const struct fb_info *info)
-{
-	int fgc;
-	
-	if (info->display_fg != NULL)
-		fgc = info->display_fg->vc_num;
-	else
-		return -1;
-		
-	if (!current->tty)
-		return fgc;
-
-	if (current->tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
-		/* XXX Should report error here? */
-		return fgc;
-
-	if (MINOR(current->tty->device) < 1)
-		return fgc;
-
-	return MINOR(current->tty->device) - 1;
-}
-
 
 /**
  *	__fb_try_mode - test a video mode
diff -u --recursive --new-file v2.5.0/linux/fs/Makefile linux/fs/Makefile
--- v2.5.0/linux/fs/Makefile	Mon Nov 12 09:34:16 2001
+++ linux/fs/Makefile	Thu Nov 29 17:39:02 2001
@@ -7,12 +7,12 @@
 
 O_TARGET := fs.o
 
-export-objs :=	filesystems.o open.o dcache.o buffer.o
+export-objs :=	filesystems.o open.o dcache.o buffer.o bio.o
 mod-subdirs :=	nls
 
 obj-y :=	open.o read_write.o devices.o file_table.o buffer.o \
-		super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
-		fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
+		bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \
+		namei.o fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
 		dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
 		filesystems.o namespace.o seq_file.o
 
@@ -24,6 +24,7 @@
 
 subdir-$(CONFIG_PROC_FS)	+= proc
 subdir-y			+= partitions
+subdir-y			+= driverfs
 
 # Do not add any filesystems before this line
 subdir-$(CONFIG_EXT3_FS)	+= ext3    # Before ext2 so root fs can be ext3
diff -u --recursive --new-file v2.5.0/linux/fs/autofs4/root.c linux/fs/autofs4/root.c
--- v2.5.0/linux/fs/autofs4/root.c	Mon Oct 23 21:57:38 2000
+++ linux/fs/autofs4/root.c	Fri Nov 30 08:26:04 2001
@@ -202,8 +202,6 @@
 {
 	struct autofs_info *inf;
 
-	lock_kernel();
-
 	DPRINTK(("autofs4_dentry_release: releasing %p\n", de));
 
 	inf = autofs4_dentry_ino(de);
@@ -215,8 +213,6 @@
 
 		autofs4_free_ino(inf);
 	}
-
-	unlock_kernel();
 }
 
 /* For dentries of directories in the root dir */
diff -u --recursive --new-file v2.5.0/linux/fs/bio.c linux/fs/bio.c
--- v2.5.0/linux/fs/bio.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/bio.c	Tue Dec 11 09:44:13 2001
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 Licens
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+ *
+ */
+#include <linux/mm.h>
+#include <linux/blk.h>
+#include <linux/slab.h>
+#include <linux/iobuf.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mempool.h>
+
+#define BIO_POOL_SIZE 256
+
+static mempool_t *bio_pool;
+static kmem_cache_t *bio_slab;
+
+#define BIOVEC_NR_POOLS 6
+
+struct biovec_pool {
+	int size;
+	kmem_cache_t *slab;
+	mempool_t *pool;
+};
+
+static struct biovec_pool bvec_array[BIOVEC_NR_POOLS];
+
+/*
+ * if you change this list, also change bvec_alloc or things will
+ * break badly! cannot be bigger than what you can fit into an
+ * unsigned short
+ */
+static const int bvec_pool_sizes[BIOVEC_NR_POOLS] = { 1, 4, 16, 64, 128, 256 };
+
+#define BIO_MAX_PAGES	(bvec_pool_sizes[BIOVEC_NR_POOLS - 1])
+
+static void * slab_pool_alloc(int gfp_mask, void *data)
+{
+	return kmem_cache_alloc(data, gfp_mask);
+}
+
+static void slab_pool_free(void *ptr, void *data)
+{
+	kmem_cache_free(data, ptr);
+}
+
+static inline struct bio_vec *bvec_alloc(int gfp_mask, int nr, int *idx)
+{
+	struct biovec_pool *bp;
+	struct bio_vec *bvl;
+
+	/*
+	 * see comment near bvec_pool_sizes define!
+	 */
+	switch (nr) {
+		case   1        : *idx = 0; break;
+		case   2 ...   4: *idx = 1; break;
+		case   5 ...  16: *idx = 2; break;
+		case  17 ...  64: *idx = 3; break;
+		case  65 ... 128: *idx = 4; break;
+		case 129 ... 256: *idx = 5; break;
+		default:
+			return NULL;
+	}
+	/*
+	 * idx now points to the pool we want to allocate from
+	 */
+	bp = bvec_array + *idx;
+
+	bvl = mempool_alloc(bp->pool, gfp_mask);
+	if (bvl)
+		memset(bvl, 0, bp->size);
+	return bvl;
+}
+
+/*
+ * default destructor for a bio allocated with bio_alloc()
+ */
+void bio_destructor(struct bio *bio)
+{
+	struct biovec_pool *bp = bvec_array + bio->bi_max;
+
+	BIO_BUG_ON(bio->bi_max >= BIOVEC_NR_POOLS);
+	/*
+	 * cloned bio doesn't own the veclist
+	 */
+	if (!(bio->bi_flags & (1 << BIO_CLONED)))
+		mempool_free(bio->bi_io_vec, bp->pool);
+
+	mempool_free(bio, bio_pool);
+}
+
+inline void bio_init(struct bio *bio)
+{
+	bio->bi_next = NULL;
+	bio->bi_flags = 0;
+	bio->bi_rw = 0;
+	bio->bi_vcnt = 0;
+	bio->bi_idx = 0;
+	bio->bi_hw_seg = 0;
+	bio->bi_size = 0;
+	bio->bi_end_io = NULL;
+	atomic_set(&bio->bi_cnt, 1);
+}
+
+/**
+ * bio_alloc - allocate a bio for I/O
+ * @gfp_mask:   the GFP_ mask given to the slab allocator
+ * @nr_iovecs:	number of iovecs to pre-allocate
+ *
+ * Description:
+ *   bio_alloc will first try it's on mempool to satisfy the allocation.
+ *   If %__GFP_WAIT is set then we will block on the internal pool waiting
+ *   for a &struct bio to become free.
+ **/
+struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
+{
+	struct bio *bio = mempool_alloc(bio_pool, gfp_mask);
+	struct bio_vec *bvl = NULL;
+
+	if (unlikely(!bio))
+		return NULL;
+
+	if (!nr_iovecs || (bvl = bvec_alloc(gfp_mask,nr_iovecs,&bio->bi_max))) {
+		bio_init(bio);
+		bio->bi_destructor = bio_destructor;
+		bio->bi_io_vec = bvl;
+		return bio;
+	}
+	mempool_free(bio, bio_pool);
+	return NULL;
+}
+
+/**
+ * bio_put - release a reference to a bio
+ * @bio:   bio to release reference to
+ *
+ * Description:
+ *   Put a reference to a &struct bio, either one you have gotten with
+ *   bio_alloc or bio_get. The last put of a bio will free it.
+ **/
+void bio_put(struct bio *bio)
+{
+	BIO_BUG_ON(!atomic_read(&bio->bi_cnt));
+
+	/*
+	 * last put frees it
+	 */
+	if (atomic_dec_and_test(&bio->bi_cnt)) {
+		bio->bi_next = NULL;
+		bio->bi_destructor(bio);
+	}
+}
+
+inline int bio_hw_segments(request_queue_t *q, struct bio *bio)
+{
+	if (unlikely(!(bio->bi_flags & BIO_SEG_VALID)))
+		blk_recount_segments(q, bio);
+
+	return bio->bi_hw_seg;
+}
+
+/**
+ * 	__bio_clone	-	clone a bio
+ * 	@bio: destination bio
+ * 	@bio_src: bio to clone
+ *
+ *	Clone a &bio. Caller will own the returned bio, but not
+ *	the actual data it points to. Reference count of returned
+ * 	bio will be one.
+ */
+inline void __bio_clone(struct bio *bio, struct bio *bio_src)
+{
+	bio->bi_io_vec = bio_src->bi_io_vec;
+
+	bio->bi_sector = bio_src->bi_sector;
+	bio->bi_dev = bio_src->bi_dev;
+	bio->bi_flags |= 1 << BIO_CLONED;
+	bio->bi_rw = bio_src->bi_rw;
+
+	/*
+	 * notes -- maybe just leave bi_idx alone. bi_max has no use
+	 * on a cloned bio. assume identical mapping for the clone
+	 */
+	bio->bi_vcnt = bio_src->bi_vcnt;
+	bio->bi_idx = bio_src->bi_idx;
+	if (bio_src->bi_flags & (1 << BIO_SEG_VALID)) {
+		bio->bi_hw_seg = bio_src->bi_hw_seg;
+		bio->bi_flags |= (1 << BIO_SEG_VALID);
+	}
+	bio->bi_size = bio_src->bi_size;
+	bio->bi_max = bio_src->bi_max;
+}
+
+/**
+ *	bio_clone	-	clone a bio
+ *	@bio: bio to clone
+ *	@gfp_mask: allocation priority
+ *
+ * 	Like __bio_clone, only also allocates the returned bio
+ */
+struct bio *bio_clone(struct bio *bio, int gfp_mask)
+{
+	struct bio *b = bio_alloc(gfp_mask, 0);
+
+	if (b)
+		__bio_clone(b, bio);
+
+	return b;
+}
+
+/**
+ *	bio_copy	-	create copy of a bio
+ *	@bio: bio to copy
+ *	@gfp_mask: allocation priority
+ *	@copy: copy data to allocated bio
+ *
+ *	Create a copy of a &bio. Caller will own the returned bio and
+ *	the actual data it points to. Reference count of returned
+ * 	bio will be one.
+ */
+struct bio *bio_copy(struct bio *bio, int gfp_mask, int copy)
+{
+	struct bio *b = bio_alloc(gfp_mask, bio->bi_vcnt);
+	unsigned long flags = 0; /* gcc silly */
+	struct bio_vec *bv;
+	int i;
+
+	if (unlikely(!b))
+		return NULL;
+
+	/*
+	 * iterate iovec list and alloc pages + copy data
+	 */
+	__bio_for_each_segment(bv, bio, i, 0) {
+		struct bio_vec *bbv = &b->bi_io_vec[i];
+		char *vfrom, *vto;
+
+		bbv->bv_page = alloc_page(gfp_mask);
+		if (bbv->bv_page == NULL)
+			goto oom;
+
+		bbv->bv_len = bv->bv_len;
+		bbv->bv_offset = bv->bv_offset;
+
+		/*
+		 * if doing a copy for a READ request, no need
+		 * to memcpy page data
+		 */
+		if (!copy)
+			continue;
+
+		if (gfp_mask & __GFP_WAIT) {
+			vfrom = kmap(bv->bv_page);
+			vto = kmap(bbv->bv_page);
+		} else {
+			local_irq_save(flags);
+			vfrom = kmap_atomic(bv->bv_page, KM_BIO_IRQ);
+			vto = kmap_atomic(bbv->bv_page, KM_BIO_IRQ);
+		}
+
+		memcpy(vto + bbv->bv_offset, vfrom + bv->bv_offset, bv->bv_len);
+		if (gfp_mask & __GFP_WAIT) {
+			kunmap(bbv->bv_page);
+			kunmap(bv->bv_page);
+		} else {
+			kunmap_atomic(vto, KM_BIO_IRQ);
+			kunmap_atomic(vfrom, KM_BIO_IRQ);
+			local_irq_restore(flags);
+		}
+	}
+
+	b->bi_sector = bio->bi_sector;
+	b->bi_dev = bio->bi_dev;
+	b->bi_rw = bio->bi_rw;
+
+	b->bi_vcnt = bio->bi_vcnt;
+	b->bi_size = bio->bi_size;
+
+	return b;
+
+oom:
+	while (--i >= 0)
+		__free_page(b->bi_io_vec[i].bv_page);
+
+	mempool_free(b, bio_pool);
+	return NULL;
+}
+
+#ifdef BIO_PAGEIO
+static int bio_end_io_page(struct bio *bio)
+{
+	struct page *page = bio_page(bio);
+
+	if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+		SetPageError(page);
+	if (!PageError(page))
+		SetPageUptodate(page);
+
+	/*
+	 * Run the hooks that have to be done when a page I/O has completed.
+	 */
+	if (PageTestandClearDecrAfter(page))
+		atomic_dec(&nr_async_pages);
+
+	UnlockPage(page);
+	bio_put(bio);
+	return 1;
+}
+#endif
+
+static int bio_end_io_kio(struct bio *bio, int nr_sectors)
+{
+	struct kiobuf *kio = (struct kiobuf *) bio->bi_private;
+
+	end_kio_request(kio, test_bit(BIO_UPTODATE, &bio->bi_flags));
+	bio_put(bio);
+	return 0;
+}
+
+/**
+ * ll_rw_kio - submit a &struct kiobuf for I/O
+ * @rw:   %READ or %WRITE
+ * @kio:   the kiobuf to do I/O on
+ * @dev:   target device
+ * @sector:   start location on disk
+ *
+ * Description:
+ *   ll_rw_kio will map the page list inside the &struct kiobuf to
+ *   &struct bio and queue them for I/O. The kiobuf given must describe
+ *   a continous range of data, and must be fully prepared for I/O.
+ **/
+void ll_rw_kio(int rw, struct kiobuf *kio, kdev_t dev, sector_t sector)
+{
+	int i, offset, size, err, map_i, total_nr_pages, nr_pages;
+	struct bio_vec *bvec;
+	struct bio *bio;
+
+	err = 0;
+	if ((rw & WRITE) && is_read_only(dev)) {
+		printk("ll_rw_bio: WRITE to ro device %s\n", kdevname(dev));
+		err = -EPERM;
+		goto out;
+	}
+
+	if (!kio->nr_pages) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * maybe kio is bigger than the max we can easily map into a bio.
+	 * if so, split it up in appropriately sized chunks.
+	 */
+	total_nr_pages = kio->nr_pages;
+	offset = kio->offset & ~PAGE_MASK;
+	size = kio->length;
+
+	atomic_set(&kio->io_count, 1);
+
+	map_i = 0;
+
+next_chunk:
+	nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - 9);
+	if (nr_pages > total_nr_pages)
+		nr_pages = total_nr_pages;
+
+	atomic_inc(&kio->io_count);
+
+	/*
+	 * allocate bio and do initial setup
+	 */
+	if ((bio = bio_alloc(GFP_NOIO, nr_pages)) == NULL) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	bio->bi_sector = sector;
+	bio->bi_dev = dev;
+	bio->bi_idx = 0;
+	bio->bi_end_io = bio_end_io_kio;
+	bio->bi_private = kio;
+
+	bvec = bio->bi_io_vec;
+	for (i = 0; i < nr_pages; i++, bvec++, map_i++) {
+		int nbytes = PAGE_SIZE - offset;
+
+		if (nbytes > size)
+			nbytes = size;
+
+		BUG_ON(kio->maplist[map_i] == NULL);
+
+		if (bio->bi_size + nbytes > (BIO_MAX_SECTORS << 9))
+			goto queue_io;
+
+		bio->bi_vcnt++;
+		bio->bi_size += nbytes;
+
+		bvec->bv_page = kio->maplist[map_i];
+		bvec->bv_len = nbytes;
+		bvec->bv_offset = offset;
+
+		/*
+		 * kiobuf only has an offset into the first page
+		 */
+		offset = 0;
+
+		sector += nbytes >> 9;
+		size -= nbytes;
+		total_nr_pages--;
+		kio->offset += nbytes;
+	}
+
+queue_io:
+	submit_bio(rw, bio);
+
+	if (total_nr_pages)
+		goto next_chunk;
+
+	if (size) {
+		printk("ll_rw_kio: size %d left (kio %d)\n", size, kio->length);
+		BUG();
+	}
+
+out:
+	if (err)
+		kio->errno = err;
+
+	/*
+	 * final atomic_dec of io_count to match our initial setting of 1.
+	 * I/O may or may not have completed at this point, final completion
+	 * handler is only run on last decrement.
+	 */
+	end_kio_request(kio, !err);
+}
+
+int bio_endio(struct bio *bio, int uptodate, int nr_sectors)
+{
+	if (uptodate)
+		set_bit(BIO_UPTODATE, &bio->bi_flags);
+	else
+		clear_bit(BIO_UPTODATE, &bio->bi_flags);
+
+	return bio->bi_end_io(bio, nr_sectors);
+}
+
+static void __init biovec_init_pool(void)
+{
+	char name[16];
+	int i, size;
+
+	memset(&bvec_array, 0, sizeof(bvec_array));
+
+	for (i = 0; i < BIOVEC_NR_POOLS; i++) {
+		struct biovec_pool *bp = bvec_array + i;
+
+		size = bvec_pool_sizes[i] * sizeof(struct bio_vec);
+
+		printk("biovec: init pool %d, %d entries, %d bytes\n", i,
+						bvec_pool_sizes[i], size);
+
+		snprintf(name, sizeof(name) - 1,"biovec-%d",bvec_pool_sizes[i]);
+		bp->slab = kmem_cache_create(name, size, 0,
+						SLAB_HWCACHE_ALIGN, NULL, NULL);
+		if (!bp->slab)
+			panic("biovec: can't init slab cache\n");
+		bp->pool = mempool_create(BIO_POOL_SIZE, slab_pool_alloc,
+					slab_pool_free, bp->slab);
+		if (!bp->pool)
+			panic("biovec: can't init mempool\n");
+		bp->size = size;
+	}
+}
+
+static int __init init_bio(void)
+{
+	bio_slab = kmem_cache_create("bio", sizeof(struct bio), 0,
+					SLAB_HWCACHE_ALIGN, NULL, NULL);
+	if (!bio_slab)
+		panic("bio: can't create slab cache\n");
+	bio_pool = mempool_create(BIO_POOL_SIZE, slab_pool_alloc, slab_pool_free, bio_slab);
+	if (!bio_pool)
+		panic("bio: can't create mempool\n");
+
+	printk("BIO: pool of %d setup, %uKb (%d bytes/bio)\n", BIO_POOL_SIZE, BIO_POOL_SIZE * sizeof(struct bio) >> 10, sizeof(struct bio));
+
+	biovec_init_pool();
+
+	return 0;
+}
+
+module_init(init_bio);
+
+EXPORT_SYMBOL(bio_alloc);
+EXPORT_SYMBOL(bio_put);
+EXPORT_SYMBOL(ll_rw_kio);
+EXPORT_SYMBOL(bio_endio);
+EXPORT_SYMBOL(bio_init);
+EXPORT_SYMBOL(bio_copy);
+EXPORT_SYMBOL(__bio_clone);
+EXPORT_SYMBOL(bio_clone);
+EXPORT_SYMBOL(bio_hw_segments);
diff -u --recursive --new-file v2.5.0/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.5.0/linux/fs/block_dev.c	Wed Nov 21 14:07:25 2001
+++ linux/fs/block_dev.c	Fri Nov 30 15:53:28 2001
@@ -102,7 +102,7 @@
 	return 0;
 }
 
-static int blkdev_get_block(struct inode * inode, long iblock, struct buffer_head * bh, int create)
+static int blkdev_get_block(struct inode * inode, sector_t iblock, struct buffer_head * bh, int create)
 {
 	if (iblock >= max_block(inode->i_rdev))
 		return -EIO;
@@ -234,7 +234,7 @@
 #define HASH_SIZE	(1UL << HASH_BITS)
 #define HASH_MASK	(HASH_SIZE-1)
 static struct list_head bdev_hashtable[HASH_SIZE];
-static spinlock_t bdev_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t bdev_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 static kmem_cache_t * bdev_cachep;
 
 #define alloc_bdev() \
diff -u --recursive --new-file v2.5.0/linux/fs/buffer.c linux/fs/buffer.c
--- v2.5.0/linux/fs/buffer.c	Wed Nov 21 14:40:17 2001
+++ linux/fs/buffer.c	Mon Dec 10 09:12:10 2001
@@ -47,6 +47,7 @@
 #include <linux/highmem.h>
 #include <linux/module.h>
 #include <linux/completion.h>
+#include <linux/compiler.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -73,7 +74,7 @@
 static rwlock_t hash_table_lock = RW_LOCK_UNLOCKED;
 
 static struct buffer_head *lru_list[NR_LIST];
-static spinlock_t lru_list_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t lru_list_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 static int nr_buffers_type[NR_LIST];
 static unsigned long size_buffers_type[NR_LIST];
 
@@ -548,7 +549,7 @@
 	spin_unlock(&lru_list_lock);
 }
 
-struct buffer_head * get_hash_table(kdev_t dev, int block, int size)
+struct buffer_head * get_hash_table(kdev_t dev, sector_t block, int size)
 {
 	struct buffer_head *bh, **p = &hash(dev, block);
 
@@ -793,9 +794,10 @@
 	return;
 }
 
-inline void set_buffer_async_io(struct buffer_head *bh) {
-    bh->b_end_io = end_buffer_io_async ;
-    mark_buffer_async(bh, 1);
+inline void set_buffer_async_io(struct buffer_head *bh)
+{
+	bh->b_end_io = end_buffer_io_async;
+	mark_buffer_async(bh, 1);
 }
 
 /*
@@ -1014,7 +1016,7 @@
  * 14.02.92: changed it to sync dirty buffers a bit: better performance
  * when the filesystem starts to get full of dirty blocks (I hope).
  */
-struct buffer_head * getblk(kdev_t dev, int block, int size)
+struct buffer_head * getblk(kdev_t dev, sector_t block, int size)
 {
 	for (;;) {
 		struct buffer_head * bh;
@@ -1035,7 +1037,7 @@
 {
 	unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit;
 
-	dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT;
+	dirty = (size_buffers_type[BUF_DIRTY] + size_buffers_type[BUF_LOCKED]) >> PAGE_SHIFT;
 	tot = nr_free_buffer_pages();
 
 	dirty *= 100;
@@ -1988,7 +1990,8 @@
 	goto done;
 }
 
-int generic_block_bmap(struct address_space *mapping, long block, get_block_t *get_block)
+sector_t generic_block_bmap(struct address_space *mapping, sector_t block,
+			    get_block_t *get_block)
 {
 	struct buffer_head tmp;
 	struct inode *inode = mapping->host;
@@ -2001,18 +2004,18 @@
 int generic_direct_IO(int rw, struct inode * inode, struct kiobuf * iobuf, unsigned long blocknr, int blocksize, get_block_t * get_block)
 {
 	int i, nr_blocks, retval;
-	unsigned long * blocks = iobuf->blocks;
+	sector_t *blocks = iobuf->blocks;
+	struct buffer_head bh;
 
+	bh.b_dev = inode->i_dev;
 	nr_blocks = iobuf->length / blocksize;
 	/* build the blocklist */
 	for (i = 0; i < nr_blocks; i++, blocknr++) {
-		struct buffer_head bh;
-
 		bh.b_state = 0;
 		bh.b_dev = inode->i_dev;
 		bh.b_size = blocksize;
 
-		retval = get_block(inode, blocknr, &bh, rw == READ ? 0 : 1);
+		retval = get_block(inode, blocknr, &bh, rw & 1);
 		if (retval)
 			goto out;
 
@@ -2033,64 +2036,14 @@
 		blocks[i] = bh.b_blocknr;
 	}
 
-	retval = brw_kiovec(rw, 1, &iobuf, inode->i_dev, iobuf->blocks, blocksize);
+	/* This does not understand multi-device filesystems currently */
+	retval = brw_kiovec(rw, 1, &iobuf, bh.b_dev, blocks, blocksize);
 
  out:
 	return retval;
 }
 
 /*
- * IO completion routine for a buffer_head being used for kiobuf IO: we
- * can't dispatch the kiobuf callback until io_count reaches 0.  
- */
-
-static void end_buffer_io_kiobuf(struct buffer_head *bh, int uptodate)
-{
-	struct kiobuf *kiobuf;
-	
-	mark_buffer_uptodate(bh, uptodate);
-
-	kiobuf = bh->b_private;
-	unlock_buffer(bh);
-	end_kio_request(kiobuf, uptodate);
-}
-
-/*
- * For brw_kiovec: submit a set of buffer_head temporary IOs and wait
- * for them to complete.  Clean up the buffer_heads afterwards.  
- */
-
-static int wait_kio(int rw, int nr, struct buffer_head *bh[], int size)
-{
-	int iosize, err;
-	int i;
-	struct buffer_head *tmp;
-
-	iosize = 0;
-	err = 0;
-
-	for (i = nr; --i >= 0; ) {
-		iosize += size;
-		tmp = bh[i];
-		if (buffer_locked(tmp)) {
-			wait_on_buffer(tmp);
-		}
-		
-		if (!buffer_uptodate(tmp)) {
-			/* We are traversing bh'es in reverse order so
-                           clearing iosize on error calculates the
-                           amount of IO before the first error. */
-			iosize = 0;
-			err = -EIO;
-		}
-	}
-	
-	if (iosize)
-		return iosize;
-	return err;
-}
-
-/*
  * Start I/O on a physical range of kernel memory, defined by a vector
  * of kiobuf structs (much like a user-space iovec list).
  *
@@ -2101,22 +2054,13 @@
  * It is up to the caller to make sure that there are enough blocks
  * passed in to completely map the iobufs to disk.
  */
-
-int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], 
-	       kdev_t dev, unsigned long b[], int size)
+int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], kdev_t dev, sector_t b[],
+	       int size)
 {
-	int		err;
-	int		length;
 	int		transferred;
 	int		i;
-	int		bufind;
-	int		pageind;
-	int		bhind;
-	int		offset;
-	unsigned long	blocknr;
-	struct kiobuf *	iobuf = NULL;
-	struct page *	map;
-	struct buffer_head *tmp, **bhs = NULL;
+	int		err;
+	struct kiobuf *	iobuf;
 
 	if (!nr)
 		return 0;
@@ -2126,8 +2070,7 @@
 	 */
 	for (i = 0; i < nr; i++) {
 		iobuf = iovec[i];
-		if ((iobuf->offset & (size-1)) ||
-		    (iobuf->length & (size-1)))
+		if ((iobuf->offset & (size-1)) || (iobuf->length & (size-1)))
 			return -EINVAL;
 		if (!iobuf->nr_pages)
 			panic("brw_kiovec: iobuf not initialised");
@@ -2136,94 +2079,28 @@
 	/* 
 	 * OK to walk down the iovec doing page IO on each page we find. 
 	 */
-	bufind = bhind = transferred = err = 0;
 	for (i = 0; i < nr; i++) {
 		iobuf = iovec[i];
-		offset = iobuf->offset;
-		length = iobuf->length;
 		iobuf->errno = 0;
-		if (!bhs)
-			bhs = iobuf->bh;
-		
-		for (pageind = 0; pageind < iobuf->nr_pages; pageind++) {
-			map  = iobuf->maplist[pageind];
-			if (!map) {
-				err = -EFAULT;
-				goto finished;
-			}
-			
-			while (length > 0) {
-				blocknr = b[bufind++];
-				if (blocknr == -1UL) {
-					if (rw == READ) {
-						/* there was an hole in the filesystem */
-						memset(kmap(map) + offset, 0, size);
-						flush_dcache_page(map);
-						kunmap(map);
-
-						transferred += size;
-						goto skip_block;
-					} else
-						BUG();
-				}
-				tmp = bhs[bhind++];
 
-				tmp->b_size = size;
-				set_bh_page(tmp, map, offset);
-				tmp->b_this_page = tmp;
-
-				init_buffer(tmp, end_buffer_io_kiobuf, iobuf);
-				tmp->b_dev = dev;
-				tmp->b_blocknr = blocknr;
-				tmp->b_state = (1 << BH_Mapped) | (1 << BH_Lock) | (1 << BH_Req);
-
-				if (rw == WRITE) {
-					set_bit(BH_Uptodate, &tmp->b_state);
-					clear_bit(BH_Dirty, &tmp->b_state);
-				} else
-					set_bit(BH_Uptodate, &tmp->b_state);
-
-				atomic_inc(&iobuf->io_count);
-				submit_bh(rw, tmp);
-				/* 
-				 * Wait for IO if we have got too much 
-				 */
-				if (bhind >= KIO_MAX_SECTORS) {
-					kiobuf_wait_for_io(iobuf); /* wake-one */
-					err = wait_kio(rw, bhind, bhs, size);
-					if (err >= 0)
-						transferred += err;
-					else
-						goto finished;
-					bhind = 0;
-				}
+		ll_rw_kio(rw, iobuf, dev, b[i] * (size >> 9));
+	}
 
-			skip_block:
-				length -= size;
-				offset += size;
-
-				if (offset >= PAGE_SIZE) {
-					offset = 0;
-					break;
-				}
-			} /* End of block loop */
-		} /* End of page loop */		
-	} /* End of iovec loop */
-
-	/* Is there any IO still left to submit? */
-	if (bhind) {
-		kiobuf_wait_for_io(iobuf); /* wake-one */
-		err = wait_kio(rw, bhind, bhs, size);
-		if (err >= 0)
-			transferred += err;
-		else
-			goto finished;
-	}
-
- finished:
-	if (transferred)
-		return transferred;
-	return err;
+	/*
+	 * now they are all submitted, wait for completion
+	 */
+	transferred = 0;
+	err = 0;
+	for (i = 0; i < nr; i++) {
+		iobuf = iovec[i];
+		kiobuf_wait_for_io(iobuf);
+		if (iobuf->errno && !err)
+			err = iobuf->errno;
+		if (!err)
+			transferred += iobuf->length;
+	}
+
+	return err ? err : transferred;
 }
 
 /*
@@ -2238,7 +2115,7 @@
  * FIXME: we need a swapper_inode->get_block function to remove
  *        some of the bmap kludges and interface ugliness here.
  */
-int brw_page(int rw, struct page *page, kdev_t dev, int b[], int size)
+int brw_page(int rw, struct page *page, kdev_t dev, sector_t b[], int size)
 {
 	struct buffer_head *head, *bh;
 
@@ -2326,7 +2203,7 @@
 	struct buffer_head *bh;
 
 	page = find_or_create_page(bdev->bd_inode->i_mapping, index, GFP_NOFS);
-	if (IS_ERR(page))
+	if (!page)
 		return NULL;
 
 	if (!PageLocked(page))
@@ -2489,6 +2366,9 @@
 int try_to_free_buffers(struct page * page, unsigned int gfp_mask)
 {
 	struct buffer_head * tmp, * bh = page->buffers;
+
+	BUG_ON(!PageLocked(page));
+	BUG_ON(!bh);
 
 cleaned_buffers_try_again:
 	spin_lock(&lru_list_lock);
diff -u --recursive --new-file v2.5.0/linux/fs/coda/cache.c linux/fs/coda/cache.c
--- v2.5.0/linux/fs/coda/cache.c	Wed Apr 25 16:18:54 2001
+++ linux/fs/coda/cache.c	Wed Dec  5 13:02:14 2001
@@ -29,7 +29,6 @@
 void coda_cache_enter(struct inode *inode, int mask)
 {
 	struct coda_inode_info *cii = ITOC(inode);
-        ENTRY;
 
         if ( !coda_cred_ok(&cii->c_cached_cred) ) {
                 coda_load_creds(&cii->c_cached_cred);
@@ -42,7 +41,6 @@
 void coda_cache_clear_inode(struct inode *inode)
 {
 	struct coda_inode_info *cii = ITOC(inode);
-	ENTRY;
         cii->c_cached_perm = 0;
 }
 
@@ -53,7 +51,6 @@
         struct coda_inode_info *cii;
         struct list_head *tmp;
 
-        ENTRY;
         sbi = coda_sbp(sb);
         if (!sbi) BUG();
 
@@ -119,7 +116,6 @@
 {
 	struct dentry *alias_de;
 
-	ENTRY;
 	if ( !inode || !S_ISDIR(inode->i_mode)) 
 		return; 
 
diff -u --recursive --new-file v2.5.0/linux/fs/coda/cnode.c linux/fs/coda/cnode.c
--- v2.5.0/linux/fs/coda/cnode.c	Wed Apr 25 16:18:54 2001
+++ linux/fs/coda/cnode.c	Wed Dec  5 13:02:14 2001
@@ -102,8 +102,6 @@
         struct coda_vattr attr;
         int error;
         
-        ENTRY;
-
 	/* We get inode numbers from Venus -- see venus source */
 	error = venus_getattr(sb, fid, &attr);
 	if ( error ) {
@@ -111,21 +109,18 @@
 		   "coda_cnode_make: coda_getvattr returned %d for %s.\n", 
 		   error, coda_f2s(fid));
 	    *inode = NULL;
-	    EXIT;
 	    return error;
 	} 
 
 	*inode = coda_iget(sb, fid, &attr);
 	if ( IS_ERR(*inode) ) {
 		printk("coda_cnode_make: coda_iget failed\n");
-		EXIT;
                 return PTR_ERR(*inode);
         }
 
 	CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n",
 		(*inode)->i_ino, atomic_read(&(*inode)->i_count), 
 		coda_f2s(&ITOC(*inode)->c_fid));
-        EXIT;
 	return 0;
 }
 
@@ -154,7 +149,6 @@
 	ino_t nr;
 	struct inode *inode;
 	struct coda_inode_info *cii;
-	ENTRY;
 
 	if ( !sb ) {
 		printk("coda_fid_to_inode: no sb!\n");
diff -u --recursive --new-file v2.5.0/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.5.0/linux/fs/coda/dir.c	Wed Apr 25 16:18:54 2001
+++ linux/fs/coda/dir.c	Wed Dec  5 13:02:14 2001
@@ -103,8 +103,6 @@
 	const char *name = entry->d_name.name;
 	size_t length = entry->d_name.len;
 	
-        ENTRY;
-
 	if ( length > CODA_MAXNAMLEN ) {
 	        printk("name too long: lookup, %s (%*s)\n", 
 		       coda_i2s(dir), (int)length, name);
@@ -154,7 +152,6 @@
 		d_drop(entry);
 		coda_flag_inode(res_inode, C_VATTR);
 	}
-        EXIT;
         return NULL;
 }
 
@@ -163,7 +160,6 @@
 {
         int error;
  
-        ENTRY;
 	coda_vfs_stat.permission++;
 
         if ( mask == 0 )
@@ -217,7 +213,6 @@
 	struct ViceFid newfid;
 	struct coda_vattr attrs;
 
-	ENTRY;
 	coda_vfs_stat.create++;
 
 	CDEBUG(D_INODE, "name: %s, length %d, mode %o\n", name, length, mode);
@@ -300,7 +295,6 @@
 	int error;
 	struct ViceFid newfid;
 
-	ENTRY;
 	coda_vfs_stat.mkdir++;
 
 	if (coda_isroot(dir) && coda_iscontrol(name, len))
@@ -344,7 +338,6 @@
 	int len = de->d_name.len;
 	int error;
 
-        ENTRY;
 	coda_vfs_stat.link++;
 
 	if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
@@ -368,7 +361,6 @@
         
 out:
 	CDEBUG(D_INODE, "link result %d\n",error);
-	EXIT;
 	return(error);
 }
 
@@ -381,7 +373,6 @@
 	int symlen;
         int error=0;
         
-        ENTRY;
 	coda_vfs_stat.symlink++;
 
 	if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
@@ -406,7 +397,6 @@
 		coda_dir_changed(dir_inode, 0);
 
         CDEBUG(D_INODE, "in symlink result %d\n",error);
-        EXIT;
         return error;
 }
 
@@ -417,7 +407,6 @@
 	const char *name = de->d_name.name;
 	int len = de->d_name.len;
 
-	ENTRY;
 	coda_vfs_stat.unlink++;
 
         CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name , 
@@ -441,7 +430,6 @@
 	int len = de->d_name.len;
         int error;
 
-	ENTRY;
 	coda_vfs_stat.rmdir++;
 
 	if (!d_unhashed(de))
@@ -471,7 +459,6 @@
         int link_adjust = 0;
         int error;
 
-	ENTRY;
 	coda_vfs_stat.rename++;
 
         CDEBUG(D_INODE, "old: %s, (%d length), new: %s"
@@ -499,7 +486,6 @@
 
 	CDEBUG(D_INODE, "result %d\n", error); 
 
-	EXIT;
 	return error;
 }
 
@@ -513,7 +499,6 @@
 	struct file *cfile, fakefile;
 	struct coda_inode_info *cii = ITOC(inode);
 
-        ENTRY;
 	coda_vfs_stat.readdir++;
 
         cfile = cii->c_container;
@@ -534,7 +519,6 @@
 		result = vfs_readdir(file, filldir, dirent);
         }
 
-        EXIT;
 	return result;
 }
 
@@ -549,6 +533,7 @@
 	fake_file->f_pos = coda_file->f_pos;
 	fake_file->f_version = coda_file->f_version;
 	fake_file->f_op = cont_dentry->d_inode->i_fop;
+	fake_file->f_flags = coda_file->f_flags;
 	return ;
 }
 
@@ -577,8 +562,6 @@
         int string_offset = (int) (&((struct venus_dirent *)(0))->d_name);
 	int i;
 
-        ENTRY;        
-
         CODA_ALLOC(buff, char *, DIR_BUFSIZE);
         if ( !buff ) { 
                 printk("coda_venus_readdir: out of memory.\n");
@@ -664,7 +647,6 @@
 {
 	struct inode *inode = de->d_inode;
 	struct coda_inode_info *cii;
-	ENTRY;
 
 	if (!inode)
 		return 1;
@@ -740,7 +722,6 @@
 	struct inode *inode = dentry->d_inode;
 	struct coda_inode_info *cii = ITOC(inode);
 
-	ENTRY;
 	CDEBUG(D_INODE, "revalidating: %*s/%*s\n", 
 	       dentry->d_name.len, dentry->d_name.name,
 	       dentry->d_parent->d_name.len, dentry->d_parent->d_name.name);
diff -u --recursive --new-file v2.5.0/linux/fs/coda/file.c linux/fs/coda/file.c
--- v2.5.0/linux/fs/coda/file.c	Sat Sep 22 11:11:09 2001
+++ linux/fs/coda/file.c	Wed Dec  5 13:02:14 2001
@@ -102,7 +102,6 @@
 	struct coda_inode_info *cii;
 
 	lock_kernel();
-	ENTRY;
 	coda_vfs_stat.open++;
 
 	CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", 
@@ -140,7 +139,6 @@
 	       fh->f_dentry->d_inode->i_ino,
 	       atomic_read(&fh->f_dentry->d_inode->i_count),
                fh->f_dentry->d_inode->i_op);
-	EXIT;
 	unlock_kernel();
 	return 0;
 }
@@ -155,7 +153,6 @@
 	struct inode *cinode, *inode;
 	int err = 0, fcnt;
 
-	ENTRY;
 	coda_vfs_stat.flush++;
 
 	/* No need to make an upcall when we have not made any modifications
@@ -200,7 +197,6 @@
 	int err = 0;
 
 	lock_kernel();
-	ENTRY;
 	coda_vfs_stat.release++;
  
 	if (!use_coda_close) {
@@ -244,7 +240,6 @@
 	struct inode *cinode, *inode = dentry->d_inode;
 	struct coda_inode_info *cii = ITOC(inode);
 	int err = 0;
-	ENTRY;
 
 	if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
 	      S_ISLNK(inode->i_mode)))
diff -u --recursive --new-file v2.5.0/linux/fs/coda/inode.c linux/fs/coda/inode.c
--- v2.5.0/linux/fs/coda/inode.c	Fri Apr 27 14:09:37 2001
+++ linux/fs/coda/inode.c	Wed Dec  5 13:02:14 2001
@@ -99,7 +99,6 @@
         ViceFid fid;
         int error;
 	int idx;
-	ENTRY;
 
 	idx = get_device_index((struct coda_mount_data *) data);
 
@@ -112,19 +111,16 @@
 	vc = &coda_comms[idx];
 	if (!vc->vc_inuse) {
 		printk("coda_read_super: No pseudo device\n");
-		EXIT;  
 		return NULL;
 	}
 
         if ( vc->vc_sb ) {
 		printk("coda_read_super: Device already mounted\n");
-		EXIT;  
 		return NULL;
 	}
 
 	sbi = kmalloc(sizeof(struct coda_sb_info), GFP_KERNEL);
 	if(!sbi) {
-		EXIT;  
 		return NULL;
 	}
 
@@ -159,11 +155,9 @@
 	printk("coda_read_super: rootinode is %ld dev %d\n", 
 	       root->i_ino, root->i_dev);
 	sb->s_root = d_alloc_root(root);
-	EXIT;  
         return sb;
 
  error:
-	EXIT;  
 	if (sbi) {
 		kfree(sbi);
 		if(vc)
@@ -179,16 +173,12 @@
 {
         struct coda_sb_info *sbi;
 
-        ENTRY;
-
 	sbi = coda_sbp(sb);
 	sbi->sbi_vcomm->vc_sb = NULL;
         list_del_init(&sbi->sbi_cihead);
 
 	printk("Coda: Bye bye.\n");
 	kfree(sbi);
-
-	EXIT;
 }
 
 /* all filling in of inodes postponed until lookup */
@@ -196,7 +186,6 @@
 {
 	struct coda_sb_info *sbi = coda_sbp(inode->i_sb);
 	struct coda_inode_info *cii;
-	ENTRY;
 
         if (!sbi) BUG();
 
@@ -229,7 +218,6 @@
 {
 	struct coda_inode_info *cii = ITOC(inode);
 
-        ENTRY;
         CDEBUG(D_SUPER, " inode->ino: %ld, count: %d\n", 
 	       inode->i_ino, atomic_read(&inode->i_count));        
 	CDEBUG(D_DOWNCALL, "clearing inode: %ld, %x\n", inode->i_ino, cii->c_flags);
@@ -244,8 +232,6 @@
 	cii_free(inode->u.generic_ip);
 	inode->u.generic_ip = NULL;
 #endif
-
-	EXIT;
 }
 
 int coda_notify_change(struct dentry *de, struct iattr *iattr)
@@ -254,7 +240,6 @@
         struct coda_vattr vattr;
         int error;
 	
-	ENTRY;
         memset(&vattr, 0, sizeof(vattr)); 
 
         coda_iattr_to_vattr(iattr, &vattr);
@@ -270,7 +255,6 @@
 	}
 	CDEBUG(D_SUPER, "inode.i_mode %o, error %d\n", inode->i_mode, error);
 
-	EXIT;
 	return error;
 }
 
diff -u --recursive --new-file v2.5.0/linux/fs/coda/pioctl.c linux/fs/coda/pioctl.c
--- v2.5.0/linux/fs/coda/pioctl.c	Tue Sep 19 15:08:59 2000
+++ linux/fs/coda/pioctl.c	Wed Dec  5 13:02:14 2001
@@ -45,8 +45,6 @@
 /* the coda pioctl inode ops */
 static int coda_ioctl_permission(struct inode *inode, int mask)
 {
-        ENTRY;
-
         return 0;
 }
 
@@ -59,7 +57,6 @@
         struct inode *target_inode = NULL;
         struct coda_inode_info *cnp;
 
-        ENTRY;
         /* get the Pioctl data arguments from user space */
         if (copy_from_user(&data, (int *)user_data, sizeof(data))) {
 	    return -EINVAL;
diff -u --recursive --new-file v2.5.0/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.5.0/linux/fs/coda/psdev.c	Sat Sep 22 11:11:09 2001
+++ linux/fs/coda/psdev.c	Wed Dec  5 13:02:14 2001
@@ -292,7 +292,6 @@
 {
         struct venus_comm *vcp;
 	int idx;
-        ENTRY;
 
 	lock_kernel();
 	idx = MINOR(inode->i_rdev);
@@ -319,7 +318,6 @@
 
 	CDEBUG(D_PSDEV, "device %i - inuse: %d\n", idx, vcp->vc_inuse);
 
-	EXIT;
 	unlock_kernel();
         return 0;
 }
@@ -330,7 +328,6 @@
         struct venus_comm *vcp = (struct venus_comm *) file->private_data;
         struct upc_req *req;
 	struct list_head *lh, *next;
-	ENTRY;
 
 	lock_kernel();
 	if ( !vcp->vc_inuse ) {
@@ -371,7 +368,6 @@
         }
 	CDEBUG(D_PSDEV, "Done.\n");
 
-	EXIT;
 	unlock_kernel();
 	return 0;
 }
@@ -410,6 +406,7 @@
 
 
 MODULE_AUTHOR("Peter J. Braam <braam@cs.cmu.edu>");
+MODULE_LICENSE("GPL");
 
 static int __init init_coda(void)
 {
@@ -435,8 +432,6 @@
 static void __exit exit_coda(void)
 {
         int err;
-
-        ENTRY;
 
 	err = unregister_filesystem(&coda_fs_type);
         if ( err != 0 ) {
diff -u --recursive --new-file v2.5.0/linux/fs/coda/sysctl.c linux/fs/coda/sysctl.c
--- v2.5.0/linux/fs/coda/sysctl.c	Wed Apr 25 16:18:54 2001
+++ linux/fs/coda/sysctl.c	Wed Dec  5 13:02:14 2001
@@ -359,7 +359,6 @@
 	char tmpbuf[80];
 	int tmplen = 0;
 
-	ENTRY;
 	/* this works as long as we are below 1024 characters! */
 	if ( offset < 80 ) 
 		len += sprintf( buffer,"%-79s\n",	"Coda upcall statistics");
@@ -392,7 +391,7 @@
 		len = length;
 	if ( len < 0 )
 		len = 0;
-	EXIT;
+
 	return len;
 }
 
diff -u --recursive --new-file v2.5.0/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
--- v2.5.0/linux/fs/coda/upcall.c	Mon Sep 10 09:11:02 2001
+++ linux/fs/coda/upcall.c	Wed Dec  5 13:02:14 2001
@@ -80,7 +80,6 @@
         union inputArgs *inp;
         union outputArgs *outp;
         int insize, outsize, error;
-	ENTRY;
 
         insize = SIZE(root);
         UPARG(CODA_ROOT);
@@ -96,7 +95,6 @@
 	}
 
 	CODA_FREE(inp, insize);
-        EXIT;
 	return error;
 }
 
@@ -106,7 +104,6 @@
         union inputArgs *inp;
         union outputArgs *outp;
         int insize, outsize, error;
-	ENTRY;
 
         insize = SIZE(getattr); 
 	UPARG(CODA_GETATTR);
@@ -117,7 +114,6 @@
 	*attr = outp->coda_getattr.attr;
 
 	CODA_FREE(inp, insize);
-        EXIT;
         return error;
 }
 
@@ -432,7 +428,6 @@
 	}
         
         CDEBUG(D_INODE, " result %d\n",error);
-        EXIT;
         CODA_FREE(inp, insize);
         return error;
 }
@@ -462,7 +457,6 @@
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
         CDEBUG(D_INODE, " result %d\n",error);
-        EXIT;
 	CODA_FREE(inp, insize);
         return error;
 }
@@ -499,7 +493,6 @@
 	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
         CDEBUG(D_INODE, " result %d\n",error);
-        EXIT;
 	CODA_FREE(inp, insize);
         return error;
 }
@@ -536,7 +529,6 @@
 	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
 	CODA_FREE(inp, insize);
-        EXIT;
 	return error;
 }
 
@@ -633,7 +625,6 @@
 	}
 
         CDEBUG(D_INODE, " result %d\n",error);
-        EXIT;
         CODA_FREE(inp, insize);
         return error;
 }
@@ -721,8 +712,6 @@
 	union outputArgs *out;
 	struct upc_req *req;
 	int error = 0;
-
-	ENTRY;
 
 	vcommp = sbi->sbi_vcomm;
 	if ( !vcommp->vc_inuse ) {
diff -u --recursive --new-file v2.5.0/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c
--- v2.5.0/linux/fs/cramfs/inode.c	Thu Oct 25 13:53:53 2001
+++ linux/fs/cramfs/inode.c	Fri Nov 30 13:19:27 2001
@@ -19,6 +19,7 @@
 #include <linux/locks.h>
 #include <linux/blkdev.h>
 #include <linux/cramfs_fs.h>
+#include <asm/semaphore.h>
 
 #include <asm/uaccess.h>
 
@@ -33,6 +34,9 @@
 static struct file_operations cramfs_directory_operations;
 static struct address_space_operations cramfs_aops;
 
+static DECLARE_MUTEX(read_mutex);
+
+
 /* These two macros may change in future, to provide better st_ino
    semantics. */
 #define CRAMINO(x)	((x)->offset?(x)->offset<<2:1)
@@ -199,8 +203,10 @@
 	for (i = 0; i < READ_BUFFERS; i++)
 		buffer_blocknr[i] = -1;
 
+	down(&read_mutex);
 	/* Read the first block and get the superblock from it */
 	memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
+	up(&read_mutex);
 
 	/* Do sanity checks on the superblock */
 	if (super.magic != CRAMFS_MAGIC) {
@@ -291,7 +297,9 @@
 		char *name;
 		int namelen, error;
 
+		down(&read_mutex);
 		de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+256);
+		up(&read_mutex);
 		name = (char *)(de+1);
 
 		/*
@@ -332,7 +340,9 @@
 		char *name;
 		int namelen, retval;
 
+		down(&read_mutex);
 		de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+256);
+		up(&read_mutex);
 		name = (char *)(de+1);
 
 		/* Try to take advantage of sorted directories */
@@ -384,18 +394,22 @@
 		u32 start_offset, compr_len;
 
 		start_offset = OFFSET(inode) + maxblock*4;
+		down(&read_mutex);
 		if (page->index)
 			start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4);
-		compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4)
-			     - start_offset);
+		compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset);
+		up(&read_mutex);
 		pgdata = kmap(page);
 		if (compr_len == 0)
 			; /* hole */
-		else
+		else {
+			down(&read_mutex);
 			bytes_filled = cramfs_uncompress_block(pgdata,
 				 PAGE_CACHE_SIZE,
 				 cramfs_read(sb, start_offset, compr_len),
 				 compr_len);
+			up(&read_mutex);
+		}
 	} else
 		pgdata = kmap(page);
 	memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled);
diff -u --recursive --new-file v2.5.0/linux/fs/dcache.c linux/fs/dcache.c
--- v2.5.0/linux/fs/dcache.c	Wed Oct  3 22:57:36 2001
+++ linux/fs/dcache.c	Mon Dec 10 14:13:25 2001
@@ -29,7 +29,7 @@
 #define DCACHE_PARANOIA 1
 /* #define DCACHE_DEBUG 1 */
 
-spinlock_t dcache_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t dcache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 /* Right now the dcache depends on the kernel lock */
 #define check_lock()	if (!kernel_locked()) BUG()
@@ -543,7 +543,7 @@
  * too much.
  *
  * Priority:
- *   0 - very urgent: shrink everything
+ *   1 - very urgent: shrink everything
  *  ...
  *   6 - base-level: try to shrink a bit.
  */
diff -u --recursive --new-file v2.5.0/linux/fs/devfs/base.c linux/fs/devfs/base.c
--- v2.5.0/linux/fs/devfs/base.c	Sat Nov  3 10:06:38 2001
+++ linux/fs/devfs/base.c	Fri Nov 30 08:41:52 2001
@@ -545,21 +545,23 @@
     20010919   Richard Gooch <rgooch@atnf.csiro.au>
 	       Set inode->i_mapping->a_ops for block nodes in <get_vfs_inode>.
   v0.116
-    20010927   Richard Gooch <rgooch@atnf.csiro.au>
-	       Went back to global rwsem for symlinks (refcount scheme no good)
-  v0.117
     20011008   Richard Gooch <rgooch@atnf.csiro.au>
 	       Fixed overrun in <devfs_link> by removing function (not needed).
-  v0.118
     20011009   Richard Gooch <rgooch@atnf.csiro.au>
 	       Fixed buffer underrun in <try_modload>.
-	       Moved down_read() from <search_for_entry_in_dir> to <find_entry>
-  v0.119
     20011029   Richard Gooch <rgooch@atnf.csiro.au>
 	       Fixed race in <devfsd_ioctl> when setting event mask.
-    20011103   Richard Gooch <rgooch@atnf.csiro.au>
-	       Avoid deadlock in <devfs_follow_link> by using temporary buffer.
-  v0.120
+    20011114   Richard Gooch <rgooch@atnf.csiro.au>
+	       First release of new locking code.
+  v1.0
+    20011117   Richard Gooch <rgooch@atnf.csiro.au>
+	       Discard temporary buffer, now use "%s" for dentry names.
+    20011118   Richard Gooch <rgooch@atnf.csiro.au>
+	       Don't generate path in <try_modload>: use fake entry instead.
+	       Use "existing" directory in <_devfs_make_parent_for_leaf>.
+    20011122   Richard Gooch <rgooch@atnf.csiro.au>
+	       Use slab cache rather than fixed buffer for devfsd events.
+  v1.1
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -592,7 +594,7 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#define DEVFS_VERSION            "0.120 (20011103)"
+#define DEVFS_VERSION            "1.1 (20011122)"
 
 #define DEVFS_NAME "devfs"
 
@@ -605,27 +607,30 @@
 #  define FALSE 0
 #endif
 
-#define IS_HIDDEN(de) (( ((de)->hide && !is_devfsd_or_child(fs_info)) || !(de)->registered))
+#define MODE_DIR (S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO)
 
-#define DEBUG_NONE         0x00000
-#define DEBUG_MODULE_LOAD  0x00001
-#define DEBUG_REGISTER     0x00002
-#define DEBUG_UNREGISTER   0x00004
-#define DEBUG_SET_FLAGS    0x00008
-#define DEBUG_S_PUT        0x00010
-#define DEBUG_I_LOOKUP     0x00020
-#define DEBUG_I_CREATE     0x00040
-#define DEBUG_I_GET        0x00080
-#define DEBUG_I_CHANGE     0x00100
-#define DEBUG_I_UNLINK     0x00200
-#define DEBUG_I_RLINK      0x00400
-#define DEBUG_I_FLINK      0x00800
-#define DEBUG_I_MKNOD      0x01000
-#define DEBUG_F_READDIR    0x02000
-#define DEBUG_D_DELETE     0x04000
-#define DEBUG_D_RELEASE    0x08000
-#define DEBUG_D_IPUT       0x10000
-#define DEBUG_ALL          0xfffff
+#define IS_HIDDEN(de) ( (de)->hide && !is_devfsd_or_child(fs_info) )
+
+#define DEBUG_NONE         0x0000000
+#define DEBUG_MODULE_LOAD  0x0000001
+#define DEBUG_REGISTER     0x0000002
+#define DEBUG_UNREGISTER   0x0000004
+#define DEBUG_FREE         0x0000008
+#define DEBUG_SET_FLAGS    0x0000010
+#define DEBUG_S_READ       0x0000100        /*  Break  */
+#define DEBUG_I_LOOKUP     0x0001000        /*  Break  */
+#define DEBUG_I_CREATE     0x0002000
+#define DEBUG_I_GET        0x0004000
+#define DEBUG_I_CHANGE     0x0008000
+#define DEBUG_I_UNLINK     0x0010000
+#define DEBUG_I_RLINK      0x0020000
+#define DEBUG_I_FLINK      0x0040000
+#define DEBUG_I_MKNOD      0x0080000
+#define DEBUG_F_READDIR    0x0100000        /*  Break  */
+#define DEBUG_D_DELETE     0x1000000        /*  Break  */
+#define DEBUG_D_RELEASE    0x2000000
+#define DEBUG_D_IPUT       0x4000000
+#define DEBUG_ALL          0xfffffff
 #define DEBUG_DISABLED     DEBUG_NONE
 
 #define OPTION_NONE             0x00
@@ -638,9 +643,11 @@
 
 struct directory_type
 {
+    rwlock_t lock;                   /*  Lock for searching(R)/updating(W)   */
     struct devfs_entry *first;
     struct devfs_entry *last;
-    unsigned int num_removable;
+    unsigned short num_removable;    /*  Lock for writing but not reading    */
+    unsigned char no_more_additions:1;
 };
 
 struct file_type
@@ -656,8 +663,6 @@
 
 struct fcb_type  /*  File, char, block type  */
 {
-    uid_t default_uid;
-    gid_t default_gid;
     void *ops;
     union 
     {
@@ -678,20 +683,13 @@
     char *linkname;              /*  This is NULL-terminated                 */
 };
 
-struct fifo_type
-{
-    uid_t uid;
-    gid_t gid;
-};
-
-struct devfs_inode  /*  This structure is for "persistent" inode storage  */
+struct devfs_inode     /*  This structure is for "persistent" inode storage  */
 {
+    struct dentry *dentry;
     time_t atime;
     time_t mtime;
     time_t ctime;
-    unsigned int ino;          /*  Inode number as seen in the VFS  */
-    struct dentry *dentry;
-    umode_t mode;
+    unsigned int ino;            /*  Inode number as seen in the VFS         */
     uid_t uid;
     gid_t gid;
 };
@@ -699,12 +697,13 @@
 struct devfs_entry
 {
     void *info;
+    atomic_t refcount;           /*  When this drops to zero, it's unused    */
     union 
     {
 	struct directory_type dir;
 	struct fcb_type fcb;
 	struct symlink_type symlink;
-	struct fifo_type fifo;
+	const char *name;        /*  Only used for (mode == 0)               */
     }
     u;
     struct devfs_entry *prev;    /*  Previous entry in the parent directory  */
@@ -713,12 +712,11 @@
     struct devfs_entry *slave;   /*  Another entry to unregister             */
     struct devfs_inode inode;
     umode_t mode;
-    unsigned short namelen;  /*  I think 64k+ filenames are a way off...  */
-    unsigned char registered:1;
+    unsigned short namelen;      /*  I think 64k+ filenames are a way off... */
     unsigned char hide:1;
-    unsigned char no_persistence:1;
-    char name[1];            /*  This is just a dummy: the allocated array is
-				 bigger. This is NULL-terminated  */
+    unsigned char vfs_created:1; /*  Whether created by driver or VFS        */
+    char name[1];                /*  This is just a dummy: the allocated array
+				     is bigger. This is NULL-terminated      */
 };
 
 /*  The root of the device tree  */
@@ -726,35 +724,38 @@
 
 struct devfsd_buf_entry
 {
-    void *data;
-    unsigned int type;
+    struct devfs_entry *de;      /*  The name is generated with this         */
+    unsigned short type;         /*  The type of event                       */
     umode_t mode;
     uid_t uid;
     gid_t gid;
+    struct devfsd_buf_entry *next;
 };
 
-struct fs_info      /*  This structure is for the mounted devfs  */
+struct fs_info                  /*  This structure is for the mounted devfs  */
 {
     struct super_block *sb;
-    volatile struct devfsd_buf_entry *devfsd_buffer;
-    spinlock_t devfsd_buffer_lock;
-    volatile unsigned int devfsd_buf_in;
-    volatile unsigned int devfsd_buf_out;
+    spinlock_t devfsd_buffer_lock;  /*  Lock when inserting/deleting events  */
+    struct devfsd_buf_entry *devfsd_first_event;
+    struct devfsd_buf_entry *devfsd_last_event;
     volatile int devfsd_sleeping;
     volatile struct task_struct *devfsd_task;
     volatile struct file *devfsd_file;
     struct devfsd_notify_struct *devfsd_info;
     volatile unsigned long devfsd_event_mask;
     atomic_t devfsd_overrun_count;
-    wait_queue_head_t devfsd_wait_queue;
-    wait_queue_head_t revalidate_wait_queue;
+    wait_queue_head_t devfsd_wait_queue;      /*  Wake devfsd on input       */
+    wait_queue_head_t revalidate_wait_queue;  /*  Wake when devfsd sleeps    */
 };
 
 static struct fs_info fs_info = {devfsd_buffer_lock: SPIN_LOCK_UNLOCKED};
-static const int devfsd_buf_size = PAGE_SIZE / sizeof(struct devfsd_buf_entry);
+static kmem_cache_t *devfsd_buf_cache;
 #ifdef CONFIG_DEVFS_DEBUG
 static unsigned int devfs_debug_init __initdata = DEBUG_NONE;
 static unsigned int devfs_debug = DEBUG_NONE;
+static spinlock_t stat_lock = SPIN_LOCK_UNLOCKED;
+static unsigned int stat_num_entries;
+static unsigned int stat_num_bytes;
 #endif
 
 #ifdef CONFIG_DEVFS_MOUNT
@@ -763,19 +764,23 @@
 static unsigned int boot_options = OPTION_NONE;
 #endif
 
-static DECLARE_RWSEM (symlink_rwsem);
-
 /*  Forward function declarations  */
-static struct devfs_entry *search_for_entry (struct devfs_entry *dir,
-					     const char *name,
-					     unsigned int namelen, int mkdir,
-					     int mkfile, int *is_new,
-					     int traverse_symlink);
+static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir,
+					const char *name, int namelen,
+					int traverse_symlink);
 static ssize_t devfsd_read (struct file *file, char *buf, size_t len,
 			    loff_t *ppos);
 static int devfsd_ioctl (struct inode *inode, struct file *file,
 			 unsigned int cmd, unsigned long arg);
 static int devfsd_close (struct inode *inode, struct file *file);
+#ifdef CONFIG_DEVFS_DEBUG
+static int stat_read (struct file *file, char *buf, size_t len,
+			    loff_t *ppos);
+static struct file_operations stat_fops =
+{
+    read:    stat_read,
+};
+#endif
 
 
 /*  Devfs daemon file operations  */
@@ -791,46 +796,95 @@
 
 
 /**
- *	search_for_entry_in_dir - Search for a devfs entry inside another devfs entry.
- *	@parent:  The parent devfs entry.
- *	@name:  The name of the entry.
+ *	devfs_get - Get a reference to a devfs entry.
+ *	@de:  The devfs entry.
+ */
+
+static struct devfs_entry *devfs_get (struct devfs_entry *de)
+{
+    if (de) atomic_inc (&de->refcount);
+    return de;
+}   /*  End Function devfs_get  */
+
+/**
+ *	devfs_put - Put (release) a reference to a devfs entry.
+ *	@de:  The devfs entry.
+ */
+
+static void devfs_put (struct devfs_entry *de)
+{
+    if (!de) return;
+    if ( !atomic_dec_and_test (&de->refcount) ) return;
+    if (de == root_entry)
+	OOPS ("%s: devfs_put(): root entry being freed\n", DEVFS_NAME);
+#ifdef CONFIG_DEVFS_DEBUG
+    if (devfs_debug & DEBUG_FREE)
+	printk ("%s: devfs_put(%s): de: %p, parent: %p \"%s\"\n",
+		DEVFS_NAME, de->name, de, de->parent,
+		de->parent ? de->parent->name : "no parent");
+#endif
+    if ( S_ISLNK (de->mode) ) kfree (de->u.symlink.linkname);
+    if ( ( S_ISCHR (de->mode) || S_ISBLK (de->mode) ) && de->u.fcb.autogen )
+    {
+	devfs_dealloc_devnum ( S_ISCHR (de->mode) ? DEVFS_SPECIAL_CHR :
+			       DEVFS_SPECIAL_BLK,
+			       MKDEV (de->u.fcb.u.device.major,
+				      de->u.fcb.u.device.minor) );
+    }
+#ifdef CONFIG_DEVFS_DEBUG
+    spin_lock (&stat_lock);
+    --stat_num_entries;
+    stat_num_bytes -= sizeof *de + de->namelen;
+    if ( S_ISLNK (de->mode) ) stat_num_bytes -= de->u.symlink.length + 1;
+    spin_unlock (&stat_lock);
+#endif
+    kfree (de);
+}   /*  End Function devfs_put  */
+
+/**
+ *	_devfs_search_dir - Search for a devfs entry in a directory.
+ *	@dir:  The directory to search.
+ *	@name:  The name of the entry to search for.
  *	@namelen:  The number of characters in @name.
- *	@traverse_symlink:  If %TRUE then the entry is traversed if it is a symlink.
  *
- *  Search for a devfs entry inside another devfs entry and returns a pointer
- *   to the entry on success, else %NULL.
+ *  Search for a devfs entry in a directory and returns a pointer to the entry
+ *   on success, else %NULL. The directory must be locked already.
+ *   An implicit devfs_get() is performed on the returned entry.
  */
 
-static struct devfs_entry *search_for_entry_in_dir (struct devfs_entry *parent,
-						    const char *name,
-						    unsigned int namelen,
-						    int traverse_symlink)
+static struct devfs_entry *_devfs_search_dir (struct devfs_entry *dir,
+					      const char *name,
+					      unsigned int namelen)
 {
-    struct devfs_entry *curr, *retval;
+    struct devfs_entry *curr;
 
-    if ( !S_ISDIR (parent->mode) )
+    if ( !S_ISDIR (dir->mode) )
     {
-	printk ("%s: entry is not a directory\n", DEVFS_NAME);
+	printk ("%s: search_dir(%s): not a directory\n", DEVFS_NAME,dir->name);
 	return NULL;
     }
-    for (curr = parent->u.dir.first; curr != NULL; curr = curr->next)
+    for (curr = dir->u.dir.first; curr != NULL; curr = curr->next)
     {
 	if (curr->namelen != namelen) continue;
 	if (memcmp (curr->name, name, namelen) == 0) break;
 	/*  Not found: try the next one  */
     }
-    if (curr == NULL) return NULL;
-    if (!S_ISLNK (curr->mode) || !traverse_symlink) return curr;
-    /*  Need to follow the link: this is a stack chomper  */
-    retval = curr->registered ?
-	search_for_entry (parent, curr->u.symlink.linkname,
-			  curr->u.symlink.length, FALSE, FALSE, NULL,
-			  TRUE) : NULL;
-    return retval;
-}   /*  End Function search_for_entry_in_dir  */
+    return devfs_get (curr);
+}   /*  End Function _devfs_search_dir  */
+
+
+/**
+ *	_devfs_alloc_entry - Allocate a devfs entry.
+ *	@name:  The name of the entry.
+ *	@namelen:  The number of characters in @name.
+ *
+ *  Allocate a devfs entry and returns a pointer to the entry on success, else
+ *   %NULL.
+ */
 
-static struct devfs_entry *create_entry (struct devfs_entry *parent,
-					 const char *name,unsigned int namelen)
+static struct devfs_entry *_devfs_alloc_entry (const char *name,
+					       unsigned int namelen,
+					       umode_t mode)
 {
     struct devfs_entry *new;
     static unsigned long inode_counter = FIRST_INODE;
@@ -839,168 +893,270 @@
     if ( name && (namelen < 1) ) namelen = strlen (name);
     if ( ( new = kmalloc (sizeof *new + namelen, GFP_KERNEL) ) == NULL )
 	return NULL;
-    /*  Magic: this will set the ctime to zero, thus subsequent lookups will
-	trigger the call to <update_devfs_inode_from_entry>  */
     memset (new, 0, sizeof *new + namelen);
+    new->mode = mode;
+    if ( S_ISDIR (mode) ) rwlock_init (&new->u.dir.lock);
+    atomic_set (&new->refcount, 1);
     spin_lock (&counter_lock);
     new->inode.ino = inode_counter++;
     spin_unlock (&counter_lock);
-    new->parent = parent;
     if (name) memcpy (new->name, name, namelen);
     new->namelen = namelen;
-    if (parent == NULL) return new;
-    new->prev = parent->u.dir.last;
-    /*  Insert into the parent directory's list of children  */
-    if (parent->u.dir.first == NULL) parent->u.dir.first = new;
-    else parent->u.dir.last->next = new;
-    parent->u.dir.last = new;
+#ifdef CONFIG_DEVFS_DEBUG
+    spin_lock (&stat_lock);
+    ++stat_num_entries;
+    stat_num_bytes += sizeof *new + namelen;
+    spin_unlock (&stat_lock);
+#endif
     return new;
-}   /*  End Function create_entry  */
+}   /*  End Function _devfs_alloc_entry  */
+
 
-static void update_devfs_inode_from_entry (struct devfs_entry *de)
+/**
+ *	_devfs_append_entry - Append a devfs entry to a directory's child list.
+ *	@dir:  The directory to add to.
+ *	@de:  The devfs entry to append.
+ *	@removable: If TRUE, increment the count of removable devices for %dir.
+ *	@old_de: If an existing entry exists, it will be written here. This may
+ *		 be %NULL.
+ *
+ *  Append a devfs entry to a directory's list of children, checking first to
+ *   see if an entry of the same name exists. The directory will be locked.
+ *   The value 0 is returned on success, else a negative error code.
+ *   On failure, an implicit devfs_put() is performed on %de.
+ */
+
+static int _devfs_append_entry (devfs_handle_t dir, devfs_handle_t de,
+				int removable, devfs_handle_t *old_de)
 {
-    if (de == NULL) return;
-    if ( S_ISDIR (de->mode) )
-    {
-	de->inode.mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
-	de->inode.uid = 0;
-	de->inode.gid = 0;
-    }
-    else if ( S_ISLNK (de->mode) )
-    {
-	de->inode.mode = S_IFLNK | S_IRUGO | S_IXUGO;
-	de->inode.uid = 0;
-	de->inode.gid = 0;
-    }
-    else if ( S_ISFIFO (de->mode) )
+    int retval;
+
+    if (old_de) *old_de = NULL;
+    if ( !S_ISDIR (dir->mode) )
     {
-	de->inode.mode = de->mode;
-	de->inode.uid = de->u.fifo.uid;
-	de->inode.gid = de->u.fifo.gid;
+	printk ("%s: append_entry(%s): dir: \"%s\" is not a directory\n",
+		DEVFS_NAME, de->name, dir->name);
+	devfs_put (de);
+	return -ENOTDIR;
     }
+    write_lock (&dir->u.dir.lock);
+    if (dir->u.dir.no_more_additions) retval = -ENOENT;
     else
     {
-	if (de->u.fcb.auto_owner)
-	    de->inode.mode = (de->mode & ~S_IALLUGO) | S_IRUGO | S_IWUGO;
-	else de->inode.mode = de->mode;
-	de->inode.uid = de->u.fcb.default_uid;
-	de->inode.gid = de->u.fcb.default_gid;
+	struct devfs_entry *old;
+
+	old = _devfs_search_dir (dir, de->name, de->namelen);
+	if (old_de) *old_de = old;
+	else devfs_put (old);
+	if (old == NULL)
+	{
+	    de->parent = dir;
+	    de->prev = dir->u.dir.last;
+	    /*  Append to the directory's list of children  */
+	    if (dir->u.dir.first == NULL) dir->u.dir.first = de;
+	    else dir->u.dir.last->next = de;
+	    dir->u.dir.last = de;
+	    if (removable) ++dir->u.dir.num_removable;
+	    retval = 0;
+	}
+	else retval = -EEXIST;
     }
-}   /*  End Function update_devfs_inode_from_entry  */
+    write_unlock (&dir->u.dir.lock);
+    if (retval) devfs_put (de);
+    return retval;
+}   /*  End Function _devfs_append_entry  */
+
 
 /**
- *	get_root_entry - Get the root devfs entry.
+ *	_devfs_get_root_entry - Get the root devfs entry.
  *
  *	Returns the root devfs entry on success, else %NULL.
  */
 
-static struct devfs_entry *get_root_entry (void)
+static struct devfs_entry *_devfs_get_root_entry (void)
 {
     kdev_t devnum;
     struct devfs_entry *new;
+    static spinlock_t root_lock = SPIN_LOCK_UNLOCKED;
 
     /*  Always ensure the root is created  */
-    if (root_entry != NULL) return root_entry;
-    if ( ( root_entry = create_entry (NULL, NULL, 0) ) == NULL ) return NULL;
-    root_entry->mode = S_IFDIR;
-    /*  Force an inode update, because lookup() is never done for the root  */
-    update_devfs_inode_from_entry (root_entry);
-    root_entry->registered = TRUE;
+    if (root_entry) return root_entry;
+    if ( ( new = _devfs_alloc_entry (NULL, 0,MODE_DIR) ) == NULL ) return NULL;
+    spin_lock (&root_lock);
+    if (root_entry)
+    {
+	spin_unlock (&root_lock);
+	devfs_put (new);
+	return (root_entry);
+    }
+    root_entry = new;
+    spin_unlock (&root_lock);
     /*  And create the entry for ".devfsd"  */
-    if ( ( new = create_entry (root_entry, ".devfsd", 0) ) == NULL )
-	return NULL;
+    if ( ( new = _devfs_alloc_entry (".devfsd", 0, S_IFCHR |S_IRUSR |S_IWUSR) )
+	 == NULL ) return NULL;
     devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
     new->u.fcb.u.device.major = MAJOR (devnum);
     new->u.fcb.u.device.minor = MINOR (devnum);
-    new->mode = S_IFCHR | S_IRUSR | S_IWUSR;
-    new->u.fcb.default_uid = 0;
-    new->u.fcb.default_gid = 0;
     new->u.fcb.ops = &devfsd_fops;
-    new->registered = TRUE;
+    _devfs_append_entry (root_entry, new, FALSE, NULL);
+#ifdef CONFIG_DEVFS_DEBUG
+    if ( ( new = _devfs_alloc_entry (".stat", 0, S_IFCHR | S_IRUGO | S_IWUGO) )
+	 == NULL ) return NULL;
+    devnum = devfs_alloc_devnum (DEVFS_SPECIAL_CHR);
+    new->u.fcb.u.device.major = MAJOR (devnum);
+    new->u.fcb.u.device.minor = MINOR (devnum);
+    new->u.fcb.ops = &stat_fops;
+    _devfs_append_entry (root_entry, new, FALSE, NULL);
+#endif
     return root_entry;
-}   /*  End Function get_root_entry  */
+}   /*  End Function _devfs_get_root_entry  */
 
 
 /**
- *	search_for_entry - Search for an entry in the devfs tree.
- *	@dir: The parent directory to search from. If this is %NULL the root is used
- *	@name: The name of the entry.
- *	@namelen: The number of characters in @name.
- *	@mkdir: If %TRUE intermediate directories are created as needed.
- *	@mkfile: If %TRUE the file entry is created if it doesn't exist.
- *	@is_new: If the returned entry was newly made, %TRUE is written here. If
- * 		this is %NULL nothing is written here.
- *	@traverse_symlink: If %TRUE then symbolic links are traversed.
+ *	_devfs_descend - Descend down a tree using the next component name.
+ *	@dir:  The directory to search.
+ *	@name:  The component name to search for.
+ *	@namelen:  The length of %name.
+ *	@next_pos:  The position of the next '/' or '\0' is written here.
  *
- *	If the entry is created, then it will be in the unregistered state.
- *	Returns a pointer to the entry on success, else %NULL.
+ *  Descend into a directory, searching for a component. This function forms
+ *   the core of a tree-walking algorithm. The directory will be locked.
+ *   The devfs entry corresponding to the component is returned. If there is
+ *   no matching entry, %NULL is returned.
+ *   An implicit devfs_get() is performed on the returned entry.
  */
 
-static struct devfs_entry *search_for_entry (struct devfs_entry *dir,
-					     const char *name,
-					     unsigned int namelen, int mkdir,
-					     int mkfile, int *is_new,
-					     int traverse_symlink)
+static struct devfs_entry *_devfs_descend (struct devfs_entry *dir,
+					   const char *name, int namelen,
+					   int *next_pos)
 {
-    int len;
-    const char *subname, *stop, *ptr;
+    const char *stop, *ptr;
     struct devfs_entry *entry;
 
-    if (is_new) *is_new = FALSE;
-    if (dir == NULL) dir = get_root_entry ();
-    if (dir == NULL) return NULL;
-    /*  Extract one filename component  */
-    subname = name;
+    if ( (namelen >= 3) && (strncmp (name, "../", 3) == 0) )
+    {   /*  Special-case going to parent directory  */
+	*next_pos = 3;
+	return devfs_get (dir->parent);
+    }
     stop = name + namelen;
-    while (subname < stop)
-    {
-	/*  Search for a possible '/'  */
-	for (ptr = subname; (ptr < stop) && (*ptr != '/'); ++ptr);
-	if (ptr >= stop)
-	{
-	    /*  Look for trailing component  */
-	    len = stop - subname;
-	    entry = search_for_entry_in_dir (dir, subname, len,
-					     traverse_symlink);
-	    if (entry != NULL) return entry;
-	    if (!mkfile) return NULL;
-	    entry = create_entry (dir, subname, len);
-	    if (entry && is_new) *is_new = TRUE;
-	    return entry;
-	}
-	/*  Found '/': search for directory  */
-	if (strncmp (subname, "../", 3) == 0)
-	{
-	    /*  Going up  */
-	    dir = dir->parent;
-	    if (dir == NULL) return NULL;  /*  Cannot escape from devfs  */
-	    subname += 3;
-	    continue;
+    /*  Search for a possible '/'  */
+    for (ptr = name; (ptr < stop) && (*ptr != '/'); ++ptr);
+    *next_pos = ptr - name;
+    read_lock (&dir->u.dir.lock);
+    entry = _devfs_search_dir (dir, name, *next_pos);
+    read_unlock (&dir->u.dir.lock);
+    return entry;
+}   /*  End Function _devfs_descend  */
+
+
+static devfs_handle_t _devfs_make_parent_for_leaf (struct devfs_entry *dir,
+						   const char *name,
+						   int namelen, int *leaf_pos)
+{
+    int next_pos = 0;
+
+    if (dir == NULL) dir = _devfs_get_root_entry ();
+    if (dir == NULL) return NULL;
+    devfs_get (dir);
+    /*  Search for possible trailing component and ignore it  */
+    for (--namelen; (namelen > 0) && (name[namelen] != '/'); --namelen);
+    *leaf_pos = (name[namelen] == '/') ? (namelen + 1) : 0;
+    for (; namelen > 0; name += next_pos, namelen -= next_pos)
+    {
+	struct devfs_entry *de, *old;
+
+	if ( ( de = _devfs_descend (dir, name, namelen, &next_pos) ) == NULL )
+	{
+	    de = _devfs_alloc_entry (name, next_pos, MODE_DIR);
+	    devfs_get (de);
+	    if ( !de || _devfs_append_entry (dir, de, FALSE, &old) )
+	    {
+		devfs_put (de);
+		if ( !old || !S_ISDIR (old->mode) )
+		{
+		    devfs_put (old);
+		    devfs_put (dir);
+		    return NULL;
+		}
+		de = old;  /*  Use the existing directory  */
+	    }
 	}
-	len = ptr - subname;
-	entry = search_for_entry_in_dir (dir, subname, len, traverse_symlink);
-	if (!entry && !mkdir) return NULL;
-	if (entry == NULL)
+	if (de == dir->parent)
 	{
-	    /*  Make it  */
-	    if ( ( entry = create_entry (dir, subname, len) ) == NULL )
-		return NULL;
-	    entry->mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
-	    if (is_new) *is_new = TRUE;
+	    devfs_put (dir);
+	    devfs_put (de);
+	    return NULL;
 	}
-	if ( !S_ISDIR (entry->mode) )
+	devfs_put (dir);
+	dir = de;
+	if (name[next_pos] == '/') ++next_pos;
+    }
+    return dir;
+}   /*  End Function _devfs_make_parent_for_leaf  */
+
+
+static devfs_handle_t _devfs_prepare_leaf (devfs_handle_t *dir,
+					   const char *name, umode_t mode)
+{
+    int namelen, leaf_pos;
+    struct devfs_entry *de;
+
+    namelen = strlen (name);
+    if ( ( *dir = _devfs_make_parent_for_leaf (*dir, name, namelen,
+					       &leaf_pos) ) == NULL )
+    {
+	printk ("%s: prepare_leaf(%s): could not create parent path\n",
+		DEVFS_NAME, name);
+	return NULL;
+    }
+    if ( ( de = _devfs_alloc_entry (name + leaf_pos, namelen - leaf_pos,mode) )
+	 == NULL )
+    {
+	printk ("%s: prepare_leaf(%s): could not allocate entry\n",
+		DEVFS_NAME, name);
+	devfs_put (*dir);
+	return NULL;
+    }
+    return de;
+}   /*  End Function _devfs_prepare_leaf  */
+
+
+static devfs_handle_t _devfs_walk_path (struct devfs_entry *dir,
+					const char *name, int namelen,
+					int traverse_symlink)
+{
+    int next_pos = 0;
+
+    if (dir == NULL) dir = _devfs_get_root_entry ();
+    if (dir == NULL) return NULL;
+    devfs_get (dir);
+    for (; namelen > 0; name += next_pos, namelen -= next_pos)
+    {
+	struct devfs_entry *de, *link;
+
+	if ( ( de = _devfs_descend (dir, name, namelen, &next_pos) ) == NULL )
 	{
-	    printk ("%s: existing non-directory entry\n", DEVFS_NAME);
+	    devfs_put (dir);
 	    return NULL;
 	}
-	/*  Ensure an unregistered entry is re-registered and visible  */
-	entry->hide = FALSE;
-	entry->registered = TRUE;
-	subname = ptr + 1;
-	dir = entry;
+	if (S_ISLNK (de->mode) && traverse_symlink)
+	{   /*  Need to follow the link: this is a stack chomper  */
+	    link = _devfs_walk_path (dir, de->u.symlink.linkname,
+				     de->u.symlink.length, TRUE);
+	    devfs_put (de);
+	    if (!link)
+	    {
+		devfs_put (dir);
+		return NULL;
+	    }
+	    de = link;
+	}
+	devfs_put (dir);
+	dir = de;
+	if (name[next_pos] == '/') ++next_pos;
     }
-    return NULL;
-}   /*  End Function search_for_entry  */
+    return dir;
+}   /*  End Function _devfs_walk_path  */
 
 
 /**
@@ -1020,20 +1176,29 @@
 {
     struct devfs_entry *entry, *de;
 
+    devfs_get (dir);
     if (dir == NULL) return NULL;
     if ( !S_ISDIR (dir->mode) )
     {
 	printk ("%s: find_by_dev(): not a directory\n", DEVFS_NAME);
+	devfs_put (dir);
 	return NULL;
     }
     /*  First search files in this directory  */
+    read_lock (&dir->u.dir.lock);
     for (entry = dir->u.dir.first; entry != NULL; entry = entry->next)
     {
 	if ( !S_ISCHR (entry->mode) && !S_ISBLK (entry->mode) ) continue;
 	if ( S_ISCHR (entry->mode) && (type != DEVFS_SPECIAL_CHR) ) continue;
 	if ( S_ISBLK (entry->mode) && (type != DEVFS_SPECIAL_BLK) ) continue;
 	if ( (entry->u.fcb.u.device.major == major) &&
-	     (entry->u.fcb.u.device.minor == minor) ) return entry;
+	     (entry->u.fcb.u.device.minor == minor) )
+	{
+	    devfs_get (entry);
+	    read_unlock (&dir->u.dir.lock);
+	    devfs_put (dir);
+	    return entry;
+	}
 	/*  Not found: try the next one  */
     }
     /*  Now recursively search the subdirectories: this is a stack chomper  */
@@ -1041,8 +1206,15 @@
     {
 	if ( !S_ISDIR (entry->mode) ) continue;
 	de = find_by_dev (entry, major, minor, type);
-	if (de) return de;
+	if (de)
+	{
+	    read_unlock (&dir->u.dir.lock);
+	    devfs_put (dir);
+	    return de;
+	}
     }
+    read_unlock (&dir->u.dir.lock);
+    devfs_put (dir);
     return NULL;
 }   /*  End Function find_by_dev  */
 
@@ -1063,7 +1235,6 @@
  *		%DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK.
  *	@traverse_symlink: If %TRUE then symbolic links are traversed.
  *
- *	FIXME: What the hell is @handle? - ch
  *	Returns the devfs_entry pointer on success, else %NULL.
  */
 
@@ -1095,10 +1266,7 @@
 	    ++name;
 	    --namelen;
 	}
-	if (traverse_symlink) down_read (&symlink_rwsem);
-	entry = search_for_entry (dir, name, namelen, FALSE, FALSE, NULL,
-				  traverse_symlink);
-	if (traverse_symlink) up_read (&symlink_rwsem);
+	entry = _devfs_walk_path (dir, name, namelen, traverse_symlink);
 	if (entry != NULL) return entry;
     }
     /*  Have to search by major and minor: slow  */
@@ -1106,42 +1274,34 @@
     return find_by_dev (root_entry, major, minor, type);
 }   /*  End Function find_entry  */
 
-static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode,
-							   int do_check)
+static struct devfs_entry *get_devfs_entry_from_vfs_inode (struct inode *inode)
 {
-    struct devfs_entry *de;
-
     if (inode == NULL) return NULL;
-    de = inode->u.generic_ip;
-    if (!de) printk (__FUNCTION__ "(): NULL de for inode %ld\n", inode->i_ino);
-    if (do_check && de && !de->registered) de = NULL;
-    return de;
+    return inode->u.generic_ip;
 }   /*  End Function get_devfs_entry_from_vfs_inode  */
 
 
 /**
- *	free_dentries - Free the dentries for a device entry and invalidate inodes.
+ *	free_dentry - Free the dentry for a device entry and invalidate inode.
  *	@de: The entry.
+ *
+ *	This must only be called after the entry has been unhooked from it's
+ *	 parent directory.
  */
 
-static void free_dentries (struct devfs_entry *de)
+static void free_dentry (struct devfs_entry *de)
 {
-    struct dentry *dentry;
+    struct dentry *dentry = de->inode.dentry;
 
+    if (!dentry) return;
     spin_lock (&dcache_lock);
-    dentry = de->inode.dentry;
-    if (dentry != NULL)
-    {
-	dget_locked (dentry);
-	de->inode.dentry = NULL;
-	spin_unlock (&dcache_lock);
-	/*  Forcefully remove the inode  */
-	if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0;
-	d_drop (dentry);
-	dput (dentry);
-    }
-    else spin_unlock (&dcache_lock);
-}   /*  End Function free_dentries  */
+    dget_locked (dentry);
+    spin_unlock (&dcache_lock);
+    /*  Forcefully remove the inode  */
+    if (dentry->d_inode != NULL) dentry->d_inode->i_nlink = 0;
+    d_drop (dentry);
+    dput (dentry);
+}   /*  End Function free_dentry  */
 
 
 /**
@@ -1172,7 +1332,7 @@
 
 static inline int devfsd_queue_empty (struct fs_info *fs_info)
 {
-    return (fs_info->devfsd_buf_out == fs_info->devfsd_buf_in) ? TRUE : FALSE;
+    return (fs_info->devfsd_last_event) ? FALSE : TRUE;
 }   /*  End Function devfsd_queue_empty  */
 
 
@@ -1201,8 +1361,9 @@
 
 
 /**
- *	devfsd_notify_one - Notify a single devfsd daemon of a change.
- *	@data: Data to be passed.
+ *	devfsd_notify_de - Notify the devfsd daemon of a change.
+ *	@de: The devfs entry that has changed. This and all parent entries will
+ *            have their reference counts incremented if the event was queued.
  *	@type: The type of change.
  *	@mode: The mode of the entry.
  *	@uid: The user ID.
@@ -1212,51 +1373,48 @@
  *	Returns %TRUE if an event was queued and devfsd woken up, else %FALSE.
  */
 
-static int devfsd_notify_one (void *data, unsigned int type, umode_t mode,
-			      uid_t uid, gid_t gid, struct fs_info *fs_info)
+static int devfsd_notify_de (struct devfs_entry *de,
+			     unsigned short type, umode_t mode,
+			     uid_t uid, gid_t gid, struct fs_info *fs_info)
 {
-    unsigned int next_pos;
-    unsigned long flags;
     struct devfsd_buf_entry *entry;
+    struct devfs_entry *curr;
 
     if ( !( fs_info->devfsd_event_mask & (1 << type) ) ) return (FALSE);
-    next_pos = fs_info->devfsd_buf_in + 1;
-    if (next_pos >= devfsd_buf_size) next_pos = 0;
-    if (next_pos == fs_info->devfsd_buf_out)
+    if ( ( entry = kmem_cache_alloc (devfsd_buf_cache, 0) ) == NULL )
     {
-	/*  Running up the arse of the reader: drop it  */
 	atomic_inc (&fs_info->devfsd_overrun_count);
 	return (FALSE);
     }
-    spin_lock_irqsave (&fs_info->devfsd_buffer_lock, flags);
-    next_pos = fs_info->devfsd_buf_in + 1;
-    if (next_pos >= devfsd_buf_size) next_pos = 0;
-    entry = (struct devfsd_buf_entry *) fs_info->devfsd_buffer +
-	fs_info->devfsd_buf_in;
-    entry->data = data;
+    for (curr = de; curr != NULL; curr = curr->parent) devfs_get (curr);
+    entry->de = de;
     entry->type = type;
     entry->mode = mode;
     entry->uid = uid;
     entry->gid = gid;
-    fs_info->devfsd_buf_in = next_pos;
-    spin_unlock_irqrestore (&fs_info->devfsd_buffer_lock, flags);
+    entry->next = NULL;
+    spin_lock (&fs_info->devfsd_buffer_lock);
+    if (!fs_info->devfsd_first_event) fs_info->devfsd_first_event = entry;
+    if (fs_info->devfsd_last_event) fs_info->devfsd_last_event->next = entry;
+    fs_info->devfsd_last_event = entry;
+    spin_unlock (&fs_info->devfsd_buffer_lock);
     wake_up_interruptible (&fs_info->devfsd_wait_queue);
     return (TRUE);
-}   /*  End Function devfsd_notify_one  */
+}   /*  End Function devfsd_notify_de  */
 
 
 /**
- *	devfsd_notify - Notify all devfsd daemons of a change.
+ *	devfsd_notify - Notify the devfsd daemon of a change.
  *	@de: The devfs entry that has changed.
  *	@type: The type of change event.
- *	@wait: If TRUE, the functions waits for all daemons to finish processing
+ *	@wait: If TRUE, the function waits for the daemon to finish processing
  *		the event.
  */
 
-static void devfsd_notify (struct devfs_entry *de, unsigned int type, int wait)
+static void devfsd_notify (struct devfs_entry *de,unsigned short type,int wait)
 {
-    if (devfsd_notify_one (de, type, de->mode, current->euid,
-			   current->egid, &fs_info) && wait)
+    if (devfsd_notify_de (de, type, de->mode, current->euid,
+			  current->egid, &fs_info) && wait)
 	wait_for_devfsd_finished (&fs_info);
 }   /*  End Function devfsd_notify  */
 
@@ -1287,7 +1445,7 @@
 			       umode_t mode, void *ops, void *info)
 {
     char devtype = S_ISCHR (mode) ? DEVFS_SPECIAL_CHR : DEVFS_SPECIAL_BLK;
-    int is_new;
+    int err;
     kdev_t devnum = NODEV;
     struct devfs_entry *de;
 
@@ -1332,146 +1490,127 @@
 	major = MAJOR (devnum);
 	minor = MINOR (devnum);
     }
-    de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new,
-			   FALSE);
-    if (de == NULL)
+    if ( ( de = _devfs_prepare_leaf (&dir, name, mode) ) == NULL )
     {
-	printk ("%s: devfs_register(): could not create entry: \"%s\"\n",
+	printk ("%s: devfs_register(%s): could not prepare leaf\n",
 		DEVFS_NAME, name);
 	if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
 	return NULL;
     }
-#ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_REGISTER)
-	printk ("%s: devfs_register(%s): de: %p %s\n",
-		DEVFS_NAME, name, de, is_new ? "new" : "existing");
-#endif
-    if (!is_new)
-    {
-	/*  Existing entry  */
-	if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) &&
-	     !S_ISREG (de->mode) )
-	{
-	    printk ("%s: devfs_register(): existing non-device/file entry: \"%s\"\n",
-		    DEVFS_NAME, name);
-	    if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
-	    return NULL;
-	}
-	if (de->registered)
-	{
-	    printk("%s: devfs_register(): device already registered: \"%s\"\n",
-		   DEVFS_NAME, name);
-	    if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
-	    return NULL;
-	}
-    }
-    de->u.fcb.autogen = FALSE;
     if ( S_ISCHR (mode) || S_ISBLK (mode) )
     {
 	de->u.fcb.u.device.major = major;
 	de->u.fcb.u.device.minor = minor;
 	de->u.fcb.autogen = (devnum == NODEV) ? FALSE : TRUE;
     }
-    else if ( S_ISREG (mode) ) de->u.fcb.u.file.size = 0;
-    else
+    else if ( !S_ISREG (mode) )
     {
-	printk ("%s: devfs_register(): illegal mode: %x\n",
-		DEVFS_NAME, mode);
+	printk ("%s: devfs_register(%s): illegal mode: %x\n",
+		DEVFS_NAME, name, mode);
+	devfs_put (de);
+	devfs_put (dir);
 	return (NULL);
     }
     de->info = info;
-    de->mode = mode;
     if (flags & DEVFS_FL_CURRENT_OWNER)
     {
-	de->u.fcb.default_uid = current->uid;
-	de->u.fcb.default_gid = current->gid;
+	de->inode.uid = current->uid;
+	de->inode.gid = current->gid;
     }
     else
     {
-	de->u.fcb.default_uid = 0;
-	de->u.fcb.default_gid = 0;
+	de->inode.uid = 0;
+	de->inode.gid = 0;
     }
     de->u.fcb.ops = ops;
     de->u.fcb.auto_owner = (flags & DEVFS_FL_AUTO_OWNER) ? TRUE : FALSE;
     de->u.fcb.aopen_notify = (flags & DEVFS_FL_AOPEN_NOTIFY) ? TRUE : FALSE;
-    if (flags & DEVFS_FL_REMOVABLE)
-    {
-	de->u.fcb.removable = TRUE;
-	++de->parent->u.dir.num_removable;
-    }
-    de->u.fcb.open = FALSE;
     de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE;
-    de->no_persistence = (flags & DEVFS_FL_NO_PERSISTENCE) ? TRUE : FALSE;
-    de->registered = TRUE;
+    if (flags & DEVFS_FL_REMOVABLE) de->u.fcb.removable = TRUE;
+    if ( ( err = _devfs_append_entry (dir, de, de->u.fcb.removable, NULL) )
+	 != 0 )
+    {
+	printk("%s: devfs_register(%s): could not append to parent, err: %d\n",
+	       DEVFS_NAME, name, err);
+	devfs_put (dir);
+	if (devnum != NODEV) devfs_dealloc_devnum (devtype, devnum);
+	return NULL;
+    }
+#ifdef CONFIG_DEVFS_DEBUG
+    if (devfs_debug & DEBUG_REGISTER)
+	printk ("%s: devfs_register(%s): de: %p dir: %p \"%s\"  pp: %p\n",
+		DEVFS_NAME, name, de, dir, dir->name, dir->parent);
+#endif
     devfsd_notify (de, DEVFSD_NOTIFY_REGISTERED, flags & DEVFS_FL_WAIT);
+    devfs_put (dir);
     return de;
 }   /*  End Function devfs_register  */
 
 
 /**
- *	unregister - Unregister a device entry.
+ *	_devfs_unhook - Unhook a device entry from its parents list
+ *	@de: The entry to unhook.
+ *
+ *	Returns %TRUE if the entry was unhooked, else %FALSE if it was
+ *		previously unhooked.
+ *	The caller must have a write lock on the parent directory.
+ */
+
+static int _devfs_unhook (struct devfs_entry *de)
+{
+    struct devfs_entry *parent;
+
+    if ( !de || (de->prev == de) ) return FALSE;
+    parent = de->parent;
+    if (de->prev == NULL) parent->u.dir.first = de->next;
+    else de->prev->next = de->next;
+    if (de->next == NULL) parent->u.dir.last = de->prev;
+    else de->next->prev = de->prev;
+    de->prev = de;          /*  Indicate we're unhooked                      */
+    de->next = NULL;        /*  Force early termination for <devfs_readdir>  */
+    if ( ( S_ISREG (de->mode) || S_ISCHR (de->mode) || S_ISBLK (de->mode) ) &&
+	 de->u.fcb.removable )
+	--parent->u.dir.num_removable;
+    return TRUE;
+}   /*  End Function _devfs_unhook  */
+
+
+/**
+ *	unregister - Unregister a device entry from it's parent.
+ *	@dir: The parent directory.
  *	@de: The entry to unregister.
+ *
+ *	The caller must have a write lock on the parent directory, which is
+ *	unlocked by this function.
  */
 
-static void unregister (struct devfs_entry *de)
+static void unregister (struct devfs_entry *dir, struct devfs_entry *de)
 {
-    struct devfs_entry *child;
+    int unhooked = _devfs_unhook (de);
 
-    if ( (child = de->slave) != NULL )
-    {
-	de->slave = NULL;  /* Unhook first in case slave is parent directory */
-	unregister (child);
-    }
-    if (de->registered)
-    {
-	devfsd_notify (de, DEVFSD_NOTIFY_UNREGISTERED, 0);
-	free_dentries (de);
-    }
-    de->info = NULL;
-    if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
-    {
-	de->registered = FALSE;
-	de->u.fcb.ops = NULL;
-	if (!S_ISREG (de->mode) && de->u.fcb.autogen)
-	{
-	    devfs_dealloc_devnum ( S_ISCHR (de->mode) ? DEVFS_SPECIAL_CHR :
-				   DEVFS_SPECIAL_BLK,
-				   MKDEV (de->u.fcb.u.device.major,
-					  de->u.fcb.u.device.minor) );
-	}
-	de->u.fcb.autogen = FALSE;
-	return;
-    }
-    if (S_ISLNK (de->mode) && de->registered)
-    {
-	de->registered = FALSE;
-	down_write (&symlink_rwsem);
-	if (de->u.symlink.linkname) kfree (de->u.symlink.linkname);
-	de->u.symlink.linkname = NULL;
-	up_write (&symlink_rwsem);
-	return;
-    }
-    if ( S_ISFIFO (de->mode) )
-    {
-	de->registered = FALSE;
-	return;
-    }
-    if (!de->registered) return;
-    if ( !S_ISDIR (de->mode) )
-    {
-	printk ("%s: unregister(): unsupported type\n", DEVFS_NAME);
-	return;
-    }
-    de->registered = FALSE;
-    /*  Now recursively search the subdirectories: this is a stack chomper  */
-    for (child = de->u.dir.first; child != NULL; child = child->next)
-    {
+    write_unlock (&dir->u.dir.lock);
+    if (!unhooked) return;
+    devfs_get (dir);
+    devfs_unregister (de->slave);  /*  Let it handle the locking  */
+    devfsd_notify (de, DEVFSD_NOTIFY_UNREGISTERED, 0);
+    free_dentry (de);
+    devfs_put (dir);
+    if ( !S_ISDIR (de->mode) ) return;
+    while (TRUE)  /*  Recursively unregister: this is a stack chomper  */
+    {
+	struct devfs_entry *child;
+
+	write_lock (&de->u.dir.lock);
+	de->u.dir.no_more_additions = TRUE;
+	child = de->u.dir.first;
+	unregister (de, child);
+	if (!child) break;
 #ifdef CONFIG_DEVFS_DEBUG
 	if (devfs_debug & DEBUG_UNREGISTER)
 	    printk ("%s: unregister(): child->name: \"%s\" child: %p\n",
 		    DEVFS_NAME, child->name, child);
 #endif
-	unregister (child);
+	devfs_put (child);
     }
 }   /*  End Function unregister  */
 
@@ -1484,20 +1623,22 @@
 
 void devfs_unregister (devfs_handle_t de)
 {
-    if (de == NULL) return;
+    if ( (de == NULL) || (de->parent == NULL) ) return;
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_UNREGISTER)
 	printk ("%s: devfs_unregister(): de->name: \"%s\" de: %p\n",
 		DEVFS_NAME, de->name, de);
 #endif
-    unregister (de);
+    write_lock (&de->parent->u.dir.lock);
+    unregister (de->parent, de);
+    devfs_put (de);
 }   /*  End Function devfs_unregister  */
 
 static int devfs_do_symlink (devfs_handle_t dir, const char *name,
 			     unsigned int flags, const char *link,
 			     devfs_handle_t *handle, void *info)
 {
-    int is_new;
+    int err;
     unsigned int linklength;
     char *newlink;
     struct devfs_entry *de;
@@ -1522,28 +1663,31 @@
 	return -ENOMEM;
     memcpy (newlink, link, linklength);
     newlink[linklength] = '\0';
-    if ( ( de = search_for_entry (dir, name, strlen (name), TRUE, TRUE,
-				  &is_new, FALSE) ) == NULL )
-    {
-	kfree (newlink);
-	return -ENOMEM;
-    }
-    down_write (&symlink_rwsem);
-    if (de->registered)
+    if ( ( de = _devfs_prepare_leaf (&dir, name, S_IFLNK | S_IRUGO | S_IXUGO) )
+	 == NULL )
     {
-	up_write (&symlink_rwsem);
-	kfree (newlink);
-	printk ("%s: devfs_do_symlink(%s): entry already exists\n",
+	printk ("%s: devfs_do_symlink(%s): could not prepare leaf\n",
 		DEVFS_NAME, name);
-	return -EEXIST;
+	kfree (newlink);
+	return -ENOTDIR;
     }
-    de->mode = S_IFLNK | S_IRUGO | S_IXUGO;
     de->info = info;
     de->hide = (flags & DEVFS_FL_HIDE) ? TRUE : FALSE;
     de->u.symlink.linkname = newlink;
     de->u.symlink.length = linklength;
-    de->registered = TRUE;
-    up_write (&symlink_rwsem);
+    if ( ( err = _devfs_append_entry (dir, de, FALSE, NULL) ) != 0 )
+    {
+	printk ("%s: devfs_do_symlink(%s): could not append to parent, err: %d\n",
+		DEVFS_NAME, name, err);
+	devfs_put (dir);
+	return err;
+    }
+    devfs_put (dir);
+#ifdef CONFIG_DEVFS_DEBUG
+    spin_lock (&stat_lock);
+    stat_num_bytes += linklength + 1;
+    spin_unlock (&stat_lock);
+#endif
     if (handle != NULL) *handle = de;
     return 0;
 }   /*  End Function devfs_do_symlink  */
@@ -1593,7 +1737,7 @@
 
 devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name, void *info)
 {
-    int is_new;
+    int err;
     struct devfs_entry *de;
 
     if (name == NULL)
@@ -1601,36 +1745,26 @@
 	printk ("%s: devfs_mk_dir(): NULL name pointer\n", DEVFS_NAME);
 	return NULL;
     }
-    de = search_for_entry (dir, name, strlen (name), TRUE, TRUE, &is_new,
-			   FALSE);
-    if (de == NULL)
+    if ( ( de = _devfs_prepare_leaf (&dir, name, MODE_DIR) ) == NULL )
     {
-	printk ("%s: devfs_mk_dir(): could not create entry: \"%s\"\n",
+	printk ("%s: devfs_mk_dir(%s): could not prepare leaf\n",
 		DEVFS_NAME, name);
 	return NULL;
     }
-    if (!S_ISDIR (de->mode) && de->registered)
+    de->info = info;
+    if ( ( err = _devfs_append_entry (dir, de, FALSE, NULL) ) != 0 )
     {
-	printk ("%s: devfs_mk_dir(): existing non-directory entry: \"%s\"\n",
-		DEVFS_NAME, name);
+	printk ("%s: devfs_mk_dir(%s): could not append to dir: %p \"%s\", err: %d\n",
+		DEVFS_NAME, name, dir, dir->name, err);
+	devfs_put (dir);
 	return NULL;
     }
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_REGISTER)
-	printk ("%s: devfs_mk_dir(%s): de: %p %s\n",
-		DEVFS_NAME, name, de, is_new ? "new" : "existing");
+	printk ("%s: devfs_mk_dir(%s): de: %p dir: %p \"%s\"\n",
+		DEVFS_NAME, name, de, dir, dir->name);
 #endif
-    if (!S_ISDIR (de->mode) && !is_new)
-    {
-	/*  Transmogrifying an old entry  */
-	de->u.dir.first = NULL;
-	de->u.dir.last = NULL;
-    }
-    de->mode = S_IFDIR | S_IRUGO | S_IXUGO;
-    de->info = info;
-    if (!de->registered) de->u.dir.num_removable = 0;
-    de->hide = FALSE;
-    de->registered = TRUE;
+    devfs_put (dir);
     return de;
 }   /*  End Function devfs_mk_dir  */
 
@@ -1660,8 +1794,8 @@
 
     if ( (name != NULL) && (name[0] == '\0') ) name = NULL;
     de = find_entry (dir, name, 0, major, minor, type, traverse_symlinks);
-    if (de == NULL) return NULL;
-    if (!de->registered) return NULL;
+    devfs_put (de);  /*  FIXME: in 2.5 consider dropping this and require a
+			 call to devfs_put()  */
     return de;
 }   /*  End Function devfs_find_handle  */
 
@@ -1679,7 +1813,6 @@
     unsigned int fl = 0;
 
     if (de == NULL) return -EINVAL;
-    if (!de->registered) return -ENODEV;
     if (de->hide) fl |= DEVFS_FL_HIDE;
     if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
     {
@@ -1703,7 +1836,6 @@
 int devfs_set_flags (devfs_handle_t de, unsigned int flags)
 {
     if (de == NULL) return -EINVAL;
-    if (!de->registered) return -ENODEV;
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_SET_FLAGS)
 	printk ("%s: devfs_set_flags(): de->name: \"%s\"\n",
@@ -1714,16 +1846,6 @@
     {
 	de->u.fcb.auto_owner = (flags & DEVFS_FL_AUTO_OWNER) ? TRUE : FALSE;
 	de->u.fcb.aopen_notify = (flags & DEVFS_FL_AOPEN_NOTIFY) ? TRUE:FALSE;
-	if ( de->u.fcb.removable && !(flags & DEVFS_FL_REMOVABLE) )
-	{
-	    de->u.fcb.removable = FALSE;
-	    --de->parent->u.dir.num_removable;
-	}
-	else if ( !de->u.fcb.removable && (flags & DEVFS_FL_REMOVABLE) )
-	{
-	    de->u.fcb.removable = TRUE;
-	    ++de->parent->u.dir.num_removable;
-	}
     }
     return 0;
 }   /*  End Function devfs_set_flags  */
@@ -1742,7 +1864,6 @@
 		       unsigned int *minor)
 {
     if (de == NULL) return -EINVAL;
-    if (!de->registered) return -ENODEV;
     if ( S_ISDIR (de->mode) ) return -EISDIR;
     if ( !S_ISCHR (de->mode) && !S_ISBLK (de->mode) ) return -EINVAL;
     if (major != NULL) *major = de->u.fcb.u.device.major;
@@ -1762,7 +1883,7 @@
 {
     if (!inode || !inode->i_sb) return NULL;
     if (inode->i_sb->s_magic != DEVFS_SUPER_MAGIC) return NULL;
-    return get_devfs_entry_from_vfs_inode (inode, TRUE);
+    return get_devfs_entry_from_vfs_inode (inode);
 }   /*  End Function devfs_get_handle_from_inode  */
 
 
@@ -1780,19 +1901,20 @@
 int devfs_generate_path (devfs_handle_t de, char *path, int buflen)
 {
     int pos;
+#define NAMEOF(de) ( (de)->mode ? (de)->name : (de)->u.name )
 
     if (de == NULL) return -EINVAL;
     if (de->namelen >= buflen) return -ENAMETOOLONG; /*  Must be first       */
     path[buflen - 1] = '\0';
     if (de->parent == NULL) return buflen - 1;       /*  Don't prepend root  */
     pos = buflen - de->namelen - 1;
-    memcpy (path + pos, de->name, de->namelen);
+    memcpy (path + pos, NAMEOF (de), de->namelen);
     for (de = de->parent; de->parent != NULL; de = de->parent)
     {
 	if (pos - de->namelen - 1 < 0) return -ENAMETOOLONG;
 	path[--pos] = '/';
 	pos -= de->namelen;
-	memcpy (path + pos, de->name, de->namelen);
+	memcpy (path + pos, NAMEOF (de), de->namelen);
     }
     return pos;
 }   /*  End Function devfs_generate_path  */
@@ -1808,7 +1930,6 @@
 void *devfs_get_ops (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
-    if (!de->registered) return NULL;
     if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
 	return de->u.fcb.ops;
     return NULL;
@@ -1826,7 +1947,6 @@
 int devfs_set_file_size (devfs_handle_t de, unsigned long size)
 {
     if (de == NULL) return -EINVAL;
-    if (!de->registered) return -EINVAL;
     if ( !S_ISREG (de->mode) ) return -EINVAL;
     if (de->u.fcb.u.file.size == size) return 0;
     de->u.fcb.u.file.size = size;
@@ -1846,7 +1966,6 @@
 void *devfs_get_info (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
-    if (!de->registered) return NULL;
     return de->info;
 }   /*  End Function devfs_get_info  */
 
@@ -1861,7 +1980,6 @@
 int devfs_set_info (devfs_handle_t de, void *info)
 {
     if (de == NULL) return -EINVAL;
-    if (!de->registered) return -EINVAL;
     de->info = info;
     return 0;
 }   /*  End Function devfs_set_info  */
@@ -1876,7 +1994,6 @@
 devfs_handle_t devfs_get_parent (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
-    if (!de->registered) return NULL;
     return de->parent;
 }   /*  End Function devfs_get_parent  */
 
@@ -1891,7 +2008,6 @@
 devfs_handle_t devfs_get_first_child (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
-    if (!de->registered) return NULL;
     if ( !S_ISDIR (de->mode) ) return NULL;
     return de->u.dir.first;
 }   /*  End Function devfs_get_first_child  */
@@ -1907,7 +2023,6 @@
 devfs_handle_t devfs_get_next_sibling (devfs_handle_t de)
 {
     if (de == NULL) return NULL;
-    if (!de->registered) return NULL;
     return de->next;
 }   /*  End Function devfs_get_next_sibling  */
 
@@ -1961,7 +2076,6 @@
 const char *devfs_get_name (devfs_handle_t de, unsigned int *namelen)
 {
     if (de == NULL) return NULL;
-    if (!de->registered) return NULL;
     if (namelen != NULL) *namelen = de->namelen;
     return de->name;
 }   /*  End Function devfs_get_name  */
@@ -2057,8 +2171,10 @@
 	{"dmod",      DEBUG_MODULE_LOAD,  &devfs_debug_init},
 	{"dreg",      DEBUG_REGISTER,     &devfs_debug_init},
 	{"dunreg",    DEBUG_UNREGISTER,   &devfs_debug_init},
+	{"dfree",     DEBUG_FREE,         &devfs_debug_init},
 	{"diget",     DEBUG_I_GET,        &devfs_debug_init},
 	{"dchange",   DEBUG_SET_FLAGS,    &devfs_debug_init},
+	{"dsread",    DEBUG_S_READ,       &devfs_debug_init},
 	{"dichange",  DEBUG_I_CHANGE,     &devfs_debug_init},
 	{"dimknod",   DEBUG_I_MKNOD,      &devfs_debug_init},
 	{"dilookup",  DEBUG_I_LOOKUP,     &devfs_debug_init},
@@ -2129,34 +2245,31 @@
 
 
 /**
- *	try_modload - Notify devfsd of an inode lookup.
+ *	try_modload - Notify devfsd of an inode lookup by a non-devfsd process.
  *	@parent: The parent devfs entry.
  *	@fs_info: The filesystem info.
  *	@name: The device name.
  *	@namelen: The number of characters in @name.
- *	@buf: A working area that will be used. This must not go out of scope until
- *		devfsd is idle again.
+ *	@buf: A working area that will be used. This must not go out of scope
+ *            until devfsd is idle again.
  *
  *	Returns 0 on success, else a negative error code.
  */
 
 static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info,
 			const char *name, unsigned namelen,
-			char buf[STRING_LENGTH])
+			struct devfs_entry *buf)
 {
-    int pos = STRING_LENGTH - namelen - 1;
-
     if ( !( fs_info->devfsd_event_mask & (1 << DEVFSD_NOTIFY_LOOKUP) ) )
 	return -ENOENT;
     if ( is_devfsd_or_child (fs_info) ) return -ENOENT;
-    if (namelen >= STRING_LENGTH - 1) return -ENAMETOOLONG;
-    memcpy (buf + pos, name, namelen);
-    buf[STRING_LENGTH - 1] = '\0';
-    if (parent->parent != NULL) pos = devfs_generate_path (parent, buf, pos);
-    if (pos < 0) return pos;
-    buf[STRING_LENGTH - namelen - 2] = '/';
-    if ( !devfsd_notify_one (buf + pos, DEVFSD_NOTIFY_LOOKUP, 0,
-			     current->euid, current->egid, fs_info) )
+    memset (buf, 0, sizeof *buf);
+    atomic_set (&buf->refcount, 1);
+    buf->parent = parent;
+    buf->namelen = namelen;
+    buf->u.name = name;
+    if ( !devfsd_notify_de (buf, DEVFSD_NOTIFY_LOOKUP, 0,
+			    current->euid, current->egid, fs_info) )
 	return -ENOENT;
     /*  Possible success  */
     return 0;
@@ -2206,7 +2319,6 @@
     if (dir->u.dir.num_removable < 1) return;
     for (de = dir->u.dir.first; de != NULL; de = de->next)
     {
-	if (!de->registered) continue;
 	if ( !S_ISBLK (de->mode) ) continue;
 	if (!de->u.fcb.removable) continue;
 	check_disc_changed (de);
@@ -2229,7 +2341,6 @@
 
     for (de = dir->u.dir.first; de != NULL; de = de->next)
     {
-	if (!de->registered) continue;
 	if ( !S_ISBLK (de->mode) ) continue;
 	if (!de->u.fcb.removable) continue;
 	if (strcmp (de->name, "disc") == 0) return check_disc_changed (de);
@@ -2258,7 +2369,7 @@
     struct inode *inode = dentry->d_inode;
     struct fs_info *fs_info = inode->i_sb->u.generic_sbp;
 
-    de = get_devfs_entry_from_vfs_inode (inode, TRUE);
+    de = get_devfs_entry_from_vfs_inode (inode);
     if (de == NULL) return -ENODEV;
     retval = inode_change_ok (inode, iattr);
     if (retval != 0) return retval;
@@ -2276,15 +2387,19 @@
 #endif
     /*  Inode is not on hash chains, thus must save permissions here rather
 	than in a write_inode() method  */
-    de->inode.mode = inode->i_mode;
-    de->inode.uid = inode->i_uid;
-    de->inode.gid = inode->i_gid;
+    if ( ( !S_ISREG (inode->i_mode) && !S_ISCHR (inode->i_mode) &&
+	   !S_ISBLK (inode->i_mode) ) || !de->u.fcb.auto_owner )
+    {
+	de->mode = inode->i_mode;
+	de->inode.uid = inode->i_uid;
+	de->inode.gid = inode->i_gid;
+    }
     de->inode.atime = inode->i_atime;
     de->inode.mtime = inode->i_mtime;
     de->inode.ctime = inode->i_ctime;
     if ( iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID) )
-	devfsd_notify_one (de, DEVFSD_NOTIFY_CHANGE, inode->i_mode,
-			   inode->i_uid, inode->i_gid, fs_info);
+	devfsd_notify_de (de, DEVFSD_NOTIFY_CHANGE, inode->i_mode,
+			  inode->i_uid, inode->i_gid, fs_info);
     return 0;
 }   /*  End Function devfs_notify_change  */
 
@@ -2299,11 +2414,10 @@
     return 0;
 }   /*  End Function devfs_statfs  */
 
-static void devfs_clear_inode(struct inode *inode)
+static void devfs_clear_inode (struct inode *inode)
 {
-	if (S_ISBLK(inode->i_mode))
-		bdput(inode->i_bdev);
-}
+    if ( S_ISBLK (inode->i_mode) ) bdput (inode->i_bdev);
+}   /*  End Function devfs_clear_inode  */
 
 static struct super_operations devfs_sops =
 { 
@@ -2319,32 +2433,37 @@
  *	@de: The devfs inode.
  *	@dentry: The dentry to register with the devfs inode.
  *
- *	Returns the inode on success, else %NULL.
+ *	Returns the inode on success, else %NULL. An implicit devfs_get() is
+ *       performed if the inode is created.
  */
 
 static struct inode *get_vfs_inode (struct super_block *sb,
 				    struct devfs_entry *de,
 				    struct dentry *dentry)
 {
+    int is_fcb = FALSE;
     struct inode *inode;
 
-    if (de->inode.dentry != NULL)
-    {
-	printk ("%s: get_vfs_inode(%u): old de->inode.dentry: %p \"%s\"  new dentry: %p \"%s\"\n",
-		DEVFS_NAME, de->inode.ino,
-		de->inode.dentry, de->inode.dentry->d_name.name,
-		dentry, dentry->d_name.name);
-	printk ("  old inode: %p\n", de->inode.dentry->d_inode);
-	return NULL;
-    }
+    if (de->prev == de) return NULL;  /*  Quick check to see if unhooked  */
     if ( ( inode = new_inode (sb) ) == NULL )
     {
 	printk ("%s: get_vfs_inode(%s): new_inode() failed, de: %p\n",
 		DEVFS_NAME, de->name, de);
 	return NULL;
     }
-    de->inode.dentry = dentry;
-    inode->u.generic_ip = de;
+    if (de->parent)
+    {
+	read_lock (&de->parent->u.dir.lock);
+	if (de->prev != de) de->inode.dentry = dentry; /*      Not unhooked  */
+	read_unlock (&de->parent->u.dir.lock);
+    }
+    else de->inode.dentry = dentry;             /*  Root: no locking needed  */
+    if (de->inode.dentry != dentry)
+    {   /*  Must have been unhooked  */
+	iput (inode);
+	return NULL;
+    }
+    inode->u.generic_ip = devfs_get (de);
     inode->i_ino = de->inode.ino;
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_I_GET)
@@ -2356,37 +2475,45 @@
     inode->i_op = &devfs_iops;
     inode->i_fop = &devfs_fops;
     inode->i_rdev = NODEV;
-    if ( S_ISCHR (de->inode.mode) )
+    if ( S_ISCHR (de->mode) )
     {
 	inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
 			       de->u.fcb.u.device.minor);
-	inode->i_cdev = cdget (kdev_t_to_nr(inode->i_rdev));
+	inode->i_cdev = cdget ( kdev_t_to_nr (inode->i_rdev) );
+	is_fcb = TRUE;
     }
-    else if ( S_ISBLK (de->inode.mode) )
+    else if ( S_ISBLK (de->mode) )
     {
 	inode->i_rdev = MKDEV (de->u.fcb.u.device.major,
 			       de->u.fcb.u.device.minor);
-	if (bd_acquire(inode) == 0)
+	if (bd_acquire (inode) == 0)
 	{
 	    if (!inode->i_bdev->bd_op && de->u.fcb.ops)
 		inode->i_bdev->bd_op = de->u.fcb.ops;
 	}
 	else printk ("%s: get_vfs_inode(%d): no block device from bdget()\n",
 		     DEVFS_NAME, (int) inode->i_ino);
+	is_fcb = TRUE;
     }
-    else if ( S_ISFIFO (de->inode.mode) ) inode->i_fop = &def_fifo_fops;
-    else if ( S_ISREG (de->inode.mode) ) inode->i_size = de->u.fcb.u.file.size;
-    else if ( S_ISDIR (de->inode.mode) )
+    else if ( S_ISFIFO (de->mode) ) inode->i_fop = &def_fifo_fops;
+    else if ( S_ISREG (de->mode) )
+    {
+	inode->i_size = de->u.fcb.u.file.size;
+	is_fcb = TRUE;
+    }
+    else if ( S_ISDIR (de->mode) )
     {
 	inode->i_op = &devfs_dir_iops;
     	inode->i_fop = &devfs_dir_fops;
     }
-    else if ( S_ISLNK (de->inode.mode) )
+    else if ( S_ISLNK (de->mode) )
     {
 	inode->i_op = &devfs_symlink_iops;
 	inode->i_size = de->u.symlink.length;
     }
-    inode->i_mode = de->inode.mode;
+    if (is_fcb && de->u.fcb.auto_owner)
+	inode->i_mode = (de->mode & S_IFMT) | S_IRUGO | S_IWUGO;
+    else inode->i_mode = de->mode;
     inode->i_uid = de->inode.uid;
     inode->i_gid = de->inode.gid;
     inode->i_atime = de->inode.atime;
@@ -2409,11 +2536,11 @@
     int err, count;
     int stored = 0;
     struct fs_info *fs_info;
-    struct devfs_entry *parent, *de;
+    struct devfs_entry *parent, *de, *next = NULL;
     struct inode *inode = file->f_dentry->d_inode;
 
     fs_info = inode->i_sb->u.generic_sbp;
-    parent = get_devfs_entry_from_vfs_inode (file->f_dentry->d_inode, TRUE);
+    parent = get_devfs_entry_from_vfs_inode (file->f_dentry->d_inode);
     if ( (long) file->f_pos < 0 ) return -EINVAL;
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_F_READDIR)
@@ -2441,19 +2568,32 @@
       default:
 	/*  Skip entries  */
 	count = file->f_pos - 2;
-	for (de = parent->u.dir.first; (de != NULL) && (count > 0);
-	     de = de->next)
+	read_lock (&parent->u.dir.lock);
+	for (de = parent->u.dir.first; de && (count > 0); de = de->next)
 	    if ( !IS_HIDDEN (de) ) --count;
+	devfs_get (de);
+	read_unlock (&parent->u.dir.lock);
 	/*  Now add all remaining entries  */
-	for (; de != NULL; de = de->next)
+	while (de)
 	{
-	    if ( IS_HIDDEN (de) ) continue;
-	    err = (*filldir) (dirent, de->name, de->namelen,
-			      file->f_pos, de->inode.ino, de->mode >> 12);
+	    if ( IS_HIDDEN (de) ) err = 0;
+	    else
+	    {
+		err = (*filldir) (dirent, de->name, de->namelen,
+				  file->f_pos, de->inode.ino, de->mode >> 12);
+		if (err >= 0)
+		{
+		    file->f_pos++;
+		    ++stored;
+		}
+	    }
+	    read_lock (&parent->u.dir.lock);
+	    next = devfs_get (de->next);
+	    read_unlock (&parent->u.dir.lock);
+	    devfs_put (de);
+	    de = next;
 	    if (err == -EINVAL) break;
 	    if (err < 0) return err;
-	    file->f_pos++;
-	    ++stored;
 	}
 	break;
     }
@@ -2467,14 +2607,9 @@
     struct devfs_entry *de;
     struct fs_info *fs_info = inode->i_sb->u.generic_sbp;
 
-    lock_kernel ();
-    de = get_devfs_entry_from_vfs_inode (inode, TRUE);
-    err = -ENODEV;
-    if (de == NULL)
-	goto out;
-    err = 0;
-    if ( S_ISDIR (de->mode) )
-	goto out;
+    de = get_devfs_entry_from_vfs_inode (inode);
+    if (de == NULL) return -ENODEV;
+    if ( S_ISDIR (de->mode) ) return 0;
     df = &de->u.fcb;
     file->private_data = de->info;
     if ( S_ISBLK (inode->i_mode) )
@@ -2482,7 +2617,7 @@
 	file->f_op = &def_blk_fops;
 	if (df->ops) inode->i_bdev->bd_op = df->ops;
     }
-    else file->f_op = fops_get ( (struct file_operations*) df->ops );
+    else file->f_op = fops_get ( (struct file_operations *) df->ops );
     if (file->f_op)
 	err = file->f_op->open ? (*file->f_op->open) (inode, file) : 0;
     else
@@ -2491,39 +2626,33 @@
 	if ( S_ISCHR (inode->i_mode) ) err = chrdev_open (inode, file);
 	else err = -ENODEV;
     }
-    if (err < 0) goto out;
+    if (err < 0) return err;
     /*  Open was successful  */
-    err = 0;
-    if (df->open) goto out;
+    if (df->open) return 0;
     df->open = TRUE;  /*  This is the first open  */
     if (df->auto_owner)
     {
-	/*  Change the ownership/protection  */
-	de->inode.mode = (de->inode.mode & ~S_IALLUGO) |(de->mode & S_IRWXUGO);
-	de->inode.uid = current->euid;
-	de->inode.gid = current->egid;
-	inode->i_mode = de->inode.mode;
-	inode->i_uid = de->inode.uid;
-	inode->i_gid = de->inode.gid;
+	/*  Change the ownership/protection to what driver specified  */
+	inode->i_mode = de->mode;
+	inode->i_uid = current->euid;
+	inode->i_gid = current->egid;
     }
     if (df->aopen_notify)
-	devfsd_notify_one (de, DEVFSD_NOTIFY_ASYNC_OPEN, inode->i_mode,
-			   current->euid, current->egid, fs_info);
-out:
-    unlock_kernel ();
-    return err;
+	devfsd_notify_de (de, DEVFSD_NOTIFY_ASYNC_OPEN, inode->i_mode,
+			  current->euid, current->egid, fs_info);
+    return 0;
 }   /*  End Function devfs_open  */
 
 static struct file_operations devfs_fops =
 {
-    open: devfs_open,
+    open:    devfs_open,
 };
 
 static struct file_operations devfs_dir_fops =
 {
-    read: generic_read_dir,
+    read:    generic_read_dir,
     readdir: devfs_readdir,
-    open: devfs_open,
+    open:    devfs_open,
 };
 
 
@@ -2556,16 +2685,18 @@
 {
     struct devfs_entry *de;
 
-    lock_kernel ();
-    de = get_devfs_entry_from_vfs_inode (inode, FALSE);
+    de = get_devfs_entry_from_vfs_inode (inode);
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_D_IPUT)
 	printk ("%s: d_iput(): dentry: %p inode: %p de: %p  de->dentry: %p\n",
 		DEVFS_NAME, dentry, inode, de, de->inode.dentry);
 #endif
-    if (de->inode.dentry == dentry) de->inode.dentry = NULL;
-    unlock_kernel ();
+    if ( de->inode.dentry && (de->inode.dentry != dentry) )
+	OOPS ("%s: d_iput(%s): de: %p dentry: %p de->dentry: %p\n",
+	      DEVFS_NAME, de->name, de, dentry, de->inode.dentry);
+    de->inode.dentry = NULL;
     iput (inode);
+    devfs_put (de);
 }   /*  End Function devfs_d_iput  */
 
 static int devfs_d_delete (struct dentry *dentry);
@@ -2610,7 +2741,7 @@
 	return 1;
     }
     fs_info = inode->i_sb->u.generic_sbp;
-    de = get_devfs_entry_from_vfs_inode (inode, TRUE);
+    de = get_devfs_entry_from_vfs_inode (inode);
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_D_DELETE)
 	printk ("%s: d_delete(): dentry: %p  inode: %p  devfs_entry: %p\n",
@@ -2622,14 +2753,11 @@
     if (!de->u.fcb.open) return 0;
     de->u.fcb.open = FALSE;
     if (de->u.fcb.aopen_notify)
-	devfsd_notify_one (de, DEVFSD_NOTIFY_CLOSE, inode->i_mode,
-			   current->euid, current->egid, fs_info);
+	devfsd_notify_de (de, DEVFSD_NOTIFY_CLOSE, inode->i_mode,
+			  current->euid, current->egid, fs_info);
     if (!de->u.fcb.auto_owner) return 0;
     /*  Change the ownership/protection back  */
-    de->inode.mode = (de->inode.mode & ~S_IALLUGO) | S_IRUGO | S_IWUGO;
-    de->inode.uid = de->u.fcb.default_uid;
-    de->inode.gid = de->u.fcb.default_gid;
-    inode->i_mode = de->inode.mode;
+    inode->i_mode = (de->mode & S_IFMT) | S_IRUGO | S_IWUGO;
     inode->i_uid = de->inode.uid;
     inode->i_gid = de->inode.gid;
     return 0;
@@ -2637,59 +2765,38 @@
 
 static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
 {
-    devfs_handle_t de = dentry->d_fsdata;
-    struct inode *dir;
-    struct fs_info *fs_info;
+    struct inode *dir = dentry->d_parent->d_inode;
+    struct fs_info *fs_info = dir->i_sb->u.generic_sbp;
 
-    lock_kernel ();
-    dir = dentry->d_parent->d_inode;
-    fs_info = dir->i_sb->u.generic_sbp;
-    if (!de || de->registered)
+    if ( !dentry->d_inode && is_devfsd_or_child (fs_info) )
     {
-	if ( !dentry->d_inode && is_devfsd_or_child (fs_info) )
-	{
-	    struct inode *inode;
-
-#ifdef CONFIG_DEVFS_DEBUG
-	    char txt[STRING_LENGTH];
-
-	    memset (txt, 0, STRING_LENGTH);
-	    memcpy (txt, dentry->d_name.name,
-		    (dentry->d_name.len >= STRING_LENGTH) ?
-		    (STRING_LENGTH - 1) : dentry->d_name.len);
-	    if (devfs_debug & DEBUG_I_LOOKUP)
-		printk ("%s: d_revalidate(): dentry: %p name: \"%s\" by: \"%s\"\n",
-			DEVFS_NAME, dentry, txt, current->comm);
+	devfs_handle_t de;
+	devfs_handle_t parent = get_devfs_entry_from_vfs_inode (dir);
+	struct inode *inode;
+
+#ifdef CONFIG_DEVFS_DEBUG
+	if (devfs_debug & DEBUG_I_LOOKUP)
+	    printk ("%s: d_revalidate(%s): dentry: %p by: \"%s\"\n",
+		    DEVFS_NAME, dentry->d_name.name, dentry, current->comm);
+#endif
+	read_lock (&parent->u.dir.lock);
+	de = _devfs_search_dir (parent, dentry->d_name.name,
+				dentry->d_name.len);
+	read_lock (&parent->u.dir.lock);
+	if (de == NULL) return 1;
+	/*  Create an inode, now that the driver information is available  */
+	inode = get_vfs_inode (dir->i_sb, de, dentry);
+	devfs_put (de);
+	if (!inode) return 1;
+#ifdef CONFIG_DEVFS_DEBUG
+	if (devfs_debug & DEBUG_I_LOOKUP)
+	    printk ("%s: d_revalidate(): new VFS inode(%u): %p  devfs_entry: %p\n",
+		    DEVFS_NAME, de->inode.ino, inode, de);
 #endif
-	    if (de == NULL)
-	    {
-		devfs_handle_t parent;
-
-		parent = get_devfs_entry_from_vfs_inode (dir, TRUE);
-		de = search_for_entry_in_dir (parent, dentry->d_name.name,
-					      dentry->d_name.len, FALSE);
-	    }
-	    if (de == NULL) goto out;
-	    /*  Create an inode, now that the driver information is available
-	     */
-	    if (de->no_persistence) update_devfs_inode_from_entry (de);
-	    else if (de->inode.ctime == 0) update_devfs_inode_from_entry (de);
-	    else de->inode.mode =
-		     (de->mode & ~S_IALLUGO) | (de->inode.mode & S_IALLUGO);
-	    if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
-		goto out;
-#ifdef CONFIG_DEVFS_DEBUG
-	    if (devfs_debug & DEBUG_I_LOOKUP)
-		printk ("%s: d_revalidate(): new VFS inode(%u): %p  devfs_entry: %p\n",
-			DEVFS_NAME, de->inode.ino, inode, de);
-#endif
-	    d_instantiate (dentry, inode);
-	    goto out;
-	}
+	d_instantiate (dentry, inode);
+	return 1;
     }
     if ( wait_for_devfsd_finished (fs_info) ) dentry->d_op = &devfs_dops;
-out:
-    unlock_kernel ();
     return 1;
 }   /*  End Function devfs_d_revalidate_wait  */
 
@@ -2701,67 +2808,61 @@
     struct fs_info *fs_info;
     struct devfs_entry *parent, *de;
     struct inode *inode;
-    char txt[STRING_LENGTH];
 
     /*  Set up the dentry operations before anything else, to ensure cleaning
 	up on any error  */
     dentry->d_op = &devfs_dops;
-    memset (txt, 0, STRING_LENGTH);
-    memcpy (txt, dentry->d_name.name,
-	    (dentry->d_name.len >= STRING_LENGTH) ?
-	    (STRING_LENGTH - 1) : dentry->d_name.len);
     fs_info = dir->i_sb->u.generic_sbp;
     /*  First try to get the devfs entry for this directory  */
-    parent = get_devfs_entry_from_vfs_inode (dir, TRUE);
+    parent = get_devfs_entry_from_vfs_inode (dir);
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_I_LOOKUP)
 	printk ("%s: lookup(%s): dentry: %p parent: %p by: \"%s\"\n",
-		DEVFS_NAME, txt, dentry, parent, current->comm);
+		DEVFS_NAME, dentry->d_name.name, dentry, parent,current->comm);
 #endif
     if (parent == NULL) return ERR_PTR (-ENOENT);
-    /*  Try to reclaim an existing devfs entry  */
-    de = search_for_entry_in_dir (parent,
-				  dentry->d_name.name, dentry->d_name.len,
-				  FALSE);
-    if ( ( (de == NULL) || !de->registered ) &&
-	 (parent->u.dir.num_removable > 0) &&
+    read_lock (&parent->u.dir.lock);
+    de = _devfs_search_dir (parent, dentry->d_name.name, dentry->d_name.len);
+    read_unlock (&parent->u.dir.lock);
+    if ( (de == NULL) && (parent->u.dir.num_removable > 0) &&
 	 get_removable_partition (parent, dentry->d_name.name,
 				  dentry->d_name.len) )
     {
-	if (de == NULL)
-	    de = search_for_entry_in_dir (parent, dentry->d_name.name,
-					  dentry->d_name.len, FALSE);
+	read_lock (&parent->u.dir.lock);
+	de = _devfs_search_dir (parent, dentry->d_name.name,
+				dentry->d_name.len);
+	read_unlock (&parent->u.dir.lock);
     }
-    if ( (de == NULL) || !de->registered )
-    {
-	/*  Try with devfsd. For any kind of failure, leave a negative dentry
+    if (de == NULL)
+    {   /*  Try with devfsd. For any kind of failure, leave a negative dentry
 	    so someone else can deal with it (in the case where the sysadmin
 	    does a mknod()). It's important to do this before hashing the
 	    dentry, so that the devfsd queue is filled before revalidates
 	    can start  */
+	struct devfs_entry tmp;
+
 	if (try_modload (parent, fs_info,
-			 dentry->d_name.name, dentry->d_name.len, txt) < 0)
+			 dentry->d_name.name, dentry->d_name.len, &tmp) < 0)
 	{
 	    d_add (dentry, NULL);
 	    return NULL;
 	}
 	/*  devfsd claimed success  */
 	dentry->d_op = &devfs_wait_dops;
-	dentry->d_fsdata = de;
 	d_add (dentry, NULL);  /*  Open the floodgates  */
 	/*  Unlock directory semaphore, which will release any waiters. They
 	    will get the hashed dentry, and may be forced to wait for
 	    revalidation  */
 	up (&dir->i_sem);
-	devfs_d_revalidate_wait (dentry, 0);  /*  I might have to wait too  */
+	devfs_d_revalidate_wait (dentry, 0);  /*  I might have to wait too   */
 	down (&dir->i_sem);      /*  Grab it again because them's the rules  */
 	/*  If someone else has been so kind as to make the inode, we go home
 	    early  */
 	if (dentry->d_inode) return NULL;
-	if (de && !de->registered) return NULL;
-	if (de == NULL)
-	    de = search_for_entry_in_dir (parent, dentry->d_name.name,
-					  dentry->d_name.len, FALSE);
+	read_lock (&parent->u.dir.lock);
+	de = _devfs_search_dir (parent, dentry->d_name.name,
+				dentry->d_name.len);
+	read_unlock (&parent->u.dir.lock);
 	if (de == NULL) return NULL;
 	/*  OK, there's an entry now, but no VFS inode yet  */
     }
@@ -2771,58 +2872,47 @@
 	d_add (dentry, NULL);  /*  Open the floodgates  */
     }
     /*  Create an inode, now that the driver information is available  */
-    if (de->no_persistence) update_devfs_inode_from_entry (de);
-    else if (de->inode.ctime == 0) update_devfs_inode_from_entry (de);
-    else de->inode.mode =
-	     (de->mode & ~S_IALLUGO) | (de->inode.mode & S_IALLUGO);
-    if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
-	return ERR_PTR (-ENOMEM);
+    inode = get_vfs_inode (dir->i_sb, de, dentry);
+    devfs_put (de);
+    if (!inode) return ERR_PTR (-ENOMEM);
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_I_LOOKUP)
 	printk ("%s: lookup(): new VFS inode(%u): %p  devfs_entry: %p\n",
 		DEVFS_NAME, de->inode.ino, inode, de);
 #endif
     d_instantiate (dentry, inode);
-    /*  Unlock directory semaphore, which will release any waiters. They will
-	get the hashed dentry, and may be forced to wait for revalidation  */
-    up (&dir->i_sem);
     if (dentry->d_op == &devfs_wait_dops)
-	devfs_d_revalidate_wait (dentry, 0);  /*  I might have to wait too  */
-    down (&dir->i_sem);          /*  Grab it again because them's the rules  */
+    {   /*  Unlock directory semaphore, which will release any waiters. They
+	    will get the hashed dentry, and may be forced to wait for
+	    revalidation  */
+	up (&dir->i_sem);
+	devfs_d_revalidate_wait (dentry, 0);  /*  I might have to wait too   */
+	down (&dir->i_sem);      /*  Grab it again because them's the rules  */
+    }
     return NULL;
 }   /*  End Function devfs_lookup  */
 
 static int devfs_unlink (struct inode *dir, struct dentry *dentry)
 {
+    int unhooked;
     struct devfs_entry *de;
     struct inode *inode = dentry->d_inode;
 
 #ifdef CONFIG_DEVFS_DEBUG
-    char txt[STRING_LENGTH];
-
     if (devfs_debug & DEBUG_I_UNLINK)
-    {
-	memset (txt, 0, STRING_LENGTH);
-	memcpy (txt, dentry->d_name.name, dentry->d_name.len);
-	txt[STRING_LENGTH - 1] = '\0';
-	printk ("%s: unlink(%s)\n", DEVFS_NAME, txt);
-    }
+	printk ("%s: unlink(%s)\n", DEVFS_NAME, dentry->d_name.name);
 #endif
-
-    de = get_devfs_entry_from_vfs_inode (dentry->d_inode, TRUE);
+    de = get_devfs_entry_from_vfs_inode (inode);
     if (de == NULL) return -ENOENT;
-    devfsd_notify_one (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
-		       inode->i_uid, inode->i_gid, dir->i_sb->u.generic_sbp);
-    de->registered = FALSE;
-    de->hide = TRUE;
-    if ( S_ISLNK (de->mode) )
-    {
-	down_write (&symlink_rwsem);
-	if (de->u.symlink.linkname) kfree (de->u.symlink.linkname);
-	de->u.symlink.linkname = NULL;
-	up_write (&symlink_rwsem);
-    }
-    free_dentries (de);
+    if (!de->vfs_created) return -EPERM;
+    write_lock (&de->parent->u.dir.lock);
+    unhooked = _devfs_unhook (de);
+    write_unlock (&de->parent->u.dir.lock);
+    if (!unhooked) return -ENOENT;
+    devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
+		      inode->i_uid, inode->i_gid, dir->i_sb->u.generic_sbp);
+    free_dentry (de);
+    devfs_put (de);
     return 0;
 }   /*  End Function devfs_unlink  */
 
@@ -2836,7 +2926,7 @@
 
     fs_info = dir->i_sb->u.generic_sbp;
     /*  First try to get the devfs entry for this directory  */
-    parent = get_devfs_entry_from_vfs_inode (dir, TRUE);
+    parent = get_devfs_entry_from_vfs_inode (dir);
     if (parent == NULL) return -ENOENT;
     err = devfs_do_symlink (parent, dentry->d_name.name, DEVFS_FL_NONE,
 			    symname, &de, NULL);
@@ -2846,7 +2936,9 @@
 		DEVFS_NAME, err);
 #endif
     if (err < 0) return err;
-    de->inode.mode = de->mode;
+    de->vfs_created = TRUE;
+    de->inode.uid = current->euid;
+    de->inode.gid = current->egid;
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
@@ -2857,50 +2949,33 @@
 	printk ("%s: symlink(): new VFS inode(%u): %p  dentry: %p\n",
 		DEVFS_NAME, de->inode.ino, inode, dentry);
 #endif
-    de->hide = FALSE;
     d_instantiate (dentry, inode);
-    devfsd_notify_one (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
-		       inode->i_uid, inode->i_gid, fs_info);
+    devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
+		      inode->i_uid, inode->i_gid, fs_info);
     return 0;
 }   /*  End Function devfs_symlink  */
 
 static int devfs_mkdir (struct inode *dir, struct dentry *dentry, int mode)
 {
-    int is_new;
+    int err;
     struct fs_info *fs_info;
     struct devfs_entry *parent, *de;
     struct inode *inode;
 
-    mode = (mode & ~S_IFMT) | S_IFDIR;
+    mode = (mode & ~S_IFMT) | S_IFDIR;  /*  VFS doesn't pass S_IFMT part  */
     fs_info = dir->i_sb->u.generic_sbp;
-    /*  First try to get the devfs entry for this directory  */
-    parent = get_devfs_entry_from_vfs_inode (dir, TRUE);
+    parent = get_devfs_entry_from_vfs_inode (dir);
     if (parent == NULL) return -ENOENT;
-    /*  Try to reclaim an existing devfs entry, create if there isn't one  */
-    de = search_for_entry (parent, dentry->d_name.name, dentry->d_name.len,
-			   FALSE, TRUE, &is_new, FALSE);
-    if (de == NULL) return -ENOMEM;
-    if (de->registered)
-    {
-	printk ("%s: mkdir(): existing entry\n", DEVFS_NAME);
-	return -EEXIST;
-    }
-    de->hide = FALSE;
-    if (!S_ISDIR (de->mode) && !is_new)
-    {
-	/*  Transmogrifying an old entry  */
-	de->u.dir.first = NULL;
-	de->u.dir.last = NULL;
-    }
-    de->mode = mode;
-    de->u.dir.num_removable = 0;
-    de->inode.mode = mode;
+    de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
+    if (!de) return -ENOMEM;
+    de->vfs_created = TRUE;
+    if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 )
+	return err;
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
-    de->registered = TRUE;
     if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
 	return -ENOMEM;
 #ifdef CONFIG_DEVFS_DEBUG
@@ -2909,100 +2984,73 @@
 		DEVFS_NAME, de->inode.ino, inode, dentry);
 #endif
     d_instantiate (dentry, inode);
-    devfsd_notify_one (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
-		       inode->i_uid, inode->i_gid, fs_info);
+    devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
+		      inode->i_uid, inode->i_gid, fs_info);
     return 0;
 }   /*  End Function devfs_mkdir  */
 
 static int devfs_rmdir (struct inode *dir, struct dentry *dentry)
 {
-    int has_children = FALSE;
+    int err = 0;
+    struct devfs_entry *de;
     struct fs_info *fs_info;
-    struct devfs_entry *de, *child;
     struct inode *inode = dentry->d_inode;
 
     if (dir->i_sb->u.generic_sbp != inode->i_sb->u.generic_sbp) return -EINVAL;
     fs_info = dir->i_sb->u.generic_sbp;
-    de = get_devfs_entry_from_vfs_inode (inode, TRUE);
+    de = get_devfs_entry_from_vfs_inode (inode);
     if (de == NULL) return -ENOENT;
     if ( !S_ISDIR (de->mode) ) return -ENOTDIR;
-    for (child = de->u.dir.first; child != NULL; child = child->next)
-    {
-	if (child->registered)
-	{
-	    has_children = TRUE;
-	    break;
-	}
-    }
-    if (has_children) return -ENOTEMPTY;
-    devfsd_notify_one (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
-		       inode->i_uid, inode->i_gid, fs_info);
-    de->hide = TRUE;
-    de->registered = FALSE;
-    free_dentries (de);
+    if (!de->vfs_created) return -EPERM;
+    /*  First ensure the directory is empty and will stay thay way  */
+    write_lock (&de->u.dir.lock);
+    de->u.dir.no_more_additions = TRUE;
+    if (de->u.dir.first) err = -ENOTEMPTY;
+    write_unlock (&de->u.dir.lock);
+    if (err) return err;
+    /*  Now unhook the directory from it's parent  */
+    write_lock (&de->parent->u.dir.lock);
+    if ( !_devfs_unhook (de) ) err = -ENOENT;
+    write_unlock (&de->parent->u.dir.lock);
+    if (err) return err;
+    devfsd_notify_de (de, DEVFSD_NOTIFY_DELETE, inode->i_mode,
+		      inode->i_uid, inode->i_gid, fs_info);
+    free_dentry (de);
+    devfs_put (de);
     return 0;
 }   /*  End Function devfs_rmdir  */
 
 static int devfs_mknod (struct inode *dir, struct dentry *dentry, int mode,
 			int rdev)
 {
-    int is_new;
+    int err;
     struct fs_info *fs_info;
     struct devfs_entry *parent, *de;
     struct inode *inode;
 
 #ifdef CONFIG_DEVFS_DEBUG
-    char txt[STRING_LENGTH];
-
     if (devfs_debug & DEBUG_I_MKNOD)
-    {
-	memset (txt, 0, STRING_LENGTH);
-	memcpy (txt, dentry->d_name.name, dentry->d_name.len);
-	txt[STRING_LENGTH - 1] = '\0';
 	printk ("%s: mknod(%s): mode: 0%o  dev: %d\n",
-		DEVFS_NAME, txt, mode, rdev);
-    }
+		DEVFS_NAME, dentry->d_name.name, mode, rdev);
 #endif
-
     fs_info = dir->i_sb->u.generic_sbp;
-    /*  First try to get the devfs entry for this directory  */
-    parent = get_devfs_entry_from_vfs_inode (dir, TRUE);
+    parent = get_devfs_entry_from_vfs_inode (dir);
     if (parent == NULL) return -ENOENT;
-    /*  Try to reclaim an existing devfs entry, create if there isn't one  */
-    de = search_for_entry (parent, dentry->d_name.name, dentry->d_name.len,
-			   FALSE, TRUE, &is_new, FALSE);
-    if (de == NULL) return -ENOMEM;
-    if (de->registered)
-    {
-	printk ("%s: mknod(): existing entry\n", DEVFS_NAME);
-	return -EEXIST;
-    }
-    de->info = NULL;
-    de->mode = mode;
+    de = _devfs_alloc_entry (dentry->d_name.name, dentry->d_name.len, mode);
+    if (!de) return -ENOMEM;
+    de->vfs_created = TRUE;
     if ( S_ISBLK (mode) || S_ISCHR (mode) )
     {
 	de->u.fcb.u.device.major = MAJOR (rdev);
 	de->u.fcb.u.device.minor = MINOR (rdev);
-	de->u.fcb.default_uid = current->euid;
-	de->u.fcb.default_gid = current->egid;
-	de->u.fcb.ops = NULL;
-	de->u.fcb.auto_owner = FALSE;
-	de->u.fcb.aopen_notify = FALSE;
-	de->u.fcb.open = FALSE;
-    }
-    else if ( S_ISFIFO (mode) )
-    {
-	de->u.fifo.uid = current->euid;
-	de->u.fifo.gid = current->egid;
     }
-    de->hide = FALSE;
-    de->inode.mode = mode;
+    if ( ( err = _devfs_append_entry (parent, de, FALSE, NULL) ) != 0 )
+	return err;
     de->inode.uid = current->euid;
     de->inode.gid = current->egid;
     de->inode.atime = CURRENT_TIME;
     de->inode.mtime = CURRENT_TIME;
     de->inode.ctime = CURRENT_TIME;
-    de->registered = TRUE;
     if ( ( inode = get_vfs_inode (dir->i_sb, de, dentry) ) == NULL )
 	return -ENOMEM;
 #ifdef CONFIG_DEVFS_DEBUG
@@ -3011,8 +3059,8 @@
 		DEVFS_NAME, de->inode.ino, inode, dentry);
 #endif
     d_instantiate (dentry, inode);
-    devfsd_notify_one (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
-		       inode->i_uid, inode->i_gid, fs_info);
+    devfsd_notify_de (de, DEVFSD_NOTIFY_CREATE, inode->i_mode,
+		      inode->i_uid, inode->i_gid, fs_info);
     return 0;
 }   /*  End Function devfs_mknod  */
 
@@ -3021,12 +3069,9 @@
     int err;
     struct devfs_entry *de;
 
-    de = get_devfs_entry_from_vfs_inode (dentry->d_inode, TRUE);
+    de = get_devfs_entry_from_vfs_inode (dentry->d_inode);
     if (!de) return -ENODEV;
-    down_read (&symlink_rwsem);
-    err = de->registered ? vfs_readlink (dentry, buffer, buflen,
-					 de->u.symlink.linkname) : -ENODEV;
-    up_read (&symlink_rwsem);
+    err = vfs_readlink (dentry, buffer, buflen, de->u.symlink.linkname);
     return err;
 }   /*  End Function devfs_readlink  */
 
@@ -3034,25 +3079,10 @@
 {
     int err;
     struct devfs_entry *de;
-    char *copy;
 
-    de = get_devfs_entry_from_vfs_inode (dentry->d_inode, TRUE);
+    de = get_devfs_entry_from_vfs_inode (dentry->d_inode);
     if (!de) return -ENODEV;
-    down_read (&symlink_rwsem);
-    if (!de->registered)
-    {
-	up_read (&symlink_rwsem);
-	return -ENODEV;
-    }
-    copy = kmalloc (de->u.symlink.length + 1, GFP_KERNEL);
-    if (copy) memcpy (copy, de->u.symlink.linkname, de->u.symlink.length + 1);
-    up_read (&symlink_rwsem);
-    if (copy)
-    {
-	err = vfs_follow_link (nd, copy);
-	kfree (copy);
-    }
-    else err = -ENOMEM;
+    err = vfs_follow_link (nd, de->u.symlink.linkname);
     return err;
 }   /*  End Function devfs_follow_link  */
 
@@ -3084,7 +3114,7 @@
 {
     struct inode *root_inode = NULL;
 
-    if (get_root_entry () == NULL) goto out_no_root;
+    if (_devfs_get_root_entry () == NULL) goto out_no_root;
     atomic_set (&fs_info.devfsd_overrun_count, 0);
     init_waitqueue_head (&fs_info.devfsd_wait_queue);
     init_waitqueue_head (&fs_info.revalidate_wait_queue);
@@ -3099,7 +3129,7 @@
     sb->s_root = d_alloc_root (root_inode);
     if (!sb->s_root) goto out_no_root;
 #ifdef CONFIG_DEVFS_DEBUG
-    if (devfs_debug & DEBUG_DISABLED)
+    if (devfs_debug & DEBUG_S_READ)
 	printk ("%s: read super, made devfs ptr: %p\n",
 		DEVFS_NAME, sb->u.generic_sbp);
 #endif
@@ -3123,6 +3153,7 @@
     int done = FALSE;
     int ival;
     loff_t pos, devname_offset, tlen, rpos;
+    devfs_handle_t de;
     struct devfsd_buf_entry *entry;
     struct fs_info *fs_info = file->f_dentry->d_inode->i_sb->u.generic_sbp;
     struct devfsd_notify_struct *info = fs_info->devfsd_info;
@@ -3149,40 +3180,28 @@
 	    current->state = TASK_RUNNING;
 	    return -EINTR;
 	}
-	set_current_state(TASK_INTERRUPTIBLE);
+	set_current_state (TASK_INTERRUPTIBLE);
     }
     remove_wait_queue (&fs_info->devfsd_wait_queue, &wait);
     current->state = TASK_RUNNING;
     /*  Now play with the data  */
     ival = atomic_read (&fs_info->devfsd_overrun_count);
-    if (ival > 0) atomic_sub (ival, &fs_info->devfsd_overrun_count);
     info->overrun_count = ival;
-    entry = (struct devfsd_buf_entry *) fs_info->devfsd_buffer +
-	fs_info->devfsd_buf_out;
+    entry = fs_info->devfsd_first_event;
     info->type = entry->type;
     info->mode = entry->mode;
     info->uid = entry->uid;
     info->gid = entry->gid;
-    if (entry->type == DEVFSD_NOTIFY_LOOKUP)
+    de = entry->de;
+    if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) )
     {
-	info->namelen = strlen (entry->data);
-	pos = 0;
-	memcpy (info->devname, entry->data, info->namelen + 1);
-    }
-    else
-    {
-	devfs_handle_t de = entry->data;
-
-	if ( S_ISCHR (de->mode) || S_ISBLK (de->mode) || S_ISREG (de->mode) )
-	{
-	    info->major = de->u.fcb.u.device.major;
-	    info->minor = de->u.fcb.u.device.minor;
-	}
-	pos = devfs_generate_path (de, info->devname, DEVFS_PATHLEN);
-	if (pos < 0) return pos;
-	info->namelen = DEVFS_PATHLEN - pos - 1;
-	if (info->mode == 0) info->mode = de->mode;
+	info->major = de->u.fcb.u.device.major;
+	info->minor = de->u.fcb.u.device.minor;
     }
+    pos = devfs_generate_path (de, info->devname, DEVFS_PATHLEN);
+    if (pos < 0) return pos;
+    info->namelen = DEVFS_PATHLEN - pos - 1;
+    if (info->mode == 0) info->mode = de->mode;
     devname_offset = info->devname - (char *) info;
     rpos = *ppos;
     if (rpos < devname_offset)
@@ -3214,10 +3233,13 @@
     tlen = rpos - *ppos;
     if (done)
     {
-	unsigned int next_pos = fs_info->devfsd_buf_out + 1;
-
-	if (next_pos >= devfsd_buf_size) next_pos = 0;
-	fs_info->devfsd_buf_out = next_pos;
+	spin_lock (&fs_info->devfsd_buffer_lock);
+	fs_info->devfsd_first_event = entry->next;
+	if (entry->next == NULL) fs_info->devfsd_last_event = NULL;
+	spin_unlock (&fs_info->devfsd_buffer_lock);
+	for (; de != NULL; de = de->parent) devfs_put (de);
+	kmem_cache_free (devfsd_buf_cache, entry);
+	if (ival > 0) atomic_sub (ival, &fs_info->devfsd_overrun_count);
 	*ppos = 0;
     }
     else *ppos = rpos;
@@ -3253,15 +3275,13 @@
 	    fs_info->devfsd_task = current;
 	    spin_unlock (&lock);
 	    fs_info->devfsd_file = file;
-	    fs_info->devfsd_buffer = (void *) __get_free_page (GFP_KERNEL);
 	    fs_info->devfsd_info = kmalloc (sizeof *fs_info->devfsd_info,
 					    GFP_KERNEL);
-	    if (!fs_info->devfsd_buffer || !fs_info->devfsd_info)
+	    if (!fs_info->devfsd_info)
 	    {
 		devfsd_close (inode, file);
 		return -ENOMEM;
 	    }
-	    fs_info->devfsd_buf_out = fs_info->devfsd_buf_in;
 	}
 	else if (fs_info->devfsd_task != current) return -EBUSY;
 	fs_info->devfsd_event_mask = arg;  /*  Let the masses come forth  */
@@ -3284,29 +3304,48 @@
 
 static int devfsd_close (struct inode *inode, struct file *file)
 {
-    unsigned long flags;
+    struct devfsd_buf_entry *entry;
     struct fs_info *fs_info = inode->i_sb->u.generic_sbp;
 
     if (fs_info->devfsd_file != file) return 0;
     fs_info->devfsd_event_mask = 0;
     fs_info->devfsd_file = NULL;
-    spin_lock_irqsave (&fs_info->devfsd_buffer_lock, flags);
-    if (fs_info->devfsd_buffer)
-    {
-	free_page ( (unsigned long) fs_info->devfsd_buffer );
-	fs_info->devfsd_buffer = NULL;
-    }
+    spin_lock (&fs_info->devfsd_buffer_lock);
+    entry = fs_info->devfsd_first_event;
+    fs_info->devfsd_first_event = NULL;
+    fs_info->devfsd_last_event = NULL;
     if (fs_info->devfsd_info)
     {
 	kfree (fs_info->devfsd_info);
 	fs_info->devfsd_info = NULL;
     }
-    spin_unlock_irqrestore (&fs_info->devfsd_buffer_lock, flags);
+    spin_unlock (&fs_info->devfsd_buffer_lock);
     fs_info->devfsd_task = NULL;
     wake_up (&fs_info->revalidate_wait_queue);
+    for (; entry; entry = entry->next)
+	kmem_cache_free (devfsd_buf_cache, entry);
     return 0;
 }   /*  End Function devfsd_close  */
 
+#ifdef CONFIG_DEVFS_DEBUG
+static ssize_t stat_read (struct file *file, char *buf, size_t len,
+			  loff_t *ppos)
+{
+    ssize_t num;
+    char txt[80];
+
+    num = sprintf (txt, "Number of entries: %u  number of bytes: %u\n",
+		   stat_num_entries, stat_num_bytes) + 1;
+    /*  Can't seek (pread) on this device  */
+    if (ppos != &file->f_pos) return -ESPIPE;
+    if (*ppos >= num) return 0;
+    if (*ppos + len > num) len = num - *ppos;
+    if ( copy_to_user (buf, txt + *ppos, len) ) return -EFAULT;
+    *ppos += len;
+    return len;
+}   /*  End Function stat_read  */
+#endif
+
 
 static int __init init_devfs_fs (void)
 {
@@ -3319,6 +3358,9 @@
     printk ("%s: devfs_debug: 0x%0x\n", DEVFS_NAME, devfs_debug);
 #endif
     printk ("%s: boot_options: 0x%0x\n", DEVFS_NAME, boot_options);
+    devfsd_buf_cache = kmem_cache_create ("devfsd_event",
+					  sizeof (struct devfsd_buf_entry),
+					  0, 0, NULL, NULL);
     err = register_filesystem (&devfs_fs_type);
     if (!err)
     {
diff -u --recursive --new-file v2.5.0/linux/fs/dquot.c linux/fs/dquot.c
--- v2.5.0/linux/fs/dquot.c	Thu Nov 22 10:38:31 2001
+++ linux/fs/dquot.c	Mon Dec 10 14:13:25 2001
@@ -408,10 +408,25 @@
 	}
 }
 
+/*
+ * This is called from kswapd when we think we need some
+ * more memory, but aren't really sure how much. So we
+ * carefully try to free a _bit_ of our dqcache, but not
+ * too much.
+ *
+ * Priority:
+ *   1 - very urgent: shrink everything
+ *   ...
+ *   6 - base-level: try to shrink a bit.
+ */
+
 int shrink_dqcache_memory(int priority, unsigned int gfp_mask)
 {
+	int count = 0;
+
 	lock_kernel();
-	prune_dqcache(nr_free_dquots / (priority + 1));
+	count = nr_free_dquots / priority;
+	prune_dqcache(count);
 	unlock_kernel();
 	kmem_cache_shrink(dquot_cachep);
 	return 0;
diff -u --recursive --new-file v2.5.0/linux/fs/driverfs/Makefile linux/fs/driverfs/Makefile
--- v2.5.0/linux/fs/driverfs/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/fs/driverfs/Makefile	Thu Nov 29 16:55:11 2001
@@ -0,0 +1,8 @@
+O_TARGET := driverfs.o
+
+export-objs := inode.o
+
+obj-y := inode.o
+obj-m := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.5.0/linux/fs/driverfs/inode.c linux/fs/driverfs/inode.c
--- v2.5.0/linux/fs/driverfs/inode.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/driverfs/inode.c	Thu Nov 29 16:55:11 2001
@@ -0,0 +1,822 @@
+/*
+ * driverfs.c - The device driver file system
+ *
+ * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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
+ *
+ * This is a simple, ram-based filesystem, which allows kernel
+ * callbacks for read/write of files.
+ *
+ * Please see Documentation/filesystems/driverfs.txt for more information.
+ */
+
+#include <linux/list.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/stat.h>
+#include <linux/fs.h>
+#include <linux/dcache.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/driverfs_fs.h>
+
+#include <asm/uaccess.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+# define DBG(x...) printk(x)
+#else
+# define DBG(x...)
+#endif
+
+/* Random magic number */
+#define DRIVERFS_MAGIC 0x42454552
+
+static struct super_operations driverfs_ops;
+static struct address_space_operations driverfs_aops;
+static struct file_operations driverfs_dir_operations;
+static struct file_operations driverfs_file_operations;
+static struct inode_operations driverfs_dir_inode_operations;
+static struct dentry_operations driverfs_dentry_dir_ops;
+static struct dentry_operations driverfs_dentry_file_ops;
+
+
+static struct vfsmount *driverfs_mount;
+static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
+static int mount_count = 0;
+
+static int driverfs_statfs(struct super_block *sb, struct statfs *buf)
+{
+	buf->f_type = DRIVERFS_MAGIC;
+	buf->f_bsize = PAGE_CACHE_SIZE;
+	buf->f_namelen = 255;
+	return 0;
+}
+
+static struct dentry *driverfs_lookup(struct inode *dir, struct dentry *dentry)
+{
+	d_add(dentry, NULL);
+	return NULL;
+}
+
+struct inode *driverfs_get_inode(struct super_block *sb, int mode, int dev)
+{
+	struct inode *inode = new_inode(sb);
+
+	if (inode) {
+		inode->i_mode = mode;
+		inode->i_uid = current->fsuid;
+		inode->i_gid = current->fsgid;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks = 0;
+		inode->i_rdev = NODEV;
+		inode->i_mapping->a_ops = &driverfs_aops;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		switch (mode & S_IFMT) {
+		default:
+			init_special_inode(inode, mode, dev);
+			break;
+		case S_IFREG:
+			inode->i_fop = &driverfs_file_operations;
+			break;
+		case S_IFDIR:
+			inode->i_op = &driverfs_dir_inode_operations;
+			inode->i_fop = &driverfs_dir_operations;
+			break;
+		}
+	}
+	return inode;
+}
+
+static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
+{
+	struct inode *inode = driverfs_get_inode(dir->i_sb, mode, dev);
+	int error = -ENOSPC;
+
+	if (inode) {
+		d_instantiate(dentry, inode);
+		dget(dentry);
+		error = 0;
+	}
+	return error;
+}
+
+static int driverfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	dentry->d_op = &driverfs_dentry_dir_ops;
+	return driverfs_mknod(dir, dentry, mode | S_IFDIR, 0);
+}
+
+static int driverfs_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	dentry->d_op = &driverfs_dentry_file_ops;
+ 	return driverfs_mknod(dir, dentry, mode | S_IFREG, 0);
+}
+
+static int
+driverfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+{
+	struct inode *inode = old_dentry->d_inode;
+
+	if(S_ISDIR(inode->i_mode))
+		return -EPERM;
+
+	inode->i_nlink++;
+	atomic_inc(&inode->i_count);
+ 	dget(dentry);
+	d_instantiate(dentry, inode);
+	return 0;
+}
+
+static inline int driverfs_positive(struct dentry *dentry)
+{
+	return (dentry->d_inode && !d_unhashed(dentry));
+}
+
+static int driverfs_empty(struct dentry *dentry)
+{
+	struct list_head *list;
+
+	spin_lock(&dcache_lock);
+
+	list_for_each(list, &dentry->d_subdirs) {
+		struct dentry *de = list_entry(list, struct dentry, d_child);
+		if (driverfs_positive(de)) {
+			spin_unlock(&dcache_lock);
+			return 0;
+		}
+	}
+
+	spin_unlock(&dcache_lock);
+	return 1;
+}
+
+static int driverfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	int error = -ENOTEMPTY;
+
+	if (driverfs_empty(dentry)) {
+		struct inode *inode = dentry->d_inode;
+
+		inode->i_nlink--;
+		dput(dentry);
+		error = 0;
+	}
+	return error;
+}
+
+static int
+driverfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+		 struct inode *new_dir, struct dentry *new_dentry)
+{
+	int error = -ENOTEMPTY;
+
+	if (driverfs_empty(new_dentry)) {
+		struct inode *inode = new_dentry->d_inode;
+		if (inode) {
+			inode->i_nlink--;
+			dput(new_dentry);
+		}
+		error = 0;
+	}
+	return error;
+}
+
+static int driverfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
+{
+	int error;
+
+	error = driverfs_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0);
+	if (!error) {
+		int l = strlen(symname) + 1;
+		struct inode *inode = dentry->d_inode;
+		error = block_symlink(inode,symname,l);
+	}
+	return error;
+}
+
+#define driverfs_rmdir driverfs_unlink
+
+/**
+ * driverfs_read_file - "read" data from a file.
+ * @file:	file pointer
+ * @buf:	buffer to fill
+ * @count:	number of bytes to read
+ * @ppos:	starting offset in file
+ *
+ * Userspace wants data from a file. It is up to the creator of the file to
+ * provide that data.
+ * There is a struct driver_file_entry embedded in file->private_data. We
+ * obtain that and check if the read callback is implemented. If so, we call
+ * it, passing the data field of the file entry.
+ * Said callback is responsible for filling the buffer and returning the number
+ * of bytes it put in it. We update @ppos correctly.
+ */
+static ssize_t
+driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+	struct driver_file_entry * entry;
+	unsigned char *page;
+	ssize_t retval = 0;
+
+	entry = (struct driver_file_entry *)file->private_data;
+	if (!entry) {
+		DBG("%s: file entry is NULL\n",__FUNCTION__);
+		return -ENOENT;
+	}
+
+	if (!entry->ops || !entry->ops->read) {
+		DBG("%s: no read callback\n",__FUNCTION__);
+		return -ENOENT;
+	}
+
+	page = (unsigned char*)__get_free_page(GFP_KERNEL);
+	if (!page) {
+		retval = -ENOMEM;
+		goto done;
+	}
+
+	while (count > 0) {
+		ssize_t len;
+
+		len = entry->ops->read(page,count,*ppos,entry->data);
+
+		if (len <= 0) {
+			if (len < 0)
+				retval = len;
+			break;
+		}
+
+		if (copy_to_user(buf,page,len)) {
+			retval = -EFAULT;
+			break;
+		}
+
+		*ppos += len;
+		count -= len;
+		buf += len;
+		retval += len;
+	}
+	free_page((unsigned long)page);
+
+ done:
+	return retval;
+}
+
+/**
+ * driverfs_write_file - "write" to a file
+ * @file:	file pointer
+ * @buf:	data to write
+ * @count:	number of bytes
+ * @ppos:	starting offset
+ *
+ * Similarly to driverfs_read_file, we act essentially as a bit pipe.
+ * We check for a "write" callback in file->private_data, and pass
+ * @buffer, @count, @ppos, and the file entry's data to the callback.
+ * The number of bytes written is returned, and we handle updating
+ * @ppos properly.
+ */
+static ssize_t
+driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+	struct driver_file_entry * entry;
+	ssize_t retval = 0;
+
+	entry = (struct driver_file_entry *)file->private_data;
+	if (!entry) {
+		DBG("%s: file entry is NULL\n",__FUNCTION__);
+		return -ENOENT;
+	}
+
+	if (!entry->ops || !entry->ops->write) {
+		DBG("%s: no write callback\n",__FUNCTION__);
+		retval = -ENOENT;
+		goto done;
+	}
+
+	while (count > 0) {
+		ssize_t len;
+
+		len = entry->ops->write(buf,count,*ppos,entry->data);
+
+		if (len <= 0) {
+			if (len < 0)
+				retval = len;
+			break;
+		}
+		retval += len;
+		count -= len;
+		*ppos += len;
+		buf += len;
+	}
+
+ done:
+	return retval;
+}
+
+static loff_t
+driverfs_file_lseek(struct file *file, loff_t offset, int orig)
+{
+	loff_t retval = -EINVAL;
+
+	switch(orig) {
+	case 0:
+		if (offset > 0) {
+			file->f_pos = offset;
+			retval = file->f_pos;
+		}
+		break;
+	case 1:
+		if ((offset + file->f_pos) > 0) {
+			file->f_pos += offset;
+			retval = file->f_pos;
+		}
+		break;
+	default:
+		break;
+	}
+	return retval;
+}
+
+static int driverfs_open_file(struct inode * inode, struct file * filp)
+{
+	if (filp && inode)
+		filp->private_data = inode->u.generic_ip;
+
+	return 0;
+}
+
+static int driverfs_sync_file (struct file *file, struct dentry *dentry, int datasync)
+{
+	return 0;
+}
+
+/* When the dentry goes away (the refcount hits 0), free the
+ * driver_file_entry for it.
+ */
+static int driverfs_d_delete_file (struct dentry * dentry)
+{
+	struct driver_file_entry * entry;
+
+	entry = (struct driver_file_entry *)dentry->d_fsdata;
+	if (entry)
+		kfree(dentry);
+	return 0;
+}
+
+/* Similar to above - if this dentry goes away, free the
+ * driver_dir_entry associated with it..
+ */
+static int driverfs_d_delete_dir (struct dentry * dentry)
+{
+	struct driver_dir_entry * entry;
+	entry = (struct driver_dir_entry *)dentry->d_fsdata;
+	if (entry)
+		kfree(entry);
+	return 0;
+}
+
+static struct address_space_operations driverfs_aops = {
+
+};
+
+static struct file_operations driverfs_file_operations = {
+	read:		driverfs_read_file,
+	write:		driverfs_write_file,
+	llseek:		driverfs_file_lseek,
+	mmap:		generic_file_mmap,
+	open:		driverfs_open_file,
+	fsync:		driverfs_sync_file,
+};
+
+static struct file_operations driverfs_dir_operations = {
+	read:		generic_read_dir,
+	readdir:	dcache_readdir,
+	fsync:		driverfs_sync_file,
+};
+
+static struct inode_operations driverfs_dir_inode_operations = {
+	create:		driverfs_create,
+	lookup:		driverfs_lookup,
+	link:		driverfs_link,
+	unlink:		driverfs_unlink,
+	symlink:	driverfs_symlink,
+	mkdir:		driverfs_mkdir,
+	rmdir:		driverfs_rmdir,
+	mknod:		driverfs_mknod,
+	rename:		driverfs_rename,
+};
+
+static struct dentry_operations driverfs_dentry_file_ops = {
+	d_delete:	driverfs_d_delete_file,
+};
+
+static struct dentry_operations driverfs_dentry_dir_ops = {
+	d_delete:	driverfs_d_delete_dir,
+};
+
+static struct super_operations driverfs_ops = {
+	statfs:		driverfs_statfs,
+	put_inode:	force_delete,
+};
+
+static struct super_block*
+driverfs_read_super(struct super_block *sb, void *data, int silent)
+{
+	struct inode *inode;
+	struct dentry *root;
+
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	sb->s_magic = DRIVERFS_MAGIC;
+	sb->s_op = &driverfs_ops;
+	inode = driverfs_get_inode(sb, S_IFDIR | 0755, 0);
+
+	if (!inode) {
+		DBG("%s: could not get inode!\n",__FUNCTION__);
+		return NULL;
+	}
+
+	root = d_alloc_root(inode);
+	if (!root) {
+		DBG("%s: could not get root dentry!\n",__FUNCTION__);
+		iput(inode);
+		return NULL;
+	}
+	sb->s_root = root;
+	return sb;
+}
+
+static DECLARE_FSTYPE(driverfs_fs_type, "driverfs", driverfs_read_super, FS_SINGLE | FS_LITTER);
+
+static int get_mount(void)
+{
+	struct vfsmount * mnt;
+
+	spin_lock(&mount_lock);
+	if (driverfs_mount) {
+		mntget(driverfs_mount);
+		++mount_count;
+		spin_unlock(&mount_lock);
+		goto go_ahead;
+	}
+
+	spin_unlock(&mount_lock);
+	mnt = kern_mount(&driverfs_fs_type);
+
+	if (IS_ERR(mnt)) {
+		printk(KERN_ERR "driverfs: could not mount!\n");
+		return -ENODEV;
+	}
+
+	spin_lock(&mount_lock);
+	if (!driverfs_mount) {
+		driverfs_mount = mnt;
+		++mount_count;
+		spin_unlock(&mount_lock);
+		goto go_ahead;
+	}
+
+	mntget(driverfs_mount);
+	++mount_count;
+	spin_unlock(&mount_lock);
+
+ go_ahead:
+	DBG("driverfs: mount_count = %d\n",mount_count);
+	return 0;
+}
+
+static void put_mount(void)
+{
+	struct vfsmount * mnt;
+
+	spin_lock(&mount_lock);
+	mnt = driverfs_mount;
+	--mount_count;
+	if (!mount_count)
+		driverfs_mount = NULL;
+	spin_unlock(&mount_lock);
+	mntput(mnt);
+	DBG("driverfs: mount_count = %d\n",mount_count);
+}
+
+int __init init_driverfs_fs(void)
+{
+	int error;
+
+	DBG("%s: registering filesystem.\n",__FUNCTION__);
+	error = register_filesystem(&driverfs_fs_type);
+
+	if (error)
+		DBG(KERN_ERR "%s: register_filesystem failed with %d\n",
+		       __FUNCTION__,error);
+
+	return error;
+}
+
+static void __exit exit_driverfs_fs(void)
+{
+	unregister_filesystem(&driverfs_fs_type);
+}
+#if 0
+module_init(init_driverfs_fs);
+module_exit(exit_driverfs_fs);
+#endif
+
+EXPORT_SYMBOL(driverfs_create_file);
+EXPORT_SYMBOL(driverfs_create_dir);
+EXPORT_SYMBOL(driverfs_remove_file);
+EXPORT_SYMBOL(driverfs_remove_dir);
+
+MODULE_DESCRIPTION("The device driver filesystem");
+MODULE_LICENSE("GPL");
+
+/**
+ * driverfs_create_dir_entry - allocate and initialise directory entry
+ * @name:	name of the directory
+ * @mode:	permissions of the dir
+ */
+struct driver_dir_entry *
+driverfs_create_dir_entry(const char * name, mode_t mode)
+{
+	struct driver_dir_entry * entry;
+	int size = sizeof(struct driver_dir_entry) + strlen(name) + 1;
+
+
+	entry = kmalloc(size, GFP_KERNEL);
+	if (!entry)
+		return NULL;
+
+	memset(entry, 0, size);
+	strcpy((char *)entry + sizeof(struct driver_dir_entry), name);
+
+	entry->name = (char *)entry + sizeof(struct driver_dir_entry);
+
+	INIT_LIST_HEAD(&entry->files);
+	entry->mode = mode;
+
+	return entry;
+}
+
+/**
+ * driverfs_create_dir - create a directory in the filesystem
+ * @entry:	directory entry
+ * @parent:	parent directory entry
+ */
+int
+driverfs_create_dir(struct driver_dir_entry * entry,
+		    struct driver_dir_entry * parent)
+{
+	struct dentry * dentry = NULL;
+	struct dentry * parent_dentry;
+	struct qstr qstr;
+	int error = 0;
+
+	if (!entry)
+		return -EINVAL;
+
+	get_mount();
+
+	parent_dentry = parent ? parent->dentry : NULL;
+
+	if (!parent_dentry)
+		if (driverfs_mount && driverfs_mount->mnt_sb)
+			parent_dentry = driverfs_mount->mnt_sb->s_root;
+
+	if (!parent_dentry) {
+		put_mount();
+		return -EFAULT;
+	}
+
+	dget(parent_dentry);
+	down(&parent_dentry->d_inode->i_sem);
+
+	qstr.name = entry->name;
+	qstr.len = strlen(entry->name);
+	qstr.hash = full_name_hash(entry->name,qstr.len);
+
+	dentry = lookup_hash(&qstr,parent_dentry);
+	if (IS_ERR(dentry)) {
+		error = PTR_ERR(dentry);
+		up(&parent_dentry->d_inode->i_sem);
+		dput(parent_dentry);
+	} else {
+		dentry->d_fsdata = (void *) entry;
+		entry->dentry = dentry;
+		error = vfs_mkdir(parent_dentry->d_inode,dentry,entry->mode);
+		up(&parent_dentry->d_inode->i_sem);
+	}
+
+	if (error)
+		put_mount();
+	return error;
+}
+
+/**
+ * driverfs_create_file - create a file
+ * @entry:	structure describing the file
+ * @parent:	directory to create it in
+ */
+int
+driverfs_create_file(struct driver_file_entry * entry,
+		     struct driver_dir_entry * parent)
+{
+	struct dentry * dentry;
+	struct dentry * parent_dentry;
+	struct qstr qstr;
+	int error = 0;
+
+	if (!entry || !parent)
+		return -EINVAL;
+
+	/* make sure we're mounted */
+	get_mount();
+
+	if (!parent->dentry) {
+		put_mount();
+		return -EINVAL;
+	}
+
+	/* make sure daddy doesn't run out on us again... */
+	parent_dentry = dget(parent->dentry);
+	down(&parent_dentry->d_inode->i_sem);
+
+	qstr.name = entry->name;
+	qstr.len = strlen(entry->name);
+	qstr.hash = full_name_hash(entry->name,qstr.len);
+
+	dentry = lookup_hash(&qstr,parent_dentry);
+	if (IS_ERR(dentry))
+		error = PTR_ERR(dentry);
+	else
+		error = vfs_create(parent_dentry->d_inode,dentry,entry->mode);
+
+
+	/* Still good? Ok, then fill in the blanks: */
+	if (!error) {
+		dentry->d_fsdata = (void *)entry;
+		dentry->d_inode->u.generic_ip = (void *)entry;
+
+		entry->dentry = dentry;
+
+		list_add_tail(&entry->node,&parent->files);
+	}
+	up(&parent_dentry->d_inode->i_sem);
+
+	if (error) {
+		dput(parent_dentry);
+		put_mount();
+	}
+	return error;
+}
+
+/**
+ * __remove_file - remove a regular file in the filesystem
+ * @dentry:	dentry of file to remove
+ *
+ * Call unlink to remove the file, and dput on the dentry to drop
+ * the refcount.
+ */
+static void __remove_file(struct dentry * dentry)
+{
+	dget(dentry);
+	down(&dentry->d_inode->i_sem);
+
+	vfs_unlink(dentry->d_parent->d_inode,dentry);
+
+	unlock_dir(dentry);
+
+	/* remove reference count from when file was created */
+	dput(dentry);
+
+	put_mount();
+}
+
+/**
+ * driverfs_remove_file - exported file removal
+ * @dir:	directory the file supposedly resides in
+ * @name:	name of the file
+ *
+ * Try and find the file in the dir's list.
+ * If it's there, call __remove_file() (above) for the dentry.
+ */
+void driverfs_remove_file(struct driver_dir_entry * dir, const char * name)
+{
+	struct dentry * dentry;
+	struct list_head * node;
+
+	if (!dir->dentry)
+		return;
+
+	dentry = dget(dir->dentry);
+	down(&dentry->d_inode->i_sem);
+
+	node = dir->files.next;
+	while (node != &dir->files) {
+		struct driver_file_entry * entry = NULL;
+
+		entry = list_entry(node,struct driver_file_entry,node);
+		if (!strcmp(entry->name,name)) {
+			list_del_init(node);
+
+			__remove_file(entry->dentry);
+			break;
+		}
+		node = node->next;
+	}
+	unlock_dir(dentry);
+}
+
+/**
+ * driverfs_remove_dir - exportable directory removal
+ * @dir:	directory to remove
+ *
+ * To make sure we don't orphan anyone, first remove
+ * all the children in the list, then do vfs_rmdir() to remove it
+ * and decrement the refcount..
+ */
+void driverfs_remove_dir(struct driver_dir_entry * dir)
+{
+	struct list_head * node;
+	struct dentry * dentry;
+
+	if (!dir->dentry)
+		goto done;
+
+	/* lock the directory while we remove the files */
+	dentry = dget(dir->dentry);
+	down(&dentry->d_inode->i_sem);
+
+	node = dir->files.next;
+	while (node != &dir->files) {
+		struct driver_file_entry * entry;
+		entry = list_entry(node,struct driver_file_entry,node);
+
+		list_del_init(node);
+
+		__remove_file(entry->dentry);
+
+		node = dir->files.next;
+	}
+
+	/* now lock the parent, so we can remove this directory */
+	lock_parent(dentry);
+
+	vfs_rmdir(dentry->d_parent->d_inode,dentry);
+	double_unlock(dentry,dentry->d_parent);
+
+	/* remove reference count from when directory was created */
+	dput(dentry);
+ done:
+	put_mount();
+}
+
+/**
+ * driverfs_create_entry - allocate and initialise a struct driver_file_entry
+ * @name:	name of the file
+ * @mode:	permissions of the file
+ * @ops:	Operations for the file
+ * @data:	data that will be passed back to the callback
+ *
+ */
+struct driver_file_entry *
+driverfs_create_entry (const char * name, mode_t mode,
+		       struct driverfs_operations * ops, void * data)
+{
+	struct driver_file_entry * entry;
+	int size;
+
+	size = sizeof(struct driver_file_entry) + strlen(name) + 1;
+
+	entry = kmalloc(size,GFP_KERNEL);
+	if (!entry)
+		return NULL;
+
+	memset(entry, 0, size);
+	strcpy((char *)entry + sizeof(struct driver_file_entry), name);
+
+	entry->name = (char *)entry + sizeof(struct driver_file_entry);
+
+	INIT_LIST_HEAD(&entry->node);
+
+	entry->mode = mode;
+	entry->ops = ops;
+	entry->data = data;
+
+	return entry;
+}
+
diff -u --recursive --new-file v2.5.0/linux/fs/exec.c linux/fs/exec.c
--- v2.5.0/linux/fs/exec.c	Fri Nov  2 17:39:20 2001
+++ linux/fs/exec.c	Wed Nov 28 09:30:47 2001
@@ -586,7 +586,7 @@
 flush_failed:
 	spin_lock_irq(&current->sigmask_lock);
 	if (current->sig != oldsig) {
-		kfree(current->sig);
+		kmem_cache_free(sigact_cachep, current->sig);
 		current->sig = oldsig;
 	}
 	spin_unlock_irq(&current->sigmask_lock);
diff -u --recursive --new-file v2.5.0/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.5.0/linux/fs/ext2/inode.c	Wed Nov 21 14:07:25 2001
+++ linux/fs/ext2/inode.c	Tue Nov 27 09:23:27 2001
@@ -505,7 +505,7 @@
  * reachable from inode.
  */
 
-static int ext2_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
+static int ext2_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
 {
 	int err = -EIO;
 	int offsets[4];
diff -u --recursive --new-file v2.5.0/linux/fs/ext3/inode.c linux/fs/ext3/inode.c
--- v2.5.0/linux/fs/ext3/inode.c	Fri Nov  9 14:25:04 2001
+++ linux/fs/ext3/inode.c	Tue Nov 27 09:23:27 2001
@@ -719,7 +719,7 @@
  */
 
 static int ext3_get_block_handle(handle_t *handle, struct inode *inode, 
-				 long iblock,
+				 sector_t iblock,
 				 struct buffer_head *bh_result, int create)
 {
 	int err = -EIO;
@@ -823,7 +823,7 @@
 	goto reread;
 }
 
-static int ext3_get_block(struct inode *inode, long iblock,
+static int ext3_get_block(struct inode *inode, sector_t iblock,
 			struct buffer_head *bh_result, int create)
 {
 	handle_t *handle = 0;
diff -u --recursive --new-file v2.5.0/linux/fs/fat/file.c linux/fs/fat/file.c
--- v2.5.0/linux/fs/fat/file.c	Sun Aug 12 10:56:56 2001
+++ linux/fs/fat/file.c	Fri Nov 30 08:30:48 2001
@@ -48,7 +48,7 @@
 }
 
 
-int fat_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
+int fat_get_block(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create)
 {
 	struct super_block *sb = inode->i_sb;
 	unsigned long phys;
diff -u --recursive --new-file v2.5.0/linux/fs/inode.c linux/fs/inode.c
--- v2.5.0/linux/fs/inode.c	Thu Nov 22 10:38:31 2001
+++ linux/fs/inode.c	Mon Dec 10 14:13:25 2001
@@ -707,7 +707,17 @@
 	if (goal)
 		schedule_task(&unused_inodes_flush_task);
 }
-
+/*
+ * This is called from kswapd when we think we need some
+ * more memory, but aren't really sure how much. So we
+ * carefully try to free a _bit_ of our icache, but not
+ * too much.
+ *
+ * Priority:
+ *   1 - very urgent: shrink everything
+ *  ...
+ *   6 - base-level: try to shrink a bit.
+ */
 int shrink_icache_memory(int priority, int gfp_mask)
 {
 	int count = 0;
@@ -1065,24 +1075,27 @@
 			if (inode->i_state != I_CLEAR)
 				BUG();
 		} else {
-			if (!list_empty(&inode->i_hash) && sb && sb->s_root) {
+			if (!list_empty(&inode->i_hash)) {
 				if (!(inode->i_state & (I_DIRTY|I_LOCK))) {
 					list_del(&inode->i_list);
 					list_add(&inode->i_list, &inode_unused);
 				}
 				inodes_stat.nr_unused++;
 				spin_unlock(&inode_lock);
-				return;
-			} else {
-				list_del_init(&inode->i_list);
+				if (!sb || sb->s_flags & MS_ACTIVE)
+					return;
+				write_inode_now(inode, 1);
+				spin_lock(&inode_lock);
+				inodes_stat.nr_unused--;
 				list_del_init(&inode->i_hash);
-				inode->i_state|=I_FREEING;
-				inodes_stat.nr_inodes--;
-				spin_unlock(&inode_lock);
-				if (inode->i_data.nrpages)
-					truncate_inode_pages(&inode->i_data, 0);
-				clear_inode(inode);
 			}
+			list_del_init(&inode->i_list);
+			inode->i_state|=I_FREEING;
+			inodes_stat.nr_inodes--;
+			spin_unlock(&inode_lock);
+			if (inode->i_data.nrpages)
+				truncate_inode_pages(&inode->i_data, 0);
+			clear_inode(inode);
 		}
 		destroy_inode(inode);
 	}
@@ -1173,6 +1186,16 @@
 	unused_inodes_flush_task.routine = try_to_sync_unused_inodes;
 }
 
+static inline void do_atime_update(struct inode *inode)
+{
+	unsigned long time = CURRENT_TIME;
+	if (inode->i_atime != time) {
+		inode->i_atime = time;
+		mark_inode_dirty_sync(inode);
+	}
+}
+
+
 /**
  *	update_atime	-	update the access time
  *	@inode: inode accessed
@@ -1187,8 +1210,7 @@
 	if ( IS_NOATIME (inode) ) return;
 	if ( IS_NODIRATIME (inode) && S_ISDIR (inode->i_mode) ) return;
 	if ( IS_RDONLY (inode) ) return;
-	inode->i_atime = CURRENT_TIME;
-	mark_inode_dirty_sync (inode);
+	do_atime_update(inode);
 }   /*  End Function update_atime  */
 
 
diff -u --recursive --new-file v2.5.0/linux/fs/iobuf.c linux/fs/iobuf.c
--- v2.5.0/linux/fs/iobuf.c	Fri Apr 27 14:23:25 2001
+++ linux/fs/iobuf.c	Tue Nov 27 09:23:27 2001
@@ -8,70 +8,45 @@
 
 #include <linux/iobuf.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 
-void end_kio_request(struct kiobuf *kiobuf, int uptodate)
+int end_kio_request(struct kiobuf *kiobuf, int uptodate)
 {
+	int ret = 1;
+
 	if ((!uptodate) && !kiobuf->errno)
 		kiobuf->errno = -EIO;
 
 	if (atomic_dec_and_test(&kiobuf->io_count)) {
+		ret = 0;
 		if (kiobuf->end_io)
 			kiobuf->end_io(kiobuf);
 		wake_up(&kiobuf->wait_queue);
 	}
+
+	return ret;
 }
 
 static void kiobuf_init(struct kiobuf *iobuf)
 {
 	memset(iobuf, 0, sizeof(*iobuf));
 	init_waitqueue_head(&iobuf->wait_queue);
+	atomic_set(&iobuf->io_count, 0);
 	iobuf->array_len = KIO_STATIC_PAGES;
 	iobuf->maplist   = iobuf->map_array;
 }
 
-int alloc_kiobuf_bhs(struct kiobuf * kiobuf)
-{
-	int i;
-
-	for (i = 0; i < KIO_MAX_SECTORS; i++)
-		if (!(kiobuf->bh[i] = kmem_cache_alloc(bh_cachep, SLAB_KERNEL))) {
-			while (i--) {
-				kmem_cache_free(bh_cachep, kiobuf->bh[i]);
-				kiobuf->bh[i] = NULL;
-			}
-			return -ENOMEM;
-		}
-	return 0;
-}
-
-void free_kiobuf_bhs(struct kiobuf * kiobuf)
-{
-	int i;
-
-	for (i = 0; i < KIO_MAX_SECTORS; i++) {
-		kmem_cache_free(bh_cachep, kiobuf->bh[i]);
-		kiobuf->bh[i] = NULL;
-	}
-}
-
 int alloc_kiovec(int nr, struct kiobuf **bufp)
 {
 	int i;
 	struct kiobuf *iobuf;
 	
 	for (i = 0; i < nr; i++) {
-		iobuf = vmalloc(sizeof(struct kiobuf));
+		iobuf = kmalloc(sizeof(struct kiobuf), GFP_KERNEL);
 		if (!iobuf) {
 			free_kiovec(i, bufp);
 			return -ENOMEM;
 		}
 		kiobuf_init(iobuf);
- 		if (alloc_kiobuf_bhs(iobuf)) {
-			vfree(iobuf);
- 			free_kiovec(i, bufp);
- 			return -ENOMEM;
- 		}
 		bufp[i] = iobuf;
 	}
 	
@@ -89,8 +64,7 @@
 			unlock_kiovec(1, &iobuf);
 		if (iobuf->array_len > KIO_STATIC_PAGES)
 			kfree (iobuf->maplist);
-		free_kiobuf_bhs(iobuf);
-		vfree(bufp[i]);
+		kfree(bufp[i]);
 	}
 }
 
diff -u --recursive --new-file v2.5.0/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.5.0/linux/fs/isofs/inode.c	Thu Oct 25 13:53:53 2001
+++ linux/fs/isofs/inode.c	Tue Nov 27 09:23:27 2001
@@ -888,7 +888,7 @@
  * or getblk() if they are not.  Returns the number of blocks inserted
  * (0 == error.)
  */
-int isofs_get_blocks(struct inode *inode, long iblock,
+int isofs_get_blocks(struct inode *inode, sector_t iblock,
 		     struct buffer_head **bh_result, unsigned long nblocks)
 {
 	unsigned long b_off;
@@ -976,7 +976,7 @@
 /*
  * Used by the standard interfaces.
  */
-static int isofs_get_block(struct inode *inode, long iblock,
+static int isofs_get_block(struct inode *inode, sector_t iblock,
 		    struct buffer_head *bh_result, int create)
 {
 	if ( create ) {
diff -u --recursive --new-file v2.5.0/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.5.0/linux/fs/minix/inode.c	Sun Sep 30 12:26:08 2001
+++ linux/fs/minix/inode.c	Wed Nov 28 08:49:23 2001
@@ -292,7 +292,7 @@
 	return 0;
 }
 
-static int minix_get_block(struct inode *inode, long block,
+static int minix_get_block(struct inode *inode, sector_t block,
 		    struct buffer_head *bh_result, int create)
 {
 	if (INODE_VERSION(inode) == MINIX_V1)
diff -u --recursive --new-file v2.5.0/linux/fs/minix/itree_common.c linux/fs/minix/itree_common.c
--- v2.5.0/linux/fs/minix/itree_common.c	Fri Sep  7 09:45:51 2001
+++ linux/fs/minix/itree_common.c	Fri Nov 30 08:30:33 2001
@@ -140,7 +140,7 @@
 	return -EAGAIN;
 }
 
-static inline int get_block(struct inode * inode, long block,
+static inline int get_block(struct inode * inode, sector_t block,
 			struct buffer_head *bh_result, int create)
 {
 	int err = -EIO;
diff -u --recursive --new-file v2.5.0/linux/fs/namei.c linux/fs/namei.c
--- v2.5.0/linux/fs/namei.c	Wed Oct 17 14:46:29 2001
+++ linux/fs/namei.c	Fri Nov 30 08:41:52 2001
@@ -434,6 +434,8 @@
 		mntput(nd->mnt);
 		nd->mnt = parent;
 	}
+	while (d_mountpoint(nd->dentry) && __follow_down(&nd->mnt, &nd->dentry))
+		;
 }
 
 /*
diff -u --recursive --new-file v2.5.0/linux/fs/namespace.c linux/fs/namespace.c
--- v2.5.0/linux/fs/namespace.c	Sun Nov 11 11:23:14 2001
+++ linux/fs/namespace.c	Fri Dec  7 16:24:52 2001
@@ -15,15 +15,10 @@
 #include <linux/quotaops.h>
 #include <linux/acct.h>
 #include <linux/module.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/seq_file.h>
 
 #include <asm/uaccess.h>
 
-#include <linux/nfs_fs.h>
-#include <linux/nfs_fs_sb.h>
-#include <linux/nfs_mount.h>
-#include <linux/seq_file.h>
-
 struct vfsmount *do_kern_mount(char *type, int flags, char *name, void *data);
 int do_remount_sb(struct super_block *sb, int flags, void * data);
 void kill_super(struct super_block *sb);
@@ -34,9 +29,7 @@
 
 static LIST_HEAD(vfsmntlist);
 static DECLARE_MUTEX(mount_sem);
-
-/* Will be static */
-struct vfsmount *root_vfsmnt;
+static struct vfsmount *root_vfsmnt;
 
 static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry)
 {
@@ -198,50 +191,10 @@
 	seq_escape(m, s, " \t\n\\");
 }
 
-static void show_nfs_mount(struct seq_file *m, struct vfsmount *mnt)
-{
-	static struct proc_nfs_info {
-		int flag;
-		char *str;
-		char *nostr;
-	} nfs_info[] = {
-		{ NFS_MOUNT_SOFT, ",soft", ",hard" },
-		{ NFS_MOUNT_INTR, ",intr", "" },
-		{ NFS_MOUNT_POSIX, ",posix", "" },
-		{ NFS_MOUNT_TCP, ",tcp", ",udp" },
-		{ NFS_MOUNT_NOCTO, ",nocto", "" },
-		{ NFS_MOUNT_NOAC, ",noac", "" },
-		{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
-		{ NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
-		{ 0, NULL, NULL }
-	};
-	struct proc_nfs_info *nfs_infop;
-	struct nfs_server *nfss = &mnt->mnt_sb->u.nfs_sb.s_server;
-
-	seq_printf(m, ",v%d", nfss->rpc_ops->version);
-	seq_printf(m, ",rsize=%d", nfss->rsize);
-	seq_printf(m, ",wsize=%d", nfss->wsize);
-	if (nfss->acregmin != 3*HZ)
-		seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
-	if (nfss->acregmax != 60*HZ)
-		seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
-	if (nfss->acdirmin != 30*HZ)
-		seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
-	if (nfss->acdirmax != 60*HZ)
-		seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
-	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
-		if (nfss->flags & nfs_infop->flag)
-			seq_puts(m, nfs_infop->str);
-		else
-			seq_puts(m, nfs_infop->nostr);
-	}
-	seq_puts(m, ",addr=");
-	mangle(m, nfss->hostname);
-}
-
 static int show_vfsmnt(struct seq_file *m, void *v)
 {
 	struct vfsmount *mnt = v;
+	int err = 0;
 	static struct proc_fs_info {
 		int flag;
 		char *str;
@@ -281,10 +234,10 @@
 		if (mnt->mnt_flags & fs_infop->flag)
 			seq_puts(m, fs_infop->str);
 	}
-	if (strcmp("nfs", mnt->mnt_sb->s_type->name) == 0)
-		show_nfs_mount(m, mnt);
+	if (mnt->mnt_sb->s_op->show_options)
+		err = mnt->mnt_sb->s_op->show_options(m, mnt);
 	seq_puts(m, " 0 0\n");
-	return 0;
+	return err;
 }
 
 struct seq_operations mounts_op = {
@@ -505,8 +458,7 @@
 	return NULL;
 }
 
-/* Will become static */
-int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
+static int graft_tree(struct vfsmount *mnt, struct nameidata *nd)
 {
 	int err;
 	if (mnt->mnt_sb->s_flags & MS_NOUSER)
@@ -604,6 +556,67 @@
 	return err;
 }
 
+static int do_move_mount(struct nameidata *nd, char *old_name)
+{
+	struct nameidata old_nd, parent_nd;
+	struct vfsmount *p;
+	int err = 0;
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	if (!old_name || !*old_name)
+		return -EINVAL;
+	if (path_init(old_name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &old_nd))
+		err = path_walk(old_name, &old_nd);
+	if (err)
+		return err;
+
+	down(&mount_sem);
+	while(d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry))
+		;
+	err = -EINVAL;
+	if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt))
+		goto out;
+
+	err = -ENOENT;
+	down(&nd->dentry->d_inode->i_zombie);
+	if (IS_DEADDIR(nd->dentry->d_inode))
+		goto out1;
+
+	spin_lock(&dcache_lock);
+	if (!IS_ROOT(nd->dentry) && d_unhashed(nd->dentry))
+		goto out2;
+
+	err = -EINVAL;
+	if (old_nd.dentry != old_nd.mnt->mnt_root)
+		goto out2;
+
+	if (old_nd.mnt == old_nd.mnt->mnt_parent)
+		goto out2;
+
+	if (S_ISDIR(nd->dentry->d_inode->i_mode) !=
+	      S_ISDIR(old_nd.dentry->d_inode->i_mode))
+		goto out2;
+
+	err = -ELOOP;
+	for (p = nd->mnt; p->mnt_parent!=p; p = p->mnt_parent)
+		if (p == old_nd.mnt)
+			goto out2;
+	err = 0;
+
+	detach_mnt(old_nd.mnt, &parent_nd);
+	attach_mnt(old_nd.mnt, nd);
+out2:
+	spin_unlock(&dcache_lock);
+out1:
+	up(&nd->dentry->d_inode->i_zombie);
+out:
+	up(&mount_sem);
+	if (!err)
+		path_release(&parent_nd);
+	path_release(&old_nd);
+	return err;
+}
+
 static int do_add_mount(struct nameidata *nd, char *type, int flags,
 			int mnt_flags, char *name, void *data)
 {
@@ -720,6 +733,8 @@
 				    data_page);
 	else if (flags & MS_BIND)
 		retval = do_loopback(&nd, dev_name, flags & MS_REC);
+	else if (flags & MS_MOVE)
+		retval = do_move_mount(&nd, dev_name);
 	else
 		retval = do_add_mount(&nd, type_page, flags, mnt_flags,
 				      dev_name, data_page);
@@ -908,6 +923,44 @@
  * In 2.5 we'll use ramfs or tmpfs, but for now it's all we need - just
  * something to go with root vfsmount.
  */
+static struct inode_operations rootfs_dir_inode_operations;
+static struct file_operations rootfs_dir_operations;
+static int rootfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	struct inode * inode = new_inode(dir->i_sb);
+	int error = -ENOSPC;
+	if (inode) {
+		inode->i_mode = S_IFDIR|mode;
+		inode->i_uid = current->fsuid;
+		inode->i_gid = current->fsgid;
+		inode->i_op = &rootfs_dir_inode_operations;
+		inode->i_fop = &rootfs_dir_operations;
+		d_instantiate(dentry, inode);
+		dget(dentry);
+		error = 0;
+	}
+	return error;
+}
+static int rootfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
+{
+	struct inode * inode = new_inode(dir->i_sb);
+	int error = -ENOSPC;
+	if (inode) {
+		inode->i_uid = current->fsuid;
+		inode->i_gid = current->fsgid;
+		init_special_inode(inode, mode, dev);
+		d_instantiate(dentry, inode);
+		dget(dentry);
+		error = 0;
+	}
+	return error;
+}
+static int rootfs_unlink(struct inode * dir, struct dentry *dentry)
+{
+	dentry->d_inode->i_nlink--;
+	dput(dentry);
+	return 0;
+}
 static struct dentry *rootfs_lookup(struct inode *dir, struct dentry *dentry)
 {
 	d_add(dentry, NULL);
@@ -919,6 +972,9 @@
 };
 static struct inode_operations rootfs_dir_inode_operations = {
 	lookup:		rootfs_lookup,
+	mkdir:		rootfs_mkdir,
+	mknod:		rootfs_mknod,
+	unlink:		rootfs_unlink,
 };
 static struct super_block *rootfs_read_super(struct super_block * sb, void * data, int silent)
 {
@@ -949,6 +1005,8 @@
 	root_vfsmnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
 	if (IS_ERR(root_vfsmnt))
 		panic("can't allocate root vfsmount");
+	set_fs_pwd(current->fs, root_vfsmnt, root_vfsmnt->mnt_root);
+	set_fs_root(current->fs, root_vfsmnt, root_vfsmnt->mnt_root);
 }
 
 void __init mnt_init(unsigned long mempages)
@@ -1008,91 +1066,3 @@
 	} while (i);
 	init_mount_tree();
 }
-
-#ifdef CONFIG_BLK_DEV_INITRD
-
-int __init change_root(kdev_t new_root_dev,const char *put_old)
-{
-	struct vfsmount *old_rootmnt;
-	struct nameidata devfs_nd, nd;
-	struct nameidata parent_nd;
-	char *new_devname = kmalloc(strlen("/dev/root.old")+1, GFP_KERNEL);
-	int error = 0;
-
-	if (new_devname)
-		strcpy(new_devname, "/dev/root.old");
-
-	read_lock(&current->fs->lock);
-	old_rootmnt = mntget(current->fs->rootmnt);
-	read_unlock(&current->fs->lock);
-	/*  First unmount devfs if mounted  */
-	if (path_init("/dev", LOOKUP_FOLLOW|LOOKUP_POSITIVE, &devfs_nd))
-		error = path_walk("/dev", &devfs_nd);
-	if (!error) {
-		if (devfs_nd.mnt->mnt_sb->s_magic == DEVFS_SUPER_MAGIC &&
-		    devfs_nd.dentry == devfs_nd.mnt->mnt_root) {
-			do_umount(devfs_nd.mnt, 0);
-		}
-		path_release(&devfs_nd);
-	}
-	spin_lock(&dcache_lock);
-	detach_mnt(old_rootmnt, &parent_nd);
-	spin_unlock(&dcache_lock);
-	ROOT_DEV = new_root_dev;
-	mount_root();
-#if 1
-	shrink_dcache();
-	printk("change_root: old root has d_count=%d\n", 
-	       atomic_read(&old_rootmnt->mnt_root->d_count));
-#endif
-	mount_devfs_fs ();
-	/*
-	 * Get the new mount directory
-	 */
-	error = 0;
-	if (path_init(put_old, LOOKUP_FOLLOW|LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &nd))
-		error = path_walk(put_old, &nd);
-	if (error) {
-		int blivet;
-		struct block_device *ramdisk = old_rootmnt->mnt_sb->s_bdev;
-
-		atomic_inc(&ramdisk->bd_count);
-		blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS);
-		printk(KERN_NOTICE "Trying to unmount old root ... ");
-		if (!blivet) {
-			spin_lock(&dcache_lock);
-			list_del_init(&old_rootmnt->mnt_list);
- 			spin_unlock(&dcache_lock);
- 			mntput(old_rootmnt);
-			mntput(old_rootmnt);
-			blivet = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
-			path_release(&parent_nd);
-			blkdev_put(ramdisk, BDEV_FS);
-		}
-		if (blivet) {
-			printk(KERN_ERR "error %d\n", blivet);
-		} else {
-			printk("okay\n");
-			error = 0;
-		}			
-		kfree(new_devname);
-		return error;
-	}
-
-	spin_lock(&dcache_lock);
-	attach_mnt(old_rootmnt, &nd);
-	if (new_devname) {
-		if (old_rootmnt->mnt_devname)
-			kfree(old_rootmnt->mnt_devname);
-		old_rootmnt->mnt_devname = new_devname;
-	}
-	spin_unlock(&dcache_lock);
-
-	/* put the old stuff */
-	path_release(&parent_nd);
-	mntput(old_rootmnt);
-	path_release(&nd);
-	return 0;
-}
-
-#endif
diff -u --recursive --new-file v2.5.0/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.5.0/linux/fs/nfs/inode.c	Fri Nov  9 14:28:15 2001
+++ linux/fs/nfs/inode.c	Sat Nov 24 13:17:18 2001
@@ -32,6 +32,7 @@
 #include <linux/nfs_flushd.h>
 #include <linux/lockd/bind.h>
 #include <linux/smp_lock.h>
+#include <linux/seq_file.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -51,6 +52,7 @@
 static void nfs_clear_inode(struct inode *);
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct super_block *, struct statfs *);
+static int  nfs_show_options(struct seq_file *, struct vfsmount *);
 
 static struct super_operations nfs_sops = { 
 	read_inode:	nfs_read_inode,
@@ -60,6 +62,7 @@
 	statfs:		nfs_statfs,
 	clear_inode:	nfs_clear_inode,
 	umount_begin:	nfs_umount_begin,
+	show_options:	nfs_show_options,
 };
 
 /*
@@ -551,6 +554,48 @@
  out_err:
 	printk("nfs_statfs: statfs error = %d\n", -error);
 	buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;
+	return 0;
+}
+
+static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+	static struct proc_nfs_info {
+		int flag;
+		char *str;
+		char *nostr;
+	} nfs_info[] = {
+		{ NFS_MOUNT_SOFT, ",soft", ",hard" },
+		{ NFS_MOUNT_INTR, ",intr", "" },
+		{ NFS_MOUNT_POSIX, ",posix", "" },
+		{ NFS_MOUNT_TCP, ",tcp", ",udp" },
+		{ NFS_MOUNT_NOCTO, ",nocto", "" },
+		{ NFS_MOUNT_NOAC, ",noac", "" },
+		{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
+		{ NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
+		{ 0, NULL, NULL }
+	};
+	struct proc_nfs_info *nfs_infop;
+	struct nfs_server *nfss = &mnt->mnt_sb->u.nfs_sb.s_server;
+
+	seq_printf(m, ",v%d", nfss->rpc_ops->version);
+	seq_printf(m, ",rsize=%d", nfss->rsize);
+	seq_printf(m, ",wsize=%d", nfss->wsize);
+	if (nfss->acregmin != 3*HZ)
+		seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);
+	if (nfss->acregmax != 60*HZ)
+		seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);
+	if (nfss->acdirmin != 30*HZ)
+		seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);
+	if (nfss->acdirmax != 60*HZ)
+		seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);
+	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {
+		if (nfss->flags & nfs_infop->flag)
+			seq_puts(m, nfs_infop->str);
+		else
+			seq_puts(m, nfs_infop->nostr);
+	}
+	seq_puts(m, ",addr=");
+	seq_escape(m, nfss->hostname, " \t\n\\");
 	return 0;
 }
 
diff -u --recursive --new-file v2.5.0/linux/fs/ntfs/Makefile linux/fs/ntfs/Makefile
--- v2.5.0/linux/fs/ntfs/Makefile	Sun Sep 30 11:42:44 2001
+++ linux/fs/ntfs/Makefile	Mon Dec 10 19:37:38 2001
@@ -5,7 +5,7 @@
 obj-y   := fs.o sysctl.o support.o util.o inode.o dir.o super.o attr.o unistr.o
 obj-m   := $(O_TARGET)
 # New version format started 3 February 2001.
-EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.20\" #-DDEBUG
+EXTRA_CFLAGS = -DNTFS_VERSION=\"1.1.21\" #-DDEBUG
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v2.5.0/linux/fs/ntfs/attr.c linux/fs/ntfs/attr.c
--- v2.5.0/linux/fs/ntfs/attr.c	Sat Sep  8 12:24:40 2001
+++ linux/fs/ntfs/attr.c	Mon Dec 10 19:37:38 2001
@@ -548,7 +548,7 @@
  * attribute.
  */
 static int ntfs_process_runs(ntfs_inode *ino, ntfs_attribute* attr,
-			     unsigned char *data)
+		unsigned char *data)
 {
 	int startvcn, endvcn;
 	int vcn, cnum;
@@ -622,7 +622,7 @@
 }
   
 /* Insert the attribute starting at attr in the inode ino. */
-int ntfs_insert_attribute(ntfs_inode *ino, unsigned char* attrdata)
+int ntfs_insert_attribute(ntfs_inode *ino, unsigned char *attrdata)
 {
 	int i, found;
 	int type;
diff -u --recursive --new-file v2.5.0/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.5.0/linux/fs/ntfs/fs.c	Thu Oct 25 00:02:26 2001
+++ linux/fs/ntfs/fs.c	Mon Dec 10 19:37:38 2001
@@ -303,10 +303,8 @@
 	ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After ntfs_getdir_unsorted()"
 			" calls, f_pos 0x%Lx.\n", filp->f_pos);
 	if (!err) {
-#ifdef DEBUG
-		if (cb.ph != 0x7fff || cb.pl)
-			BUG();
 done:
+#ifdef DEBUG
 		if (!cb.ret_code)
 			ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): EOD, f_pos "
 					"0x%Lx, returning 0.\n", filp->f_pos);
@@ -314,8 +312,6 @@
 			ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): filldir "
 					"returned %i, returning 0, f_pos "
 					"0x%Lx.\n", cb.ret_code, filp->f_pos);
-#else
-done:
 #endif
 		return 0;
 	}
diff -u --recursive --new-file v2.5.0/linux/fs/ntfs/inode.c linux/fs/ntfs/inode.c
--- v2.5.0/linux/fs/ntfs/inode.c	Sun Sep 30 11:42:44 2001
+++ linux/fs/ntfs/inode.c	Mon Dec 10 19:37:38 2001
@@ -159,7 +159,7 @@
  * Return 0 on success or -errno on error.
  */
 static int ntfs_insert_mft_attribute(ntfs_inode* ino, int mftno,
-				     ntfs_u8 *attr)
+		ntfs_u8 *attr)
 {
 	int i, error, present = 0;
 
@@ -207,6 +207,7 @@
 	int mftno, l, error;
 	int last_mft = -1;
 	int len = *plen;
+	int tries = 0;
 	
 	if (!ino->attr) {
 		ntfs_error("parse_attributes: called on inode 0x%x without a "
@@ -230,9 +231,13 @@
 			*   then occur there or the user notified to run
 			*   ntfsck. (AIA) */
 		if (mftno != ino->i_number && mftno != last_mft) {
+continue_after_loading_mft_data:
 			last_mft = mftno;
 			error = ntfs_read_mft_record(ino->vol, mftno, mft);
 			if (error) {
+				if (error == -EINVAL && !tries)
+					goto force_load_mft_data;
+failed_reading_mft_data:
 				ntfs_debug(DEBUG_FILE3, "parse_attributes: "
 					"ntfs_read_mft_record(mftno = 0x%x) "
 					"failed\n", mftno);
@@ -272,9 +277,106 @@
 	ntfs_free(mft);
 	*plen = len;
 	return 0;
+force_load_mft_data:
+{
+	ntfs_u8 *mft2, *attr2;
+	int mftno2;
+	int last_mft2 = last_mft;
+	int len2 = len;
+	int error2;
+	int found2 = 0;
+	ntfs_u8 *alist2 = alist;
+	/*
+	 * We only get here if $DATA wasn't found in $MFT which only happens
+	 * on volume mount when $MFT has an attribute list and there are
+	 * attributes before $DATA which are inside extent mft records. So
+	 * we just skip forward to the $DATA attribute and read that. Then we
+	 * restart which is safe as an attribute will not be inserted twice.
+	 *
+	 * This still will not fix the case where the attribute list is non-
+	 * resident, larger than 1024 bytes, and the $DATA attribute list entry
+	 * is not in the first 1024 bytes. FIXME: This should be implemented
+	 * somehow! Perhaps by passing special error code up to
+	 * ntfs_load_attributes() so it keeps going trying to get to $DATA
+	 * regardless. Then it would have to restart just like we do here.
+	 */
+	mft2 = ntfs_malloc(ino->vol->mft_record_size);
+	if (!mft2) {
+		ntfs_free(mft);
+		return -ENOMEM;
+	}
+	ntfs_memcpy(mft2, mft, ino->vol->mft_record_size);
+	while (len2 > 8) {
+		l = NTFS_GETU16(alist2 + 4);
+		if (l > len2)
+			break;
+		if (NTFS_GETU32(alist2 + 0x0) < ino->vol->at_data) {
+			len2 -= l;
+			alist2 += l;
+			continue;
+		}
+		if (NTFS_GETU32(alist2 + 0x0) > ino->vol->at_data) {
+			if (found2)
+				break;
+			/* Uh-oh! It really isn't there! */
+			ntfs_error("Either the $MFT is corrupt or, equally "
+					"likely, the $MFT is too complex for "
+					"the current driver to handle. Please "
+					"email the ntfs maintainer that you "
+					"saw this message. Thank you.\n");
+			goto failed_reading_mft_data;
+		}
+	        /* Process attribute description. */
+		mftno2 = NTFS_GETU32(alist2 + 0x10); 
+		if (mftno2 != ino->i_number && mftno2 != last_mft2) {
+			last_mft2 = mftno2;
+			error2 = ntfs_read_mft_record(ino->vol, mftno2, mft2);
+			if (error2) {
+				ntfs_debug(DEBUG_FILE3, "parse_attributes: "
+					"ntfs_read_mft_record(mftno2 = 0x%x) "
+					"failed\n", mftno2);
+				ntfs_free(mft2);
+				goto failed_reading_mft_data;
+			}
+		}
+		attr2 = ntfs_find_attr_in_mft_rec(
+				ino->vol,		 /* ntfs volume */
+				mftno2 == ino->i_number ?/* mft record is: */
+					ino->attr:	 /*  base record */
+					mft2,		 /*  extension record */
+				NTFS_GETU32(alist2 + 0),	/* type */
+				(wchar_t*)(alist2 + alist2[7]),	/* name */
+				alist2[6], 		 /* name length */
+				1,			 /* ignore case */
+				NTFS_GETU16(alist2 + 24) /* instance number */
+				);
+		if (!attr2) {
+			ntfs_error("parse_attributes: mft records 0x%x and/or "
+				       "0x%x corrupt!\n", ino->i_number,
+				       mftno2);
+			ntfs_free(mft2);
+			goto failed_reading_mft_data;
+		}
+		error2 = ntfs_insert_mft_attribute(ino, mftno2, attr2);
+		if (error2) {
+			ntfs_debug(DEBUG_FILE3, "parse_attributes: "
+				"ntfs_insert_mft_attribute(mftno2 0x%x, "
+				"attribute2 type 0x%x) failed\n", mftno2,
+				NTFS_GETU32(alist2 + 0));
+			ntfs_free(mft2);
+			goto failed_reading_mft_data;
+		}
+		len2 -= l;
+		alist2 += l;
+		found2 = 1;
+	}
+	ntfs_free(mft2);
+	tries = 1;
+	goto continue_after_loading_mft_data;
+}
 }
 
-static void ntfs_load_attributes(ntfs_inode* ino)
+static void ntfs_load_attributes(ntfs_inode *ino)
 {
 	ntfs_attribute *alist;
 	int datasize;
diff -u --recursive --new-file v2.5.0/linux/fs/ntfs/support.c linux/fs/ntfs/support.c
--- v2.5.0/linux/fs/ntfs/support.c	Tue Sep 11 17:02:46 2001
+++ linux/fs/ntfs/support.c	Mon Dec 10 19:37:38 2001
@@ -150,7 +150,7 @@
 		 * now as we just can't handle some on disk structures
 		 * this way. (AIA) */
 		printk(KERN_WARNING "NTFS: Invalid MFT record for 0x%x\n", mftno);
-		return -EINVAL;
+		return -EIO;
 	}
 	ntfs_debug(DEBUG_OTHER, "read_mft_record: Done 0x%x\n", mftno);
 	return 0;
diff -u --recursive --new-file v2.5.0/linux/fs/partitions/acorn.c linux/fs/partitions/acorn.c
--- v2.5.0/linux/fs/partitions/acorn.c	Mon Oct  1 20:03:26 2001
+++ linux/fs/partitions/acorn.c	Tue Dec 11 09:44:13 2001
@@ -162,12 +162,12 @@
 		struct adfs_discrecord *dr;
 		unsigned int nr_sects;
 
-		if (!(minor & mask))
-			break;
-
 		data = read_dev_sector(bdev, start_blk * 2 + 6, &sect);
 		if (!data)
 			return -1;
+
+		if (!(minor & mask))
+			break;
 
 		dr = adfs_partition(hd, name, data, first_sector, minor++);
 		if (!dr)
diff -u --recursive --new-file v2.5.0/linux/fs/partitions/check.c linux/fs/partitions/check.c
--- v2.5.0/linux/fs/partitions/check.c	Thu Oct 11 17:25:10 2001
+++ linux/fs/partitions/check.c	Tue Nov 27 09:23:27 2001
@@ -1,4 +1,6 @@
 /*
+ *  fs/partitions/check.c
+ *
  *  Code extracted from drivers/block/genhd.c
  *  Copyright (C) 1991-1998  Linus Torvalds
  *  Re-organised Feb 1998 Russell King
@@ -34,8 +36,6 @@
 #include "ibm.h"
 #include "ultrix.h"
 
-extern int *blk_size[];
-
 int warn_no_part = 1; /*This is ugly: should make genhd removable media aware*/
 
 static int (*check_part[])(struct gendisk *hd, struct block_device *bdev, unsigned long first_sect, int first_minor) = {
@@ -369,38 +369,50 @@
 {
 	if (!gdev)
 		return;
-	grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
+	grok_partitions(dev, size);
 }
 
-void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
+void grok_partitions(kdev_t dev, long size)
 {
-	int i;
-	int first_minor	= drive << dev->minor_shift;
-	int end_minor	= first_minor + dev->max_p;
+	int i, minors, first_minor, end_minor;
+	struct gendisk *g = get_gendisk(dev);
+
+	if (!g)
+		return;
+
+	minors = 1 << g->minor_shift;
+	first_minor = MINOR(dev);
+	if (first_minor & (minors-1)) {
+		printk("grok_partitions: bad device 0x%02x:%02x\n",
+		       MAJOR(dev), first_minor);
+		first_minor &= ~(minors-1);
+	}
+	end_minor = first_minor + minors;
+ 
+	if (!g->sizes)
+		blk_size[g->major] = NULL;
 
-	if(!dev->sizes)
-		blk_size[dev->major] = NULL;
+	g->part[first_minor].nr_sects = size;
 
-	dev->part[first_minor].nr_sects = size;
 	/* No such device or no minors to use for partitions */
 	if (!size || minors == 1)
 		return;
 
-	if (dev->sizes) {
-		dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
+	if (g->sizes) {
+		g->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
 		for (i = first_minor + 1; i < end_minor; i++)
-			dev->sizes[i] = 0;
+			g->sizes[i] = 0;
 	}
-	blk_size[dev->major] = dev->sizes;
-	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
+	blk_size[g->major] = g->sizes;
+	check_partition(g, MKDEV(g->major, first_minor), 1 + first_minor);
 
  	/*
  	 * We need to set the sizes array before we will be able to access
  	 * any of the partitions on this device.
  	 */
-	if (dev->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
+	if (g->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
 		for (i = first_minor; i < end_minor; i++)
-			dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
+			g->sizes[i] = g->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
 	}
 }
 
@@ -425,4 +437,44 @@
 	}
 	p->v = NULL;
 	return NULL;
+}
+
+int wipe_partitions(kdev_t dev)
+{
+	struct gendisk *g;
+	kdev_t devp;
+	int p, major, minor, minor0, max_p, res;
+
+	g = get_gendisk(dev);
+	if (g == NULL)
+		return -EINVAL;
+
+	max_p = 1 << g->minor_shift;
+	major = MAJOR(dev);
+	minor = MINOR(dev);
+	minor0 = minor & ~(max_p - 1);
+	if (minor0 != minor)		/* for now only whole-disk reread */
+		return -EINVAL;		/* %%% later.. */
+
+	/* invalidate stuff */
+	for (p = max_p - 1; p >= 0; p--) {
+		minor = minor0 + p;
+		devp = MKDEV(major,minor);
+#if 0					/* %%% superfluous? */
+		if (g->part[minor].nr_sects == 0)
+			continue;
+#endif
+		res = invalidate_device(devp, 1);
+		if (res)
+			return res;
+		g->part[minor].start_sect = 0;
+		g->part[minor].nr_sects = 0;
+	}
+
+	/* some places do blksize_size[major][minor] = 1024,
+	   as preparation for reading partition table - superfluous */
+	/* sd.c used to set blksize_size to 2048 in case
+	   rscsi_disks[target].device->sector_size == 2048 */
+
+	return 0;
 }
diff -u --recursive --new-file v2.5.0/linux/fs/partitions/check.h linux/fs/partitions/check.h
--- v2.5.0/linux/fs/partitions/check.h	Mon Oct  1 20:03:26 2001
+++ linux/fs/partitions/check.h	Tue Dec 11 09:53:36 2001
@@ -1,5 +1,7 @@
+#include <linux/pagemap.h>
+
 /*
- * add_partition adds a partitions details to the devices partition
+ * add_gd_partition adds a partitions details to the devices partition
  * description.
  */
 void add_gd_partition(struct gendisk *hd, int minor, int start, int size);
diff -u --recursive --new-file v2.5.0/linux/fs/partitions/ldm.c linux/fs/partitions/ldm.c
--- v2.5.0/linux/fs/partitions/ldm.c	Mon Nov 12 09:43:11 2001
+++ linux/fs/partitions/ldm.c	Thu Dec  6 14:03:01 2001
@@ -26,6 +26,7 @@
 #include <linux/types.h>
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
+#include <linux/pagemap.h>
 #include <linux/genhd.h>
 #include <linux/blkdev.h>
 #include <linux/slab.h>
diff -u --recursive --new-file v2.5.0/linux/fs/proc/proc_misc.c linux/fs/proc/proc_misc.c
--- v2.5.0/linux/fs/proc/proc_misc.c	Tue Nov 20 21:29:09 2001
+++ linux/fs/proc/proc_misc.c	Thu Nov 29 07:49:55 2001
@@ -57,7 +57,6 @@
 extern int get_partition_list(char *, char **, off_t, int);
 extern int get_filesystem_list(char *);
 extern int get_exec_domain_list(char *);
-extern int get_irq_list(char *);
 extern int get_dma_list(char *);
 extern int get_locks_status (char *, char **, off_t, int);
 extern int get_swaparea_info (char *);
@@ -139,24 +138,14 @@
  * display in kilobytes.
  */
 #define K(x) ((x) << (PAGE_SHIFT - 10))
-#define B(x) ((unsigned long long)(x) << PAGE_SHIFT)
 	si_meminfo(&i);
 	si_swapinfo(&i);
 	pg_size = atomic_read(&page_cache_size) - i.bufferram ;
 
-	len = sprintf(page, "        total:    used:    free:  shared: buffers:  cached:\n"
-		"Mem:  %8Lu %8Lu %8Lu %8Lu %8Lu %8Lu\n"
-		"Swap: %8Lu %8Lu %8Lu\n",
-		B(i.totalram), B(i.totalram-i.freeram), B(i.freeram),
-		B(i.sharedram), B(i.bufferram),
-		B(pg_size), B(i.totalswap),
-		B(i.totalswap-i.freeswap), B(i.freeswap));
 	/*
 	 * Tagged format, for easy grepping and expansion.
-	 * The above will go away eventually, once the tools
-	 * have been updated.
 	 */
-	len += sprintf(page+len,
+	len = sprintf(page,
 		"MemTotal:     %8lu kB\n"
 		"MemFree:      %8lu kB\n"
 		"MemShared:    %8lu kB\n"
@@ -187,7 +176,6 @@
 		K(i.freeswap));
 
 	return proc_calc_metrics(page, start, off, count, eof, len);
-#undef B
 #undef K
 }
 
@@ -328,14 +316,53 @@
 	return len;
 }
 
-#if !defined(CONFIG_ARCH_S390)
-static int interrupts_read_proc(char *page, char **start, off_t off,
-				 int count, int *eof, void *data)
+static void *single_start(struct seq_file *p, loff_t *pos)
 {
-	int len = get_irq_list(page);
-	return proc_calc_metrics(page, start, off, count, eof, len);
+	return NULL + (*pos == 0);
 }
-#endif
+static void *single_next(struct seq_file *p, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+static void single_stop(struct seq_file *p, void *v)
+{
+}
+extern int show_interrupts(struct seq_file *p, void *v);
+static struct seq_operations proc_interrupts_op = {
+	start:	single_start,
+	next:	single_next,
+	stop:	single_stop,
+	show:	show_interrupts,
+};
+static int interrupts_open(struct inode *inode, struct file *file)
+{
+	unsigned size = PAGE_SIZE;
+	/*
+	 * probably should depend on NR_CPUS, but that's only rough estimate;
+	 * if we'll need more it will be given,
+	 */
+	char *buf = kmalloc(size, GFP_KERNEL);
+	struct seq_file *m;
+	int res;
+
+	if (!buf)
+		return -ENOMEM;
+	res = seq_open(file, &proc_interrupts_op);
+	if (!res) {
+		m = file->private_data;
+		m->buf = buf;
+		m->size = size;
+	} else
+		kfree(buf);
+	return res;
+}
+static struct file_operations proc_interrupts_operations = {
+	open:		interrupts_open,
+	read:		seq_read,
+	llseek:		seq_lseek,
+	release:	seq_release,
+};
 
 static int filesystems_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
@@ -512,9 +539,6 @@
 		{"stat",	kstat_read_proc},
 		{"devices",	devices_read_proc},
 		{"partitions",	partitions_read_proc},
-#if !defined(CONFIG_ARCH_S390)
-		{"interrupts",	interrupts_read_proc},
-#endif
 		{"filesystems",	filesystems_read_proc},
 		{"dma",		dma_read_proc},
 		{"ioports",	ioports_read_proc},
@@ -537,6 +561,7 @@
 		entry->proc_fops = &proc_kmsg_operations;
 	create_seq_entry("mounts", 0, &proc_mounts_operations);
 	create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
+	create_seq_entry("interrupts", 0, &proc_interrupts_operations);
 #ifdef CONFIG_MODULES
 	create_seq_entry("ksyms", 0, &proc_ksyms_operations);
 #endif
diff -u --recursive --new-file v2.5.0/linux/fs/readdir.c linux/fs/readdir.c
--- v2.5.0/linux/fs/readdir.c	Sun Aug 12 14:59:08 2001
+++ linux/fs/readdir.c	Mon Nov 26 16:41:46 2001
@@ -79,6 +79,10 @@
 			while(1) {
 				struct dentry *de = list_entry(list, struct dentry, d_child);
 
+				/*
+				 * See comment on top of function on why we
+				 * can just drop the lock here..
+				 */
 				if (!list_empty(&de->d_hash) && de->d_inode) {
 					spin_unlock(&dcache_lock);
 					if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino, DT_UNKNOWN) < 0)
diff -u --recursive --new-file v2.5.0/linux/fs/reiserfs/inode.c linux/fs/reiserfs/inode.c
--- v2.5.0/linux/fs/reiserfs/inode.c	Tue Oct 30 15:11:34 2001
+++ linux/fs/reiserfs/inode.c	Tue Nov 27 09:23:27 2001
@@ -390,7 +390,7 @@
 
 // this is called to create file map. So, _get_block_create_0 will not
 // read direct item
-int reiserfs_bmap (struct inode * inode, long block,
+int reiserfs_bmap (struct inode * inode, sector_t block,
 		   struct buffer_head * bh_result, int create)
 {
     if (!file_capable (inode, block))
@@ -420,7 +420,7 @@
 ** don't want to send create == GET_BLOCK_NO_HOLE to reiserfs_get_block, 
 ** don't use this function.
 */
-static int reiserfs_get_block_create_0 (struct inode * inode, long block,
+static int reiserfs_get_block_create_0 (struct inode * inode, sector_t block,
 			struct buffer_head * bh_result, int create) {
     return reiserfs_get_block(inode, block, bh_result, GET_BLOCK_NO_HOLE) ;
 }
@@ -511,7 +511,7 @@
 // determine which parts are derivative, if any, understanding that
 // there are only so many ways to code to a given interface.
 //
-int reiserfs_get_block (struct inode * inode, long block,
+int reiserfs_get_block (struct inode * inode, sector_t block,
 			struct buffer_head * bh_result, int create)
 {
     int repeat, retval;
@@ -1963,7 +1963,7 @@
 //
 // this is exactly what 2.3.99-pre9's ext2_bmap is
 //
-static int reiserfs_aop_bmap(struct address_space *as, long block) {
+static int reiserfs_aop_bmap(struct address_space *as, sector_t block) {
   return generic_block_bmap(as, block, reiserfs_bmap) ;
 }
 
diff -u --recursive --new-file v2.5.0/linux/fs/reiserfs/journal.c linux/fs/reiserfs/journal.c
--- v2.5.0/linux/fs/reiserfs/journal.c	Fri Nov  9 14:18:25 2001
+++ linux/fs/reiserfs/journal.c	Fri Nov 30 08:43:34 2001
@@ -147,7 +147,7 @@
   }
   bn = allocate_bitmap_node(p_s_sb) ;
   if (!bn) {
-    current->policy = SCHED_YIELD ;
+    current->policy |= SCHED_YIELD ;
     schedule() ;
     goto repeat ;
   }
diff -u --recursive --new-file v2.5.0/linux/fs/super.c linux/fs/super.c
--- v2.5.0/linux/fs/super.c	Wed Nov 21 14:05:29 2001
+++ linux/fs/super.c	Fri Dec  7 16:24:52 2001
@@ -21,36 +21,21 @@
  */
 
 #include <linux/config.h>
-#include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
 #include <linux/devfs_fs_kernel.h>
-#include <linux/fd.h>
-#include <linux/init.h>
 #include <linux/major.h>
-#include <linux/quotaops.h>
 #include <linux/acct.h>
 
 #include <asm/uaccess.h>
 
-#include <linux/nfs_fs.h>
-#include <linux/nfs_fs_sb.h>
-#include <linux/nfs_mount.h>
-
 #include <linux/kmod.h>
 #define __NO_VERSION__
 #include <linux/module.h>
 
-extern void wait_for_keypress(void);
-
-extern int root_mountflags;
-
 int do_remount_sb(struct super_block *sb, int flags, void * data);
 
-/* this is initialized in init/main.c */
-kdev_t ROOT_DEV;
-
 LIST_HEAD(super_blocks);
 spinlock_t sb_lock = SPIN_LOCK_UNLOCKED;
 
@@ -271,22 +256,164 @@
 	return fs;
 }
 
-struct vfsmount *alloc_vfsmnt(void);
-void free_vfsmnt(struct vfsmount *mnt);
-void set_devname(struct vfsmount *mnt, const char *name);
+/**
+ *	alloc_super	-	create new superblock
+ *
+ *	Allocates and initializes a new &struct super_block.  alloc_super()
+ *	returns a pointer new superblock or %NULL if allocation had failed.
+ */
+static struct super_block *alloc_super(void)
+{
+	struct super_block *s = kmalloc(sizeof(struct super_block),  GFP_USER);
+	if (s) {
+		memset(s, 0, sizeof(struct super_block));
+		INIT_LIST_HEAD(&s->s_dirty);
+		INIT_LIST_HEAD(&s->s_locked_inodes);
+		INIT_LIST_HEAD(&s->s_files);
+		INIT_LIST_HEAD(&s->s_instances);
+		init_rwsem(&s->s_umount);
+		sema_init(&s->s_lock, 1);
+		down_write(&s->s_umount);
+		s->s_count = S_BIAS;
+		atomic_set(&s->s_active, 1);
+		sema_init(&s->s_vfs_rename_sem,1);
+		sema_init(&s->s_nfsd_free_path_sem,1);
+		sema_init(&s->s_dquot.dqio_sem, 1);
+		sema_init(&s->s_dquot.dqoff_sem, 1);
+		s->s_maxbytes = MAX_NON_LFS;
+	}
+	return s;
+}
+
+/**
+ *	destroy_super	-	frees a superblock
+ *	@s: superblock to free
+ *
+ *	Frees a superblock.
+ */
+static inline void destroy_super(struct super_block *s)
+{
+	kfree(s);
+}
+
+/* Superblock refcounting  */
+
+/**
+ *	deactivate_super	-	turn an active reference into temporary
+ *	@s: superblock to deactivate
+ *
+ *	Turns an active reference into temporary one.  Returns 0 if there are
+ *	other active references, 1 if we had deactivated the last one.
+ */
+static inline int deactivate_super(struct super_block *s)
+{
+	if (!atomic_dec_and_lock(&s->s_active, &sb_lock))
+		return 0;
+	s->s_count -= S_BIAS-1;
+	spin_unlock(&sb_lock);
+	return 1;
+}
+
+/**
+ *	put_super	-	drop a temporary reference to superblock
+ *	@s: superblock in question
+ *
+ *	Drops a temporary reference, frees superblock if there's no
+ *	references left.
+ */
+static inline void put_super(struct super_block *s)
+{
+	spin_lock(&sb_lock);
+	if (!--s->s_count)
+		destroy_super(s);
+	spin_unlock(&sb_lock);
+}
+
+/**
+ *	grab_super	- acquire an active reference
+ *	@s	- reference we are trying to make active
+ *
+ *	Tries to acquire an active reference.  grab_super() is used when we
+ * 	had just found a superblock in super_blocks or fs_type->fs_supers
+ *	and want to turn it into a full-blown active reference.  grab_super()
+ *	is called with sb_lock held and drops it.  Returns 1 in case of
+ *	success, 0 if we had failed (superblock contents was already dead or
+ *	dying when grab_super() had been called).
+ */
+static int grab_super(struct super_block *s)
+{
+	s->s_count++;
+	spin_unlock(&sb_lock);
+	down_write(&s->s_umount);
+	if (s->s_root) {
+		spin_lock(&sb_lock);
+		if (s->s_count > S_BIAS) {
+			atomic_inc(&s->s_active);
+			s->s_count--;
+			spin_unlock(&sb_lock);
+			return 1;
+		}
+		spin_unlock(&sb_lock);
+	}
+	up_write(&s->s_umount);
+	put_super(s);
+	return 0;
+}
+ 
+/**
+ *	insert_super	-	put superblock on the lists
+ *	@s:	superblock in question
+ *	@type:	filesystem type it will belong to
+ *
+ *	Associates superblock with fs type and puts it on per-type and global
+ *	superblocks' lists.  Should be called with sb_lock held; drops it.
+ */
+static void insert_super(struct super_block *s, struct file_system_type *type)
+{
+	s->s_type = type;
+	list_add(&s->s_list, super_blocks.prev);
+	list_add(&s->s_instances, &type->fs_supers);
+	spin_unlock(&sb_lock);
+	get_filesystem(type);
+}
 
-/* Will go away */
-extern struct vfsmount *root_vfsmnt;
-extern int graft_tree(struct vfsmount *mnt, struct nameidata *nd);
+void put_unnamed_dev(kdev_t dev);	/* should become static */
 
-static inline void __put_super(struct super_block *sb)
+/**
+ *	remove_super	-	makes superblock unreachable
+ *	@s:	superblock in question
+ *
+ *	Removes superblock from the lists, unlocks it, drop the reference
+ *	and releases the hosting device.  @s should have no active
+ *	references by that time and after remove_super() it's essentially
+ *	in rundown mode - all remaining references are temporary, no new
+ *	reference of any sort are going to appear and all holders of
+ *	temporary ones will eventually drop them.  At that point superblock
+ *	itself will be destroyed; all its contents is already gone.
+ */
+static void remove_super(struct super_block *s)
 {
+	kdev_t dev = s->s_dev;
+	struct block_device *bdev = s->s_bdev;
+	struct file_system_type *fs = s->s_type;
+
 	spin_lock(&sb_lock);
-	if (!--sb->s_count)
-		kfree(sb);
+	list_del(&s->s_list);
+	list_del(&s->s_instances);
 	spin_unlock(&sb_lock);
+	up_write(&s->s_umount);
+	put_super(s);
+	put_filesystem(fs);
+	if (bdev)
+		blkdev_put(bdev, BDEV_FS);
+	else
+		put_unnamed_dev(dev);
 }
 
+struct vfsmount *alloc_vfsmnt(void);
+void free_vfsmnt(struct vfsmount *mnt);
+void set_devname(struct vfsmount *mnt, const char *name);
+
 static inline struct super_block * find_super(kdev_t dev)
 {
 	struct list_head *p;
@@ -304,14 +431,7 @@
 void drop_super(struct super_block *sb)
 {
 	up_read(&sb->s_umount);
-	__put_super(sb);
-}
-
-static void put_super(struct super_block *sb)
-{
-	atomic_dec(&sb->s_active);
-	up_write(&sb->s_umount);
-	__put_super(sb);
+	put_super(sb);
 }
 
 static inline void write_super(struct super_block *sb)
@@ -322,7 +442,7 @@
 			sb->s_op->write_super(sb);
 	unlock_super(sb);
 }
- 
+
 /*
  * Note: check the dirty flag before waiting, so we don't
  * hold up the sync while mounting a device. (The newly
@@ -371,19 +491,19 @@
 
 	if (!dev)
 		return NULL;
-restart:
-	spin_lock(&sb_lock);
-	s = find_super(dev);
-	if (s) {
+
+	while (1) {
+		spin_lock(&sb_lock);
+		s = find_super(dev);
 		spin_unlock(&sb_lock);
+		if (!s)
+			break;
 		down_read(&s->s_umount);
 		if (s->s_root)
-			return s;
+			break;
 		drop_super(s);
-		goto restart;
 	}
-	spin_unlock(&sb_lock);
-	return NULL;
+	return s;
 }
 
 asmlinkage long sys_ustat(dev_t dev, struct ustat * ubuf)
@@ -410,79 +530,6 @@
 	return err;
 }
 
-/**
- *	get_empty_super	-	find empty superblocks
- *
- *	Find a superblock with no device assigned. A free superblock is 
- *	found and returned. If neccessary new superblocks are allocated.
- *	%NULL is returned if there are insufficient resources to complete
- *	the request.
- */
- 
-static struct super_block *alloc_super(void)
-{
-	struct super_block *s = kmalloc(sizeof(struct super_block),  GFP_USER);
-	if (s) {
-		memset(s, 0, sizeof(struct super_block));
-		INIT_LIST_HEAD(&s->s_dirty);
-		INIT_LIST_HEAD(&s->s_locked_inodes);
-		INIT_LIST_HEAD(&s->s_files);
-		INIT_LIST_HEAD(&s->s_instances);
-		init_rwsem(&s->s_umount);
-		sema_init(&s->s_lock, 1);
-		s->s_count = 1;
-		atomic_set(&s->s_active, 1);
-		sema_init(&s->s_vfs_rename_sem,1);
-		sema_init(&s->s_nfsd_free_path_sem,1);
-		sema_init(&s->s_dquot.dqio_sem, 1);
-		sema_init(&s->s_dquot.dqoff_sem, 1);
-		s->s_maxbytes = MAX_NON_LFS;
-	}
-	return s;
-}
-
-static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
-				       struct file_system_type *type, int flags,
-				       void *data)
-{
-	struct super_block * s;
-	s = alloc_super();
-	if (!s)
-		goto out;
-	s->s_dev = dev;
-	s->s_bdev = bdev;
-	s->s_flags = flags;
-	s->s_type = type;
-	spin_lock(&sb_lock);
-	list_add (&s->s_list, super_blocks.prev);
-	list_add (&s->s_instances, &type->fs_supers);
-	s->s_count += S_BIAS;
-	spin_unlock(&sb_lock);
-	down_write(&s->s_umount);
-	lock_super(s);
-	if (!type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
-		goto out_fail;
-	unlock_super(s);
-	/* tell bdcache that we are going to keep this one */
-	if (bdev)
-		atomic_inc(&bdev->bd_count);
-out:
-	return s;
-
-out_fail:
-	s->s_dev = 0;
-	s->s_bdev = 0;
-	s->s_type = NULL;
-	unlock_super(s);
-	spin_lock(&sb_lock);
-	list_del(&s->s_list);
-	list_del(&s->s_instances);
-	s->s_count -= S_BIAS;
-	spin_unlock(&sb_lock);
-	put_super(s);
-	return NULL;
-}
-
 /*
  * Unnamed block devices are dummy devices used by virtual
  * filesystems which don't use real block-devices.  -- jrs
@@ -511,25 +558,6 @@
 			kdevname(dev));
 }
 
-static int grab_super(struct super_block *sb)
-{
-	sb->s_count++;
-	atomic_inc(&sb->s_active);
-	spin_unlock(&sb_lock);
-	down_write(&sb->s_umount);
-	if (sb->s_root) {
-		spin_lock(&sb_lock);
-		if (sb->s_count > S_BIAS) {
-			sb->s_count--;
-			spin_unlock(&sb_lock);
-			return 1;
-		}
-		spin_unlock(&sb_lock);
-	}
-	put_super(sb);
-	return 0;
-}
-
 static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
 	char *dev_name, int flags, void * data)
 {
@@ -570,14 +598,17 @@
 		goto out;
 	check_disk_change(dev);
 	error = -EACCES;
-	if (!(flags & MS_RDONLY) && is_read_only(dev))
-		goto out1;
+	if (!(flags & MS_RDONLY) && is_read_only(dev)) {
+		blkdev_put(bdev, BDEV_FS);
+		goto out;
+	}
 
 	error = -ENOMEM;
 	s = alloc_super();
-	if (!s)
-		goto out1;
-	down_write(&s->s_umount);
+	if (!s) {
+		blkdev_put(bdev, BDEV_FS);
+		goto out;
+	}
 
 	error = -EBUSY;
 restart:
@@ -590,12 +621,13 @@
 		if (old->s_type != fs_type ||
 		    ((flags ^ old->s_flags) & MS_RDONLY)) {
 			spin_unlock(&sb_lock);
-			put_super(s);
-			goto out1;
+			destroy_super(s);
+			blkdev_put(bdev, BDEV_FS);
+			goto out;
 		}
 		if (!grab_super(old))
 			goto restart;
-		put_super(s);
+		destroy_super(s);
 		blkdev_put(bdev, BDEV_FS);
 		path_release(&nd);
 		return old;
@@ -603,35 +635,21 @@
 	s->s_dev = dev;
 	s->s_bdev = bdev;
 	s->s_flags = flags;
-	s->s_type = fs_type;
-	list_add (&s->s_list, super_blocks.prev);
-	list_add (&s->s_instances, &fs_type->fs_supers);
-	s->s_count += S_BIAS;
-
-	spin_unlock(&sb_lock);
+	insert_super(s, fs_type);
 
 	error = -EINVAL;
 	lock_super(s);
 	if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
 		goto out_fail;
+	s->s_flags |= MS_ACTIVE;
 	unlock_super(s);
-	get_filesystem(fs_type);
 	path_release(&nd);
 	return s;
 
 out_fail:
-	s->s_dev = 0;
-	s->s_bdev = 0;
-	s->s_type = NULL;
 	unlock_super(s);
-	spin_lock(&sb_lock);
-	list_del(&s->s_list);
-	list_del(&s->s_instances);
-	s->s_count -= S_BIAS;
-	spin_unlock(&sb_lock);
-	put_super(s);
-out1:
-	blkdev_put(bdev, BDEV_FS);
+	deactivate_super(s);
+	remove_super(s);
 out:
 	path_release(&nd);
 	return ERR_PTR(error);
@@ -640,20 +658,30 @@
 static struct super_block *get_sb_nodev(struct file_system_type *fs_type,
 	int flags, void * data)
 {
-	kdev_t dev;
-	int error = -EMFILE;
-	dev = get_unnamed_dev();
-	if (dev) {
-		struct super_block * sb;
-		error = -EINVAL;
-		sb = read_super(dev, NULL, fs_type, flags, data);
-		if (sb) {
-			get_filesystem(fs_type);
-			return sb;
-		}
-		put_unnamed_dev(dev);
+	struct super_block *s = alloc_super();
+
+	if (!s)
+		return ERR_PTR(-ENOMEM);
+	s->s_dev = get_unnamed_dev();
+	if (!s->s_dev) {
+		destroy_super(s);
+		return ERR_PTR(-EMFILE);
 	}
-	return ERR_PTR(error);
+	s->s_flags = flags;
+	spin_lock(&sb_lock);
+	insert_super(s, fs_type);
+	lock_super(s);
+	if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
+		goto out_fail;
+	s->s_flags |= MS_ACTIVE;
+	unlock_super(s);
+	return s;
+
+out_fail:
+	unlock_super(s);
+	deactivate_super(s);
+	remove_super(s);
+	return ERR_PTR(-EINVAL);
 }
 
 static struct super_block *get_sb_single(struct file_system_type *fs_type,
@@ -662,7 +690,6 @@
 	struct super_block * s = alloc_super();
 	if (!s)
 		return ERR_PTR(-ENOMEM);
-	down_write(&s->s_umount);
 	/*
 	 * Get the superblock of kernel-wide instance, but
 	 * keep the reference to fs_type.
@@ -675,60 +702,42 @@
 				s_instances);
 		if (!grab_super(old))
 			goto retry;
-		put_super(s);
+		destroy_super(s);
 		do_remount_sb(old, flags, data);
 		return old;
 	} else {
-		kdev_t dev = get_unnamed_dev();
-		if (!dev) {
+		s->s_dev = get_unnamed_dev();
+		if (!s->s_dev) {
 			spin_unlock(&sb_lock);
-			put_super(s);
+			destroy_super(s);
 			return ERR_PTR(-EMFILE);
 		}
-		s->s_dev = dev;
 		s->s_flags = flags;
-		s->s_type = fs_type;
-		list_add (&s->s_list, super_blocks.prev);
-		list_add (&s->s_instances, &fs_type->fs_supers);
-		s->s_count += S_BIAS;
-		spin_unlock(&sb_lock);
+		insert_super(s, fs_type);
 		lock_super(s);
 		if (!fs_type->read_super(s, data, flags & MS_VERBOSE ? 1 : 0))
 			goto out_fail;
+		s->s_flags |= MS_ACTIVE;
 		unlock_super(s);
-		get_filesystem(fs_type);
 		return s;
 
 	out_fail:
-		s->s_dev = 0;
-		s->s_bdev = 0;
-		s->s_type = NULL;
 		unlock_super(s);
-		spin_lock(&sb_lock);
-		list_del(&s->s_list);
-		list_del(&s->s_instances);
-		s->s_count -= S_BIAS;
-		spin_unlock(&sb_lock);
-		put_super(s);
-		put_unnamed_dev(dev);
+		deactivate_super(s);
+		remove_super(s);
 		return ERR_PTR(-EINVAL);
 	}
 }
 
 void kill_super(struct super_block *sb)
 {
-	struct block_device *bdev;
-	kdev_t dev;
 	struct dentry *root = sb->s_root;
 	struct file_system_type *fs = sb->s_type;
 	struct super_operations *sop = sb->s_op;
 
-	if (!atomic_dec_and_lock(&sb->s_active, &sb_lock))
+	if (!deactivate_super(sb))
 		return;
 
-	sb->s_count -= S_BIAS;
-	spin_unlock(&sb_lock);
-
 	down_write(&sb->s_umount);
 	lock_kernel();
 	sb->s_root = NULL;
@@ -739,6 +748,7 @@
 	dput(root);
 	fsync_super(sb);
 	lock_super(sb);
+	sb->s_flags &= ~MS_ACTIVE;
 	invalidate_inodes(sb);	/* bad name - it should be evict_inodes() */
 	if (sop) {
 		if (sop->write_super && sb->s_dirt)
@@ -753,24 +763,9 @@
 			"Self-destruct in 5 seconds.  Have a nice day...\n");
 	}
 
-	dev = sb->s_dev;
-	sb->s_dev = 0;		/* Free the superblock */
-	bdev = sb->s_bdev;
-	sb->s_bdev = NULL;
-	put_filesystem(fs);
-	sb->s_type = NULL;
-	unlock_super(sb);
 	unlock_kernel();
-	if (bdev)
-		blkdev_put(bdev, BDEV_FS);
-	else
-		put_unnamed_dev(dev);
-	spin_lock(&sb_lock);
-	list_del(&sb->s_list);
-	list_del(&sb->s_instances);
-	spin_unlock(&sb_lock);
-	atomic_inc(&sb->s_active);
-	put_super(sb);
+	unlock_super(sb);
+	remove_super(sb);
 }
 
 /*
@@ -865,212 +860,4 @@
 struct vfsmount *kern_mount(struct file_system_type *type)
 {
 	return do_kern_mount((char *)type->name, 0, (char *)type->name, NULL);
-}
-
-static char * __initdata root_mount_data;
-static int __init root_data_setup(char *str)
-{
-	root_mount_data = str;
-	return 1;
-}
-
-static char * __initdata root_fs_names;
-static int __init fs_names_setup(char *str)
-{
-	root_fs_names = str;
-	return 1;
-}
-
-__setup("rootflags=", root_data_setup);
-__setup("rootfstype=", fs_names_setup);
-
-static void __init get_fs_names(char *page)
-{
-	char *s = page;
-
-	if (root_fs_names) {
-		strcpy(page, root_fs_names);
-		while (*s++) {
-			if (s[-1] == ',')
-				s[-1] = '\0';
-		}
-	} else {
-		int len = get_filesystem_list(page);
-		char *p, *next;
-
-		page[len] = '\0';
-		for (p = page-1; p; p = next) {
-			next = strchr(++p, '\n');
-			if (*p++ != '\t')
-				continue;
-			while ((*s++ = *p++) != '\n')
-				;
-			s[-1] = '\0';
-		}
-	}
-	*s = '\0';
-}
-
-void __init mount_root(void)
-{
-	struct nameidata root_nd;
-	struct super_block * sb;
-	struct vfsmount *vfsmnt;
-	struct block_device *bdev = NULL;
-	mode_t mode;
-	int retval;
-	void *handle;
-	char path[64];
-	int path_start = -1;
-	char *name = "/dev/root";
-	char *fs_names, *p;
-#ifdef CONFIG_ROOT_NFS
-	void *data;
-#endif
-	root_mountflags |= MS_VERBOSE;
-
-#ifdef CONFIG_ROOT_NFS
-	if (MAJOR(ROOT_DEV) != UNNAMED_MAJOR)
-		goto skip_nfs;
-	data = nfs_root_data();
-	if (!data)
-		goto no_nfs;
-	vfsmnt = do_kern_mount("nfs", root_mountflags, "/dev/root", data);
-	if (!IS_ERR(vfsmnt)) {
-		printk ("VFS: Mounted root (%s filesystem).\n", "nfs");
-		ROOT_DEV = vfsmnt->mnt_sb->s_dev;
-		goto attach_it;
-	}
-no_nfs:
-	printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
-	ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
-skip_nfs:
-#endif
-
-#ifdef CONFIG_BLK_DEV_FD
-	if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
-#ifdef CONFIG_BLK_DEV_RAM
-		extern int rd_doload;
-		extern void rd_load_secondary(void);
-#endif
-		floppy_eject();
-#ifndef CONFIG_BLK_DEV_RAM
-		printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
-#else
-		/* rd_doload is 2 for a dual initrd/ramload setup */
-		if(rd_doload==2)
-			rd_load_secondary();
-		else
-#endif
-		{
-			printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
-			wait_for_keypress();
-		}
-	}
-#endif
-
-	fs_names = __getname();
-	get_fs_names(fs_names);
-
-	devfs_make_root (root_device_name);
-	handle = devfs_find_handle (NULL, ROOT_DEVICE_NAME,
-	                            MAJOR (ROOT_DEV), MINOR (ROOT_DEV),
-				    DEVFS_SPECIAL_BLK, 1);
-	if (handle)  /*  Sigh: bd*() functions only paper over the cracks  */
-	{
-	    unsigned major, minor;
-
-	    devfs_get_maj_min (handle, &major, &minor);
-	    ROOT_DEV = MKDEV (major, minor);
-	}
-
-	/*
-	 * Probably pure paranoia, but I'm less than happy about delving into
-	 * devfs crap and checking it right now. Later.
-	 */
-	if (!ROOT_DEV)
-		panic("I have no root and I want to scream");
-
-retry:
-	bdev = bdget(kdev_t_to_nr(ROOT_DEV));
-	if (!bdev)
-		panic(__FUNCTION__ ": unable to allocate root device");
-	bdev->bd_op = devfs_get_ops (handle);
-	path_start = devfs_generate_path (handle, path + 5, sizeof (path) - 5);
-	mode = FMODE_READ;
-	if (!(root_mountflags & MS_RDONLY))
-		mode |= FMODE_WRITE;
-	retval = blkdev_get(bdev, mode, 0, BDEV_FS);
-	if (retval == -EROFS) {
-		root_mountflags |= MS_RDONLY;
-		goto retry;
-	}
-	if (retval) {
-	        /*
-		 * Allow the user to distinguish between failed open
-		 * and bad superblock on root device.
-		 */
-		printk ("VFS: Cannot open root device \"%s\" or %s\n",
-			root_device_name, kdevname (ROOT_DEV));
-		printk ("Please append a correct \"root=\" boot option\n");
-		panic("VFS: Unable to mount root fs on %s",
-			kdevname(ROOT_DEV));
-	}
-
-	check_disk_change(ROOT_DEV);
-	sb = get_super(ROOT_DEV);
-	if (sb) {
-		/* FIXME */
-		p = (char *)sb->s_type->name;
-		atomic_inc(&sb->s_active);
-		up_read(&sb->s_umount);
-		down_write(&sb->s_umount);
-		goto mount_it;
-	}
-
-	for (p = fs_names; *p; p += strlen(p)+1) {
-		struct file_system_type * fs_type = get_fs_type(p);
-		if (!fs_type)
-  			continue;
-  		sb = read_super(ROOT_DEV, bdev, fs_type,
-				root_mountflags, root_mount_data);
-		if (sb) 
-			goto mount_it;
-		put_filesystem(fs_type);
-	}
-	panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));
-
-mount_it:
-	/* FIXME */
-	up_write(&sb->s_umount);
-	printk ("VFS: Mounted root (%s filesystem)%s.\n", p,
-		(sb->s_flags & MS_RDONLY) ? " readonly" : "");
-	putname(fs_names);
-	if (path_start >= 0) {
-		name = path + path_start;
-		devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,
-				  name + 5, NULL, NULL);
-		memcpy (name, "/dev/", 5);
-	}
-	vfsmnt = alloc_vfsmnt();
-	if (!vfsmnt)
-		panic("VFS: alloc_vfsmnt failed for root fs");
-
-	set_devname(vfsmnt, name);
-	vfsmnt->mnt_sb = sb;
-	vfsmnt->mnt_root = dget(sb->s_root);
-	bdput(bdev); /* sb holds a reference */
-
-
-#ifdef CONFIG_ROOT_NFS
-attach_it:
-#endif
-	root_nd.mnt = root_vfsmnt;
-	root_nd.dentry = root_vfsmnt->mnt_sb->s_root;
-	graft_tree(vfsmnt, &root_nd);
-
-	set_fs_root(current->fs, vfsmnt, vfsmnt->mnt_root);
-	set_fs_pwd(current->fs, vfsmnt, vfsmnt->mnt_root);
-
-	mntput(vfsmnt);
 }
diff -u --recursive --new-file v2.5.0/linux/fs/udf/inode.c linux/fs/udf/inode.c
--- v2.5.0/linux/fs/udf/inode.c	Fri Oct 12 13:48:42 2001
+++ linux/fs/udf/inode.c	Tue Nov 27 09:23:27 2001
@@ -61,7 +61,7 @@
 static void udf_update_extents(struct inode *,
 	long_ad [EXTENT_MERGE_SIZE], int, int,
 	lb_addr, Uint32, struct buffer_head **);
-static int udf_get_block(struct inode *, long, struct buffer_head *, int);
+static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
 /*
  * udf_put_inode
@@ -314,7 +314,7 @@
 	return dbh;
 }
 
-static int udf_get_block(struct inode *inode, long block, struct buffer_head *bh_result, int create)
+static int udf_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_result, int create)
 {
 	int err, new;
 	struct buffer_head *bh;
diff -u --recursive --new-file v2.5.0/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v2.5.0/linux/include/asm-alpha/io.h	Fri Nov  9 13:45:35 2001
+++ linux/include/asm-alpha/io.h	Tue Nov 27 09:23:27 2001
@@ -60,6 +60,8 @@
 	return (void *) (address + IDENT_ADDR);
 }
 
+#define page_to_phys(page)	(((page) - (page)->zone->zone_mem_map) << PAGE_SHIFT)
+
 /*
  * Change addresses as seen by the kernel (virtual) to addresses as
  * seen by a device (bus), and vice versa.
diff -u --recursive --new-file v2.5.0/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h
--- v2.5.0/linux/include/asm-alpha/page.h	Fri Oct  5 12:22:07 2001
+++ linux/include/asm-alpha/page.h	Sat Dec  8 20:07:24 2001
@@ -64,6 +64,7 @@
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__);			\
 	__asm__ __volatile__("call_pal %0  # bugchk" : : "i" (PAL_bugchk));	\
 } while (0)
+
 #define PAGE_BUG(page)	BUG()
 
 /* Pure 2^n version of get_order */
diff -u --recursive --new-file v2.5.0/linux/include/asm-arm/mach/irq.h linux/include/asm-arm/mach/irq.h
--- v2.5.0/linux/include/asm-arm/mach/irq.h	Thu Feb  8 16:32:44 2001
+++ linux/include/asm-arm/mach/irq.h	Wed Nov 28 13:22:26 2001
@@ -35,7 +35,7 @@
 
 extern void (*init_arch_irq)(void);
 extern int setup_arm_irq(int, struct irqaction *);
-extern int get_fiq_list(char *);
+extern int show_fiq_list(struct seq_file *, void *);
 extern void init_FIQ(void);
 
 #endif
diff -u --recursive --new-file v2.5.0/linux/include/asm-i386/checksum.h linux/include/asm-i386/checksum.h
--- v2.5.0/linux/include/asm-i386/checksum.h	Thu Jul 26 13:41:22 2001
+++ linux/include/asm-i386/checksum.h	Wed Nov 28 12:38:21 2001
@@ -29,9 +29,9 @@
 
 /*
  *	Note: when you get a NULL pointer exception here this means someone
- *	passed in an incorrect kernel address to one of these functions. 
- *	
- *	If you use these functions directly please don't forget the 
+ *	passed in an incorrect kernel address to one of these functions.
+ *
+ *	If you use these functions directly please don't forget the
  *	verify_area().
  */
 static __inline__
@@ -66,28 +66,28 @@
  *	Arnt Gulbrandsen.
  */
 static inline unsigned short ip_fast_csum(unsigned char * iph,
-					  unsigned int ihl) {
+					  unsigned int ihl)
+{
 	unsigned int sum;
 
-	__asm__ __volatile__("
-	    movl (%1), %0
-	    subl $4, %2
-	    jbe 2f
-	    addl 4(%1), %0
-	    adcl 8(%1), %0
-	    adcl 12(%1), %0
-1:	    adcl 16(%1), %0
-	    lea 4(%1), %1
-	    decl %2
-	    jne	1b
-	    adcl $0, %0
-	    movl %0, %2
-	    shrl $16, %0
-	    addw %w2, %w0
-	    adcl $0, %0
-	    notl %0
-2:
-	    "
+	__asm__ __volatile__(
+	    "movl (%1), %0	;\n"
+	    "subl $4, %2	;\n"
+	    "jbe 2f		;\n"
+	    "addl 4(%1), %0	;\n"
+	    "adcl 8(%1), %0	;\n"
+	    "adcl 12(%1), %0	;\n"
+"1:	    adcl 16(%1), %0	;\n"
+	    "lea 4(%1), %1	;\n"
+	    "decl %2		;\n"
+	    "jne 1b		;\n"
+	    "adcl $0, %0	;\n"
+	    "movl %0, %2	;\n"
+	    "shrl $16, %0	;\n"
+	    "addw %w2, %w0	;\n"
+	    "adcl $0, %0	;\n"
+	    "notl %0		;\n"
+"2:				;\n"
 	/* Since the input registers which are loaded with iph and ipl
 	   are modified, we must also specify them as outputs, or gcc
 	   will assume they contain their original values. */
@@ -102,28 +102,26 @@
 
 static inline unsigned int csum_fold(unsigned int sum)
 {
-	__asm__("
-		addl %1, %0
-		adcl $0xffff, %0
-		"
+	__asm__(
+		"addl %1, %0		;\n"
+		"adcl $0xffff, %0	;\n"
 		: "=r" (sum)
 		: "r" (sum << 16), "0" (sum & 0xffff0000)
 	);
 	return (~sum) >> 16;
 }
- 
+
 static inline unsigned long csum_tcpudp_nofold(unsigned long saddr,
 						   unsigned long daddr,
 						   unsigned short len,
 						   unsigned short proto,
-						   unsigned int sum) 
+						   unsigned int sum)
 {
-    __asm__("
-	addl %1, %0
-	adcl %2, %0
-	adcl %3, %0
-	adcl $0, %0
-	"
+    __asm__(
+	"addl %1, %0	;\n"
+	"adcl %2, %0	;\n"
+	"adcl %3, %0	;\n"
+	"adcl $0, %0	;\n"
 	: "=r" (sum)
 	: "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
     return sum;
@@ -137,7 +135,7 @@
 						   unsigned long daddr,
 						   unsigned short len,
 						   unsigned short proto,
-						   unsigned int sum) 
+						   unsigned int sum)
 {
 	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
 }
@@ -147,7 +145,8 @@
  * in icmp.c
  */
 
-static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
     return csum_fold (csum_partial(buff, len, 0));
 }
 
@@ -156,33 +155,32 @@
 						     struct in6_addr *daddr,
 						     __u32 len,
 						     unsigned short proto,
-						     unsigned int sum) 
+						     unsigned int sum)
 {
-	__asm__("
-		addl 0(%1), %0
-		adcl 4(%1), %0
-		adcl 8(%1), %0
-		adcl 12(%1), %0
-		adcl 0(%2), %0
-		adcl 4(%2), %0
-		adcl 8(%2), %0
-		adcl 12(%2), %0
-		adcl %3, %0
-		adcl %4, %0
-		adcl $0, %0
-		"
+	__asm__(
+		"addl 0(%1), %0		;\n"
+		"adcl 4(%1), %0		;\n"
+		"adcl 8(%1), %0		;\n"
+		"adcl 12(%1), %0	;\n"
+		"adcl 0(%2), %0		;\n"
+		"adcl 4(%2), %0		;\n"
+		"adcl 8(%2), %0		;\n"
+		"adcl 12(%2), %0	;\n"
+		"adcl %3, %0		;\n"
+		"adcl %4, %0		;\n"
+		"adcl $0, %0		;\n"
 		: "=&r" (sum)
-		: "r" (saddr), "r" (daddr), 
+		: "r" (saddr), "r" (daddr),
 		  "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
 
 	return csum_fold(sum);
 }
 
-/* 
+/*
  *	Copy and checksum to user
  */
 #define HAVE_CSUM_COPY_USER
-static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
+static __inline__ unsigned int csum_and_copy_to_user(const char *src, char *dst,
 				    int len, int sum, int *err_ptr)
 {
 	if (access_ok(VERIFY_WRITE, dst, len))
diff -u --recursive --new-file v2.5.0/linux/include/asm-i386/floppy.h linux/include/asm-i386/floppy.h
--- v2.5.0/linux/include/asm-i386/floppy.h	Thu Nov 22 11:46:19 2001
+++ linux/include/asm-i386/floppy.h	Tue Dec 11 10:06:20 2001
@@ -75,28 +75,28 @@
 
 #ifndef NO_FLOPPY_ASSEMBLER
 	__asm__ (
-       "testl %1,%1
-	je 3f
-1:	inb %w4,%b0
-	andb $160,%b0
-	cmpb $160,%b0
-	jne 2f
-	incw %w4
-	testl %3,%3
-	jne 4f
-	inb %w4,%b0
-	movb %0,(%2)
-	jmp 5f
-4:     	movb (%2),%0
-	outb %b0,%w4
-5:	decw %w4
-	outb %0,$0x80
-	decl %1
-	incl %2
-	testl %1,%1
-	jne 1b
-3:	inb %w4,%b0
-2:	"
+       "testl %1,%1"
+	"je 3f"
+"1:	inb %w4,%b0"
+	"andb $160,%b0"
+	"cmpb $160,%b0"
+	"jne 2f"
+	"incw %w4"
+	"testl %3,%3"
+	"jne 4f"
+	"inb %w4,%b0"
+	"movb %0,(%2)"
+	"jmp 5f"
+"4:    	movb (%2),%0"
+	"outb %b0,%w4"
+"5:	decw %w4"
+	"outb %0,$0x80"
+	"decl %1"
+	"incl %2"
+	"testl %1,%1"
+	"jne 1b"
+"3:	inb %w4,%b0"
+"2:	"
        : "=a" ((char) st), 
        "=c" ((long) virtual_dma_count), 
        "=S" ((long) virtual_dma_addr)
diff -u --recursive --new-file v2.5.0/linux/include/asm-i386/io.h linux/include/asm-i386/io.h
--- v2.5.0/linux/include/asm-i386/io.h	Thu Nov 22 11:46:27 2001
+++ linux/include/asm-i386/io.h	Tue Dec 11 09:51:42 2001
@@ -105,6 +105,13 @@
 #define page_to_bus page_to_phys
 
 /*
+ * can the hardware map this into one segment or not, given no other
+ * constraints.
+ */
+#define BIOVEC_MERGEABLE(vec1, vec2)	\
+	((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
+
+/*
  * readX/writeX() are used to access memory mapped devices. On some
  * architectures the memory mapped IO stuff needs to be accessed
  * differently. On the x86 architecture, we just read/write the
diff -u --recursive --new-file v2.5.0/linux/include/asm-i386/kmap_types.h linux/include/asm-i386/kmap_types.h
--- v2.5.0/linux/include/asm-i386/kmap_types.h	Mon Sep 17 13:16:30 2001
+++ linux/include/asm-i386/kmap_types.h	Tue Nov 27 09:23:27 2001
@@ -7,6 +7,7 @@
 	KM_SKB_DATA_SOFTIRQ,
 	KM_USER0,
 	KM_USER1,
+	KM_BIO_IRQ,
 	KM_TYPE_NR
 };
 
diff -u --recursive --new-file v2.5.0/linux/include/asm-i386/pgalloc.h linux/include/asm-i386/pgalloc.h
--- v2.5.0/linux/include/asm-i386/pgalloc.h	Thu Nov 22 11:46:19 2001
+++ linux/include/asm-i386/pgalloc.h	Tue Dec 11 09:51:33 2001
@@ -18,15 +18,21 @@
  * Allocate and free page tables.
  */
 
-#if CONFIG_X86_PAE
+#if defined (CONFIG_X86_PAE)
+/*
+ * We can't include <linux/slab.h> here, thus these uglinesses.
+ */
+struct kmem_cache_s;
+
+extern struct kmem_cache_s *pae_pgd_cachep;
+extern void *kmem_cache_alloc(struct kmem_cache_s *, int);
+extern void kmem_cache_free(struct kmem_cache_s *, void *);
 
-extern void *kmalloc(size_t, int);
-extern void kfree(const void *);
 
-static __inline__ pgd_t *get_pgd_slow(void)
+static inline pgd_t *get_pgd_slow(void)
 {
 	int i;
-	pgd_t *pgd = kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL);
+	pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
 
 	if (pgd) {
 		for (i = 0; i < USER_PTRS_PER_PGD; i++) {
@@ -36,32 +42,36 @@
 			clear_page(pmd);
 			set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
 		}
-		memcpy(pgd + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+		memcpy(pgd + USER_PTRS_PER_PGD,
+			swapper_pg_dir + USER_PTRS_PER_PGD,
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 	}
 	return pgd;
 out_oom:
 	for (i--; i >= 0; i--)
 		free_page((unsigned long)__va(pgd_val(pgd[i])-1));
-	kfree(pgd);
+	kmem_cache_free(pae_pgd_cachep, pgd);
 	return NULL;
 }
 
 #else
 
-static __inline__ pgd_t *get_pgd_slow(void)
+static inline pgd_t *get_pgd_slow(void)
 {
 	pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
 
 	if (pgd) {
 		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-		memcpy(pgd + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD, (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+		memcpy(pgd + USER_PTRS_PER_PGD,
+			swapper_pg_dir + USER_PTRS_PER_PGD,
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 	}
 	return pgd;
 }
 
-#endif
+#endif /* CONFIG_X86_PAE */
 
-static __inline__ pgd_t *get_pgd_fast(void)
+static inline pgd_t *get_pgd_fast(void)
 {
 	unsigned long *ret;
 
@@ -74,21 +84,21 @@
 	return (pgd_t *)ret;
 }
 
-static __inline__ void free_pgd_fast(pgd_t *pgd)
+static inline void free_pgd_fast(pgd_t *pgd)
 {
 	*(unsigned long *)pgd = (unsigned long) pgd_quicklist;
 	pgd_quicklist = (unsigned long *) pgd;
 	pgtable_cache_size++;
 }
 
-static __inline__ void free_pgd_slow(pgd_t *pgd)
+static inline void free_pgd_slow(pgd_t *pgd)
 {
-#if CONFIG_X86_PAE
+#if defined(CONFIG_X86_PAE)
 	int i;
 
 	for (i = 0; i < USER_PTRS_PER_PGD; i++)
 		free_page((unsigned long)__va(pgd_val(pgd[i])-1));
-	kfree(pgd);
+	kmem_cache_free(pae_pgd_cachep, pgd);
 #else
 	free_page((unsigned long)pgd);
 #endif
@@ -104,7 +114,8 @@
 	return pte;
 }
 
-static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
+static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm,
+					unsigned long address)
 {
 	unsigned long *ret;
 
@@ -116,7 +127,7 @@
 	return (pte_t *)ret;
 }
 
-static __inline__ void pte_free_fast(pte_t *pte)
+static inline void pte_free_fast(pte_t *pte)
 {
 	*(unsigned long *)pte = (unsigned long) pte_quicklist;
 	pte_quicklist = (unsigned long *) pte;
@@ -128,14 +139,9 @@
 	free_page((unsigned long)pte);
 }
 
-#define pte_free(pte)		pte_free_fast(pte)
-#ifdef CONFIG_X86_PAE
-#define pgd_alloc(mm)		get_pgd_slow()
+#define pte_free(pte)		pte_free_slow(pte)
 #define pgd_free(pgd)		free_pgd_slow(pgd)
-#else
 #define pgd_alloc(mm)		get_pgd_fast()
-#define pgd_free(pgd)		free_pgd_fast(pgd)
-#endif
 
 /*
  * allocating and freeing a pmd is trivial: the 1-entry pmd is
diff -u --recursive --new-file v2.5.0/linux/include/asm-m68k/machdep.h linux/include/asm-m68k/machdep.h
--- v2.5.0/linux/include/asm-m68k/machdep.h	Mon Nov 27 17:57:34 2000
+++ linux/include/asm-m68k/machdep.h	Wed Nov 28 13:22:26 2001
@@ -1,11 +1,12 @@
 #ifndef _M68K_MACHDEP_H
 #define _M68K_MACHDEP_H
 
+#include <linux/seq_file.h>
+
 struct pt_regs;
 struct kbd_repeat;
 struct mktime;
 struct hwclk_time;
-struct gendisk;
 struct buffer_head;
 
 extern void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *));
@@ -22,7 +23,7 @@
 extern void (*mach_free_irq) (unsigned int irq, void *dev_id);
 extern void (*mach_get_model) (char *model);
 extern int (*mach_get_hardware_list) (char *buffer);
-extern int (*mach_get_irq_list) (char *buf);
+extern int (*mach_get_irq_list) (struct seq_file *p, void *v);
 extern void (*mach_process_int) (int irq, struct pt_regs *fp);
 /* machine dependent timer functions */
 extern unsigned long (*mach_gettimeoffset)(void);
diff -u --recursive --new-file v2.5.0/linux/include/asm-m68k/macintosh.h linux/include/asm-m68k/macintosh.h
--- v2.5.0/linux/include/asm-m68k/macintosh.h	Sun Feb 13 11:21:42 2000
+++ linux/include/asm-m68k/macintosh.h	Wed Nov 28 13:22:26 2001
@@ -1,6 +1,8 @@
 #ifndef __ASM_MACINTOSH_H
 #define __ASM_MACINTOSH_H
 
+#include <linux/seq_file.h>
+
 /*
  *	Apple Macintoshisms
  */
@@ -15,7 +17,7 @@
 extern void mac_enable_irq(unsigned int);
 extern void mac_disable_irq(unsigned int);
 extern int mac_irq_pending(unsigned int);
-extern int mac_get_irq_list(char *);
+extern int show_mac_interrupts(struct seq_file *, void *);
 #if 0
 extern void mac_default_handler(int irq);
 #endif
diff -u --recursive --new-file v2.5.0/linux/include/asm-m68k/sun3ints.h linux/include/asm-m68k/sun3ints.h
--- v2.5.0/linux/include/asm-m68k/sun3ints.h	Mon Jun 11 19:15:27 2001
+++ linux/include/asm-m68k/sun3ints.h	Wed Nov 28 13:22:26 2001
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
+#include <linux/seq_file.h>
 #include <asm/segment.h>
 #include <asm/intersil.h>
 #include <asm/oplib.h>
@@ -32,7 +33,7 @@
 extern void sun3_free_irq (unsigned int irq, void *dev_id);
 extern void sun3_enable_interrupts (void);
 extern void sun3_disable_interrupts (void);
-extern int sun3_get_irq_list(char *buf);
+extern int show_sun3_interrupts(struct seq_file *, void *);
 extern void sun3_process_int(int, struct pt_regs *);
 extern volatile unsigned char* sun3_intreg;
 
diff -u --recursive --new-file v2.5.0/linux/include/asm-ppc/kmap_types.h linux/include/asm-ppc/kmap_types.h
--- v2.5.0/linux/include/asm-ppc/kmap_types.h	Mon Sep 17 13:16:30 2001
+++ linux/include/asm-ppc/kmap_types.h	Tue Nov 27 09:23:27 2001
@@ -11,6 +11,7 @@
 	KM_SKB_DATA_SOFTIRQ,
 	KM_USER0,
 	KM_USER1,
+	KM_BIO_IRQ,
 	KM_TYPE_NR
 };
 
diff -u --recursive --new-file v2.5.0/linux/include/asm-sh/pci.h linux/include/asm-sh/pci.h
--- v2.5.0/linux/include/asm-sh/pci.h	Fri Oct 12 15:35:54 2001
+++ linux/include/asm-sh/pci.h	Tue Dec 11 10:10:18 2001
@@ -196,6 +196,11 @@
 	return 1;
 }
 
+/* Not supporting more than 32-bit PCI bus addresses now, but
+ * must satisfy references to this function.  Change if needed.
+ */
+#define pci_dac_dma_supported(pci_dev, mask) (0)
+
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)	(0)
 
diff -u --recursive --new-file v2.5.0/linux/include/asm-sh/stat.h linux/include/asm-sh/stat.h
--- v2.5.0/linux/include/asm-sh/stat.h	Mon Jul 31 17:38:07 2000
+++ linux/include/asm-sh/stat.h	Tue Dec 11 10:10:18 2001
@@ -42,8 +42,16 @@
  * insane amounts of padding around dev_t's.
  */
 struct stat64 {
+#if defined(__BIG_ENDIAN__)
+	unsigned char   __pad0b[6];
 	unsigned short	st_dev;
-	unsigned char	__pad0[10];
+#elif defined(__LITTLE_ENDIAN__)
+	unsigned short	st_dev;
+	unsigned char	__pad0b[6];
+#else
+#error Must know endian to build stat64 structure!
+#endif
+	unsigned char	__pad0[4];
 
 	unsigned long	st_ino;
 	unsigned int	st_mode;
@@ -52,14 +60,25 @@
 	unsigned long	st_uid;
 	unsigned long	st_gid;
 
+#if defined(__BIG_ENDIAN__)
+	unsigned char	__pad3b[6];
+	unsigned short	st_rdev;
+#else /* Must be little */
 	unsigned short	st_rdev;
-	unsigned char	__pad3[10];
+	unsigned char	__pad3b[6];
+#endif
+	unsigned char	__pad3[4];
 
 	long long	st_size;
 	unsigned long	st_blksize;
 
+#if defined(__BIG_ENDIAN__)
+	unsigned long	__pad4;		/* Future possible st_blocks hi bits */
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+#else /* Must be little */
 	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-	unsigned long	__pad4;		/* future possible st_blocks high bits */
+	unsigned long	__pad4;		/* Future possible st_blocks hi bits */
+#endif
 
 	unsigned long	st_atime;
 	unsigned long	__pad5;
diff -u --recursive --new-file v2.5.0/linux/include/asm-sh/uaccess.h linux/include/asm-sh/uaccess.h
--- v2.5.0/linux/include/asm-sh/uaccess.h	Mon Oct 15 13:36:48 2001
+++ linux/include/asm-sh/uaccess.h	Tue Dec 11 10:10:18 2001
@@ -216,6 +216,7 @@
 	: "r" (val), "m" (__m(addr)), "i" (-EFAULT) \
         : "memory"); })
 #else
+#define __put_user_u64(val,addr,retval) \
 ({ \
 __asm__ __volatile__( \
 	"1:\n\t" \
diff -u --recursive --new-file v2.5.0/linux/include/asm-sparc/kmap_types.h linux/include/asm-sparc/kmap_types.h
--- v2.5.0/linux/include/asm-sparc/kmap_types.h	Mon Sep 17 13:16:30 2001
+++ linux/include/asm-sparc/kmap_types.h	Tue Nov 27 09:23:27 2001
@@ -7,6 +7,7 @@
 	KM_SKB_DATA_SOFTIRQ,
 	KM_USER0,
 	KM_USER1,
+	KM_BIO_IRQ,
 	KM_TYPE_NR
 };
 
diff -u --recursive --new-file v2.5.0/linux/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- v2.5.0/linux/include/asm-sparc64/io.h	Tue Nov 13 09:16:05 2001
+++ linux/include/asm-sparc64/io.h	Mon Dec 10 14:15:19 2001
@@ -18,6 +18,12 @@
 extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr);
 #define bus_to_virt bus_to_virt_not_defined_use_pci_map
 
+extern unsigned long phys_base;
+#define page_to_phys(page)	((((page) - mem_map) << PAGE_SHIFT)+phys_base)
+
+#define BIOVEC_MERGEABLE(vec1, vec2)	\
+	((((bvec_to_phys((vec1)) + (vec1)->bv_len) | bvec_to_phys((vec2))) & (DMA_CHUNK_SIZE - 1)) == 0)
+
 /* Different PCI controllers we support have their PCI MEM space
  * mapped to an either 2GB (Psycho) or 4GB (Sabre) aligned area,
  * so need to chop off the top 33 or 32 bits.
diff -u --recursive --new-file v2.5.0/linux/include/linux/bio.h linux/include/linux/bio.h
--- v2.5.0/linux/include/linux/bio.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/bio.h	Tue Dec 11 09:44:13 2001
@@ -0,0 +1,187 @@
+/*
+ * 2.5 block I/O model
+ *
+ * Copyright (C) 2001 Jens Axboe <axboe@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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 Licens
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-
+ */
+#ifndef __LINUX_BIO_H
+#define __LINUX_BIO_H
+
+#define BIO_DEBUG
+
+#ifdef BIO_DEBUG
+#define BIO_BUG_ON	BUG_ON
+#else
+#define BIO_BUG_ON
+#endif
+
+#define BIO_MAX_SECTORS	128
+
+/*
+ * was unsigned short, but we might as well be ready for > 64kB I/O pages
+ */
+struct bio_vec {
+	struct page	*bv_page;
+	unsigned int	bv_len;
+	unsigned int	bv_offset;
+};
+
+/*
+ * weee, c forward decl...
+ */
+struct bio;
+typedef int (bio_end_io_t) (struct bio *, int);
+typedef void (bio_destructor_t) (struct bio *);
+
+/*
+ * main unit of I/O for the block layer and lower layers (ie drivers and
+ * stacking drivers)
+ */
+struct bio {
+	sector_t		bi_sector;
+	struct bio		*bi_next;	/* request queue link */
+	kdev_t			bi_dev;		/* will be block device */
+	unsigned long		bi_flags;	/* status, command, etc */
+	unsigned long		bi_rw;		/* bottom bits READ/WRITE,
+						 * top bits priority
+						 */
+
+	unsigned short		bi_vcnt;	/* how many bio_vec's */
+	unsigned short		bi_idx;		/* current index into bvl_vec */
+	unsigned short		bi_hw_seg;	/* actual mapped segments */
+	unsigned int		bi_size;	/* residual I/O count */
+	unsigned int		bi_max;		/* max bvl_vecs we can hold,
+						   used as index into pool */
+
+	struct bio_vec		*bi_io_vec;	/* the actual vec list */
+
+	bio_end_io_t		*bi_end_io;
+	atomic_t		bi_cnt;		/* pin count */
+
+	void			*bi_private;
+
+	bio_destructor_t	*bi_destructor;	/* destructor */
+};
+
+/*
+ * bio flags
+ */
+#define BIO_UPTODATE	0	/* ok after I/O completion */
+#define BIO_RW_BLOCK	1	/* RW_AHEAD set, and read/write would block */
+#define BIO_EOF		2	/* out-out-bounds error */
+#define BIO_SEG_VALID	3	/* nr_hw_seg valid */
+#define BIO_CLONED	4	/* doesn't own data */
+
+/*
+ * bio bi_rw flags
+ *
+ * bit 0 -- read (not set) or write (set)
+ * bit 1 -- rw-ahead when set
+ * bit 2 -- barrier
+ */
+#define BIO_RW		0
+#define BIO_RW_AHEAD	1
+#define BIO_RW_BARRIER	2
+
+/*
+ * various member access, note that bio_data should of course not be used
+ * on highmem page vectors
+ */
+#define bio_iovec_idx(bio, idx)	(&((bio)->bi_io_vec[(idx)]))
+#define bio_iovec(bio)		bio_iovec_idx((bio), (bio)->bi_idx)
+#define bio_page(bio)		bio_iovec((bio))->bv_page
+#define bio_offset(bio)		bio_iovec((bio))->bv_offset
+#define bio_sectors(bio)	((bio)->bi_size >> 9)
+#define bio_data(bio)		(page_address(bio_page((bio))) + bio_offset((bio)))
+#define bio_barrier(bio)	((bio)->bi_rw & (1 << BIO_BARRIER))
+
+/*
+ * will die
+ */
+#define bio_to_phys(bio)	(page_to_phys(bio_page((bio))) + (unsigned long) bio_offset((bio)))
+#define bvec_to_phys(bv)	(page_to_phys((bv)->bv_page) + (unsigned long) (bv)->bv_offset)
+
+/*
+ * queues that have highmem support enabled may still need to revert to
+ * PIO transfers occasionally and thus map high pages temporarily. For
+ * permanent PIO fall back, user is probably better off disabling highmem
+ * I/O completely on that queue (see ide-dma for example)
+ */
+#define __bio_kmap(bio, idx) (kmap(bio_iovec_idx((bio), (idx))->bv_page) + bio_iovec_idx((bio), (idx))->bv_offset)
+#define bio_kmap(bio)	__bio_kmap((bio), (bio)->bi_idx)
+#define __bio_kunmap(bio, idx)	kunmap(bio_iovec_idx((bio), (idx))->bv_page)
+#define bio_kunmap(bio)		__bio_kunmap((bio), (bio)->bi_idx)
+
+/*
+ * merge helpers etc
+ */
+#define __BVEC_END(bio)		bio_iovec_idx((bio), (bio)->bi_vcnt - 1)
+#define __BVEC_START(bio)	bio_iovec_idx((bio), 0)
+#define BIO_CONTIG(bio, nxt) \
+	BIOVEC_MERGEABLE(__BVEC_END((bio)), __BVEC_START((nxt)))
+#define __BIO_SEG_BOUNDARY(addr1, addr2, mask) \
+	(((addr1) | (mask)) == (((addr2) - 1) | (mask)))
+#define BIOVEC_SEG_BOUNDARY(q, b1, b2) \
+	__BIO_SEG_BOUNDARY(bvec_to_phys((b1)), bvec_to_phys((b2)) + (b2)->bv_len, (q)->seg_boundary_mask)
+#define BIO_SEG_BOUNDARY(q, b1, b2) \
+	BIOVEC_SEG_BOUNDARY((q), __BVEC_END((b1)), __BVEC_START((b2)))
+
+#define bio_io_error(bio) bio_endio((bio), 0, bio_sectors((bio)))
+
+/*
+ * drivers should not use the __ version unless they _really_ want to
+ * run through the entire bio and not just pending pieces
+ */
+#define __bio_for_each_segment(bvl, bio, i, start_idx)			\
+	for (bvl = bio_iovec_idx((bio), (start_idx)), i = (start_idx);	\
+	     i < (bio)->bi_vcnt;					\
+	     bvl++, i++)
+
+#define bio_for_each_segment(bvl, bio, i)				\
+	__bio_for_each_segment(bvl, bio, i, (bio)->bi_idx)
+
+/*
+ * get a reference to a bio, so it won't disappear. the intended use is
+ * something like:
+ *
+ * bio_get(bio);
+ * submit_bio(rw, bio);
+ * if (bio->bi_flags ...)
+ *	do_something
+ * bio_put(bio);
+ *
+ * without the bio_get(), it could potentially complete I/O before submit_bio
+ * returns. and then bio would be freed memory when if (bio->bi_flags ...)
+ * runs
+ */
+#define bio_get(bio)	atomic_inc(&(bio)->bi_cnt)
+
+extern struct bio *bio_alloc(int, int);
+extern void bio_put(struct bio *);
+
+extern int bio_endio(struct bio *, int, int);
+struct request_queue;
+extern inline int bio_hw_segments(struct request_queue *, struct bio *);
+
+extern inline void __bio_clone(struct bio *, struct bio *);
+extern struct bio *bio_clone(struct bio *, int);
+extern struct bio *bio_copy(struct bio *, int, int);
+
+extern inline void bio_init(struct bio *);
+
+extern int bio_ioctl(kdev_t, unsigned int, unsigned long);
+
+#endif /* __LINUX_BIO_H */
diff -u --recursive --new-file v2.5.0/linux/include/linux/blk.h linux/include/linux/blk.h
--- v2.5.0/linux/include/linux/blk.h	Thu Nov 22 11:48:07 2001
+++ linux/include/linux/blk.h	Tue Dec 11 09:52:26 2001
@@ -5,65 +5,15 @@
 #include <linux/locks.h>
 #include <linux/config.h>
 #include <linux/spinlock.h>
+#include <linux/compiler.h>
 
 /*
- * Spinlock for protecting the request queue which
- * is mucked around with in interrupts on potentially
- * multiple CPU's..
+ * get rid of this next...
  */
-extern spinlock_t io_request_lock;
-
-/*
- * Initialization functions.
- */
-extern int isp16_init(void);
-extern int cdu31a_init(void);
-extern int acsi_init(void);
-extern int mcd_init(void);
-extern int mcdx_init(void);
-extern int sbpcd_init(void);
-extern int aztcd_init(void);
-extern int sony535_init(void);
-extern int gscd_init(void);
-extern int cm206_init(void);
-extern int optcd_init(void);
-extern int sjcd_init(void);
-extern int cdi_init(void);
-extern int hd_init(void);
 extern int ide_init(void);
-extern int xd_init(void);
-extern int mfm_init(void);
-extern int loop_init(void);
-extern int md_init(void);
-extern int ap_init(void);
-extern int ddv_init(void);
-extern int z2_init(void);
-extern int swim3_init(void);
-extern int swimiop_init(void);
-extern int amiga_floppy_init(void);
-extern int atari_floppy_init(void);
-extern int ez_init(void);
-extern int bpcd_init(void);
-extern int ps2esdi_init(void);
-extern int jsfd_init(void);
-extern int viodasd_init(void);
-extern int viocd_init(void);
-
-#if defined(CONFIG_ARCH_S390)
-extern int dasd_init(void);
-extern int xpram_init(void);
-extern int tapeblock_init(void);
-#endif /* CONFIG_ARCH_S390 */
 
 extern void set_device_ro(kdev_t dev,int flag);
-void add_blkdev_randomness(int major);
-
-extern int floppy_init(void);
-extern void rd_load(void);
-extern int rd_init(void);
-extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
-extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
-extern int rd_image_start;	/* starting block # of image */
+extern void add_blkdev_randomness(int major);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 
@@ -72,11 +22,12 @@
 extern unsigned long initrd_start,initrd_end;
 extern int mount_initrd; /* zero if initrd should not be mounted */
 extern int initrd_below_start_ok; /* 1 if it is not an error if initrd_start < memory_start */
+extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;	/* starting block # of image */
 void initrd_init(void);
 
 #endif
-
-		 
 /*
  * end_request() and friends. Must be called with the request queue spinlock
  * acquired. All functions called within end_request() _must_be_ atomic.
@@ -87,14 +38,61 @@
  * code duplication in drivers.
  */
 
-static inline void blkdev_dequeue_request(struct request * req)
+extern int end_that_request_first(struct request *, int, int);
+extern void end_that_request_last(struct request *);
+
+static inline void blkdev_dequeue_request(struct request *req)
+{
+	list_del(&req->queuelist);
+}
+
+#define __elv_next_request(q)	(q)->elevator.elevator_next_req_fn((q))
+
+extern inline struct request *elv_next_request(request_queue_t *q)
 {
-	list_del(&req->queue);
+	struct request *rq;
+
+	while ((rq = __elv_next_request(q))) {
+		rq->flags |= REQ_STARTED;
+
+		if ((rq->flags & REQ_DONTPREP) || !q->prep_rq_fn)
+			break;
+
+		/*
+		 * all ok, break and return it
+		 */
+		if (!q->prep_rq_fn(q, rq))
+			break;
+
+		/*
+		 * prep said no-go, kill it
+		 */
+		blkdev_dequeue_request(rq);
+		if (end_that_request_first(rq, 0, rq->nr_sectors))
+			BUG();
+
+		end_that_request_last(rq);
+	}
+
+	return rq;
 }
 
-int end_that_request_first(struct request *req, int uptodate, char *name);
-void end_that_request_last(struct request *req);
+#define __elv_add_request_core(q, rq, where, plug)			\
+	do {								\
+		if ((plug))						\
+			blk_plug_device((q));				\
+		(q)->elevator.elevator_add_req_fn((q), (rq), (where));	\
+	} while (0)
+
+#define __elv_add_request(q, rq, back, p) do {				      \
+	if ((back))							      \
+		__elv_add_request_core((q), (rq), (q)->queue_head.prev, (p)); \
+	else								      \
+		__elv_add_request_core((q), (rq), &(q)->queue_head, 0);	      \
+} while (0)
 
+#define elv_add_request(q, rq, back) __elv_add_request((q), (rq), (back), 1)
+	
 #if defined(MAJOR_NR) || defined(IDE_DRIVER)
 
 #undef DEVICE_ON
@@ -338,12 +336,16 @@
 #if !defined(IDE_DRIVER)
 
 #ifndef CURRENT
-#define CURRENT blkdev_entry_next_request(&blk_dev[MAJOR_NR].request_queue.queue_head)
+#define CURRENT elv_next_request(&blk_dev[MAJOR_NR].request_queue)
+#endif
+#ifndef QUEUE
+#define QUEUE (&blk_dev[MAJOR_NR].request_queue)
 #endif
 #ifndef QUEUE_EMPTY
-#define QUEUE_EMPTY list_empty(&blk_dev[MAJOR_NR].request_queue.queue_head)
+#define QUEUE_EMPTY blk_queue_empty(QUEUE)
 #endif
 
+
 #ifndef DEVICE_NAME
 #define DEVICE_NAME "unknown"
 #endif
@@ -366,17 +368,15 @@
 #define CLEAR_INTR
 #endif
 
-#define INIT_REQUEST \
-	if (QUEUE_EMPTY) {\
-		CLEAR_INTR; \
-		return; \
-	} \
-	if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \
-		panic(DEVICE_NAME ": request list destroyed"); \
-	if (CURRENT->bh) { \
-		if (!buffer_locked(CURRENT->bh)) \
-			panic(DEVICE_NAME ": block not locked"); \
-	}
+#define INIT_REQUEST						\
+	if (QUEUE_EMPTY) {					\
+		CLEAR_INTR;					\
+		return;						\
+	}							\
+	if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) 		\
+		panic(DEVICE_NAME ": request list destroyed");	\
+	if (!CURRENT->bio)					\
+		panic(DEVICE_NAME ": no bio");			\
 
 #endif /* !defined(IDE_DRIVER) */
 
@@ -385,10 +385,11 @@
 
 #if ! SCSI_BLK_MAJOR(MAJOR_NR) && (MAJOR_NR != COMPAQ_SMART2_MAJOR)
 
-static inline void end_request(int uptodate) {
+static inline void end_request(int uptodate)
+{
 	struct request *req = CURRENT;
 
-	if (end_that_request_first(req, uptodate, DEVICE_NAME))
+	if (end_that_request_first(req, uptodate, CURRENT->hard_cur_sectors))
 		return;
 
 #ifndef DEVICE_NO_RANDOM
diff -u --recursive --new-file v2.5.0/linux/include/linux/blkdev.h linux/include/linux/blkdev.h
--- v2.5.0/linux/include/linux/blkdev.h	Thu Nov 22 11:47:08 2001
+++ linux/include/linux/blkdev.h	Tue Dec 11 09:51:40 2001
@@ -6,71 +6,116 @@
 #include <linux/genhd.h>
 #include <linux/tqueue.h>
 #include <linux/list.h>
+#include <linux/mm.h>
+
+#include <asm/scatterlist.h>
 
 struct request_queue;
 typedef struct request_queue request_queue_t;
 struct elevator_s;
 typedef struct elevator_s elevator_t;
 
-/*
- * Ok, this is an expanded form so that we can use the same
- * request for paging requests.
- */
+struct request_list {
+	unsigned int count;
+	struct list_head free;
+	wait_queue_head_t wait;
+};
+
 struct request {
-	struct list_head queue;
+	struct list_head queuelist; /* looking for ->queue? you must _not_
+				     * access it directly, use
+				     * blkdev_dequeue_request! */
 	int elevator_sequence;
 
-	volatile int rq_status;	/* should split this into a few status bits */
-#define RQ_INACTIVE		(-1)
-#define RQ_ACTIVE		1
-#define RQ_SCSI_BUSY		0xffff
-#define RQ_SCSI_DONE		0xfffe
-#define RQ_SCSI_DISCONNECTING	0xffe0
+	unsigned char cmd[16];
 
+	unsigned long flags;		/* see REQ_ bits below */
+
+	int rq_status;	/* should split this into a few status bits */
 	kdev_t rq_dev;
-	int cmd;		/* READ or WRITE */
 	int errors;
-	unsigned long sector;
+	sector_t sector;
 	unsigned long nr_sectors;
-	unsigned long hard_sector, hard_nr_sectors;
-	unsigned int nr_segments;
-	unsigned int nr_hw_segments;
-	unsigned long current_nr_sectors;
-	void * special;
-	char * buffer;
-	struct completion * waiting;
-	struct buffer_head * bh;
-	struct buffer_head * bhtail;
+	unsigned long hard_sector;	/* the hard_* are block layer
+					 * internals, no driver should
+					 * touch them
+					 */
+	unsigned long hard_nr_sectors;
+	unsigned short nr_segments;
+	unsigned short nr_hw_segments;
+	unsigned int current_nr_sectors;
+	unsigned int hard_cur_sectors;
+	void *special;
+	char *buffer;
+	struct completion *waiting;
+	struct bio *bio, *biotail;
 	request_queue_t *q;
+	struct request_list *rl;
 };
 
+/*
+ * first three bits match BIO_RW* bits, important
+ */
+enum rq_flag_bits {
+	__REQ_RW,	/* not set, read. set, write */
+	__REQ_RW_AHEAD,	/* READA */
+	__REQ_BARRIER,	/* may not be passed */
+	__REQ_CMD,	/* is a regular fs rw request */
+	__REQ_NOMERGE,	/* don't touch this for merging */
+	__REQ_STARTED,	/* drive already may have started this one */
+	__REQ_DONTPREP,	/* don't call prep for this one */
+	/*
+	 * for IDE
+ 	*/
+	__REQ_DRIVE_CMD,
+	__REQ_DRIVE_TASK,
+
+	__REQ_PC,	/* packet command (special) */
+	__REQ_BLOCK_PC,	/* queued down pc from block layer */
+	__REQ_SENSE,	/* sense retrival */
+
+	__REQ_SPECIAL,	/* driver special command */
+
+	__REQ_NR_BITS,	/* stops here */
+};
+
+#define REQ_RW		(1 << __REQ_RW)
+#define REQ_RW_AHEAD	(1 << __REQ_RW_AHEAD)
+#define REQ_BARRIER	(1 << __REQ_BARRIER)
+#define REQ_CMD		(1 << __REQ_CMD)
+#define REQ_NOMERGE	(1 << __REQ_NOMERGE)
+#define REQ_STARTED	(1 << __REQ_STARTED)
+#define REQ_DONTPREP	(1 << __REQ_DONTPREP)
+#define REQ_DRIVE_CMD	(1 << __REQ_DRIVE_CMD)
+#define REQ_DRIVE_TASK	(1 << __REQ_DRIVE_TASK)
+#define REQ_PC		(1 << __REQ_PC)
+#define REQ_SENSE	(1 << __REQ_SENSE)
+#define REQ_BLOCK_PC	(1 << __REQ_BLOCK_PC)
+#define REQ_SPECIAL	(1 << __REQ_SPECIAL)
+
 #include <linux/elevator.h>
 
-typedef int (merge_request_fn) (request_queue_t *q, 
-				struct request  *req,
-				struct buffer_head *bh,
-				int);
-typedef int (merge_requests_fn) (request_queue_t *q, 
-				 struct request  *req,
-				 struct request  *req2,
-				 int);
+typedef int (merge_request_fn) (request_queue_t *, struct request *,
+				struct bio *);
+typedef int (merge_requests_fn) (request_queue_t *, struct request *,
+				 struct request *);
 typedef void (request_fn_proc) (request_queue_t *q);
 typedef request_queue_t * (queue_proc) (kdev_t dev);
-typedef int (make_request_fn) (request_queue_t *q, int rw, struct buffer_head *bh);
-typedef void (plug_device_fn) (request_queue_t *q, kdev_t device);
+typedef int (make_request_fn) (request_queue_t *q, struct bio *bio);
+typedef int (prep_rq_fn) (request_queue_t *, struct request *);
 typedef void (unplug_device_fn) (void *q);
 
+enum blk_queue_state {
+	Queue_down,
+	Queue_up,
+};
+
 /*
  * Default nr free requests per queue, ll_rw_blk will scale it down
  * according to available RAM at init time
  */
 #define QUEUE_NR_REQUESTS	8192
 
-struct request_list {
-	unsigned int count;
-	struct list_head free;
-};
-
 struct request_queue
 {
 	/*
@@ -84,46 +129,99 @@
 	struct list_head	queue_head;
 	elevator_t		elevator;
 
-	request_fn_proc		* request_fn;
-	merge_request_fn	* back_merge_fn;
-	merge_request_fn	* front_merge_fn;
-	merge_requests_fn	* merge_requests_fn;
-	make_request_fn		* make_request_fn;
-	plug_device_fn		* plug_device_fn;
+	request_fn_proc		*request_fn;
+	merge_request_fn	*back_merge_fn;
+	merge_request_fn	*front_merge_fn;
+	merge_requests_fn	*merge_requests_fn;
+	make_request_fn		*make_request_fn;
+	prep_rq_fn		*prep_rq_fn;
+
 	/*
 	 * The queue owner gets to use this for whatever they like.
 	 * ll_rw_blk doesn't touch it.
 	 */
-	void			* queuedata;
+	void			*queuedata;
 
 	/*
-	 * This is used to remove the plug when tq_disk runs.
+	 * queue needs bounce pages for pages above this limit
 	 */
-	struct tq_struct	plug_tq;
+	unsigned long		bounce_pfn;
 
 	/*
-	 * Boolean that indicates whether this queue is plugged or not.
+	 * This is used to remove the plug when tq_disk runs.
 	 */
-	char			plugged;
+	struct tq_struct	plug_tq;
 
 	/*
-	 * Boolean that indicates whether current_request is active or
-	 * not.
+	 * various queue flags, see QUEUE_* below
 	 */
-	char			head_active;
+	unsigned long		queue_flags;
 
 	/*
-	 * Is meant to protect the queue in the future instead of
-	 * io_request_lock
+	 * protects queue structures from reentrancy
 	 */
 	spinlock_t		queue_lock;
 
 	/*
-	 * Tasks wait here for free request
+	 * queue settings
 	 */
-	wait_queue_head_t	wait_for_request;
+	unsigned short		max_sectors;
+	unsigned short		max_segments;
+	unsigned short		hardsect_size;
+	unsigned int		max_segment_size;
+
+	unsigned long		seg_boundary_mask;
+
+	wait_queue_head_t	queue_wait;
 };
 
+#define RQ_INACTIVE		(-1)
+#define RQ_ACTIVE		1
+#define RQ_SCSI_BUSY		0xffff
+#define RQ_SCSI_DONE		0xfffe
+#define RQ_SCSI_DISCONNECTING	0xffe0
+
+#define QUEUE_FLAG_PLUGGED	0	/* queue is plugged */
+#define QUEUE_FLAG_NOSPLIT	1	/* can process bio over several goes */
+#define QUEUE_FLAG_CLUSTER	2	/* cluster several segments into 1 */
+
+#define blk_queue_plugged(q)	test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
+#define blk_mark_plugged(q)	set_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
+#define blk_queue_empty(q)	elv_queue_empty(q)
+#define list_entry_rq(ptr)	list_entry((ptr), struct request, queuelist)
+
+#define rq_data_dir(rq)		((rq)->flags & 1)
+
+/*
+ * noop, requests are automagically marked as active/inactive by I/O
+ * scheduler -- see elv_next_request
+ */
+#define blk_queue_headactive(q, head_active)
+
+extern unsigned long blk_max_low_pfn, blk_max_pfn;
+
+#define BLK_BOUNCE_HIGH	(blk_max_low_pfn << PAGE_SHIFT)
+#define BLK_BOUNCE_ANY	(blk_max_pfn << PAGE_SHIFT)
+
+#ifdef CONFIG_HIGHMEM
+
+extern void create_bounce(unsigned long pfn, struct bio **bio_orig);
+
+extern inline void blk_queue_bounce(request_queue_t *q, struct bio **bio)
+{
+	create_bounce(q->bounce_pfn, bio);
+}
+
+#else /* CONFIG_HIGHMEM */
+
+#define blk_queue_bounce(q, bio)	do { } while (0)
+
+#endif /* CONFIG_HIGHMEM */
+
+#define rq_for_each_bio(bio, rq)	\
+	if ((rq->bio))			\
+		for (bio = (rq)->bio; bio; bio = bio->bi_next)
+
 struct blk_dev_struct {
 	/*
 	 * queue_proc has to be atomic
@@ -148,68 +246,86 @@
 
 extern struct sec_size * blk_sec[MAX_BLKDEV];
 extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
-extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size);
+extern void grok_partitions(kdev_t dev, long size);
+extern int wipe_partitions(kdev_t dev);
 extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
-extern void generic_make_request(int rw, struct buffer_head * bh);
+extern void generic_make_request(struct bio *bio);
 extern inline request_queue_t *blk_get_queue(kdev_t dev);
 extern void blkdev_release_request(struct request *);
+extern void blk_attempt_remerge(request_queue_t *, struct request *);
+extern struct request *blk_get_request(request_queue_t *, int, int);
+extern void blk_put_request(struct request *);
+extern void blk_plug_device(request_queue_t *);
+extern void blk_recount_segments(request_queue_t *, struct bio *);
+extern inline int blk_contig_segment(request_queue_t *q, struct bio *, struct bio *);
+
+extern int block_ioctl(kdev_t, unsigned int, unsigned long);
 
 /*
  * Access functions for manipulating queue properties
  */
-extern void blk_init_queue(request_queue_t *, request_fn_proc *);
+extern int blk_init_queue(request_queue_t *, request_fn_proc *);
 extern void blk_cleanup_queue(request_queue_t *);
-extern void blk_queue_headactive(request_queue_t *, int);
 extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
+extern void blk_queue_bounce_limit(request_queue_t *, u64);
+extern void blk_queue_max_sectors(request_queue_t *q, unsigned short);
+extern void blk_queue_max_segments(request_queue_t *q, unsigned short);
+extern void blk_queue_max_segment_size(request_queue_t *q, unsigned int);
+extern void blk_queue_hardsect_size(request_queue_t *q, unsigned short);
+extern void blk_queue_segment_boundary(request_queue_t *q, unsigned long);
+extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
+extern void blk_dump_rq_flags(struct request *, char *);
 extern void generic_unplug_device(void *);
 
 extern int * blk_size[MAX_BLKDEV];
 
 extern int * blksize_size[MAX_BLKDEV];
 
-extern int * hardsect_size[MAX_BLKDEV];
-
 extern int * max_readahead[MAX_BLKDEV];
 
-extern int * max_sectors[MAX_BLKDEV];
-
-extern int * max_segments[MAX_BLKDEV];
-
 #define MAX_SEGMENTS 128
 #define MAX_SECTORS 255
 
-#define PageAlignSize(size) (((size) + PAGE_SIZE -1) & PAGE_MASK)
+#define MAX_SEGMENT_SIZE	65536
 
 /* read-ahead in pages.. */
 #define MAX_READAHEAD	31
 #define MIN_READAHEAD	3
 
-#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queue)
+#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
 #define blkdev_entry_next_request(entry) blkdev_entry_to_request((entry)->next)
 #define blkdev_entry_prev_request(entry) blkdev_entry_to_request((entry)->prev)
-#define blkdev_next_request(req) blkdev_entry_to_request((req)->queue.next)
-#define blkdev_prev_request(req) blkdev_entry_to_request((req)->queue.prev)
+#define blkdev_next_request(req) blkdev_entry_to_request((req)->queuelist.next)
+#define blkdev_prev_request(req) blkdev_entry_to_request((req)->queuelist.prev)
 
-extern void drive_stat_acct (kdev_t dev, int rw,
-					unsigned long nr_sectors, int new_io);
+extern void drive_stat_acct(struct request *, int, int);
 
-static inline int get_hardsect_size(kdev_t dev)
+extern inline void blk_clear(int major)
 {
+	blk_size[major] = NULL;
+#if 0
+	blk_size_in_bytes[major] = NULL;
+#endif
+	blksize_size[major] = NULL;
+	max_readahead[major] = NULL;
+	read_ahead[major] = 0;
+}
+
+extern inline int get_hardsect_size(kdev_t dev)
+{
+	request_queue_t *q = blk_get_queue(dev);
 	int retval = 512;
-	int major = MAJOR(dev);
 
-	if (hardsect_size[major]) {
-		int minor = MINOR(dev);
-		if (hardsect_size[major][minor])
-			retval = hardsect_size[major][minor];
-	}
+	if (q && q->hardsect_size)
+		retval = q->hardsect_size;
+
 	return retval;
 }
 
 #define blk_finished_io(nsects)	do { } while (0)
 #define blk_started_io(nsects)	do { } while (0)
 
-static inline unsigned int blksize_bits(unsigned int size)
+extern inline unsigned int blksize_bits(unsigned int size)
 {
 	unsigned int bits = 8;
 	do {
@@ -219,7 +335,7 @@
 	return bits;
 }
 
-static inline unsigned int block_size(kdev_t dev)
+extern inline unsigned int block_size(kdev_t dev)
 {
 	int retval = BLOCK_SIZE;
 	int major = MAJOR(dev);
diff -u --recursive --new-file v2.5.0/linux/include/linux/bootmem.h linux/include/linux/bootmem.h
--- v2.5.0/linux/include/linux/bootmem.h	Thu Nov 22 11:47:23 2001
+++ linux/include/linux/bootmem.h	Tue Dec 11 09:52:48 2001
@@ -18,6 +18,11 @@
 extern unsigned long min_low_pfn;
 
 /*
+ * highest page
+ */
+extern unsigned long max_pfn;
+
+/*
  * node_bootmem_map is a map pointer - the bits represent all physical 
  * memory pages (including holes) on the node.
  */
diff -u --recursive --new-file v2.5.0/linux/include/linux/cache.h linux/include/linux/cache.h
--- v2.5.0/linux/include/linux/cache.h	Thu Nov 22 11:46:18 2001
+++ linux/include/linux/cache.h	Tue Dec 11 09:51:33 2001
@@ -34,4 +34,12 @@
 #endif
 #endif /* __cacheline_aligned */
 
+#ifndef __cacheline_aligned_in_smp
+#ifdef CONFIG_SMP
+#define __cacheline_aligned_in_smp __cacheline_aligned
+#else
+#define __cacheline_aligned_in_smp
+#endif /* CONFIG_SMP */
+#endif
+
 #endif /* __LINUX_CACHE_H */
diff -u --recursive --new-file v2.5.0/linux/include/linux/coda_linux.h linux/include/linux/coda_linux.h
--- v2.5.0/linux/include/linux/coda_linux.h	Wed Apr 25 16:18:54 2001
+++ linux/include/linux/coda_linux.h	Wed Dec  5 13:02:14 2001
@@ -92,12 +92,6 @@
     printk(format, ## a); }                                       \
 } while (0)
 
-#define ENTRY    \
-    if(coda_print_entry) printk("Process %d entered %s\n",current->pid,__FUNCTION__)
-
-#define EXIT    \
-    if(coda_print_entry) printk("Process %d leaving %s\n",current->pid,__FUNCTION__)
-
 #define CODA_ALLOC(ptr, cast, size)                                       \
 do {                                                                      \
     if (size < PAGE_SIZE) {                                               \
diff -u --recursive --new-file v2.5.0/linux/include/linux/devfs_fs_kernel.h linux/include/linux/devfs_fs_kernel.h
--- v2.5.0/linux/include/linux/devfs_fs_kernel.h	Thu Nov 22 11:47:00 2001
+++ linux/include/linux/devfs_fs_kernel.h	Tue Dec 11 09:51:33 2001
@@ -3,7 +3,7 @@
 
 #include <linux/fs.h>
 #include <linux/config.h>
-#include <linux/locks.h>
+#include <linux/spinlock.h>
 #include <linux/kdev_t.h>
 #include <linux/types.h>
 
diff -u --recursive --new-file v2.5.0/linux/include/linux/device.h linux/include/linux/device.h
--- v2.5.0/linux/include/linux/device.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/device.h	Tue Dec 11 09:51:34 2001
@@ -0,0 +1,253 @@
+/*
+ * device.h - generic, centralized driver model
+ *
+ * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
+ *
+ * This is a relatively simple centralized driver model.
+ * The data structures were mainly lifted directly from the PCI
+ * driver model. These are thought to be the common fields that
+ * are relevant to all device buses.
+ *
+ * All the devices are arranged in a tree. All devices should
+ * have some sort of parent bus of whom they are children of.
+ * Devices should not be direct children of the system root.
+ *
+ * Device drivers should not directly call the device_* routines
+ * or access the contents of struct device directly. Instead,
+ * abstract that from the drivers and write bus-specific wrappers
+ * that do it for you.
+ *
+ * See Documentation/driver-model.txt for more information.
+ */
+
+#ifndef _DEVICE_H_
+#define _DEVICE_H_
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/ioport.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/driverfs_fs.h>
+
+#define DEVICE_NAME_SIZE	80
+#define DEVICE_ID_SIZE		32
+#define BUS_ID_SIZE		16
+
+
+enum {
+	SUSPEND_NOTIFY,
+	SUSPEND_SAVE_STATE,
+	SUSPEND_DISABLE,
+	SUSPEND_POWER_DOWN,
+};
+
+enum {
+	RESUME_POWER_ON,
+	RESUME_RESTORE_STATE,
+	RESUME_ENABLE,
+};
+
+enum {
+	REMOVE_NOTIFY,
+	REMOVE_FREE_RESOURCES,
+};
+
+struct device;
+struct iobus;
+
+struct device_driver {
+	int	(*probe)	(struct device * dev);
+	int 	(*remove)	(struct device * dev, u32 flags);
+
+	int	(*suspend)	(struct device * dev, u32 state, u32 stage);
+	int	(*resume)	(struct device * dev, u32 stage);
+};
+
+struct device {
+	struct list_head node;		/* node in sibling list */
+	struct iobus	*parent;	/* parent bus */
+
+	struct iobus	*subordinate;	/* only valid if this device is a
+					   bridge device */
+
+	char	name[DEVICE_NAME_SIZE];	/* descriptive ascii string */
+	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
+
+	spinlock_t	lock;		/* lock for the device to ensure two
+					   different layers don't access it at
+					   the same time. */
+	atomic_t	refcount;	/* refcount to make sure the device
+					 * persists for the right amount of time */
+
+	struct driver_dir_entry	* dir;
+
+	struct device_driver *driver;	/* which driver has allocated this
+					   device */
+	void		*driver_data;	/* data private to the driver */
+	void		*platform_data;	/* Platform specific data (e.g. ACPI,
+					   BIOS data relevant to device */
+
+	u32		current_state;  /* Current operating state. In
+					   ACPI-speak, this is D0-D3, D0
+					   being fully functional, and D3
+					   being off. */
+
+	unsigned char *saved_state;	/* saved device state */
+};
+
+/*
+ * struct bus_type - descriptor for a type of bus
+ * There are some instances when you need to know what type of bus a
+ * device is on. Instead of having some sort of enumerated integer type,
+ * each struct iobus will have a pointer to a struct bus_type that gives
+ * actually meaningful data.
+ * There should be one struct bus_type for each type of bus (one for PCI,
+ * one for USB, etc).
+ */
+struct iobus_driver {
+	char	name[16];	/* ascii descriptor of type of bus */
+	struct	list_head node; /* node in global list of bus drivers */
+
+	int	(*scan)		(struct iobus*);
+	int	(*add_device)	(struct iobus*, char*);
+};
+
+struct iobus {
+	spinlock_t	lock;		/* lock for bus */
+	atomic_t	refcount;
+
+	struct list_head node;		/* node in sibling list */
+	struct iobus *parent;		/* parent bus */
+	struct list_head children;	/* children buses */
+	struct list_head devices;	/* children devices */
+
+	struct device *self;		/* pointer to controlling device */
+	struct driver_dir_entry	* dir;	/* driverfs directory */
+
+	char	name[DEVICE_NAME_SIZE];
+	char	bus_id[BUS_ID_SIZE];
+
+	struct	iobus_driver *driver;	/* bus operations */
+};
+
+static inline struct device *
+list_to_dev(struct list_head *node)
+{
+	return list_entry(node, struct device, node);
+}
+
+static inline struct iobus *
+list_to_iobus(const struct list_head *node)
+{
+	return list_entry(node, struct iobus, node);
+}
+
+/*
+ * High level routines for use by the bus drivers
+ */
+extern int device_register(struct device * dev);
+extern struct device * device_alloc(void);
+extern void device_init_dev(struct device * dev);
+
+extern int iobus_register(struct iobus * iobus);
+extern struct iobus * iobus_alloc(void);
+extern void iobus_init(struct iobus * iobus);
+
+extern int device_create_file(struct device *device, const char * name, mode_t mode,
+			      struct driverfs_operations * ops, void * data);
+extern void device_remove_file(struct device * dev, const char * name);
+
+extern int iobus_create_file(struct iobus *bus, const char * name, mode_t mode,
+			     struct driverfs_operations * ops, void * data);
+extern void iobus_remove_file(struct iobus * iobus, const char * name);
+
+
+/*
+ * Platform "fixup" functions - allow the platform to have their say
+ * about devices and actions that the general device layer doesn't
+ * know about.
+ */
+/* Notify platform of device discovery */
+extern int (*platform_notify)(struct device * dev);
+
+extern int (*platform_notify_remove)(struct device * dev);
+
+extern int device_driver_init(void);
+
+
+/* device and bus locking helpers.
+ *
+ * FIXME: Is there anything else we need to do?
+ */
+static inline void lock_device(struct device * dev)
+{
+	spin_lock(&dev->lock);
+}
+
+static inline void unlock_device(struct device * dev)
+{
+	spin_unlock(&dev->lock);
+}
+
+/**
+ * get_device - atomically increment the reference count for the device.
+ *
+ */
+static inline void get_device(struct device * dev)
+{
+	atomic_inc(&dev->refcount);
+}
+
+extern void put_device(struct device * dev);
+
+
+/**
+ * valid_device - check if device is valid
+ * @dev:	device in question
+ *
+ * Check whether or not a device can be operated on.
+ * If so, increment the reference count and carry on.
+ */
+static inline int valid_device(struct device * dev)
+{
+	int val;
+
+	lock_device(dev);
+	val = atomic_read(&dev->refcount);
+	if (val)
+		get_device(dev);
+	unlock_device(dev);
+	return (val > 0);
+}
+
+
+static inline void lock_iobus(struct iobus * iobus)
+{
+	spin_lock(&iobus->lock);
+}
+
+static inline void unlock_iobus(struct iobus * iobus)
+{
+	spin_unlock(&iobus->lock);
+}
+
+static inline void get_iobus(struct iobus * iobus)
+{
+	atomic_inc(&iobus->refcount);
+}
+
+static inline int valid_iobus(struct iobus * iobus)
+{
+	int val;
+	lock_iobus(iobus);
+	val = atomic_read(&iobus->refcount);
+	if (val)
+		get_iobus(iobus);
+	unlock_iobus(iobus);
+	return (val > 0);
+}
+
+extern void put_iobus(struct iobus * iobus);
+
+#endif /* _DEVICE_H_ */
diff -u --recursive --new-file v2.5.0/linux/include/linux/driverfs_fs.h linux/include/linux/driverfs_fs.h
--- v2.5.0/linux/include/linux/driverfs_fs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/driverfs_fs.h	Thu Nov 29 16:55:11 2001
@@ -0,0 +1,73 @@
+/*
+ * driverfs_fs.h - definitions for the device driver filesystem
+ *
+ * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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
+ *
+ * This is a simple, ram-based filesystem, which allows kernel
+ * callbacks for read/write of files.
+ *
+ * Please see Documentation/filesystems/driverfs.txt for more information.
+ */
+
+#ifndef _DRIVER_FS_H_
+#define _DRIVER_FS_H_
+
+struct driverfs_operations {
+	ssize_t	(*read) (char *, size_t, loff_t, void *);
+	ssize_t (*write)(const char *, size_t, loff_t, void*);
+};
+
+struct driver_dir_entry {
+	char			* name;
+	struct dentry		* dentry;
+	mode_t			mode;
+	struct list_head	files;
+};
+
+struct driver_file_entry {
+	struct driver_dir_entry * parent;
+	struct list_head	node;
+	char			* name;
+	mode_t			mode;
+	struct dentry		* dentry;
+	void			* data;
+	struct driverfs_operations	* ops;
+};
+
+extern struct driver_dir_entry *
+driverfs_create_dir_entry(const char * name, mode_t mode);
+
+extern int
+driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
+
+extern void
+driverfs_remove_dir(struct driver_dir_entry * entry);
+
+extern struct driver_file_entry *
+driverfs_create_entry (const char * name, mode_t mode,
+		       struct driverfs_operations * ops, void * data);
+
+extern int
+driverfs_create_file(struct driver_file_entry * entry,
+		     struct driver_dir_entry * parent);
+
+extern void
+driverfs_remove_file(struct driver_dir_entry *, const char * name);
+
+extern int init_driverfs_fs(void);
+
+#endif /* _DDFS_H_ */
diff -u --recursive --new-file v2.5.0/linux/include/linux/elevator.h linux/include/linux/elevator.h
--- v2.5.0/linux/include/linux/elevator.h	Thu Feb 15 16:58:34 2001
+++ linux/include/linux/elevator.h	Wed Nov 28 08:49:23 2001
@@ -5,13 +5,20 @@
 			    struct list_head *,
 			    struct list_head *, int);
 
-typedef int (elevator_merge_fn) (request_queue_t *, struct request **, struct list_head *,
-				 struct buffer_head *, int, int);
+typedef int (elevator_merge_fn) (request_queue_t *, struct request **,
+				 struct list_head *, struct bio *);
 
 typedef void (elevator_merge_cleanup_fn) (request_queue_t *, struct request *, int);
 
 typedef void (elevator_merge_req_fn) (struct request *, struct request *);
 
+typedef struct request *(elevator_next_req_fn) (request_queue_t *);
+
+typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *);
+
+typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
+typedef void (elevator_exit_fn) (request_queue_t *, elevator_t *);
+
 struct elevator_s
 {
 	int read_latency;
@@ -21,31 +28,39 @@
 	elevator_merge_cleanup_fn *elevator_merge_cleanup_fn;
 	elevator_merge_req_fn *elevator_merge_req_fn;
 
-	unsigned int queue_ID;
+	elevator_next_req_fn *elevator_next_req_fn;
+	elevator_add_req_fn *elevator_add_req_fn;
+
+	elevator_init_fn *elevator_init_fn;
+	elevator_exit_fn *elevator_exit_fn;
 };
 
-int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int);
+int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct bio *);
 void elevator_noop_merge_cleanup(request_queue_t *, struct request *, int);
 void elevator_noop_merge_req(struct request *, struct request *);
 
-int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int);
+int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct bio *);
 void elevator_linus_merge_cleanup(request_queue_t *, struct request *, int);
 void elevator_linus_merge_req(struct request *, struct request *);
+int elv_linus_init(request_queue_t *, elevator_t *);
+void elv_linus_exit(request_queue_t *, elevator_t *);
+struct request *elv_next_request_fn(request_queue_t *);
+void elv_add_request_fn(request_queue_t *, struct request *,struct list_head *);
 
+/*
+ * use the /proc/iosched interface, all the below is history ->
+ */
 typedef struct blkelv_ioctl_arg_s {
 	int queue_ID;
 	int read_latency;
 	int write_latency;
 	int max_bomb_segments;
 } blkelv_ioctl_arg_t;
-
 #define BLKELVGET   _IOR(0x12,106,sizeof(blkelv_ioctl_arg_t))
 #define BLKELVSET   _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t))
 
-extern int blkelvget_ioctl(elevator_t *, blkelv_ioctl_arg_t *);
-extern int blkelvset_ioctl(elevator_t *, const blkelv_ioctl_arg_t *);
-
-extern void elevator_init(elevator_t *, elevator_t);
+extern int elevator_init(request_queue_t *, elevator_t *, elevator_t);
+extern void elevator_exit(request_queue_t *, elevator_t *);
 
 /*
  * Return values from elevator merger
@@ -81,6 +96,24 @@
 	return latency;
 }
 
+/*
+ * will change once we move to a more complex data structure than a simple
+ * list for pending requests
+ */
+#define elv_queue_empty(q)	list_empty(&(q)->queue_head)
+
+/*
+ * elevator private data
+ */
+struct elv_linus_data {
+	unsigned long flags;
+};
+
+#define ELV_DAT(e) ((struct elv_linus_data *)(e)->elevator_data)
+
+#define ELV_LINUS_BACK_MERGE	1
+#define ELV_LINUS_FRONT_MERGE	2
+
 #define ELEVATOR_NOOP							\
 ((elevator_t) {								\
 	0,				/* read_latency */		\
@@ -89,6 +122,10 @@
 	elevator_noop_merge,		/* elevator_merge_fn */		\
 	elevator_noop_merge_cleanup,	/* elevator_merge_cleanup_fn */	\
 	elevator_noop_merge_req,	/* elevator_merge_req_fn */	\
+	elv_next_request_fn,						\
+	elv_add_request_fn,						\
+	elv_linus_init,							\
+	elv_linus_exit,							\
 	})
 
 #define ELEVATOR_LINUS							\
@@ -99,6 +136,10 @@
 	elevator_linus_merge,		/* elevator_merge_fn */		\
 	elevator_linus_merge_cleanup,	/* elevator_merge_cleanup_fn */	\
 	elevator_linus_merge_req,	/* elevator_merge_req_fn */	\
+	elv_next_request_fn,						\
+	elv_add_request_fn,						\
+	elv_linus_init,							\
+	elv_linus_exit,							\
 	})
 
 #endif
diff -u --recursive --new-file v2.5.0/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.5.0/linux/include/linux/fs.h	Thu Nov 22 11:46:19 2001
+++ linux/include/linux/fs.h	Tue Dec 11 09:51:33 2001
@@ -21,6 +21,7 @@
 #include <linux/cache.h>
 #include <linux/stddef.h>
 #include <linux/string.h>
+#include <linux/bio.h>
 
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -74,6 +75,8 @@
 #define FMODE_READ 1
 #define FMODE_WRITE 2
 
+#define RW_MASK		1
+#define RWA_MASK	2
 #define READ 0
 #define WRITE 1
 #define READA 2		/* read-ahead  - don't block if no resources */
@@ -108,8 +111,10 @@
 #define MS_NOATIME	1024	/* Do not update access times. */
 #define MS_NODIRATIME	2048	/* Do not update directory access times */
 #define MS_BIND		4096
+#define MS_MOVE		8192
 #define MS_REC		16384
 #define MS_VERBOSE	32768
+#define MS_ACTIVE	(1<<30)
 #define MS_NOUSER	(1<<31)
 
 /*
@@ -237,28 +242,24 @@
 struct buffer_head {
 	/* First cache line: */
 	struct buffer_head *b_next;	/* Hash queue list */
-	unsigned long b_blocknr;	/* block number */
+	sector_t b_blocknr;		/* block number */
 	unsigned short b_size;		/* block size */
 	unsigned short b_list;		/* List that this buffer appears */
 	kdev_t b_dev;			/* device (B_FREE = free) */
 
 	atomic_t b_count;		/* users using this block */
-	kdev_t b_rdev;			/* Real device */
 	unsigned long b_state;		/* buffer state bitmap (see above) */
 	unsigned long b_flushtime;	/* Time when (dirty) buffer should be written */
 
 	struct buffer_head *b_next_free;/* lru/free list linkage */
 	struct buffer_head *b_prev_free;/* doubly linked list of buffers */
 	struct buffer_head *b_this_page;/* circular list of buffers in one page */
-	struct buffer_head *b_reqnext;	/* request queue */
-
 	struct buffer_head **b_pprev;	/* doubly linked list of hash-queue */
 	char * b_data;			/* pointer to data block */
 	struct page *b_page;		/* the page this bh is mapped to */
 	void (*b_end_io)(struct buffer_head *bh, int uptodate); /* I/O completion */
  	void *b_private;		/* reserved for b_end_io */
 
-	unsigned long b_rsector;	/* Real buffer location on disk */
 	wait_queue_head_t b_wait;
 
 	struct inode *	     b_inode;
@@ -853,6 +854,8 @@
 	int (*getattr) (struct dentry *, struct iattr *);
 };
 
+struct seq_file;
+
 /*
  * NOTE: write_inode, delete_inode, clear_inode, put_inode can be called
  * without the big kernel lock held in all filesystems.
@@ -904,6 +907,7 @@
 	 */
 	struct dentry * (*fh_to_dentry)(struct super_block *sb, __u32 *fh, int len, int fhtype, int parent);
 	int (*dentry_to_fh)(struct dentry *, __u32 *fh, int *lenp, int need_parent);
+	int (*show_options)(struct seq_file *, struct vfsmount *);
 };
 
 /* Inode state bits.. */
@@ -1169,12 +1173,25 @@
 static inline void buffer_IO_error(struct buffer_head * bh)
 {
 	mark_buffer_clean(bh);
+
 	/*
-	 * b_end_io has to clear the BH_Uptodate bitflag in the error case!
+	 * b_end_io has to clear the BH_Uptodate bitflag in the read error
+	 * case, however buffer contents are not necessarily bad if a
+	 * write fails
 	 */
-	bh->b_end_io(bh, 0);
+	bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state));
 }
 
+/*
+ * return READ, READA, or WRITE
+ */
+#define bio_rw(bio)		((bio)->bi_rw & (RW_MASK | RWA_MASK))
+
+/*
+ * return data direction, READ or WRITE
+ */
+#define bio_data_dir(bio)	((bio)->bi_rw & 1)
+
 extern void buffer_insert_inode_queue(struct buffer_head *, struct inode *);
 static inline void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
 {
@@ -1342,10 +1359,11 @@
 extern void remove_inode_hash(struct inode *);
 extern struct file * get_empty_filp(void);
 extern void file_move(struct file *f, struct list_head *list);
-extern struct buffer_head * get_hash_table(kdev_t, int, int);
-extern struct buffer_head * getblk(kdev_t, int, int);
+extern struct buffer_head * get_hash_table(kdev_t, sector_t, int);
+extern struct buffer_head * getblk(kdev_t, sector_t, int);
 extern void ll_rw_block(int, int, struct buffer_head * bh[]);
-extern void submit_bh(int, struct buffer_head *);
+extern int submit_bh(int, struct buffer_head *);
+extern int submit_bio(int, struct bio *);
 extern int is_read_only(kdev_t);
 extern void __brelse(struct buffer_head *);
 static inline void brelse(struct buffer_head *buf)
@@ -1365,9 +1383,9 @@
 extern void put_unused_buffer_head(struct buffer_head * bh);
 extern struct buffer_head * get_unused_buffer_head(int async);
 
-extern int brw_page(int, struct page *, kdev_t, int [], int);
+extern int brw_page(int, struct page *, kdev_t, sector_t [], int);
 
-typedef int (get_block_t)(struct inode*,long,struct buffer_head*,int);
+typedef int (get_block_t)(struct inode*,sector_t,struct buffer_head*,int);
 
 /* Generic buffer handling for block filesystems.. */
 extern int try_to_release_page(struct page * page, int gfp_mask);
@@ -1383,7 +1401,7 @@
 extern int block_commit_write(struct page *page, unsigned from, unsigned to);
 extern int block_sync_page(struct page *);
 
-int generic_block_bmap(struct address_space *, long, get_block_t *);
+sector_t generic_block_bmap(struct address_space *, sector_t, get_block_t *);
 int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
 int block_truncate_page(struct address_space *, loff_t, get_block_t *);
 extern int generic_direct_IO(int, struct inode *, struct kiobuf *, unsigned long, int, get_block_t *);
@@ -1429,11 +1447,9 @@
 
 
 extern void show_buffers(void);
-extern void mount_root(void);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 extern unsigned int real_root_dev;
-extern int change_root(kdev_t, const char *);
 #endif
 
 extern ssize_t char_read(struct file *, char *, size_t, loff_t *);
diff -u --recursive --new-file v2.5.0/linux/include/linux/genhd.h linux/include/linux/genhd.h
--- v2.5.0/linux/include/linux/genhd.h	Thu Nov 22 11:47:05 2001
+++ linux/include/linux/genhd.h	Tue Dec 11 09:51:33 2001
@@ -86,11 +86,11 @@
 };
 
 /* drivers/block/genhd.c */
-extern struct gendisk *gendisk_head;
-
 extern void add_gendisk(struct gendisk *gp);
 extern void del_gendisk(struct gendisk *gp);
 extern struct gendisk *get_gendisk(kdev_t dev);
+extern unsigned long get_start_sect(kdev_t dev);
+extern unsigned long get_nr_sects(kdev_t dev);
 
 #endif  /*  __KERNEL__  */
 
@@ -244,35 +244,10 @@
 extern void devfs_register_partitions (struct gendisk *dev, int minor,
 				       int unregister);
 
-
-
-/*
- * FIXME: this should use genhd->minor_shift, but that is slow to look up.
- */
 static inline unsigned int disk_index (kdev_t dev)
 {
-	int major = MAJOR(dev);
-	int minor = MINOR(dev);
-	unsigned int index;
-
-	switch (major) {
-		case DAC960_MAJOR+0:
-			index = (minor & 0x00f8) >> 3;
-			break;
-		case SCSI_DISK0_MAJOR:
-			index = (minor & 0x00f0) >> 4;
-			break;
-		case IDE0_MAJOR:	/* same as HD_MAJOR */
-		case XT_DISK_MAJOR:
-			index = (minor & 0x0040) >> 6;
-			break;
-		case IDE1_MAJOR:
-			index = ((minor & 0x0040) >> 6) + 2;
-			break;
-		default:
-			return 0;
-	}
-	return index;
+	struct gendisk *g = get_gendisk(dev);
+	return g ? (MINOR(dev) >> g->minor_shift) : 0;
 }
 
 #endif
diff -u --recursive --new-file v2.5.0/linux/include/linux/highmem.h linux/include/linux/highmem.h
--- v2.5.0/linux/include/linux/highmem.h	Thu Nov 22 11:46:23 2001
+++ linux/include/linux/highmem.h	Tue Dec 11 09:51:38 2001
@@ -13,8 +13,7 @@
 /* declarations for linux/mm/highmem.c */
 unsigned int nr_free_highpages(void);
 
-extern struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig);
-
+extern void create_bounce(unsigned long pfn, struct bio **bio_orig);
 
 static inline char *bh_kmap(struct buffer_head *bh)
 {
@@ -26,6 +25,42 @@
 	kunmap(bh->b_page);
 }
 
+/*
+ * remember to add offset! and never ever reenable interrupts between a
+ * bio_kmap_irq and bio_kunmap_irq!!
+ */
+static inline char *bio_kmap_irq(struct bio *bio, unsigned long *flags)
+{
+	unsigned long addr;
+
+	__save_flags(*flags);
+
+	/*
+	 * could be low
+	 */
+	if (!PageHighMem(bio_page(bio)))
+		return bio_data(bio);
+
+	/*
+	 * it's a highmem page
+	 */
+	__cli();
+	addr = (unsigned long) kmap_atomic(bio_page(bio), KM_BIO_IRQ);
+
+	if (addr & ~PAGE_MASK)
+		BUG();
+
+	return (char *) addr + bio_offset(bio);
+}
+
+static inline void bio_kunmap_irq(char *buffer, unsigned long *flags)
+{
+	unsigned long ptr = (unsigned long) buffer & PAGE_MASK;
+
+	kunmap_atomic((void *) ptr, KM_BIO_IRQ);
+	__restore_flags(*flags);
+}
+
 #else /* CONFIG_HIGHMEM */
 
 static inline unsigned int nr_free_highpages(void) { return 0; }
@@ -39,6 +74,9 @@
 
 #define bh_kmap(bh)	((bh)->b_data)
 #define bh_kunmap(bh)	do { } while (0)
+
+#define bio_kmap_irq(bio, flags)	(bio_data(bio))
+#define bio_kunmap_irq(buf, flags)	do { *(flags) = 0; } while (0)
 
 #endif /* CONFIG_HIGHMEM */
 
diff -u --recursive --new-file v2.5.0/linux/include/linux/i2c-old.h linux/include/linux/i2c-old.h
--- v2.5.0/linux/include/linux/i2c-old.h	Mon Dec 11 13:15:37 2000
+++ linux/include/linux/i2c-old.h	Wed Dec 31 16:00:00 1969
@@ -1,190 +0,0 @@
-#ifndef I2C_H
-#define I2C_H
-
-/*
- * linux i2c interface.  Works a little bit like the scsi subsystem.
- * There are:
- *
- *     i2c          the basic control module        (like scsi_mod)
- *     bus driver   a driver with a i2c bus         (hostadapter driver)
- *     chip driver  a driver for a chip connected
- *                  to a i2c bus                    (cdrom/hd driver)
- *
- * A device will be attached to one bus and one chip driver.  Every chip
- * driver gets a unique ID.
- *
- * A chip driver can provide a ioctl-like callback for the
- * communication with other parts of the kernel (not every i2c chip is
- * useful without other devices, a TV card tuner for example). 
- *
- * "i2c internal" parts of the structs: only the i2c module is allowed to
- * write to them, for others they are read-only.
- *
- */
-
-#include <linux/version.h>
-
-#define I2C_BUS_MAX       4    /* max # of bus drivers  */
-#define I2C_DRIVER_MAX    8    /* max # of chip drivers */
-#define I2C_DEVICE_MAX    8    /* max # if devices per bus/driver */
-
-struct i2c_bus;
-struct i2c_driver;
-struct i2c_device;
-
-#define I2C_DRIVERID_MSP3400    	 1
-#define I2C_DRIVERID_TUNER      	 2
-#define I2C_DRIVERID_VIDEOTEXT		 3
-#define I2C_DRIVERID_VIDEODECODER	 4
-#define I2C_DRIVERID_VIDEOENCODER	 5
-
-#define I2C_BUSID_BT848		1	/* I2C bus on a BT848 */
-#define I2C_BUSID_PARPORT	2	/* Bit banging on a parallel port */
-#define I2C_BUSID_BUZ		3
-#define I2C_BUSID_ZORAN		4
-#define I2C_BUSID_CYBER2000	5
-
-/*
- * struct for a driver for a i2c chip (tuner, soundprocessor,
- * videotext, ... ).
- *
- * a driver will register within the i2c module.  The i2c module will
- * callback the driver (i2c_attach) for every device it finds on a i2c
- * bus at the specified address.  If the driver decides to "accept"
- * the, device, it must return a struct i2c_device, and NULL
- * otherwise.
- *
- * i2c_detach = i2c_attach ** -1
- * 
- * i2c_command will be used to pass commands to the driver in a
- * ioctl-line manner.
- *
- */
-
-struct i2c_driver 
-{
-    char           name[32];         /* some useful label         */
-    int            id;               /* device type ID            */
-    unsigned char  addr_l, addr_h;   /* address range of the chip */
-
-    int (*attach)(struct i2c_device *device);
-    int (*detach)(struct i2c_device *device);
-    int (*command)(struct i2c_device *device,unsigned int cmd, void *arg);
-
-    /* i2c internal */
-    struct i2c_device   *devices[I2C_DEVICE_MAX];
-    int                 devcount;
-};
-
-
-/*
- * this holds the informations about a i2c bus available in the system.
- * 
- * a chip with a i2c bus interface (like bt848) registers the bus within
- * the i2c module. This struct provides functions to access the i2c bus.
- * 
- * One must hold the spinlock to access the i2c bus (XXX: is the irqsave
- * required? Maybe better use a semaphore?). 
- * [-AC-] having a spinlock_irqsave is only needed if we have drivers wishing
- *	  to bang their i2c bus from an interrupt.
- * 
- * attach/detach_inform is a callback to inform the bus driver about
- * attached chip drivers.
- *
- */
-
-/* needed: unsigned long flags */
-
-#if LINUX_VERSION_CODE >= 0x020100
-# if 0
-#  define LOCK_FLAGS unsigned long flags;
-#  define LOCK_I2C_BUS(bus)    spin_lock_irqsave(&(bus->bus_lock),flags);
-#  define UNLOCK_I2C_BUS(bus)  spin_unlock_irqrestore(&(bus->bus_lock),flags);
-# else
-#  define LOCK_FLAGS
-#  define LOCK_I2C_BUS(bus)    spin_lock(&(bus->bus_lock));
-#  define UNLOCK_I2C_BUS(bus)  spin_unlock(&(bus->bus_lock));
-# endif
-#else
-# define LOCK_FLAGS unsigned long flags;
-# define LOCK_I2C_BUS(bus)    { save_flags(flags); cli(); }
-# define UNLOCK_I2C_BUS(bus)  { restore_flags(flags);     }
-#endif
-
-struct i2c_bus 
-{
-	char  name[32];         /* some useful label */
-	int   id;
-	void  *data;            /* free for use by the bus driver */
-
-#if LINUX_VERSION_CODE >= 0x020100
-	spinlock_t bus_lock;
-#endif
-
-	/* attach/detach inform callbacks */
-	void    (*attach_inform)(struct i2c_bus *bus, int id);
-	void    (*detach_inform)(struct i2c_bus *bus, int id);
-
-	/* Software I2C */
-	void    (*i2c_setlines)(struct i2c_bus *bus, int ctrl, int data);
-	int     (*i2c_getdataline)(struct i2c_bus *bus);
-
-	/* Hardware I2C */
-	int     (*i2c_read)(struct i2c_bus *bus, unsigned char addr);
-	int     (*i2c_write)(struct i2c_bus *bus, unsigned char addr,
-			 unsigned char b1, unsigned char b2, int both);
-
-	/* internal data for i2c module */
-	struct i2c_device   *devices[I2C_DEVICE_MAX];
-	int                 devcount;
-};
-
-
-/*
- *	This holds per-device data for a i2c device
- */
-
-struct i2c_device 
-{
-	char           name[32];         /* some useful label */
-	void           *data;            /* free for use by the chip driver */
-	unsigned char  addr;             /* chip addr */
-
-	/* i2c internal */
-	struct i2c_bus     *bus;
-	struct i2c_driver  *driver;
-};
-
-
-/* ------------------------------------------------------------------- */
-/* i2c module functions                                                */
-
-/* register/unregister a i2c bus */
-int i2c_register_bus(struct i2c_bus *bus);
-int i2c_unregister_bus(struct i2c_bus *bus);
-
-/* register/unregister a chip driver */
-int i2c_register_driver(struct i2c_driver *driver);
-int i2c_unregister_driver(struct i2c_driver *driver);
-
-/* send a command to a chip using the ioctl-like callback interface */
-int i2c_control_device(struct i2c_bus *bus, int id,
-		       unsigned int cmd, void *arg);
-
-/* i2c bus access functions */
-void    i2c_start(struct i2c_bus *bus);
-void    i2c_stop(struct i2c_bus *bus);
-void    i2c_one(struct i2c_bus *bus);
-void    i2c_zero(struct i2c_bus *bus);
-int     i2c_ack(struct i2c_bus *bus);
-
-int     i2c_sendbyte(struct i2c_bus *bus,unsigned char data,int wait_for_ack);
-unsigned char i2c_readbyte(struct i2c_bus *bus,int last);
-
-/* i2c (maybe) hardware functions */
-int     i2c_read(struct i2c_bus *bus, unsigned char addr);
-int     i2c_write(struct i2c_bus *bus, unsigned char addr,
-		  unsigned char b1, unsigned char b2, int both);
-
-int	i2c_init(void);
-#endif /* I2C_H */
diff -u --recursive --new-file v2.5.0/linux/include/linux/ide.h linux/include/linux/ide.h
--- v2.5.0/linux/include/linux/ide.h	Thu Nov 22 11:48:07 2001
+++ linux/include/linux/ide.h	Tue Dec 11 09:52:26 2001
@@ -149,6 +149,21 @@
 #define DATA_READY		(DRQ_STAT)
 
 /*
+ * Our Physical Region Descriptor (PRD) table should be large enough
+ * to handle the biggest I/O request we are likely to see.  Since requests
+ * can have no more than 256 sectors, and since the typical blocksize is
+ * two or more sectors, we could get by with a limit of 128 entries here for
+ * the usual worst case.  Most requests seem to include some contiguous blocks,
+ * further reducing the number of table entries required.
+ *
+ * As it turns out though, we must allocate a full 4KB page for this,
+ * so the two PRD tables (ide0 & ide1) will each get half of that,
+ * allowing each to have about 256 entries (8 bytes each) from this.
+ */
+#define PRD_BYTES	8
+#define PRD_ENTRIES	(PAGE_SIZE / (2 * PRD_BYTES))
+
+/*
  * Some more useful definitions
  */
 #define IDE_MAJOR_NAME	"hd"	/* the same for all i/f; see also genhd.c */
@@ -223,6 +238,23 @@
 #endif
 
 /*
+ * hwif_chipset_t is used to keep track of the specific hardware
+ * chipset used by each IDE interface, if known.
+ */
+typedef enum {  ide_unknown,    ide_generic,    ide_pci,
+                ide_cmd640,     ide_dtc2278,    ide_ali14xx,
+                ide_qd65xx,     ide_umc8672,    ide_ht6560b,
+                ide_pdc4030,    ide_rz1000,     ide_trm290,
+                ide_cmd646,     ide_cy82c693,   ide_4drives,
+                ide_pmac,       ide_etrax100
+} hwif_chipset_t;
+
+#define IDE_CHIPSET_PCI_MASK    \
+    ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
+#define IDE_CHIPSET_IS_PCI(c)   ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
+
+
+/*
  * Structure to hold all information about the location of this port
  */
 typedef struct hw_regs_s {
@@ -231,6 +263,7 @@
 	int		dma;			/* our dma entry */
 	ide_ack_intr_t	*ack_intr;		/* acknowledge interrupt */
 	void		*priv;			/* interface specific data */
+	hwif_chipset_t  chipset;
 } hw_regs_t;
 
 /*
@@ -440,22 +473,6 @@
  */
 typedef int (ide_busproc_t) (struct hwif_s *, int);
 
-/*
- * hwif_chipset_t is used to keep track of the specific hardware
- * chipset used by each IDE interface, if known.
- */
-typedef enum {	ide_unknown,	ide_generic,	ide_pci,
-		ide_cmd640,	ide_dtc2278,	ide_ali14xx,
-		ide_qd65xx,	ide_umc8672,	ide_ht6560b,
-		ide_pdc4030,	ide_rz1000,	ide_trm290,
-		ide_cmd646,	ide_cy82c693,	ide_4drives,
-		ide_pmac,       ide_etrax100
-} hwif_chipset_t;
-
-#define IDE_CHIPSET_PCI_MASK	\
-    ((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
-#define IDE_CHIPSET_IS_PCI(c)	((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
-
 #ifdef CONFIG_BLK_DEV_IDEPCI
 typedef struct ide_pci_devid_s {
 	unsigned short	vid;
@@ -488,7 +505,6 @@
 	struct scatterlist *sg_table;	/* Scatter-gather list used to build the above */
 	int sg_nents;			/* Current number of entries in it */
 	int sg_dma_direction;		/* dma transfer direction */
-	int sg_dma_active;		/* is it in use */
 	struct hwif_s	*mate;		/* other hwif from same PCI chip */
 	unsigned long	dma_base;	/* base addr for dma ports */
 	unsigned	dma_extra;	/* extra addr for dma ports */
@@ -507,6 +523,7 @@
 	unsigned	reset      : 1;	/* reset after probe */
 	unsigned	autodma    : 1;	/* automatically try to enable DMA at boot */
 	unsigned	udma_four  : 1;	/* 1=ATA-66 capable, 0=default */
+	unsigned	highmem	   : 1; /* can do full 32-bit dma */
 	byte		channel;	/* for dual-port chips: 0=primary, 1=secondary */
 #ifdef CONFIG_BLK_DEV_IDEPCI
 	struct pci_dev	*pci_dev;	/* for pci chipsets */
@@ -541,10 +558,12 @@
  */
 typedef int (ide_expiry_t)(ide_drive_t *);
 
+#define IDE_BUSY	0
+#define IDE_SLEEP	1
+
 typedef struct hwgroup_s {
 	ide_handler_t		*handler;/* irq handler, if active */
-	volatile int		busy;	/* BOOL: protects all fields below */
-	int			sleeping; /* BOOL: wake us up on timer expiry */
+	unsigned long		flags;	/* BUSY, SLEEPING */
 	ide_drive_t		*drive;	/* current drive */
 	ide_hwif_t		*hwif;	/* ptr to current hwif in linked-list */
 	struct request		*rq;	/* current request */
@@ -711,7 +730,8 @@
 #define LOCAL_END_REQUEST	/* Don't generate end_request in blk.h */
 #include <linux/blk.h>
 
-void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
+inline int __ide_end_request(ide_hwgroup_t *, int, int);
+int ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
 
 /*
  * This is used for (nearly) all data transfers from/to the IDE interface
@@ -787,6 +807,11 @@
 unsigned long current_capacity (ide_drive_t *drive);
 
 /*
+ * Revalidate (read partition tables)
+ */
+void ide_revalidate_drive (ide_drive_t *drive);
+
+/*
  * Start a reset operation for an IDE interface.
  * The caller should return immediately after invoking this.
  */
@@ -814,6 +839,21 @@
 } ide_action_t;
 
 /*
+ * temporarily mapping a (possible) highmem bio for PIO transfer
+ */
+#define ide_rq_offset(rq) (((rq)->hard_cur_sectors - (rq)->current_nr_sectors) << 9)
+
+extern inline void *ide_map_buffer(struct request *rq, unsigned long *flags)
+{
+	return bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq);
+}
+
+extern inline void ide_unmap_buffer(char *buffer, unsigned long *flags)
+{
+	bio_kunmap_irq(buffer, flags);
+}
+
+/*
  * This function issues a special IDE device request
  * onto the request queue.
  *
@@ -960,5 +1000,8 @@
 #endif
 
 void hwif_unregister (ide_hwif_t *hwif);
+
+#define DRIVE_LOCK(drive)	(&(drive)->queue.queue_lock)
+extern spinlock_t ide_lock;
 
 #endif /* _IDE_H */
diff -u --recursive --new-file v2.5.0/linux/include/linux/iobuf.h linux/include/linux/iobuf.h
--- v2.5.0/linux/include/linux/iobuf.h	Thu Nov 22 11:46:26 2001
+++ linux/include/linux/iobuf.h	Tue Dec 11 09:51:40 2001
@@ -28,7 +28,7 @@
 #define KIO_STATIC_PAGES	(KIO_MAX_ATOMIC_IO / (PAGE_SIZE >> 10) + 1)
 #define KIO_MAX_SECTORS		(KIO_MAX_ATOMIC_IO * 2)
 
-/* The main kiobuf struct used for all our IO! */
+/* The main kiobuf struct */
 
 struct kiobuf 
 {
@@ -48,8 +48,7 @@
 	
 	/* Always embed enough struct pages for atomic IO */
 	struct page *	map_array[KIO_STATIC_PAGES];
-	struct buffer_head * bh[KIO_MAX_SECTORS];
-	unsigned long blocks[KIO_MAX_SECTORS];
+	sector_t	blocks[KIO_MAX_SECTORS];
 
 	/* Dynamic state for IO completion: */
 	atomic_t	io_count;	/* IOs still in progress */
@@ -69,7 +68,7 @@
 
 /* fs/iobuf.c */
 
-void	end_kio_request(struct kiobuf *, int);
+int	end_kio_request(struct kiobuf *, int);
 void	simple_wakeup_kiobuf(struct kiobuf *);
 int	alloc_kiovec(int nr, struct kiobuf **);
 void	free_kiovec(int nr, struct kiobuf **);
@@ -81,6 +80,9 @@
 /* fs/buffer.c */
 
 int	brw_kiovec(int rw, int nr, struct kiobuf *iovec[], 
-		   kdev_t dev, unsigned long b[], int size);
+		   kdev_t dev, sector_t [], int size);
+
+/* fs/bio.c */
+void	ll_rw_kio(int rw, struct kiobuf *kio, kdev_t dev, sector_t block);
 
 #endif /* __LINUX_IOBUF_H */
diff -u --recursive --new-file v2.5.0/linux/include/linux/iso_fs.h linux/include/linux/iso_fs.h
--- v2.5.0/linux/include/linux/iso_fs.h	Thu Nov 22 11:47:11 2001
+++ linux/include/linux/iso_fs.h	Tue Dec 11 09:52:19 2001
@@ -220,7 +220,7 @@
 
 extern struct dentry *isofs_lookup(struct inode *, struct dentry *);
 extern struct buffer_head *isofs_bread(struct inode *, unsigned int, unsigned int);
-extern int isofs_get_blocks(struct inode *, long, struct buffer_head **, unsigned long);
+extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
 
 extern struct inode_operations isofs_dir_inode_operations;
 extern struct file_operations isofs_dir_operations;
diff -u --recursive --new-file v2.5.0/linux/include/linux/kernel.h linux/include/linux/kernel.h
--- v2.5.0/linux/include/linux/kernel.h	Thu Nov 22 11:46:18 2001
+++ linux/include/linux/kernel.h	Tue Dec 11 09:51:33 2001
@@ -11,6 +11,7 @@
 #include <linux/linkage.h>
 #include <linux/stddef.h>
 #include <linux/types.h>
+#include <linux/compiler.h>
 
 /* Optimization barrier */
 /* The "volatile" is due to gcc bugs */
@@ -176,4 +177,5 @@
 	char _f[20-2*sizeof(long)-sizeof(int)];	/* Padding: libc5 uses this.. */
 };
 
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
 #endif
diff -u --recursive --new-file v2.5.0/linux/include/linux/loop.h linux/include/linux/loop.h
--- v2.5.0/linux/include/linux/loop.h	Mon Sep 17 13:16:30 2001
+++ linux/include/linux/loop.h	Tue Nov 27 09:23:27 2001
@@ -49,8 +49,8 @@
 	int		old_gfp_mask;
 
 	spinlock_t		lo_lock;
-	struct buffer_head	*lo_bh;
-	struct buffer_head	*lo_bhtail;
+	struct bio 		*lo_bio;
+	struct bio		*lo_biotail;
 	int			lo_state;
 	struct semaphore	lo_sem;
 	struct semaphore	lo_ctl_mutex;
diff -u --recursive --new-file v2.5.0/linux/include/linux/lvm.h linux/include/linux/lvm.h
--- v2.5.0/linux/include/linux/lvm.h	Sun Nov 11 10:09:32 2001
+++ linux/include/linux/lvm.h	Tue Nov 27 09:23:27 2001
@@ -468,6 +468,12 @@
 } lv_bmap_t;
 
 /*
+ * fixme...
+ */
+#define LVM_MAX_ATOMIC_IO	512
+#define LVM_MAX_SECTORS		(LVM_MAX_ATOMIC_IO * 2)
+
+/*
  * Structure Logical Volume (LV) Version 3
  */
 
@@ -505,6 +511,7 @@
 	uint lv_snapshot_minor;
 #ifdef __KERNEL__
 	struct kiobuf *lv_iobuf;
+	sector_t blocks[LVM_MAX_SECTORS];
 	struct kiobuf *lv_COW_table_iobuf;
 	struct rw_semaphore lv_lock;
 	struct list_head *lv_snapshot_hash_table;
diff -u --recursive --new-file v2.5.0/linux/include/linux/malloc.h linux/include/linux/malloc.h
--- v2.5.0/linux/include/linux/malloc.h	Sun Nov 11 19:09:31 2001
+++ linux/include/linux/malloc.h	Wed Dec 31 16:00:00 1969
@@ -1,7 +0,0 @@
-#ifndef _LINUX_MALLOC_H
-#define _LINUX_MALLOC_H
-
-#warning linux/malloc.h is deprecated, use linux/slab.h instead.
-
-#include <linux/slab.h>
-#endif /* _LINUX_MALLOC_H */
diff -u --recursive --new-file v2.5.0/linux/include/linux/mempool.h linux/include/linux/mempool.h
--- v2.5.0/linux/include/linux/mempool.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/mempool.h	Tue Dec 11 09:51:33 2001
@@ -0,0 +1,32 @@
+/*
+ * memory buffer pool support
+ */
+#ifndef _LINUX_MEMPOOL_H
+#define _LINUX_MEMPOOL_H
+
+#include <linux/list.h>
+#include <linux/wait.h>
+
+struct mempool_s;
+typedef struct mempool_s mempool_t;
+
+typedef void * (mempool_alloc_t)(int gfp_mask, void *pool_data);
+typedef void (mempool_free_t)(void *element, void *pool_data);
+
+struct mempool_s {
+	spinlock_t lock;
+	int min_nr, curr_nr;
+	struct list_head elements;
+
+	void *pool_data;
+	mempool_alloc_t *alloc;
+	mempool_free_t *free;
+	wait_queue_head_t wait;
+};
+extern mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
+				 mempool_free_t *free_fn, void *pool_data);
+extern void mempool_destroy(mempool_t *pool);
+extern void * mempool_alloc(mempool_t *pool, int gfp_mask);
+extern void mempool_free(void *element, mempool_t *pool);
+
+#endif /* _LINUX_MEMPOOL_H */
diff -u --recursive --new-file v2.5.0/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- v2.5.0/linux/include/linux/msdos_fs.h	Fri Oct 12 13:48:42 2001
+++ linux/include/linux/msdos_fs.h	Fri Nov 30 08:30:17 2001
@@ -273,7 +273,7 @@
 extern struct inode_operations fat_file_inode_operations;
 extern ssize_t fat_file_read(struct file *filp, char *buf, size_t count,
 			     loff_t *ppos);
-extern int fat_get_block(struct inode *inode, long iblock,
+extern int fat_get_block(struct inode *inode, sector_t iblock,
 			 struct buffer_head *bh_result, int create);
 extern ssize_t fat_file_write(struct file *filp, const char *buf, size_t count,
 			      loff_t *ppos);
diff -u --recursive --new-file v2.5.0/linux/include/linux/nbd.h linux/include/linux/nbd.h
--- v2.5.0/linux/include/linux/nbd.h	Mon Oct 15 19:29:05 2001
+++ linux/include/linux/nbd.h	Tue Nov 27 09:23:27 2001
@@ -37,24 +37,25 @@
 static void
 nbd_end_request(struct request *req)
 {
-	struct buffer_head *bh;
+	struct bio *bio;
 	unsigned nsect;
 	unsigned long flags;
 	int uptodate = (req->errors == 0) ? 1 : 0;
+	request_queue_t *q = req->q;
 
 #ifdef PARANOIA
 	requests_out++;
 #endif
-	spin_lock_irqsave(&io_request_lock, flags);
-	while((bh = req->bh) != NULL) {
-		nsect = bh->b_size >> 9;
+	spin_lock_irqsave(&q->queue_lock, flags);
+	while((bio = req->bio) != NULL) {
+		nsect = bio_sectors(bio);
 		blk_finished_io(nsect);
-		req->bh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
-		bh->b_end_io(bh, uptodate);
+		req->bio = bio->bi_next;
+		bio->bi_next = NULL;
+		bio_endio(bio, uptodate, nsect);
 	}
 	blkdev_release_request(req);
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irqrestore(&q->queue_lock, flags);
 }
 
 #define MAX_NBD 128
diff -u --recursive --new-file v2.5.0/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.5.0/linux/include/linux/pci_ids.h	Fri Nov  9 14:11:15 2001
+++ linux/include/linux/pci_ids.h	Fri Dec  7 16:26:13 2001
@@ -912,7 +912,7 @@
 #define PCI_DEVICE_ID_TTI_HPT366	0x0004
 
 #define PCI_VENDOR_ID_VIA		0x1106
-#define PCI_DEVICE_ID_VIA_8363_0	0x0305
+#define PCI_DEVICE_ID_VIA_8363_0	0x0305 
 #define PCI_DEVICE_ID_VIA_8371_0	0x0391
 #define PCI_DEVICE_ID_VIA_8501_0	0x0501
 #define PCI_DEVICE_ID_VIA_82C505	0x0505
@@ -946,9 +946,11 @@
 #define PCI_DEVICE_ID_VIA_8233_7	0x3065
 #define PCI_DEVICE_ID_VIA_82C686_6	0x3068
 #define PCI_DEVICE_ID_VIA_8233_0	0x3074
+#define PCI_DEVICE_ID_VIA_8622          0x3102 
 #define PCI_DEVICE_ID_VIA_8233C_0	0x3109
+#define PCI_DEVICE_ID_VIA_8361          0x3112 
 #define PCI_DEVICE_ID_VIA_8633_0	0x3091
-#define PCI_DEVICE_ID_VIA_8367_0	0x3099
+#define PCI_DEVICE_ID_VIA_8367_0	0x3099 
 #define PCI_DEVICE_ID_VIA_86C100A	0x6100
 #define PCI_DEVICE_ID_VIA_8231		0x8231
 #define PCI_DEVICE_ID_VIA_8231_4	0x8235
@@ -1229,6 +1231,7 @@
 #define PCI_DEVICE_ID_AVM_B1		0x0700
 #define PCI_DEVICE_ID_AVM_C4		0x0800
 #define PCI_DEVICE_ID_AVM_A1		0x0a00
+#define PCI_DEVICE_ID_AVM_A1_V2		0x0e00
 #define PCI_DEVICE_ID_AVM_C2		0x1100
 #define PCI_DEVICE_ID_AVM_T1		0x1200
 
diff -u --recursive --new-file v2.5.0/linux/include/linux/raid/md_k.h linux/include/linux/raid/md_k.h
--- v2.5.0/linux/include/linux/raid/md_k.h	Mon Nov 12 09:51:56 2001
+++ linux/include/linux/raid/md_k.h	Tue Nov 27 09:23:27 2001
@@ -220,7 +220,7 @@
 struct mdk_personality_s
 {
 	char *name;
-	int (*make_request)(mddev_t *mddev, int rw, struct buffer_head * bh);
+	int (*make_request)(mddev_t *mddev, int rw, struct bio *bio);
 	int (*run)(mddev_t *mddev);
 	int (*stop)(mddev_t *mddev);
 	int (*status)(char *page, mddev_t *mddev);
diff -u --recursive --new-file v2.5.0/linux/include/linux/reiserfs_fs.h linux/include/linux/reiserfs_fs.h
--- v2.5.0/linux/include/linux/reiserfs_fs.h	Fri Nov  9 14:18:25 2001
+++ linux/include/linux/reiserfs_fs.h	Tue Nov 27 09:23:27 2001
@@ -1856,7 +1856,7 @@
 			loff_t offset, int type, int length, int entry_count);
 /*void store_key (struct key * key);
 void forget_key (struct key * key);*/
-int reiserfs_get_block (struct inode * inode, long block,
+int reiserfs_get_block (struct inode * inode, sector_t block,
 			struct buffer_head * bh_result, int create);
 struct inode * reiserfs_iget (struct super_block * s, 
 			      const struct cpu_key * key);
diff -u --recursive --new-file v2.5.0/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.5.0/linux/include/linux/sched.h	Thu Nov 22 11:46:19 2001
+++ linux/include/linux/sched.h	Tue Dec 11 09:51:33 2001
@@ -21,7 +21,6 @@
 #include <asm/mmu.h>
 
 #include <linux/smp.h>
-#include <linux/tty.h>
 #include <linux/sem.h>
 #include <linux/signal.h>
 #include <linux/securebits.h>
diff -u --recursive --new-file v2.5.0/linux/include/linux/seq_file.h linux/include/linux/seq_file.h
--- v2.5.0/linux/include/linux/seq_file.h	Sun Nov 11 11:23:14 2001
+++ linux/include/linux/seq_file.h	Tue Dec 11 09:51:33 2001
@@ -2,7 +2,11 @@
 #define _LINUX_SEQ_FILE_H
 #ifdef __KERNEL__
 
+#include <linux/types.h>
+
 struct seq_operations;
+struct file;
+struct inode;
 
 struct seq_file {
 	char *buf;
@@ -12,6 +16,7 @@
 	loff_t index;
 	struct semaphore sem;
 	struct seq_operations *op;
+	void *private;
 };
 
 struct seq_operations {
diff -u --recursive --new-file v2.5.0/linux/include/linux/slab.h linux/include/linux/slab.h
--- v2.5.0/linux/include/linux/slab.h	Thu Nov 22 11:46:20 2001
+++ linux/include/linux/slab.h	Tue Dec 11 09:51:35 2001
@@ -38,6 +38,7 @@
 #define	SLAB_NO_REAP		0x00001000UL	/* never reap from the cache */
 #define	SLAB_HWCACHE_ALIGN	0x00002000UL	/* align objs on a h/w cache lines */
 #define SLAB_CACHE_DMA		0x00004000UL	/* use GFP_DMA memory */
+#define SLAB_MUST_HWCACHE_ALIGN	0x00008000UL	/* force alignment */
 
 /* flags passed to a constructor func */
 #define	SLAB_CTOR_CONSTRUCTOR	0x001UL		/* if not set, then deconstructor */
@@ -76,6 +77,7 @@
 extern kmem_cache_t	*bh_cachep;
 extern kmem_cache_t	*fs_cachep;
 extern kmem_cache_t	*sigact_cachep;
+extern kmem_cache_t	*bio_cachep;
 
 #endif	/* __KERNEL__ */
 
diff -u --recursive --new-file v2.5.0/linux/include/linux/types.h linux/include/linux/types.h
--- v2.5.0/linux/include/linux/types.h	Thu Nov 22 11:46:18 2001
+++ linux/include/linux/types.h	Tue Dec 11 09:51:32 2001
@@ -113,6 +113,17 @@
 typedef		__s64		int64_t;
 #endif
 
+/*
+ * transition to 64-bit sector_t, possibly making it an option...
+ */
+#undef BLK_64BIT_SECTOR
+
+#ifdef BLK_64BIT_SECTOR
+typedef u64 sector_t;
+#else
+typedef unsigned long sector_t;
+#endif
+
 #endif /* __KERNEL_STRICT_NAMES */
 
 /*
diff -u --recursive --new-file v2.5.0/linux/include/linux/usb.h linux/include/linux/usb.h
--- v2.5.0/linux/include/linux/usb.h	Thu Nov 22 11:49:34 2001
+++ linux/include/linux/usb.h	Tue Dec 11 09:55:16 2001
@@ -11,10 +11,13 @@
 #define USB_CLASS_COMM			2
 #define USB_CLASS_HID			3
 #define USB_CLASS_PHYSICAL		5
+#define USB_CLASS_STILL_IMAGE		6
 #define USB_CLASS_PRINTER		7
 #define USB_CLASS_MASS_STORAGE		8
 #define USB_CLASS_HUB			9
-#define USB_CLASS_DATA			10
+#define USB_CLASS_CDC_DATA		0x0a
+#define USB_CLASS_CSCID		0x0b /* chip+ smart card */
+#define USB_CLASS_CONTENT_SEC		0x0d /* content security */
 #define USB_CLASS_APP_SPEC		0xfe
 #define USB_CLASS_VENDOR_SPEC		0xff
 
@@ -43,31 +46,6 @@
 #define USB_DIR_IN			0x80
 
 /*
- * Descriptor types
- */
-#define USB_DT_DEVICE			0x01
-#define USB_DT_CONFIG			0x02
-#define USB_DT_STRING			0x03
-#define USB_DT_INTERFACE		0x04
-#define USB_DT_ENDPOINT			0x05
-
-#define USB_DT_HID			(USB_TYPE_CLASS | 0x01)
-#define USB_DT_REPORT			(USB_TYPE_CLASS | 0x02)
-#define USB_DT_PHYSICAL			(USB_TYPE_CLASS | 0x03)
-#define USB_DT_HUB			(USB_TYPE_CLASS | 0x09)
-
-/*
- * Descriptor sizes per descriptor type
- */
-#define USB_DT_DEVICE_SIZE		18
-#define USB_DT_CONFIG_SIZE		9
-#define USB_DT_INTERFACE_SIZE		9
-#define USB_DT_ENDPOINT_SIZE		7
-#define USB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */
-#define USB_DT_HUB_NONVAR_SIZE		7
-#define USB_DT_HID_SIZE			9
-
-/*
  * Endpoints
  */
 #define USB_ENDPOINT_NUMBER_MASK	0x0f	/* in bEndpointAddress */
@@ -115,16 +93,6 @@
 #define USB_REQ_SET_INTERFACE		0x0B
 #define USB_REQ_SYNCH_FRAME		0x0C
 
-/*
- * HID requests
- */
-#define USB_REQ_GET_REPORT		0x01
-#define USB_REQ_GET_IDLE		0x02
-#define USB_REQ_GET_PROTOCOL		0x03
-#define USB_REQ_SET_REPORT		0x09
-#define USB_REQ_SET_IDLE		0x0A
-#define USB_REQ_SET_PROTOCOL		0x0B
-
 
 #ifdef __KERNEL__
 
@@ -158,32 +126,6 @@
 } devrequest __attribute__ ((packed));
 
 /*
- * USB-status codes:
- * USB_ST* maps to -E* and should go away in the future
- */
-
-#define USB_ST_NOERROR		0
-#define USB_ST_CRC		(-EILSEQ)
-#define USB_ST_BITSTUFF		(-EPROTO)
-#define USB_ST_NORESPONSE	(-ETIMEDOUT)			/* device not responding/handshaking */
-#define USB_ST_DATAOVERRUN	(-EOVERFLOW)
-#define USB_ST_DATAUNDERRUN	(-EREMOTEIO)
-#define USB_ST_BUFFEROVERRUN	(-ECOMM)
-#define USB_ST_BUFFERUNDERRUN	(-ENOSR)
-#define USB_ST_INTERNALERROR	(-EPROTO) 			/* unknown error */
-#define USB_ST_SHORT_PACKET    	(-EREMOTEIO)
-#define USB_ST_PARTIAL_ERROR  	(-EXDEV)			/* ISO transfer only partially completed */
-#define USB_ST_URB_KILLED     	(-ENOENT)			/* URB canceled by user */
-#define USB_ST_URB_PENDING       (-EINPROGRESS)
-#define USB_ST_REMOVED		(-ENODEV) 			/* device not existing or removed */
-#define USB_ST_TIMEOUT		(-ETIMEDOUT)			/* communication timed out, also in urb->status**/
-#define USB_ST_NOTSUPPORTED	(-ENOSYS)			
-#define USB_ST_BANDWIDTH_ERROR	(-ENOSPC)			/* too much bandwidth used */
-#define USB_ST_URB_INVALID_ERROR  (-EINVAL)			/* invalid value/transfer type */
-#define USB_ST_URB_REQUEST_ERROR  (-ENXIO)			/* invalid endpoint */
-#define USB_ST_STALL		(-EPIPE) 			/* pipe stalled, also in urb->status*/
-
-/*
  * USB device number allocation bitmap. There's one bitmap
  * per USB tree.
  */
@@ -197,18 +139,46 @@
 	unsigned long busmap[USB_MAXBUS / (8*sizeof(unsigned long))];
 };
 
+struct usb_device;
+
+/*-------------------------------------------------------------------------*/
+
 /*
- * This is a USB device descriptor.
- *
- * USB device information
+ * Standard USB Descriptor support.
+ * Devices may also have class-specific or vendor-specific descriptors.
+ */
+
+/*
+ * Descriptor types ... USB 2.0 spec table 9.5
+ */
+#define USB_DT_DEVICE			0x01
+#define USB_DT_CONFIG			0x02
+#define USB_DT_STRING			0x03
+#define USB_DT_INTERFACE		0x04
+#define USB_DT_ENDPOINT			0x05
+#define USB_DT_DEVICE_QUALIFIER		0x06
+#define USB_DT_OTHER_SPEED_CONFIG	0x07
+#define USB_DT_INTERFACE_POWER		0x08
+
+// FIXME should be internal to hub driver
+#define USB_DT_HUB			(USB_TYPE_CLASS | 0x09)
+#define USB_DT_HUB_NONVAR_SIZE		7
+
+/*
+ * Descriptor sizes per descriptor type
  */
+#define USB_DT_DEVICE_SIZE		18
+#define USB_DT_CONFIG_SIZE		9
+#define USB_DT_INTERFACE_SIZE		9
+#define USB_DT_ENDPOINT_SIZE		7
+#define USB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */
 
-/* Everything but the endpoint maximums are aribtrary */
+/* most of these maximums are arbitrary */
 #define USB_MAXCONFIG		8
 #define USB_ALTSETTINGALLOC     4
 #define USB_MAXALTSETTING	128  /* Hard limit */
 #define USB_MAXINTERFACES	32
-#define USB_MAXENDPOINTS	32
+#define USB_MAXENDPOINTS	32   /* Hard limit */
 
 /* All standard descriptors have these 2 fields in common */
 struct usb_descriptor_header {
@@ -216,7 +186,7 @@
 	__u8  bDescriptorType;
 } __attribute__ ((packed));
 
-/* Device descriptor */
+/* USB_DT_DEVICE: Device descriptor */
 struct usb_device_descriptor {
 	__u8  bLength;
 	__u8  bDescriptorType;
@@ -234,7 +204,7 @@
 	__u8  bNumConfigurations;
 } __attribute__ ((packed));
 
-/* Endpoint descriptor */
+/* USB_DT_ENDPOINT: Endpoint descriptor */
 struct usb_endpoint_descriptor {
 	__u8  bLength		__attribute__ ((packed));
 	__u8  bDescriptorType	__attribute__ ((packed));
@@ -245,11 +215,12 @@
 	__u8  bRefresh		__attribute__ ((packed));
 	__u8  bSynchAddress	__attribute__ ((packed));
 
+	/* the rest is internal to the Linux implementation */
    	unsigned char *extra;   /* Extra descriptors */
 	int extralen;
 };
 
-/* Interface descriptor */
+/* USB_DT_INTERFACE: Interface descriptor */
 struct usb_interface_descriptor {
 	__u8  bLength		__attribute__ ((packed));
 	__u8  bDescriptorType	__attribute__ ((packed));
@@ -261,6 +232,7 @@
 	__u8  bInterfaceProtocol __attribute__ ((packed));
 	__u8  iInterface	__attribute__ ((packed));
 
+	/* the rest is internal to the Linux implementation */
   	struct usb_endpoint_descriptor *endpoint;
 
    	unsigned char *extra;   /* Extra descriptors */
@@ -278,7 +250,13 @@
 	void *private_data;
 };
 
-/* Configuration descriptor information.. */
+/* USB_DT_CONFIG: Configuration descriptor information.
+ *
+ * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
+ * descriptor type is different.  Highspeed-capable devices can look
+ * different depending on what speed they're currently running.  Only
+ * devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG.
+ */
 struct usb_config_descriptor {
 	__u8  bLength		__attribute__ ((packed));
 	__u8  bDescriptorType	__attribute__ ((packed));
@@ -289,33 +267,129 @@
 	__u8  bmAttributes	__attribute__ ((packed));
 	__u8  MaxPower		__attribute__ ((packed));
 
+	/* the rest is internal to the Linux implementation */
 	struct usb_interface *interface;
 
    	unsigned char *extra;   /* Extra descriptors */
 	int extralen;
 };
 
-/* String descriptor */
+/* USB_DT_STRING: String descriptor */
 struct usb_string_descriptor {
 	__u8  bLength;
 	__u8  bDescriptorType;
-	__u16 wData[1];
+	__u16 wData[1];		/* UTF-16LE encoded */
 } __attribute__ ((packed));
 
-struct usb_device;
+/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
+struct usb_qualifier_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u16 bcdUSB;
+	__u8  bDeviceClass;
+	__u8  bDeviceSubClass;
+	__u8  bDeviceProtocol;
+	__u8  bMaxPacketSize0;
+	__u8  bNumConfigurations;
+	__u8  bRESERVED;
+} __attribute__ ((packed));
+
+/* helpers for driver access to descriptors */
+extern struct usb_interface *
+	usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
+extern struct usb_endpoint_descriptor *
+	usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum);
+
+int __usb_get_extra_descriptor(char *buffer, unsigned size,
+	unsigned char type, void **ptr);
+#define usb_get_extra_descriptor(ifpoint,type,ptr)\
+	__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,\
+		type,(void**)ptr)
+
+/*-------------------------------------------------------------------------*/
 
 /*
  * Device table entry for "new style" table-driven USB drivers.
  * User mode code can read these tables to choose which modules to load.
- * Declare the table as __devinitdata, and as a MODULE_DEVICE_TABLE.
+ * Declare the table as a MODULE_DEVICE_TABLE.
  *
- * With a device table provide bind() instead of probe().  Then the
- * third bind() parameter will point to a matching entry from this
- * table.  (Null value reserved.)
+ * The third probe() parameter will point to a matching entry from this
+ * table.  (Null value reserved.)  Use the driver_data field for each
+ * match to hold information tied to that match:  device quirks, etc.
  * 
  * Terminate the driver's table with an all-zeroes entry.
- * Init the fields you care about; zeroes are not used in comparisons.
+ * Use the flag values to control which fields are compared.
  */
+
+/**
+ * struct usb_device_id - identifies USB devices for probing and hotplugging
+ * @match_flags: Bit mask controlling of the other fields are used to match
+ *	against new devices.  Any field except for driver_info may be used,
+ *	although some only make sense in conjunction with other fields.
+ *	This is usually set by a USB_DEVICE_*() macro, which sets all
+ *	other fields in this structure except for driver_info.
+ * @idVendor: USB vendor ID for a device; numbers are assigned
+ *	by the USB forum to its members.
+ * @idProduct: Vendor-assigned product ID.
+ * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers.
+ *	This is also used to identify individual product versions, for
+ *	a range consisting of a single device.
+ * @bcdDevice_hi: High end of version number range.  The range of product
+ *	versions is inclusive.
+ * @bDeviceClass: Class of device; numbers are assigned
+ *	by the USB forum.  Products may choose to implement classes,
+ *	or be vendor-specific.  Device classes specify behavior of all
+ *	the interfaces on a devices.
+ * @bDeviceSubClass: Subclass of device; associated with bDeviceClass.
+ * @bDeviceProtocol: Protocol of device; associated with bDeviceClass.
+ * @bInterfaceClass: Class of interface; numbers are assigned
+ *	by the USB forum.  Products may choose to implement classes,
+ *	or be vendor-specific.  Interface classes specify behavior only
+ *	of a given interface; other interfaces may support other classes.
+ * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass.
+ * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass.
+ * @driver_info: Holds information used by the driver.  Usually it holds
+ *	a pointer to a descriptor understood by the driver, or perhaps
+ *	device flags.
+ *
+ * In most cases, drivers will create a table of device IDs by using
+ * USB_DEVICE(), or similar macros designed for that purpose.
+ * They will then export it to userspace using MODULE_DEVICE_TABLE(),
+ * and provide it to the USB core through their usb_driver structure.
+ *
+ * See the usb_match_id() function for information about how matches are
+ * performed.  Briefly, you will normally use one of several macros to help
+ * construct these entries.  Each entry you provide will either identify
+ * one or more specific products, or will identify a class of products
+ * which have agreed to behave the same.  You should put the more specific
+ * matches towards the beginning of your table, so that driver_info can
+ * record quirks of specific products.
+ */
+struct usb_device_id {
+	/* which fields to match against? */
+	__u16		match_flags;
+
+	/* Used for product specific matches; range is inclusive */
+	__u16		idVendor;
+	__u16		idProduct;
+	__u16		bcdDevice_lo;
+	__u16		bcdDevice_hi;
+
+	/* Used for device class matches */
+	__u8		bDeviceClass;
+	__u8		bDeviceSubClass;
+	__u8		bDeviceProtocol;
+
+	/* Used for interface class matches */
+	__u8		bInterfaceClass;
+	__u8		bInterfaceSubClass;
+	__u8		bInterfaceProtocol;
+
+	/* not matched against */
+	unsigned long	driver_info;
+};
+
+/* Some useful macros to use to create struct usb_device_id */
 #define USB_DEVICE_ID_MATCH_VENDOR		0x0001
 #define USB_DEVICE_ID_MATCH_PRODUCT		0x0002
 #define USB_DEVICE_ID_MATCH_DEV_LO		0x0004
@@ -335,53 +409,98 @@
 #define USB_DEVICE_ID_MATCH_INT_INFO \
 	(USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS | USB_DEVICE_ID_MATCH_INT_PROTOCOL)
 
-/* Some useful macros */
+/**
+ * USB_DEVICE - macro used to describe a specific usb device
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific device.
+ */
 #define USB_DEVICE(vend,prod) \
 	match_flags: USB_DEVICE_ID_MATCH_DEVICE, idVendor: (vend), idProduct: (prod)
+/**
+ * USB_DEVICE_VER - macro used to describe a specific usb device with a version range
+ * @vend: the 16 bit USB Vendor ID
+ * @prod: the 16 bit USB Product ID
+ * @lo: the bcdDevice_lo value
+ * @hi: the bcdDevice_hi value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific device, with a version range.
+ */
 #define USB_DEVICE_VER(vend,prod,lo,hi) \
 	match_flags: USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, idVendor: (vend), idProduct: (prod), bcdDevice_lo: (lo), bcdDevice_hi: (hi)
+
+/**
+ * USB_DEVICE_INFO - macro used to describe a class of usb devices
+ * @cl: bDeviceClass value
+ * @sc: bDeviceSubClass value
+ * @pr: bDeviceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific class of devices.
+ */
 #define USB_DEVICE_INFO(cl,sc,pr) \
 	match_flags: USB_DEVICE_ID_MATCH_DEV_INFO, bDeviceClass: (cl), bDeviceSubClass: (sc), bDeviceProtocol: (pr)
+
+/**
+ * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces 
+ * @cl: bInterfaceClass value
+ * @sc: bInterfaceSubClass value
+ * @pr: bInterfaceProtocol value
+ *
+ * This macro is used to create a struct usb_device_id that matches a
+ * specific class of interfaces.
+ */
 #define USB_INTERFACE_INFO(cl,sc,pr) \
 	match_flags: USB_DEVICE_ID_MATCH_INT_INFO, bInterfaceClass: (cl), bInterfaceSubClass: (sc), bInterfaceProtocol: (pr)
 
-struct usb_device_id {
-	/* This bitmask is used to determine which of the following fields
-	 * are to be used for matching.
-	 */
-	__u16		match_flags;
-
-	/*
-	 * vendor/product codes are checked, if vendor is nonzero
-	 * Range is for device revision (bcdDevice), inclusive;
-	 * zero values here mean range isn't considered
-	 */
-	__u16		idVendor;
-	__u16		idProduct;
-	__u16		bcdDevice_lo, bcdDevice_hi;
-
-	/*
-	 * if device class != 0, these can be match criteria;
-	 * but only if this bDeviceClass value is nonzero
-	 */
-	__u8		bDeviceClass;
-	__u8		bDeviceSubClass;
-	__u8		bDeviceProtocol;
-
-	/*
-	 * if interface class != 0, these can be match criteria;
-	 * but only if this bInterfaceClass value is nonzero
-	 */
-	__u8		bInterfaceClass;
-	__u8		bInterfaceSubClass;
-	__u8		bInterfaceProtocol;
-
-	/*
-	 * for driver's use; not involved in driver matching.
-	 */
-	unsigned long	driver_info;
-};
+/* -------------------------------------------------------------------------- */
 
+/**
+ * struct usb_driver - identifies USB driver to usbcore
+ * @name: The driver name should be unique among USB drivers
+ * @probe: Called to see if the driver is willing to manage a particular
+ *	interface on a device.  The probe routine returns a handle that 
+ *	will later be provided to disconnect(), or a null pointer to
+ *	indicate that the driver will not handle the interface.
+ *	The handle is normally a pointer to driver-specific data.
+ *	If the probe() routine needs to access the interface
+ *	structure itself, use usb_ifnum_to_if() to make sure it's using
+ *	the right one.
+ * @disconnect: Called when the interface is no longer accessible, usually
+ *	because its device has been (or is being) disconnected.  The
+ *	handle passed is what was returned by probe(), or was provided
+ *	to usb_driver_claim_interface().
+ * @fops: USB drivers can reuse some character device framework in
+ *	the USB subsystem by providing a file operations vector and
+ *	a minor number.
+ * @minor: Used with fops to simplify creating USB character devices.
+ *	Such drivers have sixteen character devices, using the USB
+ *	major number and starting with this minor number.
+ * @ioctl: Used for drivers that want to talk to userspace through
+ *	the "usbfs" filesystem.  This lets devices provide ways to
+ *	expose information to user space regardless of where they
+ *	do (or don't) show up otherwise in the filesystem.
+ * @id_table: USB drivers use ID table to support hotplugging.
+ *	Export this with MODULE_DEVICE_TABLE(usb,...), or use NULL to
+ *	say that probe() should be called for any unclaimed interfce.
+ *
+ * USB drivers should provide a name, probe() and disconnect() methods,
+ * and an id_table.  Other driver fields are optional.
+ *
+ * The id_table is used in hotplugging.  It holds a set of descriptors,
+ * and specialized data may be associated with each entry.  That table
+ * is used by both user and kernel mode hotplugging support.
+ *
+ * The probe() and disconnect() methods are called in a context where
+ * they can sleep, but they should avoid abusing the privilage.  Most
+ * work to connect to a device should be done when the device is opened,
+ * and undone at the last close.  The disconnect code needs to address
+ * concurrency issues with respect to open() and close() methods, as
+ * well as cancel any I/O requests that are still pending.
+ */
 struct usb_driver {
 	const char *name;
 
@@ -390,7 +509,10 @@
 	    unsigned intf,			/* what interface */
 	    const struct usb_device_id *id	/* from id_table */
 	    );
-	void (*disconnect)(struct usb_device *, void *);
+	void (*disconnect)(
+	    struct usb_device *dev,		/* the device */
+	    void *handle			/* as returned by probe() */
+	    );
 
 	struct list_head driver_list;
 
@@ -402,152 +524,437 @@
 	/* ioctl -- userspace apps can talk to drivers through usbdevfs */
 	int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);
 
-	/* support for "new-style" USB hotplugging
-	 * binding policy can be driven from user mode too
-	 */
+	/* support for "new-style" USB hotplugging */
 	const struct usb_device_id *id_table;
 
 	/* suspend before the bus suspends;
 	 * disconnect or resume when the bus resumes */
-	// void (*suspend)(struct usb_device *dev);
-	// void (*resume)(struct usb_device *dev);
+	/* void (*suspend)(struct usb_device *dev); */
+	/* void (*resume)(struct usb_device *dev); */
 };
-	
-/*----------------------------------------------------------------------------* 
- * New USB Structures                                                         *
- *----------------------------------------------------------------------------*/
+
+/*
+ * use these in module_init()/module_exit()
+ * and don't forget MODULE_DEVICE_TABLE(usb, ...)
+ */
+extern int usb_register(struct usb_driver *);
+extern void usb_deregister(struct usb_driver *);
+
+/* -------------------------------------------------------------------------- */
+
+/*
+ * URB support, for asynchronous request completions
+ */
 
 /*
  * urb->transfer_flags:
+ *
+ * FIXME should be URB_* flags
  */
 #define USB_DISABLE_SPD         0x0001
 #define USB_ISO_ASAP            0x0002
 #define USB_ASYNC_UNLINK        0x0008
 #define USB_QUEUE_BULK          0x0010
 #define USB_NO_FSBR		0x0020
-#define USB_ZERO_PACKET         0x0040  // Finish bulk OUTs always with zero length packet
-#define USB_TIMEOUT_KILLED	0x1000	// only set by HCD!
+#define USB_ZERO_PACKET         0x0040  /* Finish bulk OUTs with short packet */
+#define URB_NO_INTERRUPT	0x0080	/* HINT: no non-error interrupt needed */
+					/* ... less overhead for QUEUE_BULK */
+#define USB_TIMEOUT_KILLED	0x1000	/* only set by HCD! */
 
 typedef struct
 {
 	unsigned int offset;
-	unsigned int length;		// expected length
+	unsigned int length;		/* expected length */
 	unsigned int actual_length;
 	unsigned int status;
 } iso_packet_descriptor_t, *piso_packet_descriptor_t;
 
 struct urb;
+
 typedef void (*usb_complete_t)(struct urb *);
 
-typedef struct urb
+/**
+ * struct urb - USB Request Block
+ * @urb_list: For use by current owner of the URB.
+ * @next: Used primarily to link ISO requests into rings.
+ * @pipe: Holds endpoint number, direction, type, and max packet size.
+ *	Create these values with the eight macros available;
+ *	usb_{snd,rcv}TYPEpipe(dev,endpoint), where the type is "ctrl"
+ *	(control), "bulk", "int" (interrupt), or "iso" (isochronous).
+ *	For example usb_sndbulkpipe() or usb_rcvintpipe().  Endpoint
+ *	numbers range from zero to fifteen.  Note that "in" endpoint two
+ *	is a different endpoint (and pipe) from "out" endpoint two.
+ *	The current configuration controls the existence, type, and
+ *	maximum packet size of any given endpoint.
+ * @dev: Identifies the USB device to perform the request.
+ * @status: This is read in non-iso completion functions to get the
+ *	status of the particular request.  ISO requests only use it
+ *	to tell whether the URB was unlinked; detailed status for
+ *	each frame is in the fields of the iso_frame-desc.
+ * @transfer_flags: A variety of flags may be used to affect how URB
+ *	submission, unlinking, or operation are handled.  Different
+ *	kinds of URB can use different flags.
+ * @transfer_buffer: For non-iso transfers, this identifies the buffer
+ *	to (or from) which the I/O request will be performed.  This
+ *	buffer must be suitable for DMA; allocate it with kmalloc()
+ *	or equivalent.  For transfers to "in" endpoints, contents of
+ *	this buffer will be modified.
+ * @transfer_buffer_length: How big is transfer_buffer.  The transfer may
+ *	be broken up into chunks according to the current maximum packet
+ *	size for the endpoint, which is a function of the configuration
+ *	and is encoded in the pipe.
+ * @actual_length: This is read in non-iso completion functions, and
+ *	it tells how many bytes (out of transfer_buffer_length) were
+ *	transferred.  It will normally be the same as requested, unless
+ *	either an error was reported or a short read was performed and
+ *	the USB_DISABLE_SPD transfer flag was used to say that such
+ *	short reads are not errors. 
+ * @setup_packet: Only used for control transfers, this points to eight bytes
+ *	of setup data.  Control transfers always start by sending this data
+ *	to the device.  Then transfer_buffer is read or written, if needed.
+ * @start_frame: Returns the initial frame for interrupt or isochronous
+ *	transfers.
+ * @number_of_packets: Lists the number of ISO transfer buffers.
+ * @interval: Specifies the polling interval for interrupt transfers, in
+ *	milliseconds.
+ * @error_count: Returns the number of ISO transfers that reported errors.
+ * @context: For use in completion functions.  This normally points to
+ *	request-specific driver context.
+ * @complete: Completion handler. This URB is passed as the parameter to the
+ *	completion function.  Except for interrupt or isochronous transfers
+ *	that aren't being unlinked, the completion function may then do what
+ *	it likes with the URB, including resubmitting or freeing it.
+ * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to 
+ *	collect the transfer status for each buffer.
+ *
+ * This structure identifies USB transfer requests.  URBs may be allocated
+ * in any way, although usb_alloc_urb() is often convenient.  Initialization
+ * may be done using various FILL_*_URB() macros.  URBs are submitted
+ * using usb_submit_urb(), and pending requests may be canceled using
+ * usb_unlink_urb().
+ *
+ * Initialization:
+ *
+ * All URBs submitted must initialize dev, pipe, next (may be null),
+ * transfer_flags (may be zero), complete, timeout (may be zero).
+ * The USB_ASYNC_UNLINK transfer flag affects later invocations of
+ * the usb_unlink_urb() routine.
+ *
+ * All non-isochronous URBs must also initialize 
+ * transfer_buffer and transfer_buffer_length.  They may provide the
+ * USB_DISABLE_SPD transfer flag, indicating that short reads are
+ * not to be treated as errors.
+ *
+ * Bulk URBs may pass the USB_QUEUE_BULK transfer flag, telling the host
+ * controller driver never to report an error if several bulk requests get
+ * queued to the same endpoint.  Such queueing supports more efficient use
+ * of bus bandwidth, minimizing delays due to interrupts and scheduling,
+ * if the host controller hardware is smart enough.  Bulk URBs can also
+ * use the USB_ZERO_PACKET transfer flag, indicating that bulk OUT transfers
+ * should always terminate with a short packet, even if it means adding an
+ * extra zero length packet.
+ *
+ * Control URBs must provide a setup_packet.
+ *
+ * Interupt UBS must provide an interval, saying how often (in milliseconds)
+ * to poll for transfers.  After the URB has been submitted, the interval
+ * and start_frame fields reflect how the transfer was actually scheduled.
+ * The polling interval may be more frequent than requested.
+ * For example, some controllers have a maximum interval of 32 microseconds,
+ * while others support intervals of up to 1024 microseconds.
+ *
+ * Isochronous URBs normally use the USB_ISO_ASAP transfer flag, telling
+ * the host controller to schedule the transfer as soon as bandwidth
+ * utilization allows, and then set start_frame to reflect the actual frame
+ * selected during submission.  Otherwise drivers must specify the start_frame
+ * and handle the case where the transfer can't begin then.  However, drivers
+ * won't know how bandwidth is currently allocated, and while they can
+ * find the current frame using usb_get_current_frame_number () they can't
+ * know the range for that frame number.  (Common ranges for the frame
+ * counter include 256, 512, and 1024 frames.)
+ *
+ * Isochronous URBs have a different data transfer model, in part because
+ * the quality of service is only "best effort".  Callers provide specially
+ * allocated URBs, with number_of_packets worth of iso_frame_desc structures
+ * at the end.  Each such packet is an individual ISO transfer.  Isochronous
+ * URBs are normally submitted with urb->next fields set up as a ring, so
+ * that data (such as audio or video) streams at as constant a rate as the
+ * host controller scheduler can support.
+ *
+ * Completion Callbacks:
+ *
+ * The completion callback is made in_interrupt(), and one of the first
+ * things that a completion handler should do is check the status field.
+ * The status field is provided for all URBs.  It is used to report
+ * unlinked URBs, and status for all non-ISO transfers.  It should not
+ * be examined outside of the completion handler.
+ *
+ * The context field is normally used to link URBs back to the relevant
+ * driver or request state.
+ *
+ * When completion callback is invoked for non-isochronous URBs, the
+ * actual_length field tells how many bytes were transferred.
+ *
+ * For interrupt and isochronous URBs, the URB provided to the callback
+ * function is still "owned" by the USB core subsystem unless the status
+ * indicates that the URB has been unlinked.  Completion handlers should
+ * not modify such URBs until they have been unlinked.
+ *
+ * ISO transfer status is reported in the status and actual_length fields
+ * of the iso_frame_desc array, and the number of errors is reported in
+ * error_count.
+ */
+struct urb
 {
-	spinlock_t lock;		// lock for the URB
-	void *hcpriv;			// private data for host controller
-	struct list_head urb_list;	// list pointer to all active urbs 
-	struct urb *next;		// pointer to next URB	
-	struct usb_device *dev;		// pointer to associated USB device
-	unsigned int pipe;		// pipe information
-	int status;			// returned status
-	unsigned int transfer_flags;	// USB_DISABLE_SPD | USB_ISO_ASAP | etc.
-	void *transfer_buffer;		// associated data buffer
-	int transfer_buffer_length;	// data buffer length
-	int actual_length;              // actual data buffer length	
-	int bandwidth;			// bandwidth for this transfer request (INT or ISO)
-	unsigned char *setup_packet;	// setup packet (control only)
-	//
-	int start_frame;		// start frame (iso/irq only)
-	int number_of_packets;		// number of packets in this request (iso)
-	int interval;                   // polling interval (irq only)
-	int error_count;		// number of errors in this transfer (iso only)
-	int timeout;			// timeout (in jiffies)
-	//
-	void *context;			// context for completion routine
-	usb_complete_t complete;	// pointer to completion routine
-	//
-	iso_packet_descriptor_t iso_frame_desc[0];
-} urb_t, *purb_t;
+	spinlock_t lock;		/* lock for the URB */
+	void *hcpriv;			/* private data for host controller */
+	struct list_head urb_list;	/* list pointer to all active urbs */
+	struct urb *next; 		/* (in) pointer to next URB */
+	struct usb_device *dev; 	/* (in) pointer to associated device */
+	unsigned int pipe;		/* (in) pipe information */
+	int status;			/* (return) non-ISO status */
+	unsigned int transfer_flags;	/* (in) USB_DISABLE_SPD | ...*/
+	void *transfer_buffer;		/* (in) associated data buffer */
+	int transfer_buffer_length;	/* (in) data buffer length */
+	int actual_length;              /* (return) actual transfer length */
+	int bandwidth;			/* bandwidth for INT/ISO request */
+	unsigned char *setup_packet;	/* (in) setup packet (control only) */
+	int start_frame;		/* (modify) start frame (INT/ISO) */
+	int number_of_packets;		/* (in) number of ISO packets */
+	int interval;                   /* (in) polling interval (INT only) */
+	int error_count;		/* (return) number of ISO errors */
+	int timeout;			/* (in) timeout, in jiffies */
+	void *context;			/* (in) context for completion */
+	usb_complete_t complete;	/* (in) completion routine */
+	iso_packet_descriptor_t iso_frame_desc[0];	/* (in) ISO ONLY */
+};
+
+typedef struct urb urb_t, *purb_t;
 
-#define FILL_CONTROL_URB(a,aa,b,c,d,e,f,g) \
+/**
+ * FILL_CONTROL_URB - macro to help initialize a control urb
+ * @URB: pointer to the urb to initialize.
+ * @DEV: pointer to the struct usb_device for this urb.
+ * @PIPE: the endpoint pipe
+ * @SETUP_PACKET: pointer to the setup_packet buffer
+ * @TRANSFER_BUFFER: pointer to the transfer buffer
+ * @BUFFER_LENGTH: length of the transfer buffer
+ * @COMPLETE: pointer to the usb_complete_t function
+ * @CONTEXT: what to set the urb context to.
+ *
+ * Initializes a control urb with the proper information needed to submit
+ * it to a device.  This macro is depreciated, the usb_fill_control_urb()
+ * function should be used instead.
+ */
+#define FILL_CONTROL_URB(URB,DEV,PIPE,SETUP_PACKET,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
     do {\
-	spin_lock_init(&(a)->lock);\
-	(a)->dev=aa;\
-	(a)->pipe=b;\
-	(a)->setup_packet=c;\
-	(a)->transfer_buffer=d;\
-	(a)->transfer_buffer_length=e;\
-	(a)->complete=f;\
-	(a)->context=g;\
+	spin_lock_init(&(URB)->lock);\
+	(URB)->dev=DEV;\
+	(URB)->pipe=PIPE;\
+	(URB)->setup_packet=SETUP_PACKET;\
+	(URB)->transfer_buffer=TRANSFER_BUFFER;\
+	(URB)->transfer_buffer_length=BUFFER_LENGTH;\
+	(URB)->complete=COMPLETE;\
+	(URB)->context=CONTEXT;\
     } while (0)
 
-#define FILL_BULK_URB(a,aa,b,c,d,e,f) \
+/**
+ * FILL_BULK_URB - macro to help initialize a bulk urb
+ * @URB: pointer to the urb to initialize.
+ * @DEV: pointer to the struct usb_device for this urb.
+ * @PIPE: the endpoint pipe
+ * @TRANSFER_BUFFER: pointer to the transfer buffer
+ * @BUFFER_LENGTH: length of the transfer buffer
+ * @COMPLETE: pointer to the usb_complete_t function
+ * @CONTEXT: what to set the urb context to.
+ *
+ * Initializes a bulk urb with the proper information needed to submit it
+ * to a device.  This macro is depreciated, the usb_fill_bulk_urb()
+ * function should be used instead.
+ */
+#define FILL_BULK_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT) \
     do {\
-	spin_lock_init(&(a)->lock);\
-	(a)->dev=aa;\
-	(a)->pipe=b;\
-	(a)->transfer_buffer=c;\
-	(a)->transfer_buffer_length=d;\
-	(a)->complete=e;\
-	(a)->context=f;\
+	spin_lock_init(&(URB)->lock);\
+	(URB)->dev=DEV;\
+	(URB)->pipe=PIPE;\
+	(URB)->transfer_buffer=TRANSFER_BUFFER;\
+	(URB)->transfer_buffer_length=BUFFER_LENGTH;\
+	(URB)->complete=COMPLETE;\
+	(URB)->context=CONTEXT;\
     } while (0)
     
-#define FILL_INT_URB(a,aa,b,c,d,e,f,g) \
+/**
+ * FILL_INT_URB - macro to help initialize a interrupt urb
+ * @URB: pointer to the urb to initialize.
+ * @DEV: pointer to the struct usb_device for this urb.
+ * @PIPE: the endpoint pipe
+ * @TRANSFER_BUFFER: pointer to the transfer buffer
+ * @BUFFER_LENGTH: length of the transfer buffer
+ * @COMPLETE: pointer to the usb_complete_t function
+ * @CONTEXT: what to set the urb context to.
+ * @INTERVAL: what to set the urb interval to.
+ *
+ * Initializes a interrupt urb with the proper information needed to submit
+ * it to a device.  This macro is depreciated, the usb_fill_int_urb()
+ * function should be used instead.
+ */
+#define FILL_INT_URB(URB,DEV,PIPE,TRANSFER_BUFFER,BUFFER_LENGTH,COMPLETE,CONTEXT,INTERVAL) \
     do {\
-	spin_lock_init(&(a)->lock);\
-	(a)->dev=aa;\
-	(a)->pipe=b;\
-	(a)->transfer_buffer=c;\
-	(a)->transfer_buffer_length=d;\
-	(a)->complete=e;\
-	(a)->context=f;\
-	(a)->interval=g;\
-	(a)->start_frame=-1;\
+	spin_lock_init(&(URB)->lock);\
+	(URB)->dev=DEV;\
+	(URB)->pipe=PIPE;\
+	(URB)->transfer_buffer=TRANSFER_BUFFER;\
+	(URB)->transfer_buffer_length=BUFFER_LENGTH;\
+	(URB)->complete=COMPLETE;\
+	(URB)->context=CONTEXT;\
+	(URB)->interval=INTERVAL;\
+	(URB)->start_frame=-1;\
     } while (0)
 
-#define FILL_CONTROL_URB_TO(a,aa,b,c,d,e,f,g,h) \
-    do {\
-	spin_lock_init(&(a)->lock);\
-	(a)->dev=aa;\
-	(a)->pipe=b;\
-	(a)->setup_packet=c;\
-	(a)->transfer_buffer=d;\
-	(a)->transfer_buffer_length=e;\
-	(a)->complete=f;\
-	(a)->context=g;\
-	(a)->timeout=h;\
-    } while (0)
+/**
+ * usb_fill_control_urb - initializes a control urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @setup_packet: pointer to the setup_packet buffer
+ * @transfer_buffer: pointer to the transfer buffer
+ * @buffer_length: length of the transfer buffer
+ * @complete: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ *
+ * Initializes a control urb with the proper information needed to submit
+ * it to a device.
+ */
+static inline void usb_fill_control_urb (struct urb *urb,
+					 struct usb_device *dev,
+					 unsigned int pipe,
+					 unsigned char *setup_packet,
+					 void *transfer_buffer,
+					 int buffer_length,
+					 usb_complete_t complete,
+					 void *context)
+{
+	spin_lock_init(&urb->lock);
+	urb->dev = dev;
+	urb->pipe = pipe;
+	urb->setup_packet = setup_packet;
+	urb->transfer_buffer = transfer_buffer;
+	urb->transfer_buffer_length = buffer_length;
+	urb->complete = complete;
+	urb->context = context;
+}
 
-#define FILL_BULK_URB_TO(a,aa,b,c,d,e,f,g) \
-    do {\
-	spin_lock_init(&(a)->lock);\
-	(a)->dev=aa;\
-	(a)->pipe=b;\
-	(a)->transfer_buffer=c;\
-	(a)->transfer_buffer_length=d;\
-	(a)->complete=e;\
-	(a)->context=f;\
-	(a)->timeout=g;\
-    } while (0)
+/**
+ * usb_fill_bulk_urb - macro to help initialize a bulk urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @transfer_buffer: pointer to the transfer buffer
+ * @buffer_length: length of the transfer buffer
+ * @complete: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ *
+ * Initializes a bulk urb with the proper information needed to submit it
+ * to a device.
+ */
+static inline void usb_fill_bulk_urb (struct urb *urb,
+				      struct usb_device *dev,
+				      unsigned int pipe,
+				      void *transfer_buffer,
+				      int buffer_length,
+				      usb_complete_t complete,
+				      void *context)
+				      
+{
+	spin_lock_init(&urb->lock);
+	urb->dev = dev;
+	urb->pipe = pipe;
+	urb->transfer_buffer = transfer_buffer;
+	urb->transfer_buffer_length = buffer_length;
+	urb->complete = complete;
+	urb->context = context;
+}
     
-purb_t usb_alloc_urb(int iso_packets);
-void usb_free_urb (purb_t purb);
-int usb_submit_urb(purb_t purb);
-int usb_unlink_urb(purb_t purb);
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd,  void *data, int len, int timeout);
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout);
+/**
+ * usb_fill_int_urb - macro to help initialize a interrupt urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @transfer_buffer: pointer to the transfer buffer
+ * @buffer_length: length of the transfer buffer
+ * @complete: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ * @interval: what to set the urb interval to.
+ *
+ * Initializes a interrupt urb with the proper information needed to submit
+ * it to a device.
+ */
+static inline void usb_fill_int_urb (struct urb *urb,
+				     struct usb_device *dev,
+				     unsigned int pipe,
+				     void *transfer_buffer,
+				     int buffer_length,
+				     usb_complete_t complete,
+				     void *context,
+				     int interval)
+{
+	spin_lock_init(&urb->lock);
+	urb->dev = dev;
+	urb->pipe = pipe;
+	urb->transfer_buffer = transfer_buffer;
+	urb->transfer_buffer_length = buffer_length;
+	urb->complete = complete;
+	urb->context = context;
+	urb->interval = interval;
+	urb->start_frame = -1;
+}
+    
+extern struct urb *usb_alloc_urb(int iso_packets);
+extern void usb_free_urb(struct urb *purb);
+extern int usb_submit_urb(struct urb *purb);
+extern int usb_unlink_urb(struct urb *purb);
 
 /*-------------------------------------------------------------------*
  *                         SYNCHRONOUS CALL SUPPORT                  *
  *-------------------------------------------------------------------*/
 
-struct usb_api_data
-{
-	wait_queue_head_t wqh;
-	int done;
-	/* void* stuff;	*/	/* Possible extension later. */
-};
+extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
+	__u8 request, __u8 requesttype, __u16 value, __u16 index,
+	void *data, __u16 size, int timeout);
+extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
+	void *data, int len, int *actual_length,
+	int timeout);
+
+/* wrappers around usb_control_msg() for the most common standard requests */
+extern int usb_clear_halt(struct usb_device *dev, int pipe);
+extern int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
+	unsigned char descindex, void *buf, int size);
+extern int usb_get_device_descriptor(struct usb_device *dev);
+extern int usb_get_status(struct usb_device *dev,
+	int type, int target, void *data);
+extern int usb_get_string(struct usb_device *dev,
+	unsigned short langid, unsigned char index, void *buf, int size);
+extern int usb_string(struct usb_device *dev, int index,
+	char *buf, size_t size);
+extern int usb_set_configuration(struct usb_device *dev, int configuration);
+extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
+
+/*
+ * timeouts, in seconds, used for sending/receiving control messages
+ * they typically complete within a few frames (msec) after they're issued
+ */
+#ifdef CONFIG_USB_LONG_TIMEOUT
+#define USB_CTRL_GET_TIMEOUT 4
+#else
+#define USB_CTRL_GET_TIMEOUT 3
+#endif
+
+#define USB_CTRL_SET_TIMEOUT 3
 
 /* -------------------------------------------------------------------------- */
 
+/* Host Controller Driver (HCD) support */
+
 struct usb_operations {
 	int (*allocate)(struct usb_device *);
 	int (*deallocate)(struct usb_device *);
@@ -588,6 +995,60 @@
 	atomic_t refcnt;
 };
 
+extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
+extern void usb_free_bus(struct usb_bus *);
+extern void usb_register_bus(struct usb_bus *);
+extern void usb_deregister_bus(struct usb_bus *);
+
+extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
+extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb,
+		int bustime, int isoc);
+extern void usb_release_bandwidth(struct usb_device *dev, struct urb *urb,
+		int isoc);
+extern int usb_root_hub_string(int id, int serial,
+		char *type, __u8 *data, int len);
+
+/*
+ * Some USB 1.1 bandwidth allocation constants.
+ */
+#define BW_HOST_DELAY	1000L		/* nanoseconds */
+#define BW_HUB_LS_SETUP	333L		/* nanoseconds */
+                        /* 4 full-speed bit times (est.) */
+
+#define FRAME_TIME_BITS         12000L		/* frame = 1 millisecond */
+#define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
+#define FRAME_TIME_USECS	1000L
+#define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
+
+#define BitTime(bytecount)  (7 * 8 * bytecount / 6)  /* with integer truncation */
+		/* Trying not to use worst-case bit-stuffing
+                   of (7/6 * 8 * bytecount) = 9.33 * bytecount */
+		/* bytecount = data payload byte count */
+
+#define NS_TO_US(ns)	((ns + 500L) / 1000L)
+			/* convert & round nanoseconds to microseconds */
+
+
+/* -------------------------------------------------------------------------- */
+
+/* Enumeration is only for the hub driver, or HCD virtual root hubs */
+extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
+	struct usb_bus *);
+extern void usb_free_dev(struct usb_device *);
+extern int usb_new_device(struct usb_device *dev);
+extern void usb_connect(struct usb_device *dev);
+extern void usb_disconnect(struct usb_device **);
+
+#ifndef _LINUX_HUB_H
+/* exported to hub driver ONLY to support usb_reset_device () */
+extern int usb_get_configuration(struct usb_device *dev);
+extern void usb_set_maxpacket(struct usb_device *dev);
+extern void usb_destroy_configuration(struct usb_device *dev);
+extern int usb_set_address(struct usb_device *dev);
+#endif /* _LINUX_HUB_H */
+
+/* -------------------------------------------------------------------------- */
+
 /* This is arbitrary.
  * From USB 2.0 spec Table 11-13, offset 7, a hub can
  * have up to 255 ports. The most yet reported is 10.
@@ -645,44 +1106,30 @@
 	struct usb_device *children[USB_MAXCHILDREN];
 };
 
-extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
-extern struct usb_endpoint_descriptor *usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum);
-
-extern int usb_register(struct usb_driver *);
-extern void usb_deregister(struct usb_driver *);
+/* for when layers above USB add new non-USB drivers */
 extern void usb_scan_devices(void);
 
-/* used these for multi-interface device registration */
-extern void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv);
-extern int usb_interface_claimed(struct usb_interface *iface);
-extern void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface);
-const struct usb_device_id *usb_match_id(struct usb_device *dev,
-					 struct usb_interface *interface,
-					 const struct usb_device_id *id);
+/* mostly for devices emulating SCSI over USB */
+extern int usb_reset_device(struct usb_device *dev);
 
-extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
-extern void usb_free_bus(struct usb_bus *);
-extern void usb_register_bus(struct usb_bus *);
-extern void usb_deregister_bus(struct usb_bus *);
+/* for drivers using iso endpoints */
+extern int usb_get_current_frame_number (struct usb_device *usb_dev);
 
-extern struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *);
-extern void usb_free_dev(struct usb_device *);
+/* drivers must track when they bind to a device's interfaces */
 extern void usb_inc_dev_use(struct usb_device *);
 #define usb_dec_dev_use usb_free_dev
 
-extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb);
-extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, int bustime, int isoc);
-extern void usb_release_bandwidth(struct usb_device *dev, struct urb *urb, int isoc);
-
-extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
-
-extern int usb_root_hub_string(int id, int serial, char *type, __u8 *data, int len);
-extern void usb_connect(struct usb_device *dev);
-extern void usb_disconnect(struct usb_device **);
-
-extern void usb_destroy_configuration(struct usb_device *dev);
+/* used these for multi-interface device registration */
+extern void usb_driver_claim_interface(struct usb_driver *driver,
+			struct usb_interface *iface, void* priv);
+extern int usb_interface_claimed(struct usb_interface *iface);
+extern void usb_driver_release_interface(struct usb_driver *driver,
+			struct usb_interface *iface);
+const struct usb_device_id *usb_match_id(struct usb_device *dev,
+					 struct usb_interface *interface,
+					 const struct usb_device_id *id);
 
-int usb_get_current_frame_number (struct usb_device *usb_dev);
+/* -------------------------------------------------------------------------- */
 
 /*
  * Calling this entity a "pipe" is glorifying it. A USB pipe
@@ -690,7 +1137,7 @@
  * of the following information:
  *  - device number (7 bits)
  *  - endpoint number (4 bits)
- *  - current Data0/1 state (1 bit)
+ *  - current Data0/1 state (1 bit) [Historical; now gone]
  *  - direction (1 bit)
  *  - speed (1 bit)
  *  - max packet size (2 bits: 8, 16, 32 or 64) [Historical; now gone.]
@@ -707,7 +1154,7 @@
  *  - direction:	bit 7		(0 = Host-to-Device [Out], 1 = Device-to-Host [In])
  *  - device:		bits 8-14
  *  - endpoint:		bits 15-18
- *  - Data0/1:		bit 19
+ *  - Data0/1:		bit 19		[Historical; now gone. ]
  *  - speed:		bit 26		(0 = Full, 1 = Low Speed)
  *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk)
  *
@@ -720,6 +1167,8 @@
  * like full speed devices.
  */
 
+// FIXME 2.5 get rid of usb_pipeslow(), just use dev->speed
+
 #define PIPE_ISOCHRONOUS		0
 #define PIPE_INTERRUPT			1
 #define PIPE_CONTROL			2
@@ -735,7 +1184,6 @@
 #define usb_pipedevice(pipe)	(((pipe) >> 8) & 0x7f)
 #define usb_pipe_endpdev(pipe)	(((pipe) >> 8) & 0x7ff)
 #define usb_pipeendpoint(pipe)	(((pipe) >> 15) & 0xf)
-#define usb_pipedata(pipe)	(((pipe) >> 19) & 1)
 #define usb_pipeslow(pipe)	(((pipe) >> 26) & 1)
 #define usb_pipetype(pipe)	(((pipe) >> 30) & 3)
 #define usb_pipeisoc(pipe)	(usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
@@ -779,58 +1227,10 @@
 #define usb_snddefctrl(dev)		((PIPE_CONTROL << 30) | __default_pipe(dev))
 #define usb_rcvdefctrl(dev)		((PIPE_CONTROL << 30) | __default_pipe(dev) | USB_DIR_IN)
 
-/*
- * Send and receive control messages..
- */
-int usb_new_device(struct usb_device *dev);
-int usb_reset_device(struct usb_device *dev);
-int usb_set_address(struct usb_device *dev);
-int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
-	unsigned char descindex, void *buf, int size);
-int usb_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char desctype,
-	unsigned char descindex, void *buf, int size);
-int usb_get_device_descriptor(struct usb_device *dev);
-int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr);
-int usb_get_status(struct usb_device *dev, int type, int target, void *data);
-int usb_get_configuration(struct usb_device *dev);
-int usb_get_protocol(struct usb_device *dev, int ifnum);
-int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
-int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
-int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id);
-int usb_set_configuration(struct usb_device *dev, int configuration);
-int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
-	unsigned char id, void *buf, int size);
-int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type,
-	unsigned char id, void *buf, int size);
-int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
-int usb_clear_halt(struct usb_device *dev, int pipe);
-void usb_set_maxpacket(struct usb_device *dev);
-
-#define usb_get_extra_descriptor(ifpoint,type,ptr)\
-	__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,type,(void**)ptr)
-
-/*
- * Some USB bandwidth allocation constants.
- */
-#define BW_HOST_DELAY	1000L		/* nanoseconds */
-#define BW_HUB_LS_SETUP	333L		/* nanoseconds */
-                        /* 4 full-speed bit times (est.) */
-
-#define FRAME_TIME_BITS         12000L		/* frame = 1 millisecond */
-#define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
-#define FRAME_TIME_USECS	1000L
-#define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
-
-#define BitTime(bytecount)  (7 * 8 * bytecount / 6)  /* with integer truncation */
-		/* Trying not to use worst-case bit-stuffing
-                   of (7/6 * 8 * bytecount) = 9.33 * bytecount */
-		/* bytecount = data payload byte count */
-
-#define NS_TO_US(ns)	((ns + 500L) / 1000L)
-			/* convert & round nanoseconds to microseconds */
+/* -------------------------------------------------------------------------- */
 
 /*
- * Debugging helpers..
+ * Debugging and troubleshooting/diagnostic helpers.
  */
 void usb_show_device_descriptor(struct usb_device_descriptor *);
 void usb_show_config_descriptor(struct usb_config_descriptor *);
@@ -844,13 +1244,17 @@
 #else
 #define dbg(format, arg...) do {} while (0)
 #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)
 
 
+/* -------------------------------------------------------------------------- */
+
 /*
  * bus and driver list
+ * exported only for usbdevfs (not visible outside usbcore)
  */
 
 extern struct list_head usb_driver_list;
diff -u --recursive --new-file v2.5.0/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h
--- v2.5.0/linux/include/net/irda/irlmp.h	Fri Nov  9 14:22:17 2001
+++ linux/include/net/irda/irlmp.h	Fri Nov 30 13:25:10 2001
@@ -264,4 +264,16 @@
 	return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap);
 }
 
+/* After doing a irlmp_dup(), this get one of the two socket back into
+ * a state where it's waiting incomming connections.
+ * Note : this can be used *only* if the socket is not yet connected
+ * (i.e. NO irlmp_connect_response() done on this socket).
+ * - Jean II */
+static inline void irlmp_listen(struct lsap_cb *self)
+{
+	self->dlsap_sel = LSAP_ANY;
+	self->lap = NULL;
+	self->lsap_state = LSAP_DISCONNECTED;
+}
+
 #endif
diff -u --recursive --new-file v2.5.0/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h
--- v2.5.0/linux/include/net/irda/irttp.h	Mon Dec 11 13:33:09 2000
+++ linux/include/net/irda/irttp.h	Fri Nov 30 13:25:10 2001
@@ -148,6 +148,17 @@
 	return self->max_seg_size;
 }
 
+/* After doing a irttp_dup(), this get one of the two socket back into
+ * a state where it's waiting incomming connections.
+ * Note : this can be used *only* if the socket is not yet connected
+ * (i.e. NO irttp_connect_response() done on this socket).
+ * - Jean II */
+static inline void irttp_listen(struct tsap_cb *self)
+{
+	irlmp_listen(self->lsap);
+	self->dtsap_sel = LSAP_ANY;
+}
+
 extern struct irttp_cb *irttp;
 
 #endif /* IRTTP_H */
diff -u --recursive --new-file v2.5.0/linux/init/do_mounts.c linux/init/do_mounts.c
--- v2.5.0/linux/init/do_mounts.c	Wed Dec 31 16:00:00 1969
+++ linux/init/do_mounts.c	Mon Dec 10 14:11:40 2001
@@ -0,0 +1,561 @@
+#define __KERNEL_SYSCALLS__
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/unistd.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <linux/blk.h>
+#include <linux/tty.h>
+#include <linux/fd.h>
+
+#include <linux/nfs_fs.h>
+#include <linux/nfs_fs_sb.h>
+#include <linux/nfs_mount.h>
+
+#include <asm/uaccess.h>
+
+/* syscalls missing from unistd.h */
+ 
+static inline _syscall2(int,mkdir,char *,name,int,mode);
+static inline _syscall1(int,chdir,char *,name);
+static inline _syscall1(int,chroot,char *,name);
+static inline _syscall1(int,unlink,char *,name);
+static inline _syscall3(int,mknod,char *,name,int,mode,dev_t,dev);
+static inline _syscall5(int,mount,char *,dev,char *,dir,char *,type,
+			unsigned long,flags,void *,data);
+static inline _syscall2(int,umount,char *,name,int,flags);
+
+extern void rd_load(void);
+extern void initrd_load(void);
+extern int get_filesystem_list(char * buf);
+extern void wait_for_keypress(void);
+
+asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
+	 unsigned long flags, void * data);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+unsigned int real_root_dev;	/* do_proc_dointvec cannot handle kdev_t */
+#endif
+int root_mountflags = MS_RDONLY;
+char root_device_name[64];
+
+/* this is initialized in init/main.c */
+kdev_t ROOT_DEV;
+
+static int __init readonly(char *str)
+{
+	if (*str)
+		return 0;
+	root_mountflags |= MS_RDONLY;
+	return 1;
+}
+
+static int __init readwrite(char *str)
+{
+	if (*str)
+		return 0;
+	root_mountflags &= ~MS_RDONLY;
+	return 1;
+}
+
+__setup("ro", readonly);
+__setup("rw", readwrite);
+
+static struct dev_name_struct {
+	const char *name;
+	const int num;
+} root_dev_names[] __initdata = {
+	{ "nfs",     0x00ff },
+	{ "hda",     0x0300 },
+	{ "hdb",     0x0340 },
+	{ "loop",    0x0700 },
+	{ "hdc",     0x1600 },
+	{ "hdd",     0x1640 },
+	{ "hde",     0x2100 },
+	{ "hdf",     0x2140 },
+	{ "hdg",     0x2200 },
+	{ "hdh",     0x2240 },
+	{ "hdi",     0x3800 },
+	{ "hdj",     0x3840 },
+	{ "hdk",     0x3900 },
+	{ "hdl",     0x3940 },
+	{ "hdm",     0x5800 },
+	{ "hdn",     0x5840 },
+	{ "hdo",     0x5900 },
+	{ "hdp",     0x5940 },
+	{ "hdq",     0x5A00 },
+	{ "hdr",     0x5A40 },
+	{ "hds",     0x5B00 },
+	{ "hdt",     0x5B40 },
+	{ "sda",     0x0800 },
+	{ "sdb",     0x0810 },
+	{ "sdc",     0x0820 },
+	{ "sdd",     0x0830 },
+	{ "sde",     0x0840 },
+	{ "sdf",     0x0850 },
+	{ "sdg",     0x0860 },
+	{ "sdh",     0x0870 },
+	{ "sdi",     0x0880 },
+	{ "sdj",     0x0890 },
+	{ "sdk",     0x08a0 },
+	{ "sdl",     0x08b0 },
+	{ "sdm",     0x08c0 },
+	{ "sdn",     0x08d0 },
+	{ "sdo",     0x08e0 },
+	{ "sdp",     0x08f0 },
+	{ "ada",     0x1c00 },
+	{ "adb",     0x1c10 },
+	{ "adc",     0x1c20 },
+	{ "add",     0x1c30 },
+	{ "ade",     0x1c40 },
+	{ "fd",      0x0200 },
+	{ "md",      0x0900 },	     
+	{ "xda",     0x0d00 },
+	{ "xdb",     0x0d40 },
+	{ "ram",     0x0100 },
+	{ "scd",     0x0b00 },
+	{ "mcd",     0x1700 },
+	{ "cdu535",  0x1800 },
+	{ "sonycd",  0x1800 },
+	{ "aztcd",   0x1d00 },
+	{ "cm206cd", 0x2000 },
+	{ "gscd",    0x1000 },
+	{ "sbpcd",   0x1900 },
+	{ "eda",     0x2400 },
+	{ "edb",     0x2440 },
+	{ "pda",	0x2d00 },
+	{ "pdb",	0x2d10 },
+	{ "pdc",	0x2d20 },
+	{ "pdd",	0x2d30 },
+	{ "pcd",	0x2e00 },
+	{ "pf",		0x2f00 },
+	{ "apblock", APBLOCK_MAJOR << 8},
+	{ "ddv", DDV_MAJOR << 8},
+	{ "jsfd",    JSFD_MAJOR << 8},
+#if defined(CONFIG_ARCH_S390)
+	{ "dasda", (DASD_MAJOR << MINORBITS) },
+	{ "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
+	{ "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
+	{ "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
+	{ "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
+	{ "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
+	{ "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
+	{ "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
+#endif
+#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
+	{ "ida/c0d0p",0x4800 },
+	{ "ida/c0d1p",0x4810 },
+	{ "ida/c0d2p",0x4820 },
+	{ "ida/c0d3p",0x4830 },
+	{ "ida/c0d4p",0x4840 },
+	{ "ida/c0d5p",0x4850 },
+	{ "ida/c0d6p",0x4860 },
+	{ "ida/c0d7p",0x4870 },
+	{ "ida/c0d8p",0x4880 },
+	{ "ida/c0d9p",0x4890 },
+	{ "ida/c0d10p",0x48A0 },
+	{ "ida/c0d11p",0x48B0 },
+	{ "ida/c0d12p",0x48C0 },
+	{ "ida/c0d13p",0x48D0 },
+	{ "ida/c0d14p",0x48E0 },
+	{ "ida/c0d15p",0x48F0 },
+#endif
+#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
+	{ "cciss/c0d0p",0x6800 },
+	{ "cciss/c0d1p",0x6810 },
+	{ "cciss/c0d2p",0x6820 },
+	{ "cciss/c0d3p",0x6830 },
+	{ "cciss/c0d4p",0x6840 },
+	{ "cciss/c0d5p",0x6850 },
+	{ "cciss/c0d6p",0x6860 },
+	{ "cciss/c0d7p",0x6870 },
+	{ "cciss/c0d8p",0x6880 },
+	{ "cciss/c0d9p",0x6890 },
+	{ "cciss/c0d10p",0x68A0 },
+	{ "cciss/c0d11p",0x68B0 },
+	{ "cciss/c0d12p",0x68C0 },
+	{ "cciss/c0d13p",0x68D0 },
+	{ "cciss/c0d14p",0x68E0 },
+	{ "cciss/c0d15p",0x68F0 },
+#endif
+	{ "nftla", 0x5d00 },
+	{ "nftlb", 0x5d10 },
+	{ "nftlc", 0x5d20 },
+	{ "nftld", 0x5d30 },
+	{ "ftla", 0x2c00 },
+	{ "ftlb", 0x2c08 },
+	{ "ftlc", 0x2c10 },
+	{ "ftld", 0x2c18 },
+	{ "mtdblock", 0x1f00 },
+	{ NULL, 0 }
+};
+
+kdev_t __init name_to_kdev_t(char *line)
+{
+	int base = 0;
+
+	if (strncmp(line,"/dev/",5) == 0) {
+		struct dev_name_struct *dev = root_dev_names;
+		line += 5;
+		do {
+			int len = strlen(dev->name);
+			if (strncmp(line,dev->name,len) == 0) {
+				line += len;
+				base = dev->num;
+				break;
+			}
+			dev++;
+		} while (dev->name);
+	}
+	return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
+}
+
+static int __init root_dev_setup(char *line)
+{
+	int i;
+	char ch;
+
+	ROOT_DEV = name_to_kdev_t(line);
+	memset (root_device_name, 0, sizeof root_device_name);
+	if (strncmp (line, "/dev/", 5) == 0) line += 5;
+	for (i = 0; i < sizeof root_device_name - 1; ++i)
+	{
+	    ch = line[i];
+	    if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
+	    root_device_name[i] = ch;
+	}
+	return 1;
+}
+
+__setup("root=", root_dev_setup);
+
+static char * __initdata root_mount_data;
+static int __init root_data_setup(char *str)
+{
+	root_mount_data = str;
+	return 1;
+}
+
+static char * __initdata root_fs_names;
+static int __init fs_names_setup(char *str)
+{
+	root_fs_names = str;
+	return 1;
+}
+
+__setup("rootflags=", root_data_setup);
+__setup("rootfstype=", fs_names_setup);
+
+static void __init get_fs_names(char *page)
+{
+	char *s = page;
+
+	if (root_fs_names) {
+		strcpy(page, root_fs_names);
+		while (*s++) {
+			if (s[-1] == ',')
+				s[-1] = '\0';
+		}
+	} else {
+		int len = get_filesystem_list(page);
+		char *p, *next;
+
+		page[len] = '\0';
+		for (p = page-1; p; p = next) {
+			next = strchr(++p, '\n');
+			if (*p++ != '\t')
+				continue;
+			while ((*s++ = *p++) != '\n')
+				;
+			s[-1] = '\0';
+		}
+	}
+	*s = '\0';
+}
+
+static void __init mount_root(void)
+{
+	void *handle;
+	char path[64];
+	char *name = "/dev/root";
+	char *fs_names, *p;
+	int do_devfs = 0;
+
+	root_mountflags |= MS_VERBOSE;
+
+	fs_names = __getname();
+	get_fs_names(fs_names);
+
+#ifdef CONFIG_ROOT_NFS
+	if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+		void *data;
+		data = nfs_root_data();
+		if (data) {
+			int err = mount("/dev/root", "/root", "nfs", root_mountflags, data);
+			if (!err)
+				goto done;
+		}
+		printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
+		ROOT_DEV = MKDEV(FLOPPY_MAJOR, 0);
+	}
+#endif
+
+#ifdef CONFIG_BLK_DEV_FD
+	if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
+#ifdef CONFIG_BLK_DEV_RAM
+		extern int rd_doload;
+		extern void rd_load_secondary(void);
+#endif
+		floppy_eject();
+#ifndef CONFIG_BLK_DEV_RAM
+		printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
+#else
+		/* rd_doload is 2 for a dual initrd/ramload setup */
+		if(rd_doload==2)
+			rd_load_secondary();
+		else
+#endif
+		{
+			printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
+			wait_for_keypress();
+		}
+	}
+#endif
+
+	devfs_make_root (root_device_name);
+	handle = devfs_find_handle (NULL, ROOT_DEVICE_NAME,
+	                            MAJOR (ROOT_DEV), MINOR (ROOT_DEV),
+				    DEVFS_SPECIAL_BLK, 1);
+	if (handle) {
+		int n;
+		unsigned major, minor;
+
+		devfs_get_maj_min (handle, &major, &minor);
+		ROOT_DEV = MKDEV (major, minor);
+		if (!ROOT_DEV)
+			panic("I have no root and I want to scream");
+		n = devfs_generate_path (handle, path + 5, sizeof (path) - 5);
+		if (n >= 0) {
+			name = path + n;
+			devfs_mk_symlink (NULL, "root", DEVFS_FL_DEFAULT,
+					  name + 5, NULL, NULL);
+			memcpy (name, "/dev/", 5);
+			do_devfs = 1;
+		}
+	}
+	chdir("/dev");
+	unlink("root");
+	mknod("root", S_IFBLK|0600, kdev_t_to_nr(ROOT_DEV));
+	if (do_devfs)
+		mount("devfs", ".", "devfs", 0, NULL);
+retry:
+	for (p = fs_names; *p; p += strlen(p)+1) {
+		int err;
+		err = sys_mount(name,"/root",p,root_mountflags,root_mount_data);
+		switch (err) {
+			case 0:
+				goto done;
+			case -EACCES:
+				root_mountflags |= MS_RDONLY;
+				goto retry;
+			case -EINVAL:
+				continue;
+		}
+	        /*
+		 * Allow the user to distinguish between failed open
+		 * and bad superblock on root device.
+		 */
+		printk ("VFS: Cannot open root device \"%s\" or %s\n",
+			root_device_name, kdevname (ROOT_DEV));
+		printk ("Please append a correct \"root=\" boot option\n");
+		panic("VFS: Unable to mount root fs on %s",
+			kdevname(ROOT_DEV));
+	}
+	panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));
+
+done:
+	putname(fs_names);
+	if (do_devfs)
+		umount(".", 0);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int __init change_root(kdev_t new_root_dev,const char *put_old)
+{
+	struct vfsmount *old_rootmnt;
+	struct nameidata devfs_nd;
+	char *new_devname = kmalloc(strlen("/dev/root.old")+1, GFP_KERNEL);
+	int error = 0;
+
+	if (new_devname)
+		strcpy(new_devname, "/dev/root.old");
+
+	/* .. here is directory mounted over root */
+	mount("..", ".", NULL, MS_MOVE, NULL);
+	chdir("/old");
+
+	read_lock(&current->fs->lock);
+	old_rootmnt = mntget(current->fs->pwdmnt);
+	read_unlock(&current->fs->lock);
+
+	/*  First unmount devfs if mounted  */
+	if (path_init("/old/dev", LOOKUP_FOLLOW|LOOKUP_POSITIVE, &devfs_nd))
+		error = path_walk("/old/dev", &devfs_nd);
+	if (!error) {
+		if (devfs_nd.mnt->mnt_sb->s_magic == DEVFS_SUPER_MAGIC &&
+		    devfs_nd.dentry == devfs_nd.mnt->mnt_root)
+			umount("/old/dev", 0);
+		path_release(&devfs_nd);
+	}
+
+	ROOT_DEV = new_root_dev;
+	mount_root();
+
+	chdir("/root");
+	ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
+	printk("VFS: Mounted root (%s filesystem)%s.\n",
+		current->fs->pwdmnt->mnt_sb->s_type->name,
+		(current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : "");
+
+#if 1
+	shrink_dcache();
+	printk("change_root: old root has d_count=%d\n", 
+	       atomic_read(&old_rootmnt->mnt_root->d_count));
+#endif
+
+	error = mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
+	if (error) {
+		int blivet;
+		struct block_device *ramdisk = old_rootmnt->mnt_sb->s_bdev;
+
+		atomic_inc(&ramdisk->bd_count);
+		blivet = blkdev_get(ramdisk, FMODE_READ, 0, BDEV_FS);
+		printk(KERN_NOTICE "Trying to unmount old root ... ");
+		umount("/old", MNT_DETACH);
+		if (!blivet) {
+			blivet = ioctl_by_bdev(ramdisk, BLKFLSBUF, 0);
+			blkdev_put(ramdisk, BDEV_FS);
+		}
+		if (blivet) {
+			printk(KERN_ERR "error %d\n", blivet);
+		} else {
+			printk("okay\n");
+			error = 0;
+		}
+	} else {
+		spin_lock(&dcache_lock);
+		if (new_devname) {
+			void *p = old_rootmnt->mnt_devname;
+			old_rootmnt->mnt_devname = new_devname;
+			new_devname = p;
+		}
+		spin_unlock(&dcache_lock);
+	}
+
+	/* put the old stuff */
+	mntput(old_rootmnt);
+	kfree(new_devname);
+	return error;
+}
+
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+static int do_linuxrc(void * shell)
+{
+	static char *argv[] = { "linuxrc", NULL, };
+	extern char * envp_init[];
+
+	chdir("/root");
+	mount(".", "/", NULL, MS_MOVE, NULL);
+	chroot(".");
+
+	mount_devfs_fs ();
+
+	close(0);close(1);close(2);
+	setsid();
+	(void) open("/dev/console",O_RDWR,0);
+	(void) dup(0);
+	(void) dup(0);
+	return execve(shell, argv, envp_init);
+}
+
+#endif
+
+/*
+ * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
+ */
+void prepare_namespace(void)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	int real_root_mountflags = root_mountflags;
+	if (!initrd_start)
+		mount_initrd = 0;
+	if (mount_initrd)
+		root_mountflags &= ~MS_RDONLY;
+	real_root_dev = ROOT_DEV;
+#endif
+	mkdir("/dev", 0700);
+	mkdir("/root", 0700);
+
+#ifdef CONFIG_BLK_DEV_RAM
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (mount_initrd)
+		initrd_load();
+	else
+#endif
+	rd_load();
+#endif
+
+	/* Mount the root filesystem.. */
+	mount_root();
+	chdir("/root");
+	ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
+	printk("VFS: Mounted root (%s filesystem)%s.\n",
+		current->fs->pwdmnt->mnt_sb->s_type->name,
+		(current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : "");
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	root_mountflags = real_root_mountflags;
+	if (mount_initrd && ROOT_DEV != real_root_dev
+	    && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
+		int error;
+		int i, pid;
+		mkdir("/old", 0700);
+		chdir("/old");
+
+		pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
+		if (pid > 0) {
+			while (pid != wait(&i)) {
+				current->policy |= SCHED_YIELD;
+				schedule();
+			}
+		}
+		if (MAJOR(real_root_dev) != RAMDISK_MAJOR
+		     || MINOR(real_root_dev) != 0) {
+			error = change_root(real_root_dev,"/initrd");
+			if (error)
+				printk(KERN_ERR "Change root to /initrd: "
+				    "error %d\n",error);
+
+			chdir("/root");
+			mount(".", "/", NULL, MS_MOVE, NULL);
+			chroot(".");
+
+			mount_devfs_fs ();
+			return;
+		}
+		chroot("..");
+		chdir("/");
+		return;
+	}
+#endif
+	mount(".", "/", NULL, MS_MOVE, NULL);
+	chroot(".");
+
+	mount_devfs_fs ();
+}
diff -u --recursive --new-file v2.5.0/linux/init/main.c linux/init/main.c
--- v2.5.0/linux/init/main.c	Fri Nov  9 14:15:00 2001
+++ linux/init/main.c	Fri Dec  7 16:24:52 2001
@@ -31,6 +31,8 @@
 #include <asm/io.h>
 #include <asm/bugs.h>
 
+#include <linux/device.h>
+
 #if defined(CONFIG_ARCH_S390)
 #include <asm/s390mach.h>
 #include <asm/ccwcache.h>
@@ -118,17 +120,10 @@
 
 int rows, cols;
 
-#ifdef CONFIG_BLK_DEV_INITRD
-unsigned int real_root_dev;	/* do_proc_dointvec cannot handle kdev_t */
-#endif
-
-int root_mountflags = MS_RDONLY;
 char *execute_command;
-char root_device_name[64];
-
 
 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
-static char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
+char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 
 static int __init profile_setup(char *str)
 {
@@ -139,175 +134,6 @@
 
 __setup("profile=", profile_setup);
 
-
-static struct dev_name_struct {
-	const char *name;
-	const int num;
-} root_dev_names[] __initdata = {
-	{ "nfs",     0x00ff },
-	{ "hda",     0x0300 },
-	{ "hdb",     0x0340 },
-	{ "loop",    0x0700 },
-	{ "hdc",     0x1600 },
-	{ "hdd",     0x1640 },
-	{ "hde",     0x2100 },
-	{ "hdf",     0x2140 },
-	{ "hdg",     0x2200 },
-	{ "hdh",     0x2240 },
-	{ "hdi",     0x3800 },
-	{ "hdj",     0x3840 },
-	{ "hdk",     0x3900 },
-	{ "hdl",     0x3940 },
-	{ "hdm",     0x5800 },
-	{ "hdn",     0x5840 },
-	{ "hdo",     0x5900 },
-	{ "hdp",     0x5940 },
-	{ "hdq",     0x5A00 },
-	{ "hdr",     0x5A40 },
-	{ "hds",     0x5B00 },
-	{ "hdt",     0x5B40 },
-	{ "sda",     0x0800 },
-	{ "sdb",     0x0810 },
-	{ "sdc",     0x0820 },
-	{ "sdd",     0x0830 },
-	{ "sde",     0x0840 },
-	{ "sdf",     0x0850 },
-	{ "sdg",     0x0860 },
-	{ "sdh",     0x0870 },
-	{ "sdi",     0x0880 },
-	{ "sdj",     0x0890 },
-	{ "sdk",     0x08a0 },
-	{ "sdl",     0x08b0 },
-	{ "sdm",     0x08c0 },
-	{ "sdn",     0x08d0 },
-	{ "sdo",     0x08e0 },
-	{ "sdp",     0x08f0 },
-	{ "ada",     0x1c00 },
-	{ "adb",     0x1c10 },
-	{ "adc",     0x1c20 },
-	{ "add",     0x1c30 },
-	{ "ade",     0x1c40 },
-	{ "fd",      0x0200 },
-	{ "md",      0x0900 },	     
-	{ "xda",     0x0d00 },
-	{ "xdb",     0x0d40 },
-	{ "ram",     0x0100 },
-	{ "scd",     0x0b00 },
-	{ "mcd",     0x1700 },
-	{ "cdu535",  0x1800 },
-	{ "sonycd",  0x1800 },
-	{ "aztcd",   0x1d00 },
-	{ "cm206cd", 0x2000 },
-	{ "gscd",    0x1000 },
-	{ "sbpcd",   0x1900 },
-	{ "eda",     0x2400 },
-	{ "edb",     0x2440 },
-	{ "pda",	0x2d00 },
-	{ "pdb",	0x2d10 },
-	{ "pdc",	0x2d20 },
-	{ "pdd",	0x2d30 },
-	{ "pcd",	0x2e00 },
-	{ "pf",		0x2f00 },
-	{ "apblock", APBLOCK_MAJOR << 8},
-	{ "ddv", DDV_MAJOR << 8},
-	{ "jsfd",    JSFD_MAJOR << 8},
-#if defined(CONFIG_ARCH_S390)
-	{ "dasda", (DASD_MAJOR << MINORBITS) },
-	{ "dasdb", (DASD_MAJOR << MINORBITS) + (1 << 2) },
-	{ "dasdc", (DASD_MAJOR << MINORBITS) + (2 << 2) },
-	{ "dasdd", (DASD_MAJOR << MINORBITS) + (3 << 2) },
-	{ "dasde", (DASD_MAJOR << MINORBITS) + (4 << 2) },
-	{ "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
-	{ "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
-	{ "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
-#endif
-#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
-	{ "ida/c0d0p",0x4800 },
-	{ "ida/c0d1p",0x4810 },
-	{ "ida/c0d2p",0x4820 },
-	{ "ida/c0d3p",0x4830 },
-	{ "ida/c0d4p",0x4840 },
-	{ "ida/c0d5p",0x4850 },
-	{ "ida/c0d6p",0x4860 },
-	{ "ida/c0d7p",0x4870 },
-	{ "ida/c0d8p",0x4880 },
-	{ "ida/c0d9p",0x4890 },
-	{ "ida/c0d10p",0x48A0 },
-	{ "ida/c0d11p",0x48B0 },
-	{ "ida/c0d12p",0x48C0 },
-	{ "ida/c0d13p",0x48D0 },
-	{ "ida/c0d14p",0x48E0 },
-	{ "ida/c0d15p",0x48F0 },
-#endif
-#if defined(CONFIG_BLK_CPQ_CISS_DA) || defined(CONFIG_BLK_CPQ_CISS_DA_MODULE)
-	{ "cciss/c0d0p",0x6800 },
-	{ "cciss/c0d1p",0x6810 },
-	{ "cciss/c0d2p",0x6820 },
-	{ "cciss/c0d3p",0x6830 },
-	{ "cciss/c0d4p",0x6840 },
-	{ "cciss/c0d5p",0x6850 },
-	{ "cciss/c0d6p",0x6860 },
-	{ "cciss/c0d7p",0x6870 },
-	{ "cciss/c0d8p",0x6880 },
-	{ "cciss/c0d9p",0x6890 },
-	{ "cciss/c0d10p",0x68A0 },
-	{ "cciss/c0d11p",0x68B0 },
-	{ "cciss/c0d12p",0x68C0 },
-	{ "cciss/c0d13p",0x68D0 },
-	{ "cciss/c0d14p",0x68E0 },
-	{ "cciss/c0d15p",0x68F0 },
-#endif
-	{ "nftla", 0x5d00 },
-	{ "nftlb", 0x5d10 },
-	{ "nftlc", 0x5d20 },
-	{ "nftld", 0x5d30 },
-	{ "ftla", 0x2c00 },
-	{ "ftlb", 0x2c08 },
-	{ "ftlc", 0x2c10 },
-	{ "ftld", 0x2c18 },
-	{ "mtdblock", 0x1f00 },
-	{ NULL, 0 }
-};
-
-kdev_t __init name_to_kdev_t(char *line)
-{
-	int base = 0;
-
-	if (strncmp(line,"/dev/",5) == 0) {
-		struct dev_name_struct *dev = root_dev_names;
-		line += 5;
-		do {
-			int len = strlen(dev->name);
-			if (strncmp(line,dev->name,len) == 0) {
-				line += len;
-				base = dev->num;
-				break;
-			}
-			dev++;
-		} while (dev->name);
-	}
-	return to_kdev_t(base + simple_strtoul(line,NULL,base?10:16));
-}
-
-static int __init root_dev_setup(char *line)
-{
-	int i;
-	char ch;
-
-	ROOT_DEV = name_to_kdev_t(line);
-	memset (root_device_name, 0, sizeof root_device_name);
-	if (strncmp (line, "/dev/", 5) == 0) line += 5;
-	for (i = 0; i < sizeof root_device_name - 1; ++i)
-	{
-	    ch = line[i];
-	    if ( isspace (ch) || (ch == ',') || (ch == '\0') ) break;
-	    root_device_name[i] = ch;
-	}
-	return 1;
-}
-
-__setup("root=", root_dev_setup);
-
 static int __init checksetup(char *line)
 {
 	struct kernel_param *p;
@@ -374,22 +200,6 @@
 		(loops_per_jiffy/(5000/HZ)) % 100);
 }
 
-static int __init readonly(char *str)
-{
-	if (*str)
-		return 0;
-	root_mountflags |= MS_RDONLY;
-	return 1;
-}
-
-static int __init readwrite(char *str)
-{
-	if (*str)
-		return 0;
-	root_mountflags &= ~MS_RDONLY;
-	return 1;
-}
-
 static int __init debug_kernel(char *str)
 {
 	if (*str)
@@ -406,8 +216,6 @@
 	return 1;
 }
 
-__setup("ro", readonly);
-__setup("rw", readwrite);
 __setup("debug", debug_kernel);
 __setup("quiet", quiet_kernel);
 
@@ -591,6 +399,8 @@
 #endif
 	mem_init();
 	kmem_cache_sizes_init();
+	pgtable_cache_init();
+
 	mempages = num_physpages;
 
 	fork_init(mempages);
@@ -620,21 +430,6 @@
 	rest_init();
 }
 
-#ifdef CONFIG_BLK_DEV_INITRD
-static int do_linuxrc(void * shell)
-{
-	static char *argv[] = { "linuxrc", NULL, };
-
-	close(0);close(1);close(2);
-	setsid();
-	(void) open("/dev/console",O_RDWR,0);
-	(void) dup(0);
-	(void) dup(0);
-	return execve(shell, argv, envp_init);
-}
-
-#endif
-
 struct task_struct *child_reaper = &init_task;
 
 static void __init do_initcalls(void)
@@ -692,6 +487,9 @@
 	s390_init_machine_check();
 #endif
 
+	/* bring up the device tree */
+	device_driver_init();
+
 #ifdef CONFIG_PCI
 	pci_init();
 #endif
@@ -738,61 +536,7 @@
 #endif
 }
 
-extern void rd_load(void);
-extern void initrd_load(void);
-
-/*
- * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
- */
-static void prepare_namespace(void)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
-	int real_root_mountflags = root_mountflags;
-	if (!initrd_start)
-		mount_initrd = 0;
-	if (mount_initrd)
-		root_mountflags &= ~MS_RDONLY;
-	real_root_dev = ROOT_DEV;
-#endif
-
-#ifdef CONFIG_BLK_DEV_RAM
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (mount_initrd)
-		initrd_load();
-	else
-#endif
-	rd_load();
-#endif
-
-	/* Mount the root filesystem.. */
-	mount_root();
-
-	mount_devfs_fs ();
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	root_mountflags = real_root_mountflags;
-	if (mount_initrd && ROOT_DEV != real_root_dev
-	    && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
-		int error;
-		int i, pid;
-
-		pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
-		if (pid > 0) {
-			while (pid != wait(&i)) {
-				current->policy |= SCHED_YIELD;
-				schedule();
-			}
-		}
-		if (MAJOR(real_root_dev) != RAMDISK_MAJOR
-		     || MINOR(real_root_dev) != 0) {
-			error = change_root(real_root_dev,"/initrd");
-			if (error)
-				printk(KERN_ERR "Change root to /initrd: "
-				    "error %d\n",error);
-		}
-	}
-#endif
-}
+extern void prepare_namespace(void);
 
 static int init(void * unused)
 {
diff -u --recursive --new-file v2.5.0/linux/ipc/shm.c linux/ipc/shm.c
--- v2.5.0/linux/ipc/shm.c	Wed Oct 17 14:16:39 2001
+++ linux/ipc/shm.c	Sat Dec  8 20:31:51 2001
@@ -569,6 +569,7 @@
 {
 	struct shmid_kernel *shp;
 	unsigned long addr;
+	unsigned long size;
 	struct file * file;
 	int    err;
 	unsigned long flags;
@@ -588,8 +589,12 @@
 				return -EINVAL;
 		}
 		flags = MAP_SHARED | MAP_FIXED;
-	} else
+	} else {
+		if ((shmflg & SHM_REMAP))
+			return -EINVAL;
+
 		flags = MAP_SHARED;
+	}
 
 	if (shmflg & SHM_RDONLY) {
 		prot = PROT_READ;
@@ -603,7 +608,7 @@
 
 	/*
 	 * We cannot rely on the fs check since SYSV IPC does have an
-	 * aditional creator id...
+	 * additional creator id...
 	 */
 	shp = shm_lock(shmid);
 	if(shp == NULL)
@@ -618,11 +623,27 @@
 		return -EACCES;
 	}
 	file = shp->shm_file;
+	size = file->f_dentry->d_inode->i_size;
 	shp->shm_nattch++;
 	shm_unlock(shmid);
 
 	down_write(&current->mm->mmap_sem);
-	user_addr = (void *) do_mmap (file, addr, file->f_dentry->d_inode->i_size, prot, flags, 0);
+	if (addr && !(shmflg & SHM_REMAP)) {
+		user_addr = ERR_PTR(-EINVAL);
+		if (find_vma_intersection(current->mm, addr, addr + size))
+			goto invalid;
+		/*
+		 * If shm segment goes below stack, make sure there is some
+		 * space left for the stack to grow (at least 4 pages).
+		 */
+		if (addr < current->mm->start_stack &&
+		    addr > current->mm->start_stack - size - PAGE_SIZE * 5)
+			goto invalid;
+	}
+		
+	user_addr = (void*) do_mmap (file, addr, size, prot, flags, 0);
+
+invalid:
 	up_write(&current->mm->mmap_sem);
 
 	down (&shm_ids.sem);
diff -u --recursive --new-file v2.5.0/linux/kernel/Makefile linux/kernel/Makefile
--- v2.5.0/linux/kernel/Makefile	Sun Sep 16 21:22:40 2001
+++ linux/kernel/Makefile	Thu Nov 29 16:53:45 2001
@@ -9,12 +9,13 @@
 
 O_TARGET := kernel.o
 
-export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o printk.o
+export-objs = signal.o sys.o kmod.o context.o ksyms.o pm.o exec_domain.o \
+		printk.o device.o
 
 obj-y     = sched.o dma.o fork.o exec_domain.o panic.o printk.o \
 	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
 	    sysctl.o acct.o capability.o ptrace.o timer.o user.o \
-	    signal.o sys.o kmod.o context.o
+	    signal.o sys.o kmod.o context.o device.o
 
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += ksyms.o
diff -u --recursive --new-file v2.5.0/linux/kernel/device.c linux/kernel/device.c
--- v2.5.0/linux/kernel/device.c	Wed Dec 31 16:00:00 1969
+++ linux/kernel/device.c	Mon Dec 10 14:15:12 2001
@@ -0,0 +1,950 @@
+/*
+ * device.c
+ *
+ * Copyright (c) Patrick Mochel <mochel@osdl.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  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
+ *
+ * Please see Documentation/driver-model.txt for more explanation.
+ */
+
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/module.h>
+#include <linux/stat.h>
+#include <linux/driverfs_fs.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/spinlock.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+# define DBG(x...) printk(x)
+#else
+# define DBG(x...)
+#endif
+
+static struct iobus device_root = {
+	bus_id: "root",
+	name:	"Logical System Root",
+};
+
+int (*platform_notify)(struct device * dev) = NULL;
+int (*platform_notify_remove)(struct device * dev) = NULL;
+
+static spinlock_t device_lock;
+
+static ssize_t device_read_status(char *, size_t, loff_t, void *);
+static ssize_t device_write_status(const char *, size_t, loff_t, void *);
+
+static struct driverfs_operations device_status_ops = {
+	read:	device_read_status,
+	write:	device_write_status,
+};
+
+static ssize_t device_read_power(char *, size_t, loff_t, void *);
+static ssize_t device_write_power(const char *, size_t, loff_t, void *);
+
+static struct driverfs_operations device_power_ops = {
+	read:	device_read_power,
+	write:	device_write_power,
+};
+
+static ssize_t iobus_read_status(char *, size_t, loff_t, void *);
+static ssize_t iobus_write_status(const char *, size_t, loff_t, void *);
+
+static struct driverfs_operations iobus_status_ops = {
+	read:	iobus_read_status,
+	write:	iobus_write_status,
+};
+
+
+/**
+ * device_create_file - create a driverfs file for a device
+ * @dev:	device requesting file
+ * @name:	name of file
+ * @mode:	permissions of file
+ * @ops:	operations for the file
+ * @data:	private data for the file
+ *
+ * Create a driverfs entry, then create the actual file the entry describes.
+ */
+int device_create_file(struct device * dev, const char * name, mode_t mode,
+		       struct driverfs_operations * ops, void * data)
+{
+	int error = -EFAULT;
+	struct driver_file_entry * entry;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!valid_device(dev))
+		return -EFAULT;
+
+	entry = driverfs_create_entry(name,mode,ops,data);
+	if (entry)
+		error = driverfs_create_file(entry,dev->dir);
+
+	put_device(dev);
+	return error;
+}
+
+/**
+ * device_remove_file - remove a device's file by name
+ * @dev:	device requesting removal
+ * @name:	name of the file
+ *
+ */
+void device_remove_file(struct device * dev, const char * name)
+{
+	if (!dev)
+		return;
+
+	if (!valid_device(dev))
+		return;
+
+	driverfs_remove_file(dev->dir,name);
+
+	put_device(dev);
+}
+
+/**
+ * device_remove_dir - remove a device's directory
+ * @dev:	device in question
+ */
+void device_remove_dir(struct device * dev)
+{
+	struct driver_dir_entry * dir;
+
+	if (!dev)
+		return;
+
+	lock_device(dev);
+	dir = dev->dir;
+	dev->dir = NULL;
+	unlock_device(dev);
+
+	if (dir)
+		driverfs_remove_dir(dir);
+}
+
+/**
+ * device_make_dir - create a driverfs directory
+ * @name:	name of directory
+ * @parent:	dentry for the parent directory
+ *
+ * Do the initial creation of the device's driverfs directory
+ * and populate it with the one default file.
+ *
+ * This is just a helper for device_register(), as we
+ * don't export this function. (Yes, that means we don't allow
+ * devices to create subdirectories).
+ */
+static int device_make_dir(struct device * dev)
+{
+	struct driver_dir_entry * entry;
+	int error;
+
+	entry = driverfs_create_dir_entry(dev->bus_id,(S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO));
+	if (!entry)
+		return -EFAULT;
+
+	error = driverfs_create_dir(entry,dev->parent->dir);
+
+	if (error) {
+		kfree(entry);
+		return error;
+	}
+
+	lock_device(dev);
+	dev->dir = entry;
+	unlock_device(dev);
+
+	/* first the status file */
+	error = device_create_file(dev, "status", S_IRUGO | S_IWUSR,
+				   &device_status_ops, (void *) dev);
+	if (error) {
+		device_remove_dir(dev);
+		goto done;
+	}
+
+	/* now the power file */
+	error = device_create_file(dev,"power",S_IRUGO | S_IWUSR,
+				   &device_power_ops, (void *) dev);
+	if (error)
+		device_remove_dir(dev);
+
+ done:
+	return error;
+}
+
+/* iobus interface.
+ * For practical purposes, it's exactly the same as the device interface above.
+ * Even below, the two are almost identical, only taking different pointer
+ * types.
+ * I have fantasized about removing struct iobus completely. It would reduce
+ * this file by about 30%, and make life much easier. However, it will take some
+ * time to really work everything out..
+ */
+
+int iobus_create_file(struct iobus * iobus, const char * name, mode_t mode,
+		      struct driverfs_operations * ops, void * data)
+{
+	int error = -EFAULT;
+	struct driver_file_entry * entry;
+
+	if (!iobus)
+		return -EINVAL;
+
+	if (!valid_iobus(iobus))
+		return -EFAULT;
+
+	entry = driverfs_create_entry(name,mode,ops,data);
+	if (entry)
+		error = driverfs_create_file(entry,iobus->dir);
+
+	put_iobus(iobus);
+	return error;
+}
+
+void iobus_remove_file(struct iobus * iobus, const char * name)
+{
+	if (!iobus)
+		return;
+
+	if (!valid_iobus(iobus))
+		return;
+
+	driverfs_remove_file(iobus->dir,name);
+
+	put_iobus(iobus);
+}
+
+void iobus_remove_dir(struct iobus * iobus)
+{
+	struct driver_dir_entry * dir;
+
+	if (!iobus)
+		return;
+
+	lock_iobus(iobus);
+	dir = iobus->dir;
+	iobus->dir = NULL;
+	unlock_iobus(iobus);
+
+	if (dir)
+		driverfs_remove_dir(dir);
+}
+
+static int iobus_make_dir(struct iobus * iobus)
+{
+	struct driver_dir_entry * entry;
+	struct driver_dir_entry * parent = NULL;
+	int error;
+
+	entry = driverfs_create_dir_entry(iobus->bus_id,(S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO));
+	if (!entry)
+		return -EFAULT;
+
+	if (iobus->parent)
+		parent = iobus->parent->dir;
+
+	error = driverfs_create_dir(entry,parent);
+	if (error) {
+		kfree(entry);
+		return error;
+	}
+
+	lock_iobus(iobus);
+	iobus->dir = entry;
+	unlock_iobus(iobus);
+
+	error = iobus_create_file(iobus, "status", S_IRUGO | S_IWUSR,
+				  &iobus_status_ops, (void *)iobus);
+	if (error)
+		iobus_remove_dir(iobus);
+
+	return error;
+}
+
+/**
+ * device_register - register a device
+ * @dev:	pointer to the device structure
+ *
+ * First, make sure that the device has a parent, create
+ * a directory for it, then add it to the parent's list of
+ * children.
+ */
+int device_register(struct device *dev)
+{
+	struct iobus * parent;
+	int error = -EFAULT;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!dev->parent)
+		dev->parent = &device_root;
+	parent = dev->parent;
+
+	if (valid_iobus(parent)) {
+		if (!valid_device(dev)) {
+			put_iobus(parent);
+			goto register_done;
+		}
+	} else
+		return -EFAULT;
+
+	if (!strlen(dev->name)) {
+		error = -EINVAL;
+		goto register_done;
+	}
+
+	error = device_make_dir(dev);
+	if (error)
+		goto register_done;
+
+
+	/* finally add it to its parent's list */
+	lock_iobus(parent);
+	list_add_tail(&dev->node, &parent->devices);
+	unlock_iobus(parent);
+
+	DBG("DEV: registering device: ID = '%s', name = %s, parent = %s\n",
+	    dev->bus_id, dev->name, parent->bus_id);
+
+	/* notify platform of device entry */
+	if (platform_notify)
+		platform_notify(dev);
+
+	return 0;
+
+ register_done:
+	put_device(dev);
+	put_iobus(parent);
+
+	return error;
+}
+
+/**
+ * put_device - clean up device
+ * @dev:	device in question
+ *
+ * Decrement reference count for device.
+ * If it hits 0, we need to clean it up.
+ * However, we may be here in interrupt context, and it may
+ * take some time to do proper clean up (removing files, calling
+ * back down to device to clean up everything it has).
+ * So, we remove it from its parent's list and add it to the list of
+ * devices to be cleaned up.
+ */
+void put_device(struct device * dev)
+{
+	struct iobus * parent;
+
+	if (!atomic_dec_and_lock(&dev->refcount,&dev->lock))
+		return;
+
+	parent = dev->parent;
+	dev->parent = NULL;
+	unlock_device(dev);
+
+	DBG("DEV: Unregistering device. ID = '%s', name = '%s'\n",
+	    dev->bus_id,dev->name);
+
+	/* disavow parent's knowledge */
+	lock_iobus(parent);
+	list_del_init(&dev->node);
+	unlock_iobus(parent);
+
+	/* remove the driverfs directory */
+	device_remove_dir(dev);
+
+	if (dev->subordinate)
+		iobus_remove_dir(dev->subordinate);
+
+	/* Notify the platform of the removal, in case they
+	 * need to do anything...
+	 */
+	if (platform_notify_remove)
+		platform_notify_remove(dev);
+
+	/* Tell the driver to clean up after itself.
+	 * Note that we likely didn't allocate the device,
+	 * so this is the driver's chance to free that up...
+	 */
+	if (dev->driver && dev->driver->remove)
+		dev->driver->remove(dev,REMOVE_FREE_RESOURCES);
+
+	put_iobus(parent);
+}
+
+int iobus_register(struct iobus *bus)
+{
+	struct iobus * parent;
+	int error = -EINVAL;
+
+	if (!bus)
+		return -EINVAL;
+
+	if (!bus->parent)
+		bus->parent = &device_root;
+	parent = bus->parent;
+
+	DBG("DEV: registering bus. ID = '%s' name = '%s' parent = %p\n",
+	    bus->bus_id,bus->name,bus->parent);
+
+	if (valid_iobus(parent)) {
+		if (!valid_iobus(bus)) {
+			put_iobus(parent);
+			goto register_done;
+		}
+	} else
+		goto register_done;
+
+	if (!strlen(bus->bus_id))
+		goto register_done_put;
+
+	error = iobus_make_dir(bus);
+	if (error)
+		goto register_done_put;
+
+	lock_iobus(parent);
+	list_add_tail(&bus->node,&parent->children);
+	unlock_iobus(parent);
+
+	return 0;
+
+ register_done_put:
+	put_iobus(bus);
+	put_iobus(parent);
+ register_done:
+	return error;
+}
+
+/**
+ * iobus_unregister - remove bus and children from device tree
+ * @bus:	pointer to bus structure
+ *
+ * Remove device from parent's list of children and decrement
+ * reference count on controlling device. That should take care of
+ * the rest of the cleanup.
+ */
+void put_iobus(struct iobus * iobus)
+{
+	struct iobus * parent;
+
+	if (!atomic_dec_and_lock(&iobus->refcount,&iobus->lock))
+		return;
+
+	parent = iobus->parent;
+	iobus->parent = NULL;
+	unlock_iobus(iobus);
+
+	if (!list_empty(&iobus->devices) ||
+	    !list_empty(&iobus->children))
+		BUG();
+
+	/* disavow parent's knowledge */
+	if (parent) {
+		lock_iobus(parent);
+		list_del(&iobus->node);
+		unlock_iobus(parent);
+
+		put_iobus(parent);
+	}
+
+	/* unregister itself */
+	put_device(iobus->self);
+
+	return;
+}
+
+/**
+ * device_init_dev - initialise a struct device
+ * @dev:	pointer to device struct
+ */
+void device_init_dev(struct device * dev)
+{
+	INIT_LIST_HEAD(&dev->node);
+	spin_lock_init(&dev->lock);
+	atomic_set(&dev->refcount,1);
+}
+
+/**
+ * device_alloc_dev - allocate and initialise a device structure
+ *
+ */
+struct device * device_alloc(void)
+{
+	struct device * dev;
+
+	dev = kmalloc(sizeof(struct device), GFP_KERNEL);
+
+	if (!dev)
+		return NULL;
+
+	memset(dev,0,sizeof(struct device));
+	device_init_dev(dev);
+
+	return dev;
+}
+
+void iobus_init(struct iobus *bus)
+{
+	spin_lock_init(&bus->lock);
+	atomic_set(&bus->refcount,1);
+
+	INIT_LIST_HEAD(&bus->node);
+	INIT_LIST_HEAD(&bus->children);
+	INIT_LIST_HEAD(&bus->devices);
+}
+
+struct iobus *iobus_alloc(void)
+{
+	struct iobus *bus;
+
+	bus = kmalloc(sizeof(struct iobus), GFP_KERNEL);
+
+	if (!bus)
+		return NULL;
+
+	memset(bus,0,sizeof(struct iobus));
+
+	iobus_init(bus);
+
+	return bus;
+}
+
+static int do_device_suspend(struct device * dev, u32 state)
+{
+	int error = 0;
+
+	if (!dev->driver->suspend)
+		return error;
+
+	error = dev->driver->suspend(dev,state,SUSPEND_NOTIFY);
+
+	if (error)
+		return error;
+
+	error = dev->driver->suspend(dev,state,SUSPEND_SAVE_STATE);
+	if (error) {
+		if (dev->driver->resume)
+			dev->driver->resume(dev,RESUME_RESTORE_STATE);
+		return error;
+	}
+	error = dev->driver->suspend(dev,state,SUSPEND_POWER_DOWN);
+	if (error) {
+		if (dev->driver->resume)
+			dev->driver->resume(dev,RESUME_RESTORE_STATE);
+	}
+	return error;
+}
+
+static int do_device_resume(struct device * dev)
+{
+	int error = 0;
+
+	if (!dev->driver->resume)
+		return 0;
+	error = dev->driver->resume(dev,RESUME_POWER_ON);
+	if (error)
+		return error;
+	error = dev->driver->resume(dev,RESUME_RESTORE_STATE);
+	return error;
+}
+
+/**
+ * device_read_status - report some device information
+ * @page:	page-sized buffer to write into
+ * @count:	number of bytes requested
+ * @off:	offset into buffer
+ * @data:	device-specific data
+ *
+ * Report some human-readable information about the device.
+ * This includes the name, the bus id, and the current power state.
+ */
+static ssize_t device_read_status(char * page, size_t count,
+				  loff_t off, void * data)
+{
+	char *str = page;
+	struct device *dev = (struct device*)data;
+	ssize_t len = 0;
+
+	if (!dev)
+		return -EINVAL;
+
+	if (!valid_device(dev))
+		return -EFAULT;
+
+	if (off)
+		goto done;
+
+	str += sprintf(str,"Name:       %s\n",dev->name);
+	str += sprintf(str,"Bus ID:     %s\n",dev->bus_id);
+
+	len = str - page;
+
+	if (len > count)
+		len = count;
+
+	if (len < 0)
+		len = 0;
+
+ done:
+	put_device(dev);
+
+	return len;
+}
+
+/**
+ * device_write_status - forward a command to a driver
+ * @buf:	encoded command
+ * @count:	number of bytes in buffer
+ * @off:	offset into buffer to start with
+ * @data:	device-specific data
+ *
+ * Send a comamnd to a device driver.
+ * The following actions are supported:
+ * probe - scan slot for device
+ * remove - detach driver from slot
+ * suspend <state> <stage> - perform <stage> for entering <state>
+ * resume <stage> - perform <stage> for waking device up.
+ * (See Documentation/driver-model.txt for the theory of an n-stage
+ * suspend sequence).
+ */
+static ssize_t device_write_status(const char* buf, size_t count, loff_t off, void *data)
+{
+	char command[20];
+	struct device *dev = (struct device *)data;
+	int num;
+	int arg = 0;
+	int error = 0;
+
+	if (!dev)
+		return 0;
+
+	if (!valid_device(dev))
+		return -EFAULT;
+
+	if (off)
+		goto done_put;
+
+	/* everything involves dealing with the driver. */
+	if (!dev->driver)
+		goto done_put;
+
+	num = sscanf(buf,"%10s %d",command,&arg);
+
+	if (!num)
+		goto done_put;
+
+	if (!strcmp(command,"probe")) {
+		if (dev->driver->probe)
+			error = dev->driver->probe(dev);
+
+	} else if (!strcmp(command,"remove")) {
+		if (dev->driver->remove)
+			error = dev->driver->remove(dev,REMOVE_NOTIFY);
+	} else
+		error = -EFAULT;
+
+ done_put:
+	put_device(dev);
+	return error < 0 ? error : count;
+}
+
+static ssize_t
+device_read_power(char * page, size_t count, loff_t off, void * data)
+{
+	char	* str = page;
+	struct	device * dev = (struct device *)data;
+	ssize_t len = 0;
+
+	if (!dev)
+		return 0;
+
+	if (!valid_device(dev))
+		return 0;
+
+	str += sprintf(str,"State:      %d\n",dev->current_state);
+
+	len = str - page;
+
+	if (off) {
+		if (len < off) {
+			len = 0;
+			goto done;
+		}
+		str += off;
+		len -= off;
+	}
+
+	if (len > count)
+		len = count;
+
+ done:
+	put_device(dev);
+	return len;
+}
+
+static ssize_t
+device_write_power(const char * buf, size_t count, loff_t off, void * data)
+{
+	struct	device * dev = (struct device *)data;
+	char	str_command[20];
+	char	str_stage[20];
+	int	num_args;
+	u32	state;
+	u32	int_stage;
+	int	error = 0;
+
+	if (!dev)
+		return 0;
+
+	if (!valid_device(dev))
+		return -EFAULT;
+
+	if (off)
+		goto done;
+	if (!dev->driver)
+		goto done;
+
+	num_args = sscanf(buf,"%s %s %u",str_command,str_stage,&state);
+
+	error = -EINVAL;
+
+	if (!num_args) {
+		printk("have no arguments\n");
+		goto done;
+	}
+
+	if (!strnicmp(str_command,"suspend",7)) {
+
+		printk("%s: we know it's a suspend action\n",__FUNCTION__);
+
+		if (num_args != 3)
+			goto done;
+		if (!strnicmp(str_stage,"notify",6))
+			int_stage = SUSPEND_NOTIFY;
+		else if (!strnicmp(str_stage,"save",4))
+			int_stage = SUSPEND_SAVE_STATE;
+		else if (!strnicmp(str_stage,"disable",7))
+			int_stage = SUSPEND_DISABLE;
+		else if (!strnicmp(str_stage,"powerdown",8))
+			int_stage = SUSPEND_POWER_DOWN;
+		else
+			goto done;
+
+		if (dev->driver->suspend)
+			error = dev->driver->suspend(dev,state,int_stage);
+		else
+			error = 0;
+	} else if (!strnicmp(str_command,"resume",6)) {
+		if (num_args != 2)
+			goto done;
+
+		if (!strnicmp(str_stage,"poweron",7))
+			int_stage = RESUME_POWER_ON;
+		else if (!strnicmp(str_stage,"restore",7))
+			int_stage = RESUME_RESTORE_STATE;
+		else if (!strnicmp(str_stage,"enable",6))
+			int_stage = RESUME_ENABLE;
+		else
+			goto done;
+
+		if (dev->driver->resume)
+			error = dev->driver->resume(dev,int_stage);
+		else
+			error = 0;
+	} else
+		printk("%s: couldn't find any thing to do\n",__FUNCTION__);
+ done:
+	put_device(dev);
+
+	DBG("%s: returning %d\n",__FUNCTION__,error);
+
+	return error < 0 ? error : count;
+}
+
+/**
+ * bus_read_status - report human readable information
+ * @page:	page-sized buffer to write into
+ * @count:	number of bytes requested
+ * @off:	offset into buffer to start at
+ * @data:	bus-specific data
+ */
+static ssize_t iobus_read_status(char *page, size_t count,
+				 loff_t off, void *data)
+{
+	char *str = page;
+	struct iobus *bus = (struct iobus*)data;
+	ssize_t len = 0;
+
+	if (!bus)
+		return -EINVAL;
+
+	if (!valid_iobus(bus))
+		return -EFAULT;
+
+	if (off)
+		goto done;
+
+	str += sprintf(str,"Name:       %s\n",bus->name);
+	str += sprintf(str,"Bus ID:     %s\n",bus->bus_id);
+
+	if (bus->driver)
+		str += sprintf(str,"Type:       %s\n",bus->driver->name);
+
+	len = str - page;
+	if (len < off)
+		len = 0;
+	if (len > count)
+		len = count;
+	if (len < 0)
+		len = 0;
+
+ done:
+	put_iobus(bus);
+	return len;
+}
+
+/**
+ * bus_write_status - forward a command to a bus
+ * @buf:	string encoded command
+ * @count:	number of bytes requested
+ * @off:	offset into buffer to start at
+ * @data:	bus-specific data
+ *
+ * Like device_write_status, this sends a command to a bus driver.
+ * Supported actions are:
+ * scan - scan a bus for devices
+ * add_device <id> - add a child device
+ */
+static ssize_t iobus_write_status(const char *buf, size_t count, loff_t off, void *data)
+{
+	char command[10];
+	char which[15];
+	char id[10];
+	struct iobus *bus = (struct iobus*)data;
+	int num;
+	int error = -EINVAL;
+
+	if (!bus)
+		return -EINVAL;
+
+	if (!valid_iobus(bus))
+		return -EFAULT;
+
+	if (!bus->driver)
+		goto done;
+
+	num = sscanf(buf,"%10s %15s %10s",command,which,id);
+
+	if (!num)
+		goto done;
+
+	if (!strnicmp(command,"scan",4)) {
+		if (bus->driver->scan)
+			error = bus->driver->scan(bus);
+	} else if (!strnicmp(command,"add",3) && num == 2) {
+		error = bus->driver->add_device(bus,id);
+	} else if (!strnicmp(command, "suspend",7)) {
+		u32 state = simple_strtoul(which,NULL,0);
+		if (state > 0)
+			error = do_device_suspend(bus->self,state);
+
+	} else if (!strnicmp(command,"resume",6)) {
+		error = do_device_resume(bus->self);
+
+	}
+
+ done:
+	put_iobus(bus);
+	return error < 0 ? error : count;
+}
+
+static int __init device_init_root(void)
+{
+	/* initialize parent bus lists */
+	iobus_init(&device_root);
+
+	/* don't call iobus_register, as the only thing it really
+	 * needs to do is create the root directory. Easier
+	 * to just do it here than special case it elsewhere..
+	 */
+	iobus_make_dir(&device_root);
+
+	return (device_root.dir ? 0 : -EFAULT);
+}
+
+int __init device_driver_init(void)
+{
+	int error = 0;
+
+	DBG("DEV: Initialising Device Tree\n");
+
+	spin_lock_init(&device_lock);
+
+	error = init_driverfs_fs();
+
+	if (error) {
+		panic("DEV: could not initialise driverfs\n");
+		return error;
+	}
+
+	error = device_init_root();
+	if (error) {
+		printk(KERN_ERR "%s: device root init failed!\n", __FUNCTION__);
+		return error;
+	}
+
+	DBG("DEV: Done Initialising\n");
+	return error;
+}
+
+void __exit device_driver_exit(void)
+{
+
+}
+
+static int __init device_setup(char *str)
+{
+	return 0;
+}
+
+__setup("device=",device_setup);
+
+EXPORT_SYMBOL(device_register);
+EXPORT_SYMBOL(device_alloc);
+EXPORT_SYMBOL(device_init_dev);
+
+EXPORT_SYMBOL(device_create_file);
+EXPORT_SYMBOL(device_remove_file);
+
+EXPORT_SYMBOL(iobus_register);
+EXPORT_SYMBOL(iobus_alloc);
+EXPORT_SYMBOL(iobus_init);
+
+EXPORT_SYMBOL(iobus_create_file);
+EXPORT_SYMBOL(iobus_remove_file);
+
+EXPORT_SYMBOL(device_driver_init);
diff -u --recursive --new-file v2.5.0/linux/kernel/exec_domain.c linux/kernel/exec_domain.c
--- v2.5.0/linux/kernel/exec_domain.c	Sun Nov 11 10:20:21 2001
+++ linux/kernel/exec_domain.c	Sat Nov 24 14:27:27 2001
@@ -102,7 +102,7 @@
 	}
 #endif
 
-	ep = NULL;
+	ep = &default_exec_domain;
 out:
 	read_unlock(&exec_domains_lock);
 	return (ep);
@@ -162,8 +162,6 @@
 	struct exec_domain	*ep, *oep;
 
 	ep = lookup_exec_domain(personality);
-	if (ep == NULL)
-		return -EINVAL;
 	if (ep == current->exec_domain) {
 		current->personality = personality;
 		return 0;
diff -u --recursive --new-file v2.5.0/linux/kernel/exit.c linux/kernel/exit.c
--- v2.5.0/linux/kernel/exit.c	Wed Nov 21 14:42:27 2001
+++ linux/kernel/exit.c	Fri Nov 30 10:02:34 2001
@@ -150,21 +150,34 @@
 }
 
 /*
- * When we die, we re-parent all our children to
+ * When we die, we re-parent all our children.
+ * Try to give them to another thread in our process
+ * group, and if no such member exists, give it to
  * the global child reaper process (ie "init")
  */
 static inline void forget_original_parent(struct task_struct * father)
 {
-	struct task_struct * p;
+	struct task_struct * p, *reaper;
 
 	read_lock(&tasklist_lock);
 
+	/* Next in our thread group */
+	reaper = next_thread(father);
+	if (reaper == father)
+		reaper = child_reaper;
+
 	for_each_task(p) {
 		if (p->p_opptr == father) {
 			/* We dont want people slaying init */
 			p->exit_signal = SIGCHLD;
 			p->self_exec_id++;
-			p->p_opptr = child_reaper;
+
+			/* Make sure we're not reparenting to ourselves */
+			if (p == reaper)
+				p->p_opptr = child_reaper;
+			else
+				p->p_opptr = reaper;
+
 			if (p->pdeath_signal) send_sig(p->pdeath_signal, p, 0);
 		}
 	}
diff -u --recursive --new-file v2.5.0/linux/kernel/fork.c linux/kernel/fork.c
--- v2.5.0/linux/kernel/fork.c	Wed Nov 21 10:18:42 2001
+++ linux/kernel/fork.c	Fri Nov 30 15:53:28 2001
@@ -206,7 +206,7 @@
 	return retval;
 }
 
-spinlock_t mmlist_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+spinlock_t mmlist_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 int mmlist_nr;
 
 #define allocate_mm()	(kmem_cache_alloc(mm_cachep, SLAB_KERNEL))
diff -u --recursive --new-file v2.5.0/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.5.0/linux/kernel/ksyms.c	Wed Nov 21 14:07:25 2001
+++ linux/kernel/ksyms.c	Tue Dec 11 10:05:32 2001
@@ -121,6 +121,8 @@
 EXPORT_SYMBOL(kunmap_high);
 EXPORT_SYMBOL(highmem_start_page);
 EXPORT_SYMBOL(create_bounce);
+EXPORT_SYMBOL(kmap_prot);
+EXPORT_SYMBOL(kmap_pte);
 #endif
 
 /* filesystem internal functions */
@@ -290,7 +292,6 @@
 
 /* block device driver support */
 EXPORT_SYMBOL(blksize_size);
-EXPORT_SYMBOL(hardsect_size);
 EXPORT_SYMBOL(blk_size);
 EXPORT_SYMBOL(blk_dev);
 EXPORT_SYMBOL(is_read_only);
@@ -307,8 +308,8 @@
 EXPORT_SYMBOL(tq_disk);
 EXPORT_SYMBOL(init_buffer);
 EXPORT_SYMBOL(refile_buffer);
-EXPORT_SYMBOL(max_sectors);
 EXPORT_SYMBOL(max_readahead);
+EXPORT_SYMBOL(wipe_partitions);
 
 /* tty routines */
 EXPORT_SYMBOL(tty_hangup);
diff -u --recursive --new-file v2.5.0/linux/kernel/softirq.c linux/kernel/softirq.c
--- v2.5.0/linux/kernel/softirq.c	Wed Oct 31 10:26:02 2001
+++ linux/kernel/softirq.c	Fri Nov 30 15:53:28 2001
@@ -42,7 +42,7 @@
 
 irq_cpustat_t irq_stat[NR_CPUS];
 
-static struct softirq_action softirq_vec[32] __cacheline_aligned;
+static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp;
 
 /*
  * we cannot loop indefinitely here to avoid userspace starvation,
@@ -146,8 +146,8 @@
 
 /* Tasklets */
 
-struct tasklet_head tasklet_vec[NR_CPUS] __cacheline_aligned;
-struct tasklet_head tasklet_hi_vec[NR_CPUS] __cacheline_aligned;
+struct tasklet_head tasklet_vec[NR_CPUS] __cacheline_aligned_in_smp;
+struct tasklet_head tasklet_hi_vec[NR_CPUS] __cacheline_aligned_in_smp;
 
 void __tasklet_schedule(struct tasklet_struct *t)
 {
diff -u --recursive --new-file v2.5.0/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.5.0/linux/kernel/sysctl.c	Fri Oct  5 12:23:53 2001
+++ linux/kernel/sysctl.c	Mon Dec 10 10:39:20 2001
@@ -45,7 +45,8 @@
 extern int bdf_prm[], bdflush_min[], bdflush_max[];
 extern int sysctl_overcommit_memory;
 extern int max_threads;
-extern int nr_queued_signals, max_queued_signals;
+extern atomic_t nr_queued_signals;
+extern int max_queued_signals;
 extern int sysrq_enabled;
 extern int core_uses_pid;
 extern int cad_pid;
diff -u --recursive --new-file v2.5.0/linux/mm/Makefile linux/mm/Makefile
--- v2.5.0/linux/mm/Makefile	Wed Oct 24 15:21:18 2001
+++ linux/mm/Makefile	Tue Dec 11 09:49:40 2001
@@ -9,12 +9,12 @@
 
 O_TARGET := mm.o
 
-export-objs := shmem.o filemap.o
+export-objs := shmem.o filemap.o mempool.o
 
 obj-y	 := memory.o mmap.o filemap.o mprotect.o mlock.o mremap.o \
 	    vmalloc.o slab.o bootmem.o swap.o vmscan.o page_io.o \
 	    page_alloc.o swap_state.o swapfile.o numa.o oom_kill.o \
-	    shmem.o
+	    shmem.o mempool.o
 
 obj-$(CONFIG_HIGHMEM) += highmem.o
 
diff -u --recursive --new-file v2.5.0/linux/mm/bootmem.c linux/mm/bootmem.c
--- v2.5.0/linux/mm/bootmem.c	Tue Sep 18 14:10:43 2001
+++ linux/mm/bootmem.c	Tue Nov 27 09:23:27 2001
@@ -25,6 +25,7 @@
  */
 unsigned long max_low_pfn;
 unsigned long min_low_pfn;
+unsigned long max_pfn;
 
 /* return the number of _pages_ that will be allocated for the boot bitmap */
 unsigned long __init bootmem_bootmap_pages (unsigned long pages)
diff -u --recursive --new-file v2.5.0/linux/mm/filemap.c linux/mm/filemap.c
--- v2.5.0/linux/mm/filemap.c	Wed Nov 21 14:07:25 2001
+++ linux/mm/filemap.c	Tue Dec 11 09:34:17 2001
@@ -47,7 +47,7 @@
 unsigned int page_hash_bits;
 struct page **page_hash_table;
 
-spinlock_t pagecache_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_t pagecache_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 /*
  * NOTE: to avoid deadlocking you must never acquire the pagemap_lru_lock 
  *	with the pagecache_lock held.
@@ -57,7 +57,7 @@
  *		pagemap_lru_lock ->
  *			pagecache_lock
  */
-spinlock_t pagemap_lru_lock ____cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+spinlock_t pagemap_lru_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
 
 #define CLUSTER_PAGES		(1 << page_cluster)
 #define CLUSTER_OFFSET(x)	(((x) >> page_cluster) << page_cluster)
@@ -935,7 +935,6 @@
 	spin_unlock(&pagecache_lock);
 	if (!page) {
 		struct page *newpage = alloc_page(gfp_mask);
-		page = ERR_PTR(-ENOMEM);
 		if (newpage) {
 			spin_lock(&pagecache_lock);
 			page = __find_lock_page_helper(mapping, index, *hash);
@@ -1486,8 +1485,8 @@
 	ssize_t retval;
 	int new_iobuf, chunk_size, blocksize_mask, blocksize, blocksize_bits, iosize, progress;
 	struct kiobuf * iobuf;
-	struct inode * inode = filp->f_dentry->d_inode;
-	struct address_space * mapping = inode->i_mapping;
+	struct address_space * mapping = filp->f_dentry->d_inode->i_mapping;
+	struct inode * inode = mapping->host;
 
 	new_iobuf = 0;
 	iobuf = filp->f_iobuf;
diff -u --recursive --new-file v2.5.0/linux/mm/highmem.c linux/mm/highmem.c
--- v2.5.0/linux/mm/highmem.c	Mon Oct 22 15:01:57 2001
+++ linux/mm/highmem.c	Tue Dec 11 09:43:41 2001
@@ -18,9 +18,7 @@
 
 #include <linux/mm.h>
 #include <linux/pagemap.h>
-#include <linux/highmem.h>
-#include <linux/swap.h>
-#include <linux/slab.h>
+#include <linux/mempool.h>
 
 /*
  * Virtual_count is not a pure "count".
@@ -186,265 +184,186 @@
 		wake_up(&pkmap_map_wait);
 }
 
-#define POOL_SIZE 32
+#define POOL_SIZE 64
 
-/*
- * This lock gets no contention at all, normally.
- */
-static spinlock_t emergency_lock = SPIN_LOCK_UNLOCKED;
-
-int nr_emergency_pages;
-static LIST_HEAD(emergency_pages);
-
-int nr_emergency_bhs;
-static LIST_HEAD(emergency_bhs);
-
-/*
- * Simple bounce buffer support for highmem pages.
- * This will be moved to the block layer in 2.5.
- */
+static mempool_t *page_pool;
 
-static inline void copy_from_high_bh (struct buffer_head *to,
-			 struct buffer_head *from)
+static void * page_pool_alloc(int gfp_mask, void *data)
 {
-	struct page *p_from;
-	char *vfrom;
-
-	p_from = from->b_page;
-
-	vfrom = kmap_atomic(p_from, KM_USER0);
-	memcpy(to->b_data, vfrom + bh_offset(from), to->b_size);
-	kunmap_atomic(vfrom, KM_USER0);
+	return alloc_page(gfp_mask & ~ __GFP_HIGHIO);
 }
 
-static inline void copy_to_high_bh_irq (struct buffer_head *to,
-			 struct buffer_head *from)
+static void page_pool_free(void *page, void *data)
 {
-	struct page *p_to;
-	char *vto;
-	unsigned long flags;
-
-	p_to = to->b_page;
-	__save_flags(flags);
-	__cli();
-	vto = kmap_atomic(p_to, KM_BOUNCE_READ);
-	memcpy(vto + bh_offset(to), from->b_data, to->b_size);
-	kunmap_atomic(vto, KM_BOUNCE_READ);
-	__restore_flags(flags);
-}
-
-static inline void bounce_end_io (struct buffer_head *bh, int uptodate)
-{
-	struct page *page;
-	struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_private);
-	unsigned long flags;
-
-	bh_orig->b_end_io(bh_orig, uptodate);
-
-	page = bh->b_page;
-
-	spin_lock_irqsave(&emergency_lock, flags);
-	if (nr_emergency_pages >= POOL_SIZE)
-		__free_page(page);
-	else {
-		/*
-		 * We are abusing page->list to manage
-		 * the highmem emergency pool:
-		 */
-		list_add(&page->list, &emergency_pages);
-		nr_emergency_pages++;
-	}
-	
-	if (nr_emergency_bhs >= POOL_SIZE) {
-#ifdef HIGHMEM_DEBUG
-		/* Don't clobber the constructed slab cache */
-		init_waitqueue_head(&bh->b_wait);
-#endif
-		kmem_cache_free(bh_cachep, bh);
-	} else {
-		/*
-		 * Ditto in the bh case, here we abuse b_inode_buffers:
-		 */
-		list_add(&bh->b_inode_buffers, &emergency_bhs);
-		nr_emergency_bhs++;
-	}
-	spin_unlock_irqrestore(&emergency_lock, flags);
+	__free_page(page);
 }
 
 static __init int init_emergency_pool(void)
 {
 	struct sysinfo i;
-        si_meminfo(&i);
-        si_swapinfo(&i);
+	si_meminfo(&i);
+	si_swapinfo(&i);
         
-        if (!i.totalhigh)
-        	return 0;
+	if (!i.totalhigh)
+		return 0;
 
-	spin_lock_irq(&emergency_lock);
-	while (nr_emergency_pages < POOL_SIZE) {
-		struct page * page = alloc_page(GFP_ATOMIC);
-		if (!page) {
-			printk("couldn't refill highmem emergency pages");
-			break;
-		}
-		list_add(&page->list, &emergency_pages);
-		nr_emergency_pages++;
-	}
-	while (nr_emergency_bhs < POOL_SIZE) {
-		struct buffer_head * bh = kmem_cache_alloc(bh_cachep, SLAB_ATOMIC);
-		if (!bh) {
-			printk("couldn't refill highmem emergency bhs");
-			break;
-		}
-		list_add(&bh->b_inode_buffers, &emergency_bhs);
-		nr_emergency_bhs++;
-	}
-	spin_unlock_irq(&emergency_lock);
-	printk("allocated %d pages and %d bhs reserved for the highmem bounces\n",
-	       nr_emergency_pages, nr_emergency_bhs);
+	page_pool = mempool_create(POOL_SIZE, page_pool_alloc, page_pool_free, NULL);
+	if (!page_pool)
+		BUG();
+	printk("highmem bounce pool size: %d pages and bhs.\n", POOL_SIZE);
 
 	return 0;
 }
 
 __initcall(init_emergency_pool);
 
-static void bounce_end_io_write (struct buffer_head *bh, int uptodate)
+/*
+ * Simple bounce buffer support for highmem pages. Depending on the
+ * queue gfp mask set, *to may or may not be a highmem page. kmap it
+ * always, it will do the Right Thing
+ */
+static inline void copy_to_high_bio_irq(struct bio *to, struct bio *from)
 {
-	bounce_end_io(bh, uptodate);
-}
+	unsigned char *vto, *vfrom;
+	unsigned long flags;
+	struct bio_vec *tovec, *fromvec;
+	int i;
 
-static void bounce_end_io_read (struct buffer_head *bh, int uptodate)
-{
-	struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_private);
+	__bio_for_each_segment(tovec, to, i, 0) {
+		fromvec = &from->bi_io_vec[i];
 
-	if (uptodate)
-		copy_to_high_bh_irq(bh_orig, bh);
-	bounce_end_io(bh, uptodate);
+		/*
+		 * not bounced
+		 */
+		if (tovec->bv_page == fromvec->bv_page)
+			continue;
+
+		vfrom = page_address(fromvec->bv_page) + fromvec->bv_offset;
+
+		local_irq_save(flags);
+		vto = kmap_atomic(tovec->bv_page, KM_BOUNCE_READ);
+		memcpy(vto + tovec->bv_offset, vfrom, tovec->bv_len);
+		kunmap_atomic(vto, KM_BOUNCE_READ);
+		local_irq_restore(flags);
+	}
 }
 
-struct page *alloc_bounce_page (void)
+static inline int bounce_end_io (struct bio *bio, int nr_sectors)
 {
-	struct list_head *tmp;
-	struct page *page;
+	struct bio *bio_orig = bio->bi_private;
+	struct bio_vec *bvec, *org_vec;
+	int ret, i;
 
-	page = alloc_page(GFP_NOHIGHIO);
-	if (page)
-		return page;
-	/*
-	 * No luck. First, kick the VM so it doesnt idle around while
-	 * we are using up our emergency rations.
-	 */
-	wakeup_bdflush();
+	if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+		goto out_eio;
+
+	set_bit(BIO_UPTODATE, &bio_orig->bi_flags);
 
-repeat_alloc:
 	/*
-	 * Try to allocate from the emergency pool.
+	 * free up bounce indirect pages used
 	 */
-	tmp = &emergency_pages;
-	spin_lock_irq(&emergency_lock);
-	if (!list_empty(tmp)) {
-		page = list_entry(tmp->next, struct page, list);
-		list_del(tmp->next);
-		nr_emergency_pages--;
+	__bio_for_each_segment(bvec, bio, i, 0) {
+		org_vec = &bio_orig->bi_io_vec[i];
+		if (bvec->bv_page == org_vec->bv_page)
+			continue;
+
+		mempool_free(bvec->bv_page, page_pool);	
 	}
-	spin_unlock_irq(&emergency_lock);
-	if (page)
-		return page;
 
-	/* we need to wait I/O completion */
-	run_task_queue(&tq_disk);
+out_eio:
+	ret = bio_orig->bi_end_io(bio_orig, nr_sectors);
 
-	current->policy |= SCHED_YIELD;
-	__set_current_state(TASK_RUNNING);
-	schedule();
-	goto repeat_alloc;
+	bio_put(bio);
+	return ret;
 }
 
-struct buffer_head *alloc_bounce_bh (void)
+static int bounce_end_io_write(struct bio *bio, int nr_sectors)
 {
-	struct list_head *tmp;
-	struct buffer_head *bh;
-
-	bh = kmem_cache_alloc(bh_cachep, SLAB_NOHIGHIO);
-	if (bh)
-		return bh;
-	/*
-	 * No luck. First, kick the VM so it doesnt idle around while
-	 * we are using up our emergency rations.
-	 */
-	wakeup_bdflush();
+	return bounce_end_io(bio, nr_sectors);
+}
 
-repeat_alloc:
-	/*
-	 * Try to allocate from the emergency pool.
-	 */
-	tmp = &emergency_bhs;
-	spin_lock_irq(&emergency_lock);
-	if (!list_empty(tmp)) {
-		bh = list_entry(tmp->next, struct buffer_head, b_inode_buffers);
-		list_del(tmp->next);
-		nr_emergency_bhs--;
-	}
-	spin_unlock_irq(&emergency_lock);
-	if (bh)
-		return bh;
+static int bounce_end_io_read (struct bio *bio, int nr_sectors)
+{
+	struct bio *bio_orig = bio->bi_private;
 
-	/* we need to wait I/O completion */
-	run_task_queue(&tq_disk);
+	if (test_bit(BIO_UPTODATE, &bio->bi_flags))
+		copy_to_high_bio_irq(bio_orig, bio);
 
-	current->policy |= SCHED_YIELD;
-	__set_current_state(TASK_RUNNING);
-	schedule();
-	goto repeat_alloc;
+	return bounce_end_io(bio, nr_sectors);
 }
 
-struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig)
+void create_bounce(unsigned long pfn, struct bio **bio_orig)
 {
 	struct page *page;
-	struct buffer_head *bh;
+	struct bio *bio = NULL;
+	int i, rw = bio_data_dir(*bio_orig);
+	struct bio_vec *to, *from;
+
+	BUG_ON((*bio_orig)->bi_idx);
+
+	bio_for_each_segment(from, *bio_orig, i) {
+		page = from->bv_page;
+
+		/*
+		 * is destination page below bounce pfn?
+		 */
+		if ((page - page->zone->zone_mem_map) + (page->zone->zone_start_paddr >> PAGE_SHIFT) < pfn)
+			continue;
+
+		/*
+		 * irk, bounce it
+		 */
+		if (!bio)
+			bio = bio_alloc(GFP_NOHIGHIO, (*bio_orig)->bi_vcnt);
 
-	if (!PageHighMem(bh_orig->b_page))
-		return bh_orig;
+		to = &bio->bi_io_vec[i];
+
+		to->bv_page = mempool_alloc(page_pool, GFP_NOHIGHIO);
+		to->bv_len = from->bv_len;
+		to->bv_offset = from->bv_offset;
+
+		if (rw & WRITE) {
+			char *vto, *vfrom;
+
+			vto = page_address(to->bv_page) + to->bv_offset;
+			vfrom = kmap(from->bv_page) + from->bv_offset;
+			memcpy(vto, vfrom, to->bv_len);
+			kunmap(from->bv_page);
+		}
+	}
 
-	bh = alloc_bounce_bh();
 	/*
-	 * This is wasteful for 1k buffers, but this is a stopgap measure
-	 * and we are being ineffective anyway. This approach simplifies
-	 * things immensly. On boxes with more than 4GB RAM this should
-	 * not be an issue anyway.
+	 * no pages bounced
 	 */
-	page = alloc_bounce_page();
+	if (!bio)
+		return;
 
-	set_bh_page(bh, page, 0);
+	/*
+	 * at least one page was bounced, fill in possible non-highmem
+	 * pages
+	 */
+	bio_for_each_segment(from, *bio_orig, i) {
+		to = &bio->bi_io_vec[i];
+		if (!to->bv_page) {
+			to->bv_page = from->bv_page;
+			to->bv_len = from->bv_len;
+			to->bv_offset = to->bv_offset;
+		}
+	}
 
-	bh->b_next = NULL;
-	bh->b_blocknr = bh_orig->b_blocknr;
-	bh->b_size = bh_orig->b_size;
-	bh->b_list = -1;
-	bh->b_dev = bh_orig->b_dev;
-	bh->b_count = bh_orig->b_count;
-	bh->b_rdev = bh_orig->b_rdev;
-	bh->b_state = bh_orig->b_state;
-#ifdef HIGHMEM_DEBUG
-	bh->b_flushtime = jiffies;
-	bh->b_next_free = NULL;
-	bh->b_prev_free = NULL;
-	/* bh->b_this_page */
-	bh->b_reqnext = NULL;
-	bh->b_pprev = NULL;
-#endif
-	/* bh->b_page */
-	if (rw == WRITE) {
-		bh->b_end_io = bounce_end_io_write;
-		copy_from_high_bh(bh, bh_orig);
-	} else
-		bh->b_end_io = bounce_end_io_read;
-	bh->b_private = (void *)bh_orig;
-	bh->b_rsector = bh_orig->b_rsector;
-#ifdef HIGHMEM_DEBUG
-	memset(&bh->b_wait, -1, sizeof(bh->b_wait));
-#endif
+	bio->bi_dev = (*bio_orig)->bi_dev;
+	bio->bi_sector = (*bio_orig)->bi_sector;
+	bio->bi_rw = (*bio_orig)->bi_rw;
+
+	bio->bi_vcnt = (*bio_orig)->bi_vcnt;
+	bio->bi_idx = 0;
+	bio->bi_size = (*bio_orig)->bi_size;
+
+	if (rw & WRITE)
+		bio->bi_end_io = bounce_end_io_write;
+	else
+		bio->bi_end_io = bounce_end_io_read;
 
-	return bh;
+	bio->bi_private = *bio_orig;
+	*bio_orig = bio;
 }
-
diff -u --recursive --new-file v2.5.0/linux/mm/mempool.c linux/mm/mempool.c
--- v2.5.0/linux/mm/mempool.c	Wed Dec 31 16:00:00 1969
+++ linux/mm/mempool.c	Tue Dec 11 09:43:41 2001
@@ -0,0 +1,206 @@
+/*
+ *  linux/mm/mempool.c
+ *
+ *  memory buffer pool support. Such pools are mostly used to
+ *  guarantee deadlock-free IO operations even during extreme
+ *  VM load.
+ *
+ *  started by Ingo Molnar, Copyright (C) 2001
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mempool.h>
+
+/**
+ * mempool_create - create a memory pool
+ * @min_nr:    the minimum number of elements guaranteed to be
+ *             allocated for this pool.
+ * @alloc_fn:  user-defined element-allocation function.
+ * @free_fn:   user-defined element-freeing function.
+ * @pool_data: optional private data available to the user-defined functions.
+ *
+ * this function creates and allocates a guaranteed size, preallocated
+ * memory pool. The pool can be used from the mempool_alloc and mempool_free
+ * functions. This function might sleep. Both the alloc_fn() and the free_fn()
+ * functions might sleep - as long as the mempool_alloc function is not called
+ * from IRQ contexts. The element allocated by alloc_fn() must be able to
+ * hold a struct list_head. (8 bytes on x86.)
+ */
+mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
+				mempool_free_t *free_fn, void *pool_data)
+{
+	mempool_t *pool;
+	int i;
+
+	pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+	if (!pool)
+		return NULL;
+	memset(pool, 0, sizeof(*pool));
+
+	spin_lock_init(&pool->lock);
+	pool->min_nr = min_nr;
+	pool->pool_data = pool_data;
+	INIT_LIST_HEAD(&pool->elements);
+	init_waitqueue_head(&pool->wait);
+	pool->alloc = alloc_fn;
+	pool->free = free_fn;
+
+	/*
+	 * First pre-allocate the guaranteed number of buffers.
+	 */
+	for (i = 0; i < min_nr; i++) {
+		void *element;
+		struct list_head *tmp;
+		element = pool->alloc(GFP_KERNEL, pool->pool_data);
+
+		if (unlikely(!element)) {
+			/*
+			 * Not enough memory - free the allocated ones
+			 * and return:
+			 */
+			list_for_each(tmp, &pool->elements) {
+				element = tmp;
+				pool->free(element, pool->pool_data);
+			}
+			kfree(pool);
+
+			return NULL;
+		}
+		tmp = element;
+		list_add(tmp, &pool->elements);
+		pool->curr_nr++;
+	}
+	return pool;
+}
+
+/**
+ * mempool_destroy - deallocate a memory pool
+ * @pool:      pointer to the memory pool which was allocated via
+ *             mempool_create().
+ *
+ * this function only sleeps if the free_fn() function sleeps. The caller
+ * has to guarantee that no mempool_alloc() nor mempool_free() happens in
+ * this pool when calling this function.
+ */
+void mempool_destroy(mempool_t *pool)
+{
+	void *element;
+	struct list_head *head, *tmp;
+
+	if (!pool)
+		return;
+
+	head = &pool->elements;
+	for (tmp = head->next; tmp != head; ) {
+		element = tmp;
+		tmp = tmp->next;
+		pool->free(element, pool->pool_data);
+		pool->curr_nr--;
+	}
+	if (pool->curr_nr)
+		BUG();
+	kfree(pool);
+}
+
+/**
+ * mempool_alloc - allocate an element from a specific memory pool
+ * @pool:      pointer to the memory pool which was allocated via
+ *             mempool_create().
+ * @gfp_mask:  the usual allocation bitmask.
+ *
+ * this function only sleeps if the alloc_fn function sleeps or
+ * returns NULL. Note that due to preallocation guarantees this function
+ * *never* fails.
+ */
+void * mempool_alloc(mempool_t *pool, int gfp_mask)
+{
+	void *element;
+	unsigned long flags;
+	struct list_head *tmp;
+	int curr_nr;
+	DECLARE_WAITQUEUE(wait, current);
+	int gfp_nowait = gfp_mask & ~__GFP_WAIT;
+
+repeat_alloc:
+	element = pool->alloc(gfp_nowait, pool->pool_data);
+	if (likely(element != NULL))
+		return element;
+
+	/*
+	 * If the pool is less than 50% full then try harder
+	 * to allocate an element:
+	 */
+	if (gfp_mask != gfp_nowait) {
+		if (pool->curr_nr <= pool->min_nr/2) {
+			element = pool->alloc(gfp_mask, pool->pool_data);
+			if (likely(element != NULL))
+				return element;
+		}
+	} else
+		/* we must not sleep */
+		return NULL;
+
+	/*
+	 * Kick the VM at this point.
+	 */
+	wakeup_bdflush();
+
+	spin_lock_irqsave(&pool->lock, flags);
+	if (likely(pool->curr_nr)) {
+		tmp = pool->elements.next;
+		list_del(tmp);
+		element = tmp;
+		pool->curr_nr--;
+		spin_unlock_irqrestore(&pool->lock, flags);
+
+		return element;
+	}
+	add_wait_queue_exclusive(&pool->wait, &wait);
+	set_task_state(current, TASK_UNINTERRUPTIBLE);
+
+	curr_nr = pool->curr_nr;
+	spin_unlock_irqrestore(&pool->lock, flags);
+
+	if (!curr_nr) {
+		run_task_queue(&tq_disk);
+		schedule();
+	}
+
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&pool->wait, &wait);
+
+	goto repeat_alloc;
+}
+
+/**
+ * mempool_free - return an element to the pool.
+ * @gfp_mask:  pool element pointer.
+ * @pool:      pointer to the memory pool which was allocated via
+ *             mempool_create().
+ *
+ * this function only sleeps if the free_fn() function sleeps.
+ */
+void mempool_free(void *element, mempool_t *pool)
+{
+	unsigned long flags;
+
+	if (pool->curr_nr < pool->min_nr) {
+		spin_lock_irqsave(&pool->lock, flags);
+		if (pool->curr_nr < pool->min_nr) {
+			list_add(element, &pool->elements);
+			pool->curr_nr++;
+			spin_unlock_irqrestore(&pool->lock, flags);
+			wake_up(&pool->wait);
+			return;
+		}
+		spin_unlock_irqrestore(&pool->lock, flags);
+	}
+	pool->free(element, pool->pool_data);
+}
+
+EXPORT_SYMBOL(mempool_create);
+EXPORT_SYMBOL(mempool_destroy);
+EXPORT_SYMBOL(mempool_alloc);
+EXPORT_SYMBOL(mempool_free);
+
diff -u --recursive --new-file v2.5.0/linux/mm/page_io.c linux/mm/page_io.c
--- v2.5.0/linux/mm/page_io.c	Mon Nov 19 15:19:42 2001
+++ linux/mm/page_io.c	Tue Nov 27 09:23:27 2001
@@ -36,7 +36,7 @@
 static int rw_swap_page_base(int rw, swp_entry_t entry, struct page *page)
 {
 	unsigned long offset;
-	int zones[PAGE_SIZE/512];
+	sector_t zones[PAGE_SIZE/512];
 	int zones_used;
 	kdev_t dev = 0;
 	int block_size;
diff -u --recursive --new-file v2.5.0/linux/mm/slab.c linux/mm/slab.c
--- v2.5.0/linux/mm/slab.c	Tue Sep 18 14:16:26 2001
+++ linux/mm/slab.c	Tue Nov 27 09:31:22 2001
@@ -109,9 +109,11 @@
 #if DEBUG
 # define CREATE_MASK	(SLAB_DEBUG_INITIAL | SLAB_RED_ZONE | \
 			 SLAB_POISON | SLAB_HWCACHE_ALIGN | \
-			 SLAB_NO_REAP | SLAB_CACHE_DMA)
+			 SLAB_NO_REAP | SLAB_CACHE_DMA | \
+			 SLAB_MUST_HWCACHE_ALIGN)
 #else
-# define CREATE_MASK	(SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | SLAB_CACHE_DMA)
+# define CREATE_MASK	(SLAB_HWCACHE_ALIGN | SLAB_NO_REAP | \
+			 SLAB_CACHE_DMA | SLAB_MUST_HWCACHE_ALIGN)
 #endif
 
 /*
@@ -649,7 +651,7 @@
 		flags &= ~SLAB_POISON;
 	}
 #if FORCED_DEBUG
-	if (size < (PAGE_SIZE>>3))
+	if ((size < (PAGE_SIZE>>3)) && !(flags & SLAB_MUST_HWCACHE_ALIGN))
 		/*
 		 * do not red zone large object, causes severe
 		 * fragmentation.
diff -u --recursive --new-file v2.5.0/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.5.0/linux/mm/swapfile.c	Sat Nov  3 17:05:25 2001
+++ linux/mm/swapfile.c	Fri Nov 30 13:33:44 2001
@@ -804,25 +804,17 @@
 {
 	char * page = (char *) __get_free_page(GFP_KERNEL);
 	struct swap_info_struct *ptr = swap_info;
-	int i, j, len = 0, usedswap;
+	int i, len;
 
 	if (!page)
 		return -ENOMEM;
 
-	len += sprintf(buf, "Filename\t\t\tType\t\tSize\tUsed\tPriority\n");
+	len = sprintf(buf, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
 	for (i = 0 ; i < nr_swapfiles ; i++, ptr++) {
 		if ((ptr->flags & SWP_USED) && ptr->swap_map) {
 			char * path = d_path(ptr->swap_file, ptr->swap_vfsmnt,
 						page, PAGE_SIZE);
-
-			len += sprintf(buf + len, "%-31s ", path);
-
-			if (!ptr->swap_device)
-				len += sprintf(buf + len, "file\t\t");
-			else
-				len += sprintf(buf + len, "partition\t");
-
-			usedswap = 0;
+			int j, usedswap = 0;
 			for (j = 0; j < ptr->max; ++j)
 				switch (ptr->swap_map[j]) {
 					case SWAP_MAP_BAD:
@@ -831,8 +823,12 @@
 					default:
 						usedswap++;
 				}
-			len += sprintf(buf + len, "%d\t%d\t%d\n", ptr->pages << (PAGE_SHIFT - 10), 
-				usedswap << (PAGE_SHIFT - 10), ptr->prio);
+			len += sprintf(buf + len, "%-39s %s\t%d\t%d\t%d\n",
+				       path,
+				       ptr->swap_device ? "partition" : "file\t",
+				       ptr->pages << (PAGE_SHIFT - 10),
+				       usedswap << (PAGE_SHIFT - 10),
+				       ptr->prio);
 		}
 	}
 	free_page((unsigned long) page);
diff -u --recursive --new-file v2.5.0/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- v2.5.0/linux/net/ipv4/ipconfig.c	Tue Nov 20 15:47:27 2001
+++ linux/net/ipv4/ipconfig.c	Thu Nov 29 07:49:10 2001
@@ -47,6 +47,7 @@
 #include <linux/route.h>
 #include <linux/udp.h>
 #include <linux/proc_fs.h>
+#include <linux/major.h>
 #include <net/arp.h>
 #include <net/ip.h>
 #include <net/ipconfig.h>
diff -u --recursive --new-file v2.5.0/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.5.0/linux/net/ipv4/tcp_input.c	Tue Nov 13 21:04:15 2001
+++ linux/net/ipv4/tcp_input.c	Mon Dec 10 11:19:42 2001
@@ -3881,6 +3881,7 @@
 			}
 		}
 		/* Fall through */
+	case TCP_LAST_ACK:
 	case TCP_ESTABLISHED: 
 		tcp_data_queue(sk, skb);
 		queued = 1;
diff -u --recursive --new-file v2.5.0/linux/net/irda/Config.in linux/net/irda/Config.in
--- v2.5.0/linux/net/irda/Config.in	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/Config.in	Fri Nov 30 13:25:10 2001
@@ -14,13 +14,10 @@
       source net/irda/irnet/Config.in
       source net/irda/ircomm/Config.in
       bool '  Ultra (connectionless) protocol' CONFIG_IRDA_ULTRA
-      bool '  IrDA protocol options' CONFIG_IRDA_OPTIONS
-      if [ "$CONFIG_IRDA_OPTIONS" != "n" ]; then
-	 comment '  IrDA options'
-	 bool '    Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
-	 bool '    Fast RRs' CONFIG_IRDA_FAST_RR
-	 bool '    Debug information' CONFIG_IRDA_DEBUG
-      fi
+      comment 'IrDA options'
+      bool '  Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
+      bool '  Fast RRs (low latency)' CONFIG_IRDA_FAST_RR
+      bool '  Debug information' CONFIG_IRDA_DEBUG
    fi
 
    if [ "$CONFIG_IRDA" != "n" ]; then
diff -u --recursive --new-file v2.5.0/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.5.0/linux/net/irda/af_irda.c	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/af_irda.c	Fri Nov 30 13:25:10 2001
@@ -914,8 +914,7 @@
 	memcpy(&new->qos_tx, &self->qos_tx, sizeof(struct qos_info));
 
 	/* Clean up the original one to keep it in listen state */
-	self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
-	self->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+	irttp_listen(self->tsap);
 
 	skb->sk = NULL;
 	skb->destructor = NULL;
@@ -1845,15 +1844,36 @@
 		  	return -EFAULT;
 		}
 
-		/* Find the object we target */
-		ias_obj = irias_find_object(ias_opt->irda_class_name);
+		/* Find the object we target.
+		 * If the user gives us an empty string, we use the object
+		 * associated with this socket. This will workaround
+		 * duplicated class name - Jean II */
+		if(ias_opt->irda_class_name[0] == '\0') {
+			if(self->ias_obj == NULL) {
+				kfree(ias_opt);
+				return -EINVAL;
+			}
+			ias_obj = self->ias_obj;
+		} else
+			ias_obj = irias_find_object(ias_opt->irda_class_name);
+
+		/* Only ROOT can mess with the global IAS database.
+		 * Users can only add attributes to the object associated
+		 * with the socket they own - Jean II */
+		if((!capable(CAP_NET_ADMIN)) &&
+		   ((ias_obj == NULL) || (ias_obj != self->ias_obj))) {
+			kfree(ias_opt);
+			return -EPERM;
+		}
+
+		/* If the object doesn't exist, create it */
 		if(ias_obj == (struct ias_object *) NULL) {
 			/* Create a new object */
 			ias_obj = irias_new_object(ias_opt->irda_class_name,
 						   jiffies);
 		}
 
-		/* Do we have it already ? */
+		/* Do we have the attribute already ? */
 		if(irias_find_attrib(ias_obj, ias_opt->irda_attrib_name)) {
 			kfree(ias_opt);
 			return -EINVAL;
@@ -1927,13 +1947,28 @@
 		  	return -EFAULT;
 		}
 
-		/* Find the object we target */
-		ias_obj = irias_find_object(ias_opt->irda_class_name);
+		/* Find the object we target.
+		 * If the user gives us an empty string, we use the object
+		 * associated with this socket. This will workaround
+		 * duplicated class name - Jean II */
+		if(ias_opt->irda_class_name[0] == '\0')
+			ias_obj = self->ias_obj;
+		else
+			ias_obj = irias_find_object(ias_opt->irda_class_name);
 		if(ias_obj == (struct ias_object *) NULL) {
 			kfree(ias_opt);
 			return -EINVAL;
 		}
 
+		/* Only ROOT can mess with the global IAS database.
+		 * Users can only del attributes from the object associated
+		 * with the socket they own - Jean II */
+		if((!capable(CAP_NET_ADMIN)) &&
+		   ((ias_obj == NULL) || (ias_obj != self->ias_obj))) {
+			kfree(ias_opt);
+			return -EPERM;
+		}
+
 		/* Find the attribute (in the object) we target */
 		ias_attr = irias_find_attrib(ias_obj,
 					     ias_opt->irda_attrib_name); 
@@ -2166,8 +2201,14 @@
 		  	return -EFAULT;
 		}
 
-		/* Find the object we target */
-		ias_obj = irias_find_object(ias_opt->irda_class_name);
+		/* Find the object we target.
+		 * If the user gives us an empty string, we use the object
+		 * associated with this socket. This will workaround
+		 * duplicated class name - Jean II */
+		if(ias_opt->irda_class_name[0] == '\0')
+			ias_obj = self->ias_obj;
+		else
+			ias_obj = irias_find_object(ias_opt->irda_class_name);
 		if(ias_obj == (struct ias_object *) NULL) {
 			kfree(ias_opt);
 			return -EINVAL;
diff -u --recursive --new-file v2.5.0/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.5.0/linux/net/irda/iriap.c	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/iriap.c	Fri Nov 30 13:25:10 2001
@@ -800,9 +800,7 @@
 	new->max_header_size = max_header_size;
 
 	/* Clean up the original one to keep it in listen state */
-	self->lsap->dlsap_sel = LSAP_ANY;
-	self->lsap->lsap_state = LSAP_DISCONNECTED;
-	/* FIXME: refcount in irlmp might get wrong */
+	irlmp_listen(self->lsap);
 	
 	iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
 }
diff -u --recursive --new-file v2.5.0/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.5.0/linux/net/irda/irlap.c	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/irlap.c	Fri Nov 30 13:25:10 2001
@@ -51,6 +51,11 @@
 hashbin_t *irlap = NULL;
 int sysctl_slot_timeout = SLOT_TIMEOUT * 1000 / HZ;
 
+/* This is the delay of missed pf period before generating an event
+ * to the application. The spec mandate 3 seconds, but in some cases
+ * it's way too long. - Jean II */
+int sysctl_warn_noreply_time = 3;
+
 extern void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb);
 static void __irlap_close(struct irlap_cb *self);
 
@@ -527,22 +532,7 @@
 	self->discovery_cmd = discovery;
 	info.discovery = discovery;
 	
-	/* Check if the slot timeout is within limits */
-	if (sysctl_slot_timeout < 20) {
-		ERROR(__FUNCTION__ 
-		      "(), to low value for slot timeout!\n");
-		sysctl_slot_timeout = 20;
-	}
-	/* 
-	 * Highest value is actually 8, but we allow higher since
-	 * some devices seems to require it.
-	 */
-	if (sysctl_slot_timeout > 160) {
-		ERROR(__FUNCTION__ 
-		      "(), to high value for slot timeout!\n");
-		sysctl_slot_timeout = 160;
-	}
-	
+	/* sysctl_slot_timeout bounds are checked in irsysctl.c - Jean II */
 	self->slot_timeout = sysctl_slot_timeout * HZ / 1000;
 	
 	irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);
@@ -931,9 +921,6 @@
 	/* Set data size */
 	/*self->qos_rx.data_size.bits &= 0x03;*/
 
-	/* Set disconnect time -> done properly in qos.c */
-	/*self->qos_rx.link_disc_time.bits &= 0x07;*/
-
 	irda_qos_bits_to_value(&self->qos_rx);
 }
 
@@ -1070,8 +1057,11 @@
 	/*
 	 *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
 	 *  3 seconds otherwise. See page 71 in IrLAP for more details.
+	 *  Actually, it's not always 3 seconds, as we allow to set
+	 *  it via sysctl... Max maxtt is 500ms, and N1 need to be multiple
+	 *  of 2, so 1 second is minimum we can allow. - Jean II
 	 */
-	if (self->qos_tx.link_disc_time.value == 3)
+	if (self->qos_tx.link_disc_time.value == sysctl_warn_noreply_time)
 		/* 
 		 * If we set N1 to 0, it will trigger immediately, which is
 		 * not what we want. What we really want is to disable it,
@@ -1079,7 +1069,8 @@
 		 */
 		self->N1 = -2; /* Disable - Need to be multiple of 2*/
 	else
-		self->N1 = 3000 / self->qos_rx.max_turn_time.value;
+		self->N1 = sysctl_warn_noreply_time * 1000 /
+		  self->qos_rx.max_turn_time.value;
 	
 	IRDA_DEBUG(4, "Setting N1 = %d\n", self->N1);
 	
diff -u --recursive --new-file v2.5.0/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.5.0/linux/net/irda/irlap_event.c	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/irlap_event.c	Fri Nov 30 13:25:10 2001
@@ -1405,30 +1405,29 @@
 		}
 		self->add_wait = FALSE;
 
-		if ((self->retry_count < self->N2) && 
-		    (self->retry_count != self->N1)) {
-			
+		/* N2 is the disconnect timer. Until we reach it, we retry */
+		if (self->retry_count < self->N2) {
+			/* Retry sending the pf bit to the secondary */
 			irlap_wait_min_turn_around(self, &self->qos_tx);
 			irlap_send_rr_frame(self, CMD_FRAME);
 			
 			irlap_start_final_timer(self, self->final_timeout);
 		 	self->retry_count++;
-
 			IRDA_DEBUG(4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
 				   " retry_count=%d\n", self->retry_count);
-			/* Keep state */
-		} else if (self->retry_count == self->N1) {
-			irlap_status_indication(self, STATUS_NO_ACTIVITY);
-			irlap_wait_min_turn_around(self, &self->qos_tx);
-			irlap_send_rr_frame(self, CMD_FRAME);
-			
-			irlap_start_final_timer(self, self->final_timeout);
-			self->retry_count++;
 
-			IRDA_DEBUG(4, "retry count = N1; retry_count=%d\n", 
-				   self->retry_count);
+			/* Early warning event. I'm using a pretty liberal
+			 * interpretation of the spec and generate an event
+			 * every time the timer is multiple of N1 (and not
+			 * only the first time). This allow application
+			 * to know precisely if connectivity restart...
+			 * Jean II */
+			if((self->retry_count % self->N1) == 0)
+				irlap_status_indication(self,
+							STATUS_NO_ACTIVITY);
+
 			/* Keep state */
-		} else if (self->retry_count >= self->N2) {
+		} else {
 			irlap_apply_default_connection_parameters(self);
 
 			/* Always switch state before calling upper layers */
@@ -1991,6 +1990,7 @@
 		 *  Wait until retry_count * n matches negotiated threshold/
 		 *  disconnect time (note 2 in IrLAP p. 82)
 		 *
+		 * Similar to irlap_state_nrm_p() -> FINAL_TIMER_EXPIRED
 		 * Note : self->wd_timeout = (self->final_timeout * 2),
 		 *   which explain why we use (self->N2 / 2) here !!!
 		 * Jean II
@@ -1998,16 +1998,15 @@
 		IRDA_DEBUG(1, __FUNCTION__ "(), retry_count = %d\n", 
 			   self->retry_count);
 
-		if ((self->retry_count <  (self->N2 / 2))  && 
-		    (self->retry_count != (self->N1 / 2))) {
-			
+		if (self->retry_count < (self->N2 / 2)) {
+			/* No retry, just wait for primary */
 			irlap_start_wd_timer(self, self->wd_timeout);
 			self->retry_count++;
-		} else if (self->retry_count == (self->N1 / 2)) {
-			irlap_status_indication(self, STATUS_NO_ACTIVITY);
-			irlap_start_wd_timer(self, self->wd_timeout);
-			self->retry_count++;
-		} else if (self->retry_count >= (self->N2 / 2)) {
+
+			if((self->retry_count % (self->N1 / 2)) == 0)
+				irlap_status_indication(self,
+							STATUS_NO_ACTIVITY);
+		} else {
 			irlap_apply_default_connection_parameters(self);
 			
 			/* Always switch state before calling upper layers */
diff -u --recursive --new-file v2.5.0/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.5.0/linux/net/irda/irlmp.c	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/irlmp.c	Fri Nov 30 13:25:10 2001
@@ -469,7 +469,12 @@
 
 	IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n", 
 		   self->slsap_sel, self->dlsap_sel);
-	
+
+	/* Note : self->lap is set in irlmp_link_data_indication(),
+	 * (case CONNECT_CMD:) because we have no way to set it here.
+	 * Similarly, self->dlsap_sel is usually set in irlmp_find_lsap().
+	 * Jean II */
+
 	self->qos = *self->lap->qos;
 
 	max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
@@ -577,7 +582,9 @@
 	/* Dup */
 	memcpy(new, orig, sizeof(struct lsap_cb));
 	new->notify.instance = instance;
-	
+	/* new->lap = orig->lap; => done in the memcpy() */
+	/* new->slsap_sel = orig->slsap_sel; => done in the memcpy() */
+
 	init_timer(&new->watchdog_timer);
 	
 	hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new, (int) new, 
diff -u --recursive --new-file v2.5.0/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
--- v2.5.0/linux/net/irda/irlmp_event.c	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/irlmp_event.c	Fri Nov 30 13:25:10 2001
@@ -407,12 +407,7 @@
 		 *  removed later and moved to the list of unconnected LSAPs
 		 */
 		if (HASHBIN_GET_SIZE(self->lsaps) > 0) {
-			/* Make sure the timer has sensible value (the user
-			 * may have set it) - Jean II */
-			if(sysctl_lap_keepalive_time < 100)	/* 100ms */
-				sysctl_lap_keepalive_time = 100;
-			if(sysctl_lap_keepalive_time > 10000)	/* 10s */
-				sysctl_lap_keepalive_time = 10000;
+			/* Timer value is checked in irsysctl - Jean II */
 			irlmp_start_idle_timer(self, sysctl_lap_keepalive_time * HZ / 1000);
 		} else {
 			/* No more connections, so close IrLAP */
diff -u --recursive --new-file v2.5.0/linux/net/irda/irnet/irnet.h linux/net/irda/irnet/irnet.h
--- v2.5.0/linux/net/irda/irnet/irnet.h	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/irnet/irnet.h	Fri Nov 30 13:25:10 2001
@@ -199,6 +199,13 @@
  *	o Avoid leaking discovery log and skb
  *	o Replace "self" with "server" in irnet_connect_indication() to
  *	  better detect cut'n'paste error ;-)
+ *
+ * v9 - 29.11.01 - Jean II
+ *	o Fix event generation in disconnect indication that I broke in v8
+ *	  It was always generation "No-Answer" because I was testing ttp_open
+ *	  just after clearing it. *blush*.
+ *	o Use newly created irttp_listen() to fix potential crash when LAP
+ *	  destroyed before irnet module removed.
  */
 
 /***************************** INCLUDES *****************************/
diff -u --recursive --new-file v2.5.0/linux/net/irda/irnet/irnet_irda.c linux/net/irda/irnet/irnet_irda.c
--- v2.5.0/linux/net/irda/irnet/irnet_irda.c	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/irnet/irnet_irda.c	Fri Nov 30 13:25:10 2001
@@ -830,8 +830,7 @@
 #endif /* STREAM_COMPAT */
 
   /* Clean up the original one to keep it in listen state */
-  server->tsap->dtsap_sel = server->tsap->lsap->dlsap_sel = LSAP_ANY;
-  server->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+  irttp_listen(server->tsap);
 
   /* Send a connection response on the new socket */
   irttp_connect_response(new->tsap, new->max_sdu_size_rx, NULL);
@@ -897,8 +896,7 @@
 		   self->saddr, self->daddr, self->rname);
 
   /* Clean up the server to keep it in listen state */
-  self->tsap->dtsap_sel = self->tsap->lsap->dlsap_sel = LSAP_ANY;
-  self->tsap->lsap->lsap_state = LSAP_DISCONNECTED;
+  irttp_listen(self->tsap);
 
   DEXIT(IRDA_SERV_TRACE, "\n");
   return;
@@ -1081,7 +1079,8 @@
 			    struct sk_buff *skb)
 {
   irnet_socket *	self = (irnet_socket *) instance;
-  int			test = 0;
+  int			test_open;
+  int			test_connect;
 
   DENTER(IRDA_TCB_TRACE, "(self=0x%X)\n", (unsigned int) self);
   DASSERT(self != NULL, , IRDA_CB_ERROR, "Self is NULL !!!\n");
@@ -1091,23 +1090,23 @@
     dev_kfree_skb(skb);
 
   /* Prevent higher layer from accessing IrTTP */
-  test = test_and_clear_bit(0, &self->ttp_open);
+  test_open = test_and_clear_bit(0, &self->ttp_open);
   /* Not connecting anymore...
    * (note : TSAP is open, so IAP callbacks are no longer pending...) */
-  test |= test_and_clear_bit(0, &self->ttp_connect);
+  test_connect = test_and_clear_bit(0, &self->ttp_connect);
 
   /* If both self->ttp_open and self->ttp_connect are NULL, it mean that we
    * have a race condition with irda_irnet_destroy() or
    * irnet_connect_indication(), so don't mess up tsap...
    */
-  if(!test)
+  if(!(test_open || test_connect))
     {
       DERROR(IRDA_CB_ERROR, "Race condition detected...\n");
       return;
     }
 
   /* If we were active, notify the control channel */
-  if(test_bit(0, &self->ttp_open))
+  if(test_open)
     irnet_post_event(self, IRNET_DISCONNECT_FROM,
 		     self->saddr, self->daddr, self->rname);
   else
diff -u --recursive --new-file v2.5.0/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c
--- v2.5.0/linux/net/irda/irsysctl.c	Thu Sep 13 16:26:52 2001
+++ linux/net/irda/irsysctl.c	Fri Nov 30 13:25:10 2001
@@ -10,6 +10,7 @@
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
+ *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
  *      
  *     This program is free software; you can redistribute it and/or 
  *     modify it under the terms of the GNU General Public License as 
@@ -32,24 +33,47 @@
 #include <net/irda/irias_object.h>
 
 #define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, DEBUG, SLOTS, DISCOVERY_TIMEOUT, 
-       SLOT_TIMEOUT, MAX_BAUD_RATE, MAX_INACTIVE_TIME, LAP_KEEPALIVE_TIME, };
+enum { DISCOVERY=1, DEVNAME, DEBUG, FAST_POLL, DISCOVERY_SLOTS,
+       DISCOVERY_TIMEOUT, SLOT_TIMEOUT, MAX_BAUD_RATE, MIN_TX_TURN_TIME,
+       MAX_NOREPLY_TIME, WARN_NOREPLY_TIME, LAP_KEEPALIVE_TIME };
 
 extern int  sysctl_discovery;
 extern int  sysctl_discovery_slots;
 extern int  sysctl_discovery_timeout;
-extern int  sysctl_slot_timeout;
+extern int  sysctl_slot_timeout;	/* Candidate */
 extern int  sysctl_fast_poll_increase;
 int         sysctl_compression = 0;
 extern char sysctl_devname[];
 extern int  sysctl_max_baud_rate;
-extern int  sysctl_max_inactive_time;
+extern int  sysctl_min_tx_turn_time;
+extern int  sysctl_max_noreply_time;
+extern int  sysctl_warn_noreply_time;
 extern int  sysctl_lap_keepalive_time;
 
 #ifdef CONFIG_IRDA_DEBUG
 extern unsigned int irda_debug;
 #endif
 
+/* this is needed for the proc_dointvec_minmax - Jean II */
+static int max_discovery_slots = 16;		/* ??? */
+static int min_discovery_slots = 1;
+/* IrLAP 6.13.2 says 25ms to 10+70ms - allow higher since some devices
+ * seems to require it. (from Dag's comment) */
+static int max_slot_timeout = 160;
+static int min_slot_timeout = 20;
+static int max_max_baud_rate = 16000000;	/* See qos.c - IrLAP spec */
+static int min_max_baud_rate = 2400;
+static int max_min_tx_turn_time = 10000;	/* See qos.c - IrLAP spec */
+static int min_min_tx_turn_time = 0;
+static int max_max_noreply_time = 40;		/* See qos.c - IrLAP spec */
+static int min_max_noreply_time = 3;
+static int max_warn_noreply_time = 3;		/* 3s == standard */
+static int min_warn_noreply_time = 1;		/* 1s == min WD_TIMER */
+static int max_lap_keepalive_time = 10000;	/* 10s */
+static int min_lap_keepalive_time = 100;	/* 100us */
+/* For other sysctl, I've no idea of the range. Maybe Dag could help
+ * us on that - Jean II */
+
 static int do_devname(ctl_table *table, int write, struct file *filp,
 		      void *buffer, size_t *lenp)
 {
@@ -77,21 +101,32 @@
 	  sizeof(int), 0644, NULL, &proc_dointvec },
 #endif
 #ifdef CONFIG_IRDA_FAST_RR
-        { SLOTS, "fast_poll_increase", &sysctl_fast_poll_increase,
+        { FAST_POLL, "fast_poll_increase", &sysctl_fast_poll_increase,
 	  sizeof(int), 0644, NULL, &proc_dointvec },
 #endif
-	{ SLOTS, "discovery_slots", &sysctl_discovery_slots,
-	  sizeof(int), 0644, NULL, &proc_dointvec },
+	{ DISCOVERY_SLOTS, "discovery_slots", &sysctl_discovery_slots,
+	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+	  NULL, &min_discovery_slots, &max_discovery_slots },
 	{ DISCOVERY_TIMEOUT, "discovery_timeout", &sysctl_discovery_timeout,
 	  sizeof(int), 0644, NULL, &proc_dointvec },
 	{ SLOT_TIMEOUT, "slot_timeout", &sysctl_slot_timeout,
-	  sizeof(int), 0644, NULL, &proc_dointvec },
+	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+	  NULL, &min_slot_timeout, &max_slot_timeout },
 	{ MAX_BAUD_RATE, "max_baud_rate", &sysctl_max_baud_rate,
-	  sizeof(int), 0644, NULL, &proc_dointvec },
-	{ MAX_INACTIVE_TIME, "max_inactive_time", &sysctl_max_inactive_time,
-	  sizeof(int), 0644, NULL, &proc_dointvec },
+	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+	  NULL, &min_max_baud_rate, &max_max_baud_rate },
+	{ MIN_TX_TURN_TIME, "min_tx_turn_time", &sysctl_min_tx_turn_time,
+	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+	  NULL, &min_min_tx_turn_time, &max_min_tx_turn_time },
+	{ MAX_NOREPLY_TIME, "max_noreply_time", &sysctl_max_noreply_time,
+	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+	  NULL, &min_max_noreply_time, &max_max_noreply_time },
+	{ WARN_NOREPLY_TIME, "warn_noreply_time", &sysctl_warn_noreply_time,
+	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+	  NULL, &min_warn_noreply_time, &max_warn_noreply_time },
 	{ LAP_KEEPALIVE_TIME, "lap_keepalive_time", &sysctl_lap_keepalive_time,
-	  sizeof(int), 0644, NULL, &proc_dointvec },
+	  sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
+	  NULL, &min_lap_keepalive_time, &max_lap_keepalive_time },
 	{ 0 }
 };
 
diff -u --recursive --new-file v2.5.0/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.5.0/linux/net/irda/qos.c	Fri Nov  9 14:22:17 2001
+++ linux/net/irda/qos.c	Fri Nov 30 13:25:10 2001
@@ -51,7 +51,16 @@
  * may want to keep the LAP alive longuer or shorter in case of link failure.
  * Remember that the threshold time (early warning) is fixed to 3s...
  */
-int sysctl_max_inactive_time = 12;
+int sysctl_max_noreply_time = 12;
+/*
+ * Minimum turn time to be applied before transmitting to the peer.
+ * Nonzero values (usec) are used as lower limit to the per-connection
+ * mtt value which was announced by the other end during negotiation.
+ * Might be helpful if the peer device provides too short mtt.
+ * Default is 10 which means using the unmodified value given by the peer
+ * except if it's 0 (0 is likely a bug in the other stack).
+ */
+unsigned sysctl_min_tx_turn_time = 10;
 
 static int irlap_param_baud_rate(void *instance, irda_param_t *param, int get);
 static int irlap_param_link_disconnect(void *instance, irda_param_t *parm, 
@@ -184,7 +193,6 @@
  * Function value_lower_bits (value, array)
  *
  *    Returns a bit field marking all possibility lower than value.
- *    We may need a "value_higher_bits" in the future...
  */
 static inline int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field)
 {
@@ -207,6 +215,33 @@
 	return i;
 }
 
+/*
+ * Function value_highest_bit (value, array)
+ *
+ *    Returns a bit field marking the highest possibility lower than value.
+ */
+static inline int value_highest_bit(__u32 value, __u32 *array, int size, __u16 *field)
+{
+	int	i;
+	__u16	mask = 0x1;
+	__u16	result = 0x0;
+
+	for (i=0; i < size; i++) {
+		/* Finished ? */
+		if (array[i] <= value)
+			break;
+		/* Shift mask */
+		mask <<= 1;
+	}
+	/* Set the current value to the bit field */
+	result |= mask;
+	/* Send back a valid index */
+	if(i >= size)
+	  i = size - 1;	/* Last item */
+	*field = result;
+	return i;
+}
+
 /* -------------------------- MAIN CALLS -------------------------- */
 
 /*
@@ -254,9 +289,9 @@
 	sysctl_max_baud_rate = index_value(i, baud_rates);
 
 	/* Set configured max disc time */
-	i = value_lower_bits(sysctl_max_inactive_time, link_disc_times, 8,
+	i = value_lower_bits(sysctl_max_noreply_time, link_disc_times, 8,
 			     &qos->link_disc_time.bits);
-	sysctl_max_inactive_time = index_value(i, link_disc_times);
+	sysctl_max_noreply_time = index_value(i, link_disc_times);
 
 	/* LSB is first byte, MSB is second byte */
 	qos->baud_rate.bits    &= 0x03ff;
@@ -281,6 +316,19 @@
 	int index;
 
 	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	/*
+	 * Make sure the mintt is sensible.
+	 */
+	if (sysctl_min_tx_turn_time > qos->min_turn_time.value) {
+		int i;
+
+		/* We don't really need bits, but easier this way */
+		i = value_highest_bit(sysctl_min_tx_turn_time, min_turn_times,
+				      8, &qos->min_turn_time.bits);
+		sysctl_min_tx_turn_time = index_value(i, min_turn_times);
+		qos->min_turn_time.value = sysctl_min_tx_turn_time;
+	}
 
 	/* 
 	 * Not allowed to use a max turn time less than 500 ms if the baudrate
