diff -u --recursive --new-file v2.3.39/linux/CREDITS linux/CREDITS
--- v2.3.39/linux/CREDITS	Tue Jan 11 22:31:35 2000
+++ linux/CREDITS	Mon Jan 17 22:19:08 2000
@@ -1638,6 +1638,15 @@
 E: orc@pell.chi.il.us
 D: improved memory detection code.
 
+N: Ivan Passos
+E: ivan@cyclades.com
+D: Author of the Cyclades-PC300 synchronous card driver
+D: Maintainer of the Cyclom-Y/Cyclades-Z asynchronous card driver
+S: Cyclades Corp
+S: 41934 Christy St
+S: Fremont, CA 94538
+S: USA
+
 N: Mikulas Patocka
 E: mikulas@artax.karlin.mff.cuni.cz
 W: http://artax.karlin.mff.cuni.cz/~mikulas/
@@ -2348,18 +2357,15 @@
 
 N: Lars Wirzenius
 E: liw@iki.fi
-D: Linux System Administrator's Guide
-D: Co-moderator, comp.os.linux.announce
+D: Linux System Administrator's Guide, author, former maintainer
+D: comp.os.linux.announce, former moderator
+D: Linux Documentation Project, co-founder
 D: Original sprintf in kernel
-D: Personal information about Linus
-D: Original kernel README
-D: Linux News (electronic magazine)
-D: Meta-FAQ, originator
+D: Original kernel README (for version 0.97)
+D: Linux News (electronic magazine, now dead), founder and former editor
+D: Meta-FAQ, originator, former maintainer
 D: INFO-SHEET, former maintainer
 D: Author of the longest-living linux bug
-S: Hernesaarenkatu 15 A 2
-S: Fin-00150 Helsinki
-S: Finland
 
 N: Jonathan Woithe
 E: jwoithe@physics.adelaide.edu.au
diff -u --recursive --new-file v2.3.39/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.39/linux/Documentation/Configure.help	Tue Jan 11 22:31:36 2000
+++ linux/Documentation/Configure.help	Thu Jan 20 15:00:16 2000
@@ -29,7 +29,7 @@
 #
 # Information about what a kernel is, what it does, how to patch and
 # compile it and much more is contained in the Kernel-HOWTO, available
-# at http://metalab.unc.edu/mdw/linux.html#howto . Before you start
+# at http://www.linuxdoc.org/docs.html#howto . Before you start
 # compiling, make sure that you have the necessary versions of all
 # programs and libraries required to compile and run this kernel; they
 # are listed in the file Documentation/Changes. Make sure to read the
@@ -118,6 +118,13 @@
   
   If you don't know what to do here, say N.
   
+APIC and IO-APIC Support on Uniprocessors
+CONFIG_X86_UP_IOAPIC
+  This option enables uniprocessor-kernels to switch into IO-APIC mode
+  if there is an IO-APIC in the system. Such a kernel will still boot
+  on IO-APIC-less systems with no slowdown at all. SMP kernels include
+  IO-APIC support unconditionally.
+
 Kernel math emulation
 CONFIG_MATH_EMULATION
   Linux can emulate a math coprocessor (used for floating point
@@ -134,7 +141,7 @@
   is broken. Try "man bootparam" or see the documentation of your boot
   loader (lilo or loadlin) about how to pass options to the kernel at
   boot time. The lilo procedure is also explained in the SCSI-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto .) This
+  available from http://www.linuxdoc.org/docs.html#howto .) This
   means that it is a good idea to say Y here if you intend to use this
   kernel on different machines.
 
@@ -326,7 +333,7 @@
   detected, sound card IDE ports, module support, and other topics, is
   contained in Documentation/ide.txt. For detailed information about
   hard drives, consult the Disk-HOWTO and the Multi-Disk-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto .
+  available from http://www.linuxdoc.org/docs.html#howto .
 
   To fine-tune IDE drive/interface parameters for improved
   performance, look for the hdparm package at
@@ -359,7 +366,7 @@
   If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver
   instead of this one. For more detailed information, read the
   Disk-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   People with SCSI-only systems can say N here.
 
@@ -420,7 +427,7 @@
   to say Y or M to "ISO 9660 CDROM filesystem support".
 
   Read the CDROM-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto and the file
+  http://www.linuxdoc.org/docs.html#howto and the file
   Documentation/cdrom/ide-cd. Note that older versions of lilo (the
   Linux boot loader) cannot properly deal with IDE/ATAPI CDROMs, so
   install lilo-16 or higher, available from
@@ -431,17 +438,6 @@
   say M here and read Documentation/modules.txt. The module will be
   called ide-cd.o.
 
-Include CD-Changer Reporting
-CONFIG_IDECD_SLOTS
-  If you have an IDE/ATAPI multi-slot cd-changer and you want
-  to report which slots have a disk present, say Y.  If you say Y
-  and there is no multi-slot cdrom present, this code is skipped.
-
-  This code could be the basis of multi-disk access based on
-  multi-mounts, but this is still pie-in-the-sky.
-
-  If unsure, say N.
-
 Include IDE/ATAPI TAPE support
 CONFIG_BLK_DEV_IDETAPE
   If you have an IDE tape drive using the ATAPI protocol, say Y.
@@ -450,6 +446,8 @@
   can say N here.
 
   This now includes the OnStream DI-30 tape drive support.
+  Will not work with SCSI protocol, until there is support for the
+  SC-30 and SC-50 versions.
 
   If you say Y here, the tape drive will be identified at boot time
   along with other IDE devices, as "hdb" or "hdc", or something
@@ -489,6 +487,9 @@
   and will allow you to use a SCSI device driver instead of a native
   ATAPI driver.
 
+  Must pass "hdx=scsi" per devices if you want the native EIDE sub-drivers
+  to skip over the native support.  This is required for use of CD-RW's.
+
   This is useful if you have an ATAPI device for which no native
   driver has been written (for example, an ATAPI PD-CD or CDR drive);
   you can then use this emulation together with an appropriate SCSI
@@ -503,6 +504,13 @@
 
   People with SCSI-only systems can say N here. If unsure, say N.
 
+ISA-PNP EIDE support
+CONFIG_BLK_DEV_ISAPNP
+  If you have an ISA EIDE card that is PnP and requires setup first
+  before scanning for devices, say Y here.
+
+  If unsure, say N.
+
 CMD640 chipset bugfix/support
 CONFIG_BLK_DEV_CMD640
   The CMD-Technologies CMD640 IDE chip is used on many common 486 and
@@ -521,7 +529,7 @@
   bootparam" or see the documentation of your boot loader about how to
   pass options to the kernel. The lilo procedure is also explained in
   the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .)
+  http://www.linuxdoc.org/docs.html#howto .)
 
   The CMD640 chip is also used on add-in cards by Acculogic, and on
   the "CSA-6400E PCI to IDE controller" that some people have. For
@@ -603,7 +611,7 @@
   documentation of your boot loader (lilo or loadlin) about how to
   pass options to the kernel at boot time. The lilo procedure is also
   explained in the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .)
+  http://www.linuxdoc.org/docs.html#howto .)
 
   Note that, if you do this, the order of the hd* devices will be
   rearranged which may require modification of fstab and other files.
@@ -634,7 +642,7 @@
 
   Please read the comments at the top of drivers/block/aec6210.c
 
-ALI M15x3 chipset support (EXPERIMENTAL)
+ALI M15x3 chipset support
 CONFIG_BLK_DEV_ALI15X3
   This driver ensures (U)DMA support for ALI 1543 and 1543C,
   1535, 1535D onboard chipsets.  It also tests for Simplex mode and
@@ -642,14 +650,29 @@
 
   If you say Y here, you also need to say Y to "Use DMA by default
   when available", above.
-
   Please read the comments at the top of drivers/block/alim15x3.c
 
   If unsure, say N.
 
-CMD646 chipset support (EXPERIMENTAL)
-CONFIG_BLK_DEV_CMD646
-  Say Y here if you have an IDE controller which uses this chipset.
+AMD7409 chipset support (EXPERIMENTAL)
+CONFIG_BLK_DEV_AMD7409
+  This driver ensures (U)DMA support for AMD756 Viper chipset.
+
+  If you say Y here, you also need to say Y to "Use DMA by default
+  when available", above.
+  Please read the comments at the top of drivers/block/amd7409.c
+
+  If unsure, say N.
+
+CMD64X chipset support
+CONFIG_BLK_DEV_CMD64X
+  Say Y here if you have an IDE controller which uses any of these chipsets,
+  CMD643, CMD646, or CMD648.
+
+CMD64X chipset RAID support (EXPERIMENTAL) (WIP)
+CONFIG_BLK_DEV_CMD64X
+  Work in progress for hardware raid ata-33/66..........rev 7 minimum.
+  Say N for now.
 
 CY82C693 chipset support (EXPERIMENTAL)
 CONFIG_BLK_DEV_CY82C693
@@ -687,11 +710,16 @@
 
   Please read the comments at the top of drivers/block/hpt366.c
 
-HPT366 Fast Interrupt support (EXPERIMENTAL)
+HPT366 Fast Interrupt support (EXPERIMENTAL) (WIP)
 HPT366_FAST_IRQ_PREDICTION
 
   If unsure, say N.
 
+HPT366 mode three unsupported (EXPERIMENTAL) (WIP)
+HPT366_MODE3
+  This is an undocumented mode that the HA366 can default to in many cases.
+  If unsure, say N.
+
 NS87415 support (EXPERIMENTAL)
 CONFIG_BLK_DEV_NS87415
   This driver adds detection and support for the NS87415 chip
@@ -713,7 +741,8 @@
 
   Please read the comments at the top of drivers/block/piix.c
 
-  If unsure, say N.
+  Should also include "PIIXn Tuning support" CONFIG_BLK_DEV_PIIX_TUNING
+  If unsure, say Y.
 
 PIIXn Tuning support
 CONFIG_BLK_DEV_PIIX_TUNING
@@ -725,7 +754,7 @@
   Case 430HX/440FX PIIX3 need speed limits to reduce UDMA to DMA mode
   2 if the BIOS can not perform this task at initialization.
 
-  If unsure, say N.
+  If unsure, say Y.
 
 PROMISE PDC20246/PDC20262 support
 CONFIG_BLK_DEV_PDC202XX
@@ -1237,7 +1266,7 @@
 
   More information about Software RAID on Linux is contained in the
   Software-RAID mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . There you will also
+  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.
@@ -1265,7 +1294,7 @@
 
   Information about Software RAID on Linux is contained in the
   Software-RAID mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . There you will also
+  http://www.linuxdoc.org/docs.html#howto . There you will also
   learn where to get the supporting user space utilities raidtools.
 
   If you want to compile this as a module ( = code which can be
@@ -1287,7 +1316,7 @@
 
   Information about Software RAID on Linux is contained in the
   Software-RAID mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . There you will also
+  http://www.linuxdoc.org/docs.html#howto . There you will also
   learn where to get the supporting user space utilities raidtools.
 
   If you want to use such a RAID-1 set, say Y. This code is also
@@ -1310,7 +1339,7 @@
 
   Information about Software RAID on Linux is contained in the
   Software-RAID mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . There you will also
+  http://www.linuxdoc.org/docs.html#howto . There you will also
   learn where to get the supporting user space utilities raidtools.
 
   If you want to use such a RAID-4/RAID-5 set, say Y. This code is
@@ -1416,7 +1445,7 @@
 
   For a general introduction to Linux networking, it is highly
   recommended to read the NET-3-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
 Socket filtering
 CONFIG_FILTER
@@ -1623,7 +1652,7 @@
   Say Y here if you have dumb serial boards other than the four
   standard COM 1/2/3/4 ports. This may happen if you have an AST
   FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto ), or other custom
+  from http://www.linuxdoc.org/docs.html#howto ), or other custom
   serial port hardware which acts similar to standard serial port
   hardware. If you only use the standard COM 1/2/3/4 ports, you can
   say N here to save some memory. You can also say Y if you have an
@@ -1700,7 +1729,7 @@
   VESA. If you have PCI, say Y, otherwise N. 
 
   The PCI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , contains valuable
+  http://www.linuxdoc.org/docs.html#howto , contains valuable
   information about which PCI hardware does work under Linux and which
   doesn't.
 
@@ -1901,12 +1930,12 @@
   and some programs won't run unless you say Y here. In particular, if
   you want to run the DOS emulator dosemu under Linux (read the
   DOSEMU-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto ), you'll need to say Y
+  http://www.linuxdoc.org/docs.html#howto ), you'll need to say Y
   here.
   
   You can find documentation about IPC with "info ipc" and also in
   section 6.4 of the Linux Programmer's Guide, available from
-  http://metalab.unc.edu/mdw/linux.html#guide .
+  http://www.linuxdoc.org/docs.html#guide .
 
   Saying Y here enlarges your kernel by about 18 KB. Just say Y.
 
@@ -1968,7 +1997,7 @@
   want to say Y here.
 
   Information about ELF is contained in the ELF HOWTO available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you find that after upgrading from Linux kernel 1.2 and saying Y
   here, you still can't run any ELF binaries (they just crash), then
@@ -2023,7 +2052,7 @@
   programs that need an interpreter to run like Java, Python or
   Emacs-Lisp. It's also useful if you often run DOS executables under
   the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto ). Once you have
+  http://www.linuxdoc.org/docs.html#howto ). Once you have
   registered such a binary class with the kernel, you can start one of
   those programs simply by typing in its name at a shell prompt; Linux
   will automatically feed it to the correct interpreter.
@@ -2101,7 +2130,7 @@
   "man bootparam" or see the documentation of your boot loader about
   how to pass options to the kernel. The lilo procedure is also
   explained in the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .)
+  http://www.linuxdoc.org/docs.html#howto .)
 
   Read the file Documentation/svga.txt for more information about the
   Video mode selection support. If unsure, say N.
@@ -2686,7 +2715,7 @@
 
   For an excellent introduction to Linux networking, please read the
   NET-3-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   This option is also necessary if you want to use the full power of
   term (term is a program which gives you almost full Internet
@@ -2914,7 +2943,7 @@
   connect to you. This is called "multihosting" or "virtual domains"
   or "virtual hosting services" and is explained in the
   Virtual-Services-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   Another scenario would be that there are two logical networks living
   on your local Ethernet and you want to access them both with the
@@ -3088,7 +3117,7 @@
   Novell client ncpfs (available from
   ftp://metalab.unc.edu/pub/Linux/system/filesystems/ ) or from within
   the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto ). In order to do the
+  http://www.linuxdoc.org/docs.html#howto ). In order to do the
   former, you'll also have to say Y to "NCP filesystem support",
   below.
 
@@ -3101,7 +3130,7 @@
   ftp://metalab.unc.edu/pub/Linux/system/network/daemons/ or mars_nwe
   from ftp://ftp.gwdg.de/pub/linux/misc/ncpfs . For more information,
   read the IPX-HOWTO available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   General information about how to connect Linux, Windows machines and
   Macs is on the WWW at http://www.eats.com/linux_mac_win.html .
@@ -3122,7 +3151,7 @@
   same address). The way this is done is to create a virtual internal
   "network" inside your box and to assign an IPX address to this
   network. Say Y here if you want to do this; read the IPX-HOWTO at
-  http://metalab.unc.edu/mdw/linux.html#howto for details.
+  http://www.linuxdoc.org/docs.html#howto for details.
 
   The full internal IPX network enables you to allocate sockets on
   different virtual nodes of the internal network. This is done by
@@ -3152,7 +3181,7 @@
   space programs lwared or mars_nwe for the server side).
 
   Say Y here if you have use for SPX; read the IPX-HOWTO at
-  http://metalab.unc.edu/mdw/linux.html#howto for details.
+  http://www.linuxdoc.org/docs.html#howto for details.
 
   This driver is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -3221,7 +3250,7 @@
   General information about how to connect Linux, Windows machines and
   Macs is on the WWW at http://www.eats.com/linux_mac_win.html The
   NET-3-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , contains valuable
+  http://www.linuxdoc.org/docs.html#howto , contains valuable
   information as well.
 
   This driver is also available as a module ( = code which can be
@@ -3309,7 +3338,7 @@
   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://metalab.unc.edu/mdw/linux.html#howto .
+  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 this configure script to skip all
@@ -3333,7 +3362,7 @@
   Information about where to get supporting software for Linux amateur
   radio as well as information about how to configure an AX.25 port is
   contained in the AX25-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . You might also want to
+  http://www.linuxdoc.org/docs.html#howto . You might also want to
   check out the file Documentation/networking/ax25.txt in the kernel
   source. More information about digital amateur radio in general is
   on the WWW at http://www.tapr.org/tapr/html/pkthome.html .
@@ -3369,7 +3398,7 @@
   A comprehensive listing of all the software for Linux amateur radio
   users as well as information about how to configure an AX.25 port is
   contained in the AX25-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . You also might want to
+  http://www.linuxdoc.org/docs.html#howto . You also might want to
   check out the file Documentation/networking/ax25.txt. More
   information about digital amateur radio in general is on the WWW at
   http://www.tapr.org/tapr/html/pkthome.html .
@@ -3388,7 +3417,7 @@
   A comprehensive listing of all the software for Linux amateur radio
   users as well as information about how to configure an AX.25 port is
   contained in the AX25-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . You also might want to
+  http://www.linuxdoc.org/docs.html#howto . You also might want to
   check out the file Documentation/networking/ax25.txt. More
   information about digital amateur radio in general is on the WWW at
   http://www.tapr.org/tapr/html/pkthome.html .
@@ -3454,7 +3483,7 @@
   (http://www.paccomm.com/gracilis.html ) boards. They are detected
   automatically. If you have one of these cards, say Y here and read
   the AX25-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   This driver can operate multiple boards simultaneously. If you
   compile it as a module (by saying M instead of Y), it will be called
@@ -3477,7 +3506,7 @@
   These cards are used to connect your Linux box to an amateur radio
   in order to communicate with other computers. If you want to use
   this, read Documentation/networking/z8530drv.txt and the AX25-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto . Also
+  available from http://www.linuxdoc.org/docs.html#howto . Also
   make sure to say Y to "Amateur Radio AX.25 Level 2" support.
 
   If you want to compile this as a module ( = code which can be
@@ -3736,7 +3765,7 @@
   as a bridge, it probably contains several Ethernet devices, but the
   kernel is not able to recognize more than one at boot time without
   help; for details read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   The Bridging code is still in test. If unsure, say N.
 
@@ -4008,7 +4037,7 @@
   port version of the 100 MB IOMEGA ZIP drive.
 
   Please read the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . The
+  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.
@@ -4026,7 +4055,7 @@
   If you want to use a SCSI hard disk or the SCSI or parallel port
   version of the IOMEGA ZIP drive under Linux, say Y and read the
   SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . This is NOT for SCSI
+  http://www.linuxdoc.org/docs.html#howto . This is NOT for SCSI
   CDROMs.
 
   This driver is also available as a module ( = code which can be
@@ -4042,7 +4071,7 @@
 CONFIG_CHR_DEV_ST
   If you want to use a SCSI tape drive under Linux, say Y and read the
   SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , and
+  http://www.linuxdoc.org/docs.html#howto , and
   drivers/scsi/README.st in the kernel source. This is NOT for SCSI
   CDROMs.
 
@@ -4056,7 +4085,7 @@
 CONFIG_BLK_DEV_SR
   If you want to use a SCSI CDROM under Linux, say Y and read the
   SCSI-HOWTO and the CDROM-HOWTO at
-  http://metalab.unc.edu/mdw/linux.html#howto . Also make sure to say Y
+  http://www.linuxdoc.org/docs.html#howto . Also make sure to say Y
   or M to "ISO 9660 CDROM filesystem support" later.
 
   This driver is also available as a module ( = code which can be
@@ -4084,7 +4113,7 @@
   devices, it's possible that you'll have to write the driver software
   yourself, so have a look at the SCSI-HOWTO and at the
   SCSI-Programming-HOWTO, both available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Please read the file
+  http://www.linuxdoc.org/docs.html#howto . Please read the file
   Documentation/scsi-generic.txt for more information.
 
   If you want to compile this as a module ( = code which can be
@@ -4160,7 +4189,7 @@
   must be manually specified in this case.
 
   It is explained in section 3.3 of the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . You might also want to
+  http://www.linuxdoc.org/docs.html#howto . You might also want to
   read the comments at the top of drivers/scsi/aha152x.c.
 
   This driver is also available as a module ( = code which can be
@@ -4172,7 +4201,7 @@
 CONFIG_SCSI_AHA1542
   This is support for a SCSI host adapter. It is explained in section
   3.4 of the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Note that Trantor was
+  http://www.linuxdoc.org/docs.html#howto . Note that Trantor was
   purchased by Adaptec, and some former Trantor products are being
   sold under the Adaptec name. If it doesn't work out of the box, you
   may have to change some settings in drivers/scsi/aha1542.h.
@@ -4186,7 +4215,7 @@
 CONFIG_SCSI_AHA1740
   This is support for a SCSI host adapter. It is explained in section
   3.5 of the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . If it doesn't work out
+  http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
   of the box, you may have to change some settings in
   drivers/scsi/aha1740.h.
 
@@ -4221,7 +4250,7 @@
   configuration options. You should read drivers/scsi/README.aic7xxx
   at a minimum before contacting the maintainer with any questions.
   The SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , can also be of great
+  http://www.linuxdoc.org/docs.html#howto , can also be of great
   help.
 
   If you want to compile this driver as a module ( = code which can be
@@ -4334,7 +4363,7 @@
 CONFIG_SCSI_BUSLOGIC
   This is support for BusLogic MultiMaster and FlashPoint SCSI Host
   Adapters. Consult the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , and the files
+  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
@@ -4357,7 +4386,7 @@
 CONFIG_SCSI_DTC3280
   This is support for DTC 3180/3280 SCSI Host Adapters. Please read
   the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , and the file
+  http://www.linuxdoc.org/docs.html#howto , and the file
   drivers/scsi/README.dtc3x80.
 
   This driver is also available as a module ( = code which can be
@@ -4374,7 +4403,7 @@
   Note that this driver is obsolete; if you have one of the above SCSI
   Host Adapters, you should normally say N here and Y to "EATA
   ISA/EISA/PCI support", below. Please read the SCSI-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -4388,7 +4417,7 @@
   host adapters could also use this driver but are discouraged from
   doing so, since this driver only supports hard disks and lacks
   numerous features. You might want to have a look at the SCSI-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto . 
+  available from http://www.linuxdoc.org/docs.html#howto . 
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -4402,7 +4431,7 @@
   this hardware. If the driver doesn't work out of the box, you may
   have to change some settings in drivers/scsi/u14-34f.c. Read the
   SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Note that there is also
+  http://www.linuxdoc.org/docs.html#howto . Note that there is also
   another driver for the same hardware: "UltraStor SCSI support",
   below. You should say Y to both only if you want 24F support as
   well.
@@ -4437,7 +4466,7 @@
   other adapters based on the Future Domain chipsets (Quantum
   ISA-200S, ISA-250MG; Adaptec AHA-2920A; and at least one IBM board).
   It is explained in section 3.7 of the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   NOTE: Newer Adaptec AHA-2920C boards use the Adaptec AIC-7850 chip
   and should use the aic7xxx driver ("Adaptec AIC7xxx chipset SCSI
@@ -4467,7 +4496,7 @@
   This is the generic NCR family of SCSI controllers, not to be
   confused with the NCR 53c7 or 8xx controllers. It is explained in
   section 3.8 of the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . If it doesn't work out
+  http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
   of the box, you may have to change some settings in
   drivers/scsi/g_NCR5380.h.
 
@@ -4496,7 +4525,7 @@
   This is a driver for the 53c7 and 8xx NCR family of SCSI
   controllers, not to be confused with the NCR 5380 controllers. It is
   explained in section 3.8 of the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . If it doesn't work out
+  http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
   of the box, you may have to change some settings in
   drivers/scsi/53c7,8xx.h. Please read drivers/scsi/README.ncr53c7xx
   for the available boot time command line options.
@@ -4718,7 +4747,7 @@
   bootparam" or see the documentation of your boot loader about how to
   pass options to the kernel. The lilo procedure is also explained in
   the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   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),
@@ -4796,7 +4825,7 @@
 CONFIG_SCSI_INITIO
   This is support for the Initio 91XXU(W) SCSI host adapter. Please
   read the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -4807,7 +4836,7 @@
 CONFIG_SCSI_PAS16
   This is support for a SCSI host adapter. It is explained in section
   3.10 of the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . If it doesn't work out
+  http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
   of the box, you may have to change some settings in
   drivers/scsi/pas16.h.
   
@@ -4820,7 +4849,7 @@
 CONFIG_SCSI_INIA100
   This is support for the Initio INI-A100U2W SCSI host adapter. Please
   read the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be 
   inserted in and removed from the running kernel whenever you want),
@@ -4831,7 +4860,7 @@
 CONFIG_SCSI_PCI2000
   This is support for the PCI2000I EIDE interface card which acts as a
   SCSI host adapter. Please read the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   This driver is also available as a module called pci2000.o ( = code
   which can be inserted in and removed from the running kernel
@@ -4842,7 +4871,7 @@
 CONFIG_SCSI_PCI2220I
   This is support for the PCI2220i EIDE interface card which acts as a
   SCSI host adapter. Please read the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   This driver is also available as a module called pci2220i.o ( = code
   which can be inserted in and removed from the running kernel
@@ -4853,7 +4882,7 @@
 CONFIG_SCSI_PSI240I
   This is support for the PSI240i EIDE interface card which acts as a
   SCSI host adapter. Please read the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   This driver is also available as a module called psi240i.o ( = code
   which can be inserted in and removed from the running kernel
@@ -4872,7 +4901,7 @@
 
   Information about this driver is contained in
   drivers/scsi/README.qlogicfas. You should also read the SCSI-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#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).
@@ -4890,7 +4919,7 @@
 
   Please read the file drivers/scsi/README.qlogicisp. You should also
   read the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -4910,7 +4939,7 @@
 CONFIG_SCSI_SEAGATE
   These are 8-bit SCSI controllers; the ST-01 is also supported by
   this driver. It is explained in section 3.9 of the SCSI-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto . If it
+  available from http://www.linuxdoc.org/docs.html#howto . If it
   doesn't work out of the box, you may have to change some settings in
   drivers/scsi/seagate.h.
 
@@ -4923,7 +4952,7 @@
 CONFIG_SCSI_T128
   This is support for a SCSI host adapter. It is explained in section
   3.11 of the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . If it doesn't work out
+  http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
   of the box, you may have to change some settings in
   drivers/scsi/t128.h. Note that Trantor was purchased by Adaptec, and
   some former Trantor products are being sold under the Adaptec name.
@@ -4938,7 +4967,7 @@
   This is support for the UltraStor 14F, 24F and 34F SCSI-2 host
   adapter family. This driver is explained in section 3.12 of the
   SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . If it doesn't work out
+  http://www.linuxdoc.org/docs.html#howto . If it doesn't work out
   of the box, you may have to change some settings in
   drivers/scsi/ultrastor.h.
   
@@ -4979,7 +5008,7 @@
 
   You want to read the start of drivers/scsi/eata.c and the
   SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   Note that there is also another driver for the same hardware
   available: "EATA-DMA support". You should say Y to only one of them.
@@ -5019,7 +5048,7 @@
   This is support for the NCR53c406a SCSI host adapter. For user
   configurable parameters, check out drivers/scsi/NCR53c406.c in the
   kernel source. Also read the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   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),
@@ -5082,7 +5111,7 @@
 CONFIG_SCSI_AM53C974
   This is support for the AM53/79C974 SCSI host adapters. Please read
   drivers/scsi/README.AM53C974 for details. Also, the SCSI-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto , is for
+  available from http://www.linuxdoc.org/docs.html#howto , is for
   you.
 
   Note that there is another driver for AM53C974 based adapters:
@@ -5132,7 +5161,7 @@
   For more information about this driver and how to use it you should
   read the file drivers/scsi/README.ppa. You should also read the
   SCSI-HOWTO, which is available from
-  http://metalab.unc.edu/mdw/linux.html#howto . If you use this driver,
+  http://www.linuxdoc.org/docs.html#howto . If you use this driver,
   you will still be able to use the parallel port for other tasks,
   such as a printer; it is safe to compile both drivers into the
   kernel.
@@ -5159,7 +5188,7 @@
   For more information about this driver and how to use it you should
   read the file drivers/scsi/README.ppa. You should also read the
   SCSI-HOWTO, which is available from
-  http://metalab.unc.edu/mdw/linux.html#howto . If you use this driver,
+  http://www.linuxdoc.org/docs.html#howto . If you use this driver,
   you will still be able to use the parallel port for other tasks,
   such as a printer; it is safe to compile both drivers into the
   kernel.
@@ -5284,7 +5313,7 @@
   telephone line with a modem either via UUCP (UUCP is a protocol to
   forward mail and news between unix hosts over telephone lines; read
   the UUCP-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto ) or dialing up a shell
+  http://www.linuxdoc.org/docs.html#howto ) or dialing up a shell
   account or a BBS, even using term (term is a program which gives you
   almost full Internet connectivity if you have a regular dial up
   shell account on some Internet connected Unix computer. Read
@@ -5344,7 +5373,7 @@
   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
-  http://metalab.unc.edu/mdw/linux.html#howto , explains how to
+  http://www.linuxdoc.org/docs.html#howto , explains how to
   configure SLIP. Note that you don't need this option if you just
   want to run term (term is a program which gives you almost full
   Internet connectivity if you have a regular dial up shell account on
@@ -5368,7 +5397,7 @@
   ftp://metalab.unc.edu/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://metalab.unc.edu/mdw/linux.html#howto , explains how to
+  http://www.linuxdoc.org/docs.html#howto , explains how to
   configure CSLIP. This won't enlarge your kernel.
 
 Keepalive and linefill
@@ -5397,7 +5426,7 @@
 
   To use PPP, you need an additional program called pppd as described
   in Documentation/networking/ppp.txt and in the PPP-HOWTO, available
-  at http://metalab.unc.edu/mdw/linux.html#howto . If you upgrade
+  at http://www.linuxdoc.org/docs.html#howto . If you upgrade
   from an older kernel, you might need to upgrade pppd as well. The
   PPP option enlarges your kernel by about 16 KB.
 
@@ -5517,7 +5546,7 @@
 
   If you want to use an ISA WaveLAN card under Linux, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Some more specific
+  http://www.linuxdoc.org/docs.html#howto . Some more specific
   information is contained in Documentation/networking/wavelan.txt and
   in the source code drivers/net/wavelan.p.h.
 
@@ -5821,7 +5850,7 @@
 
   If you want to use PLIP, say Y and read the PLIP mini-HOWTO as well
   as the NET-3-HOWTO, both available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Note that the PLIP
+  http://www.linuxdoc.org/docs.html#howto . Note that the PLIP
   protocol has been changed and this PLIP driver won't work together
   with the PLIP support in Linux versions 1.0.x. This option enlarges
   your kernel by about 8 KB.
@@ -5844,7 +5873,7 @@
 
   Say Y if you want this and read Documentation/networking/eql.txt.
   You may also want to read section 6.2 of the NET-3-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6419,7 +6448,7 @@
   If your Linux machine will be connected to an Ethernet and you have
   an Ethernet network interface card (NIC) installed in your computer,
   say Y here and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . You will then also have
+  http://www.linuxdoc.org/docs.html#howto . You will then also have
   to say Y to the driver for your particular NIC.
 
   Note that the answer to this question won't directly affect the
@@ -6446,7 +6475,7 @@
 CONFIG_NET_VENDOR_SMC
   If you have a network (Ethernet) card belonging to this class, say Y
   and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   Note that the answer to this question doesn't directly affect the
   kernel: saying N will just cause this configure script to skip all
@@ -6457,7 +6486,7 @@
 CONFIG_WD80x3
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6469,7 +6498,7 @@
 CONFIG_ULTRAMCA
   If you have a network (Ethernet) card of this type and are running
   an MCA based system (PS/2), say Y and read the Ethernet-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#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).
@@ -6481,7 +6510,7 @@
 CONFIG_ULTRA
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
   
   Important: There have been many reports that, with some motherboards
   mixing an SMC Ultra and an Adaptec AHA154x SCSI card (or compatible,
@@ -6500,7 +6529,7 @@
 CONFIG_ULTRA32
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6515,7 +6544,7 @@
   another SMC9192/9194 based chipset. Say Y if you want it compiled
   into the kernel, and read the file
   Documentation/networking/smc9.txt and the Ethernet-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto .
+  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
@@ -6529,7 +6558,7 @@
   with ISA NE2000 cards (they have their own driver, "NE2000/NE1000
   support" below). If you have a PCI NE2000 network (Ethernet) card,
   say Y and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6553,7 +6582,7 @@
 CONFIG_NET_VENDOR_RACAL
   If you have a network (Ethernet) card belonging to this class, such
   as the NI5010, NI5210 or NI6210, say Y and read the Ethernet-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto .
+  available from http://www.linuxdoc.org/docs.html#howto .
 
   Note that the answer to this question doesn't directly affect the
   kernel: saying N will just cause this configure script to skip all
@@ -6564,7 +6593,7 @@
 CONFIG_NI5010
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Note that this is still
+  http://www.linuxdoc.org/docs.html#howto . Note that this is still
   experimental code.
 
   This driver is also available as a module ( = code which can be
@@ -6577,7 +6606,7 @@
 CONFIG_NI52
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6589,7 +6618,7 @@
 CONFIG_NI65
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6602,7 +6631,7 @@
   This is a driver for the Fast Ethernet PCI network cards based on
   the RTL8129 and RTL8139 chips. If you have one of those, say Y and
   read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   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),
@@ -6712,7 +6741,7 @@
 CONFIG_LANCE
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Some LinkSys cards are
+  http://www.linuxdoc.org/docs.html#howto . Some LinkSys cards are
   of this type.
 
   If you want to compile this driver as a module ( = code which can be
@@ -6724,7 +6753,7 @@
 CONFIG_NET_VENDOR_3COM
   If you have a network (Ethernet) card belonging to this class, say Y
   and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   Note that the answer to this question doesn't directly affect the
   kernel: saying N will just cause this configure script to skip all
@@ -6735,7 +6764,7 @@
 CONFIG_EL1
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Also, consider buying a
+  http://www.linuxdoc.org/docs.html#howto . Also, consider buying a
   new card, since the 3c501 is slow, broken, and obsolete: you will
   have problems. Some people suggest to ping ("man ping") a nearby
   machine every minute ("man cron") when using this card.
@@ -6750,7 +6779,7 @@
 CONFIG_EL2
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6763,7 +6792,7 @@
   Information about this network (Ethernet) card can be found in
   Documentation/networking/3c505.txt. If you have a card of this type,
   say Y and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -6775,7 +6804,7 @@
 CONFIG_EL16
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6787,7 +6816,7 @@
 CONFIG_ELMC
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6799,7 +6828,7 @@
 CONFIG_ELMC_II
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6811,7 +6840,7 @@
 CONFIG_EL3
   If you have a network (Ethernet) card belonging to the 3Com
   EtherLinkIII series, say Y and read the Ethernet-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto .
+  from http://www.linuxdoc.org/docs.html#howto .
 
   If your card is not working you may need to use the DOS
   setup disk to disable Plug & Play mode, and to select the default
@@ -6828,7 +6857,7 @@
   If you have a 3Com "Vortex" (Fast EtherLink 3c590/3c592/3c595/3c597)
   or "Boomerang" series (EtherLink XL 3c900 or 3c905) network
   (Ethernet) card, say Y and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . More specific
+  http://www.linuxdoc.org/docs.html#howto . More specific
   information is in Documentation/networking/vortex.txt and in the
   comments at the beginning of drivers/net/3c59x.c.
 
@@ -6843,7 +6872,7 @@
   bus system (that's the way the cards talks to the other components
   of your computer) is ISA (as opposed to EISA, VLB or PCI), say Y.
   Make sure you know the name of your card. Read the Ethernet-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto . 
+  available from http://www.linuxdoc.org/docs.html#howto . 
 
   If unsure, say Y.
 
@@ -6863,7 +6892,7 @@
   support" below.
 
   You might also want to have a look at the Ethernet-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto (even though ARCnet
+  from http://www.linuxdoc.org/docs.html#howto (even though ARCnet
   is not really Ethernet).
 
   This driver is also available as a module ( = code which can be
@@ -6951,7 +6980,7 @@
 CONFIG_E2100
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -6964,7 +6993,7 @@
   Support for CS89x0 chipset based Ethernet cards. If you have a
   network (Ethernet) card of this type, say Y and read the
   Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto as well as
+  http://www.linuxdoc.org/docs.html#howto as well as
   Documentation/networking/cs89x0.txt.
 
   If you want to compile this as a module ( = code which can be
@@ -6977,7 +7006,7 @@
 CONFIG_DEPCA
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto as well as
+  http://www.linuxdoc.org/docs.html#howto as well as
   drivers/net/depca.c.
 
   If you want to compile this as a module ( = code which can be
@@ -6992,7 +7021,7 @@
   cards. If this is for you, say Y and read
   Documentation/networking/ewrk3.txt in the kernel source as well as
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -7004,7 +7033,7 @@
 CONFIG_SEEQ8005
   This is a driver for the SEEQ 8005 network (Ethernet) card. If this
   is for you, read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -7016,7 +7045,7 @@
 CONFIG_AT1700
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7029,7 +7058,7 @@
 CONFIG_FMV18X
   If you have a Fujitsu FMV-181/182/183/184 network (Ethernet) card,
   say Y and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you use an FMV-183 or FMV-184 and it is not working, you may need
   to disable Plug & Play mode of the card.
@@ -7045,7 +7074,7 @@
   If you have a network (Ethernet) card of this type, say Y. Note
   however that the EtherExpress PRO/100 Ethernet card has its own
   separate driver. Please read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7057,7 +7086,7 @@
 CONFIG_EEXPRESS
   If you have an EtherExpress16 network (Ethernet) card, say Y and
   read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Note that the Intel
+  http://www.linuxdoc.org/docs.html#howto . Note that the Intel
   EtherExpress16 card used to be regarded as a very poor choice
   because the driver was very unreliable. We now have a new driver
   that should do better.
@@ -7072,7 +7101,7 @@
 CONFIG_HPLAN_PLUS
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7084,7 +7113,7 @@
 CONFIG_HPLAN
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7096,7 +7125,7 @@
 CONFIG_HP100
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -7108,7 +7137,7 @@
 CONFIG_NE2000
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Many Ethernet cards
+  http://www.linuxdoc.org/docs.html#howto . Many Ethernet cards
   without a specific driver are compatible with NE2000.
 
   If you have a PCI NE2000 card however, say N here and Y to "PCI
@@ -7127,13 +7156,13 @@
 CONFIG_SK_G16
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
 NE/2 (ne2000 MCA version) support
 CONFIG_NE2_MCA
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7160,7 +7189,7 @@
 CONFIG_NET_EISA
   This is another class of network cards which attach directly to the
   bus. If you have one of those, say Y and read the Ethernet-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto .
+  available from http://www.linuxdoc.org/docs.html#howto .
 
   Note that the answer to this question doesn't directly affect the
   kernel: saying N will just cause this configure script to skip all
@@ -7172,7 +7201,7 @@
 CONFIG_PCNET32
   If you have a PCnet32 or PCnetPCI based network (Ethernet) card,
   answer Y here and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7184,7 +7213,7 @@
 CONFIG_AC3200
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7196,7 +7225,7 @@
 CONFIG_LNE390
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7208,7 +7237,7 @@
 CONFIG_NE3210
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Note that this driver
+  http://www.linuxdoc.org/docs.html#howto . Note that this driver
   will NOT WORK for NE3200 cards as they are completely different.
 
   This driver is also available as a module ( = code which can be
@@ -7221,7 +7250,7 @@
 CONFIG_APRICOT
   If you have a network (Ethernet) controller of this type, say Y and
   read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -7235,7 +7264,7 @@
   These include the DE425, DE434, DE435, DE450 and DE500 models. If
   you have a network card of this type, say Y and read the
   Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . More specific
+  http://www.linuxdoc.org/docs.html#howto . More specific
   information is contained in Documentation/networking/de4x5.txt.
 
   This driver is also available as a module ( = code which can be
@@ -7253,7 +7282,7 @@
   (smc9332dst), you can also try the driver for "Generic DECchip"
   cards, above. However, most people with a network card of this type
   will say Y here.) Do read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . More specific
+  http://www.linuxdoc.org/docs.html#howto . More specific
   information is contained in Documentation/networking/tulip.txt.
 
   This driver is also available as a module ( = code which can be
@@ -7268,7 +7297,7 @@
   PCI/EISA Ethernet switch cards. These include the SE-4 and the SE-6
   models. If you have a network card of this type, say Y and read the
   Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . More specific
+  http://www.linuxdoc.org/docs.html#howto . More specific
   information is contained in Documentation/networking/dgrs.txt.
 
   This driver is also available as a module ( = code which can be
@@ -7281,7 +7310,7 @@
 CONFIG_EEXPRESS_PRO100
   If you have an Intel EtherExpress PRO/100 PCI network (Ethernet)
   card, say Y and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7293,7 +7322,7 @@
 CONFIG_ETH16I
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7306,7 +7335,7 @@
   If you have a PCI Ethernet network card based on the ThunderLAN chip
   which is supported by this driver, say Y and read the
   Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   Devices currently supported by this driver are Compaq Netelligent,
   Compaq NetFlex and Olicom cards. Please read the file
@@ -7335,7 +7364,7 @@
 CONFIG_ES3210
   If you have a network (Ethernet) card of this type, say Y and read
   the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7347,7 +7376,7 @@
 CONFIG_EPIC100
   If you have an SMC EtherPower II 9432 PCI Ethernet network card
   which is based on the SMC83c170, say Y and read the Ethernet-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#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).
@@ -7366,13 +7395,13 @@
   (Ethernet) card, and this is the Linux driver for it. Note that the
   IBM Thinkpad 300 is compatible with the Z-Note and is also supported
   by this driver. Read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
 Adaptec Starfire support
 CONFIG_ADAPTEC_STARFIRE
   If you have an Ethernet network card like this, say Y and read the
   Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7385,7 +7414,7 @@
   Cute little network (Ethernet) devices which attach to the parallel
   port ("pocket adapters"), commonly used with laptops. If you have
   one of those, say Y and read the Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to plug a network (or some other) card into the PCMCIA
   (or PC-card) slot of your laptop instead (PCMCIA is the standard for
@@ -7405,7 +7434,7 @@
 CONFIG_ATP
   This is a network (Ethernet) device which attaches to your parallel
   port. Read drivers/net/atp.c as well as the Ethernet-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto , if you
+  available from http://www.linuxdoc.org/docs.html#howto , if you
   want to use this. If you intend to use this driver, you should have
   said N to the Parallel Printer support, because the two drivers
   don't like each other.
@@ -7415,7 +7444,7 @@
   This is a network (Ethernet) device which attaches to your parallel
   port. Read Documentation/networking/DLINK.txt as well as the
   Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , if you want to use
+  http://www.linuxdoc.org/docs.html#howto , if you want to use
   this. It is possible to have several devices share a single parallel
   port and it is safe to compile the corresponding drivers into the
   kernel.
@@ -7430,7 +7459,7 @@
   This is a network (Ethernet) device which attaches to your parallel
   port. Read Documentation/networking/DLINK.txt as well as the
   Ethernet-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , if you want to use
+  http://www.linuxdoc.org/docs.html#howto , if you want to use
   this. It is possible to have several devices share a single parallel
   port and it is safe to compile the corresponding drivers into the
   kernel.
@@ -7448,14 +7477,14 @@
   connected to such a Token Ring network and want to use your Token
   Ring card under Linux, say Y here and to the driver for your
   particular card below and read the Token-Ring mini-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto . Most people can
+  from http://www.linuxdoc.org/docs.html#howto . Most people can
   say N here.
 
 IBM Tropic chipset based adapter support
 CONFIG_IBMTR
   This is support for all IBM Token Ring cards that don't use DMA. If
   you have such a beast, say Y and read the Token-Ring mini-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto .
+  available from http://www.linuxdoc.org/docs.html#howto .
 
   Warning: this driver will almost definitely fail if more than one
   active Token Ring card is present. 
@@ -7473,7 +7502,7 @@
 
   If you have such an adapter, say Y and read the Token-Ring
   mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  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).
@@ -7495,7 +7524,7 @@
 
   If you have such an adapter and would like to use it, say Y or M and
   read the Token-Ring mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   Also read the file linux/Documentation/networking/tms380tr.txt or check
   http://www.auk.cx/tms380tr/
@@ -7507,7 +7536,7 @@
 
   If you have such an adapter and would like to use it, say Y or M and
   read the Token-Ring mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
 Traffic Shaper (EXPERIMENTAL)
 CONFIG_SHAPER
@@ -7598,7 +7627,7 @@
 CONFIG_CD_NO_IDESCSI
   If you have a CDROM drive that is neither SCSI nor IDE/ATAPI, say Y
   here, otherwise N. Read the CDROM-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   Note that the answer to this question doesn't directly affect the
   kernel: saying N will just cause this configure script to skip all
@@ -7865,10 +7894,10 @@
   usage (also called disk quotas). Currently, it works only for the
   ext2 filesystem. You need additional software in order to use quota
   support; for details, read the Quota mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . Probably the quota
+  http://www.linuxdoc.org/docs.html#howto . Probably the quota
   support is only useful for multi user systems. If unsure, say N.
 
-Support for USB (EXPERIMENTAL)
+Support for USB
 CONFIG_USB
   Universal Serial Bus (USB) is a specification for a serial bus
   subsystem which offers higher speeds and more features than the
@@ -7892,7 +7921,7 @@
   The module will be called usbcore.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-UHCI (intel PIIX4, VIA, and others) support?
+UHCI (intel PIIX4, VIA, ...) support?
 CONFIG_USB_UHCI
   The Universal Host Controller Interface is a standard by Intel for
   accessing the USB hardware in the PC (which is also called the USB
@@ -7908,17 +7937,17 @@
   The module will be called usb-uhci.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
   
-OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, and others) support?
+OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, ...) support?
 CONFIG_USB_OHCI_HCD
   The Open Host Controller Interface is a standard by
   Compaq/Microsoft/National for accessing the USB PC hardware (also
   called USB host controller). If your USB host controller conforms
   to this standard, say Y. The USB host controllers on most
-  non-Intel architectures and on several x86 compatibles  with non-Intel
-  chipsets - like SiS (aktual 610, 610 and so on) or ALi (ALi IV, ALi V,
-  Aladin Pro..) - conform to this standard.
+  non-Intel architectures and on several x86 compatibles with non-Intel
+  chipsets - like SiS (actual 610, 610 and so on) or ALi (ALi IV, ALi V,
+  Aladdin Pro..) - conform to this standard.
 
-  You may want to read the file drivers/usb/README.ohci_hcd.
+  You may want to read the file Documentation/usb/ohci-hcd.txt.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -7943,6 +7972,19 @@
   USB mouse and prefer to use the mouse in its limited Boot Protocol
   mode. This driver is much smaller than the HID one.
 
+Wacom Graphire tablet support
+CONFIG_USB_GRAPHIRE
+  Say Y here if you want to use the USB version of the Wacom
+  Graphire tablet. Make sure you select Mouse and Event support,
+  don't select HID support, because this driver collides with it.
+  Use HIDBP support for keyboards and mice instead if you need it.
+
+Logitech WingMan Force joystick support
+CONFIG_USB_WMFORCE
+  Say Y here if you want to use the Logitech WingMan Force with Linux
+  on the USB port. No force-feedback support yet, but other than that,
+  it should work like a normal joystick.
+
 Keyboard support
 CONFIG_INPUT_KEYBDEV
   Say Y here if you want your USB HID keyboard to be able to serve as
@@ -7971,29 +8013,18 @@
   under /dev/inputX (misc 64+) in a generic way.
   This is the future ...
 
-USB HID debug output
-CONFIG_USB_HID_DEBUG
-  Say Y here if you want to see what the HID driver is doing,
-  perhaps it's doing something wrong with your device.
-
-USB HID lots of debug output
-CONFIG_USB_HID_DEBUG_LOTS
-  Say Y here if you don't fear to read all the HID dumps the
-  HID driver will generate when you switch this on. Really LOTS
-  of debug output.
-
-USB scanner support
+USB Scanner support
 CONFIG_USB_SCANNER
   Say Y here if you want to connect a USB scanner to your
-  computer's USB port. Please read drivers/usb/README.scanner
-  and drivers/usb/README.scanner_hp_sane for more information.
+  computer's USB port. Please read Documentation/usb/scanner.txt
+  and Documentation/usb/scanner-hp-sane.txt for more information.
 
   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 hp_scanner.o. If you want to compile it as
   a module, say M here and read Documentation/modules.txt.
 
-USB audio parsing support
+USB Audio support
 CONFIG_USB_AUDIO
   Say Y here if you want to connect USB audio equipment such as
   speakers to your computer's USB port.
@@ -8003,28 +8034,55 @@
   The module will be called audio.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-USB Communications Device Class (ACM) support (Preliminary)
+USB Modem (CDC ACM) support
 CONFIG_USB_ACM
-  This driver allows for devices which support the Abstract Control
-  Model, including many USB-based modems, ISDN adapters, and network
-  adapters.
+  This driver supports USB modems and ISDN adapters which support the
+  Communication Device Class Abstract Control Model interface.
 
   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 acm.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-USB serial converter support
+USB Serial converter support
 CONFIG_USB_SERIAL
   Say Y here if you want to connect a Connect Tech WhiteHEAT 
   multi-port USB to serial converter; a Belkin, Peracom, or eTek
   single port USB to serial converter; or a Handspring Visor.
+  Please read Documentation/usb/usb-serial.txt for more information.
 
   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 usb-serial.o. If you want to compile it 
   as a module, say M here and read Documentation/modules.txt.
 
+USB Generic Serial Driver
+CONFIG_USB_SERIAL_GENERIC
+  Say Y here if you want to use the generic USB serial driver.
+  Please read Documentation/usb/usb-serial.txt for more information
+  on using this driver. It is recommended that the USB Serial
+  Driver be compiled as a module for this driver to be used properly.
+
+USB ConnectTech WhiteHEAT Serial Driver
+CONFIG_USB_SERIAL_WHITEHEAT
+  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
+  USB to serial converter device.
+
+USB Handspring Visor Driver
+CONFIG_USB_SERIAL_VISOR
+  Say Y here if you want to connect to your HandSpring Visor through
+  its USB docking station.
+
+USB Belkin Single Port Serial Driver
+CONFIG_USB_SERIAL_BELKIN
+  Say Y here if you want to use a Belkin single port USB to serial 
+  converter device.
+  
+USB Peracom Single Port Serial Driver
+CONFIG_USB_SERIAL_PERACOM
+  Say Y here if you want to use a Peracom single port USB to serial 
+  converter device.
+
 USB Printer support
 CONFIG_USB_PRINTER
   Say Y here if you want to connect a USB printer to your computer's USB
@@ -8059,7 +8117,7 @@
 USB Kodak DC-2xx Camera support
 CONFIG_USB_DC2XX
   Say Y here if you want to connect this type of still camera to
-  your computer's USB port.  See drivers/usb/README.dc2xx for more
+  your computer's USB port.  See Documentation/usb/dc2xx.txt for more
   information; some non-Kodak cameras may also work with this
   driver, given application support (such as www.gPhoto.org).
 
@@ -8068,7 +8126,7 @@
   The module will be called dc2xx.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
-USB SCSI Support
+USB SCSI (mass storage) support
 CONFIG_USB_SCSI
   Say Y here if you want to connect USB mass storage devices to your
   computer's USB port.
@@ -8083,9 +8141,6 @@
   Say Y here in order to have the USB SCSI code generate verbose
   debugging messages.
 
-#EZUSB Firmware downloader
-#CONFIG_USB_EZUSB
-
 USS720 parport driver
 CONFIG_USB_USS720
   This driver is for USB parallel port adapters that use the Lucent
@@ -8113,16 +8168,7 @@
   The module will be called uss720.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
   
-USB /proc filesystem support
-CONFIG_USB_PROC
-  This reports USB drivers and devices in the /proc filesystem.
-  Entries are located in /proc/bus/usb. The entries are described in
-  the file Documentation/proc_usb_info.txt.
-
-  Note that you must say Y to global "/proc filesystem support" under
-  Filesystems for this to work.
-
-USB device file system
+USB device filesystem
 CONFIG_USB_DEVICEFS
   This file system implements a "devices" file, that lists
   the currently connected to your USB busses, a "drivers" file
@@ -8144,7 +8190,7 @@
   inserted in and removed from the running kernel whenever you want).
   The module will be called dabusb.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
-  
+ 
 ACPI support
 CONFIG_ACPI
   Advanced Configuration and Power Interface (ACPI) is an interface
@@ -8189,7 +8235,7 @@
   by about 44 kB.
 
   The Ext2fs-Undeletion mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , gives information about
+  http://www.linuxdoc.org/docs.html#howto , gives information about
   how to retrieve deleted files on ext2fs filesystems.
 
   To change the behavior of ext2 filesystems, you can use the tune2fs
@@ -8239,7 +8285,7 @@
   If you have a CDROM drive and want to do more with it than just
   listen to audio CDs and watch its LEDs, say Y (and read
   Documentation/filesystems/isofs.txt and the CDROM-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto ), thereby
+  from http://www.linuxdoc.org/docs.html#howto ), thereby
   enlarging your kernel by about 27 KB; otherwise say N.
 
   If you want to compile this as a module ( = code which can be
@@ -8318,7 +8364,7 @@
   they are compressed; to access compressed MSDOS partitions under
   Linux, you can either use the DOS emulator DOSEMU, described in the
   DOSEMU-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto , or try dmsdosfs in
+  http://www.linuxdoc.org/docs.html#howto , or try dmsdosfs in
   ftp://metalab.unc.edu/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
@@ -8833,7 +8879,7 @@
   works only if the Windows machines use TCP/IP as the underlying
   transport protocol, and not NetBEUI. For details, read
   Documentation/filesystems/smbfs.txt and the SMB-HOWTO, available
-  from http://metalab.unc.edu/mdw/linux.html#howto .
+  from http://www.linuxdoc.org/docs.html#howto .
 
   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
@@ -8878,7 +8924,7 @@
   mount NetWare file server volumes and to access them just like any
   other Unix directory. For details, please read the file
   Documentation/filesystems/ncpfs.txt in the kernel source and the
-  IPX-HOWTO from http://metalab.unc.edu/mdw/linux.html#howto .
+  IPX-HOWTO from http://www.linuxdoc.org/docs.html#howto .
 
   You do not have to say Y here if you want your Linux box to act as a
   file *server* for Novell NetWare clients.
@@ -9319,7 +9365,7 @@
   bootparam" or see the documentation of your boot loader (lilo or
   loadlin) about how to pass options to the kernel at boot time. The
   lilo procedure is also explained in the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .)
+  http://www.linuxdoc.org/docs.html#howto .)
 
   If unsure, say Y.
 
@@ -9383,7 +9429,7 @@
   your boot loader (lilo or loadlin) about how to pass options to the
   kernel at boot time. The lilo procedure is also explained in the
   SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .)
+  http://www.linuxdoc.org/docs.html#howto .)
 
   If you don't have a VGA card installed and you say Y here, the
   kernel will automatically use the first serial line, /dev/ttyS0, as
@@ -9634,7 +9680,7 @@
   box (as opposed to using a serial printer; if the connector at the
   printer has 9 or 25 holes ["female"], then it's serial), say Y. Also
   read the Printing-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   It is possible to share one parallel port among several devices
   (e.g. printer and ZIP drive) and it is safe to compile the
@@ -9649,7 +9695,7 @@
   or see the documentation of your boot loader (lilo or loadlin) about
   how to pass options to the kernel at boot time. The lilo procedure
   is also explained in the SCSI-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .) The syntax of the "lp"
+  http://www.linuxdoc.org/docs.html#howto .) The syntax of the "lp"
   command line option can be found in drivers/char/lp.c.
 
   If you have more than 3 printers, you need to increase the LP_NO
@@ -9675,7 +9721,7 @@
   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://metalab.unc.edu/mdw/linux.html#howto , and say Y here.
+  http://www.linuxdoc.org/docs.html#howto , and say Y 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
@@ -9698,7 +9744,7 @@
   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://metalab.unc.edu/mdw/linux.html#howto . This HOWTO contains
+  http://www.linuxdoc.org/docs.html#howto . This HOWTO contains
   information about all non-serial mice, not just bus mice.
 
   If you have a laptop, you either have to check the documentation or
@@ -9715,7 +9761,7 @@
   generally a round connector with 9 pins. Note that the newer mice
   made by Logitech don't use the Logitech protocol anymore; for those,
   you don't need this option. You want to read the Busmouse-HOWTO ,
-  available from http://metalab.unc.edu/mdw/linux.html#howto .
+  available from http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -9735,7 +9781,7 @@
 
   Although PS/2 mice are not technically bus mice, they are explained
   in detail in the Busmouse-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   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
@@ -9748,7 +9794,7 @@
   This is a certain kind of PS/2 mouse used on the TI Travelmate. If
   you are unsure, try first to say N here and come back if the mouse
   doesn't work. Read the Busmouse-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
 PC110 digitizer pad support
 CONFIG_PC110_PAD
@@ -9766,7 +9812,7 @@
   These animals (also called Inport mice) are connected to an
   expansion board using a round connector with 9 pins. If this is what
   you have, say Y and read the Busmouse-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you are unsure, say N and read the HOWTO nevertheless: it will
   tell you what you have. Also be aware that several vendors talk
@@ -9782,7 +9828,7 @@
 CONFIG_ADBMOUSE
   Say Y here if you have this type of bus mouse (4 pin connector) as
   is common on Macintoshes. You may want to read the Busmouse-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto .
+  available from http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -9796,7 +9842,7 @@
   most mice by ATI are actually Microsoft busmice; you should say Y to
   "Microsoft busmouse support" above if you have one of those. Read
   the Busmouse-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   If you want to compile this as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
@@ -10228,7 +10274,7 @@
 
   Supporting software is available; for more information, read the
   Battery Powered Linux mini-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto .
+  http://www.linuxdoc.org/docs.html#howto .
 
   This driver does not spin down disk drives (see the hdparm(8)
   manpage ("man 8 hdparm") for that), and it doesn't turn off
@@ -10691,7 +10737,7 @@
   interrupt and DMA channel), because you will be asked for it. 
 
   You want to read the Sound-HOWTO, available from
-  http://metalab.unc.edu/mdw/linux.html#howto . General information
+  http://www.linuxdoc.org/docs.html#howto . General information
   about the modular sound system is contained in the files
   Documentation/sound/Introduction. The file
   Documentation/sound/README.OSS contains some slightly outdated but
@@ -11102,7 +11148,7 @@
   Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
   similar sound card. See Documentation/sound/README.awe,
   Documentation/sound/AWE32 and the Soundblaster-AWE mini-HOWTO,
-  available from http://metalab.unc.edu/mdw/linux.html#howto for more
+  available from http://www.linuxdoc.org/docs.html#howto for more
   info.
 
 Gallant's Audio Excel DSP 16 support (SC-6000 and SC-6600)
@@ -11775,6 +11821,84 @@
 ### Please someone fill these in.
 ###
 
+IEEE 1394 (aka FireWire) support
+CONFIG_IEEE1394
+  IEEE 1394 describes a high performance serial bus, which is also
+  known as FireWire(tm) or i.Link(tm) and is used for connecting all
+  sorts of devices (most notably digital video cameras).
+
+  If you have FireWire hardware and want to use it, say Y here.  This
+  is the core support only, you will also need to select a driver for
+  your IEEE 1394 adapter.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called ieee1394.o.
+
+  FireWire is a trademark by Apple Inc. and i.Link is a trademark by 
+  Sony.
+
+TI PCILynx IEEE 1394 support
+CONFIG_IEEE1394_PCILYNX
+  Say Y here if you have a IEEE-1394 controller with the Texas
+  Instruments PCILynx chip.  Note: this driver is written for revision
+  2 of this chip and may not work with revision 0.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called pcilynx.o.
+
+Use local RAM on PCILynx board
+CONFIG_IEEE1394_PCILYNX_LOCALRAM
+  This option makes the PCILynx driver use local RAM available on some
+  PCILynx setups for Packet Control Lists.  Local RAM may speed up
+  command processing because no PCI transfers are necessary during 
+  use of the Packet Control Lists.
+  
+  Note that there are no known PCILynx systems providing local RAM
+  except for the evaluation boards by Texas Instruments and that the
+  PCILynx does not reliably report missing RAM.
+  
+  Unless you are absolutely sure that you have 64kB of local RAM and
+  that you want to use it or if you don't know what this is all about,
+  say N here.
+
+Adaptec AIC-5800 IEEE 1394 support
+CONFIG_IEEE1394_AIC5800
+  Say Y here if you have a IEEE 1394 controller using the Adaptec
+  AIC-5800 chip. All Adaptec host adapters (89xx series) use this
+  chip, as well as miro's DV boards.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called aic5800.o.
+
+OHCI (Open Host Controller Interface) support
+CONFIG_IEEE1394_OHCI1394
+  Say Y here if you have a IEEE 1394 controller based on OHCI.
+  The current driver was only tested with OHCI chipsets made
+  by Texas Instruments. However, most third-party vendors use
+  TI chips.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called ohci1394.o.
+
+RAW IEEE 1394 I/O support
+CONFIG_IEEE1394_RAWIO
+  Say Y here if you want support for the raw device. This is generally
+  a good idea, so you should say Y here. The raw device enables
+  direct communication of user programs to the IEEE 1394 bus.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called raw1394.o.
+
 #
 # m68k-specific kernel options
 # Documented by Chris Lawrence <quango@themall.net> et al.
@@ -12792,7 +12916,7 @@
   such as "mem=256M". (Try "man bootparam" or see the documentation of
   your boot loader (lilo or loadlin) about how to pass options to the
   kernel at boot time. The lilo procedure is also explained in the
-  SCSI-HOWTO, available from http://metalab.unc.edu/mdw/linux.html#howto .)
+  SCSI-HOWTO, available from http://www.linuxdoc.org/docs.html#howto .)
 
 Math emulation
 CONFIG_NWFPE
@@ -12950,7 +13074,7 @@
   some user-space utilities like the irmanager and probably irattach
   as well. For more information, see the file
   Documentation/networking/irda.txt. You also want to read the
-  IR-HOWTO, available at http://metalab.unc.edu/mdw/linux.html#howto .
+  IR-HOWTO, available at http://www.linuxdoc.org/docs.html#howto .
 
   This support is also available as a module. If you want to compile
   it as a module, say M here and read Documentation/modules.txt.
diff -u --recursive --new-file v2.3.39/linux/Documentation/README.moxa linux/Documentation/README.moxa
--- v2.3.39/linux/Documentation/README.moxa	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/README.moxa	Thu Jan 20 10:44:46 2000
@@ -0,0 +1,18 @@
+ ===================================================================	
+ Release Note of Linux Driver for Moxa's C104/C168/CI-104J
+ ===================================================================	
+
+ -------------------------------------------------------------------
+ Ver. 1.1  				               Sep.  1, 1999
+ -------------------------------------------------------------------
+ 1. Improved:
+   a. Static driver (kernel) and dynamic driver (loadable module) 
+      modes are supported.
+   b. Multiple Smartio PCI series boards sharing the same IRQ 
+      supported.
+
+ -------------------------------------------------------------------
+ Ver. 1.0  				               Feb  17, 1997
+ -------------------------------------------------------------------
+ 1. Newly release.
+
diff -u --recursive --new-file v2.3.39/linux/Documentation/computone.txt linux/Documentation/computone.txt
--- v2.3.39/linux/Documentation/computone.txt	Sun Nov  7 16:37:33 1999
+++ linux/Documentation/computone.txt	Thu Jan 20 10:44:46 2000
@@ -7,7 +7,7 @@
 kernel and have been tested on Linux kernels 2.0, 2.2, and 2.3.
 
 Version: 1.2.4
-Date: 08/04/99
+Date: 12/15/99
 Author: Andrew Manison <amanison@america.net>
 Testing: larryg@computone.com
 Support: support@computone.com
@@ -28,7 +28,7 @@
 products previous to the Intelliport II.
 
 This driver was developed on the v2.0.x Linux tree and has been tested up
-to v2.2.9; it will probably not work with earlier v1.X kernels,.
+to v2.2.13; it will probably not work with earlier v1.X kernels,.
 
 
 2. QUICK INSTALLATION
@@ -204,9 +204,94 @@
 
 7. ip2mkdev shell script
 
-===== Cut Here ===== 
+Previously, this script was simply attached here.  It is now attached as a
+shar archive to make it easier to extract the script from the documentation.
+To create the ip2mkdev shell script change to a convenient directory (/tmp
+works just fine) and run the following command:
+
+	unshar /usr/src/linux/Documentation/computone.txt
+		(This file)
+
+You should now have a file ip2mkdev in your current working directory with
+permissions set to execute.  Running that script with then create the
+necessary devices for the Computone boards, interfaces, and ports which
+are present on you system at the time it is run.
+
+
+#!/bin/sh
+# This is a shell archive (produced by GNU sharutils 4.2).
+# To extract the files from this archive, save it to some FILE, remove
+# everything before the `!/bin/sh' line above, then type `sh FILE'.
+#
+# Made on 1999-12-17 16:06 EST by <root@alcove.wittsend.com>.
+# Source directory was `/mnt2/src/linux-2.3.33/Documentation'.
+#
+# Existing files will *not* be overwritten unless `-c' is specified.
+#
+# This shar contains:
+# length mode       name
+# ------ ---------- ------------------------------------------
+#   3300 -rwxr-xr-x ip2mkdev
+#
+save_IFS="${IFS}"
+IFS="${IFS}:"
+gettext_dir=FAILED
+locale_dir=FAILED
+first_param="$1"
+for dir in $PATH
+do
+  if test "$gettext_dir" = FAILED && test -f $dir/gettext \
+     && ($dir/gettext --version >/dev/null 2>&1)
+  then
+    set `$dir/gettext --version 2>&1`
+    if test "$3" = GNU
+    then
+      gettext_dir=$dir
+    fi
+  fi
+  if test "$locale_dir" = FAILED && test -f $dir/shar \
+     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)
+  then
+    locale_dir=`$dir/shar --print-text-domain-dir`
+  fi
+done
+IFS="$save_IFS"
+if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED
+then
+  echo=echo
+else
+  TEXTDOMAINDIR=$locale_dir
+  export TEXTDOMAINDIR
+  TEXTDOMAIN=sharutils
+  export TEXTDOMAIN
+  echo="$gettext_dir/gettext -s"
+fi
+touch -am 1231235999 $$.touch >/dev/null 2>&1
+if test ! -f 1231235999 && test -f $$.touch; then
+  shar_touch=touch
+else
+  shar_touch=:
+  echo
+  $echo 'WARNING: not restoring timestamps.  Consider getting and'
+  $echo "installing GNU \`touch', distributed in GNU File Utilities..."
+  echo
+fi
+rm -f 1231235999 $$.touch
+#
+if mkdir _sh06360; then
+  $echo 'x -' 'creating lock directory'
+else
+  $echo 'failed to create lock directory'
+  exit 1
+fi
+# ============= ip2mkdev ==============
+if test -f 'ip2mkdev' && test "$first_param" != -c; then
+  $echo 'x -' SKIPPING 'ip2mkdev' '(file already exists)'
+else
+  $echo 'x -' extracting 'ip2mkdev' '(text)'
+  sed 's/^X//' << 'SHAR_EOF' > 'ip2mkdev' &&
 #!/bin/sh -
-
+X
 #	ip2mkdev
 #
 #	Make or remove devices as needed for Computone Intelliport drivers
@@ -227,117 +312,134 @@
 #
 if test ! -f /proc/tty/drivers
 then
-	echo "\
+X	echo "\
 Unable to check driver status.
 Make sure proc file system is mounted."
-
-	exit 255
+X
+X	exit 255
 fi
-
+X
 if test ! -f /proc/tty/driver/ip2
 then
-	echo "\
+X	echo "\
 Unable to locate ip2 proc file.
 Attempting to load driver"
-
-	if insmod ip2
-	then
-		if test ! -f /proc/tty/driver/ip2
-		then
-			echo "\
+X
+X	if /sbin/insmod ip2
+X	then
+X		if test ! -f /proc/tty/driver/ip2
+X		then
+X			echo "\
 Unable to locate ip2 proc file after loading driver.
 Driver initialization failure or driver version error.
 "
-		exit 255
-		fi
-	else
-		echo "Unable to load ip2 driver."
-		exit 255
-	fi
+X		exit 255
+X		fi
+X	else
+X		echo "Unable to load ip2 driver."
+X		exit 255
+X	fi
 fi
-
+X
 # Ok...  So we got the driver loaded and we can locate the procfs files.
 # Next we need our major numbers.
-
+X
 TTYMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/tty/!d' -e 's/.*tty.[ 	]*\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/drivers`
 CUAMAJOR=`sed -e '/^ip2/!d' -e '/\/dev\/cu/!d' -e 's/.*cu.[ 	]*\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/drivers`
 BRDMAJOR=`sed -e '/^Driver: /!d' -e 's/.*IMajor=\([0-9]*\)[ 	]*.*/\1/' < /proc/tty/driver/ip2`
-
+X
 echo "\
 TTYMAJOR = $TTYMAJOR
 CUAMAJOR = $CUAMAJOR
 BRDMAJOR = $BRDMAJOR
 "
-
+X
 # Ok...  Now we should know our major numbers, if appropriate...
 # Now we need our boards and start the device loops.
-
+X
 grep '^Board [0-9]:' /proc/tty/driver/ip2 | while read token number type alltherest
 do
-	# The test for blank "type" will catch the stats lead-in lines
-	# if they exist in the file
-	if test "$type" = "vacant" -o "$type" = "Vacant" -o "$type" = ""
-	then
-		continue
-	fi
-
-	BOARDNO=`expr "$number" : '\([0-9]\):'`
-	PORTS=`expr "$alltherest" : '.*ports=\([0-9]*\)' | tr ',' ' '`
-	MINORS=`expr "$alltherest" : '.*minors=\([0-9,]*\)' | tr ',' ' '`
-
-	if test "$BOARDNO" = "" -o "$PORTS" = ""
-	then
+X	# The test for blank "type" will catch the stats lead-in lines
+X	# if they exist in the file
+X	if test "$type" = "vacant" -o "$type" = "Vacant" -o "$type" = ""
+X	then
+X		continue
+X	fi
+X
+X	BOARDNO=`expr "$number" : '\([0-9]\):'`
+X	PORTS=`expr "$alltherest" : '.*ports=\([0-9]*\)' | tr ',' ' '`
+X	MINORS=`expr "$alltherest" : '.*minors=\([0-9,]*\)' | tr ',' ' '`
+X
+X	if test "$BOARDNO" = "" -o "$PORTS" = ""
+X	then
 #	This may be a bug.  We should at least get this much information
-		echo "Unable to process board line"
-		continue
-	fi
-
-	if test "$MINORS" = ""
-	then
+X		echo "Unable to process board line"
+X		continue
+X	fi
+X
+X	if test "$MINORS" = ""
+X	then
 #	Silently skip this one.  This board seems to have no boxes
-		continue
-	fi
-
-	echo "board $BOARDNO: $type ports = $PORTS; port numbers = $MINORS"
-
-	if test "$BRDMAJOR" != ""
-	then
-		BRDMINOR=`expr $BOARDNO \* 4`
-		STSMINOR=`expr $BRDMINOR + 1`
-		if test ! -c /dev/ip2ipl$BOARDNO ; then
-			mknod /dev/ip2ipl$BOARDNO c $BRDMAJOR $BRDMINOR
-		fi
-		if test ! -c /dev/ip2stat$BOARDNO ; then
-			mknod /dev/ip2stat$BOARDNO c $BRDMAJOR $STSMINOR
-		fi
-	fi
-
-	if test "$TTYMAJOR" != ""
-	then
-		PORTNO=$BOARDBASE
-
-		for PORTNO in $MINORS
-		do
-			if test ! -c /dev/ttyF$PORTNO ; then
-				# We got the harware but no device - make it
-				mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
-			fi	
-		done
-	fi
-
-	if test "$CUAMAJOR" != ""
-	then
-		PORTNO=$BOARDBASE
-
-		for PORTNO in $MINORS
-		do
-			if test ! -c /dev/cuf$PORTNO ; then
-				# We got the harware but no device - make it
-				mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
-			fi	
-		done
-	fi
+X		continue
+X	fi
+X
+X	echo "board $BOARDNO: $type ports = $PORTS; port numbers = $MINORS"
+X
+X	if test "$BRDMAJOR" != ""
+X	then
+X		BRDMINOR=`expr $BOARDNO \* 4`
+X		STSMINOR=`expr $BRDMINOR + 1`
+X		if test ! -c /dev/ip2ipl$BOARDNO ; then
+X			mknod /dev/ip2ipl$BOARDNO c $BRDMAJOR $BRDMINOR
+X		fi
+X		if test ! -c /dev/ip2stat$BOARDNO ; then
+X			mknod /dev/ip2stat$BOARDNO c $BRDMAJOR $STSMINOR
+X		fi
+X	fi
+X
+X	if test "$TTYMAJOR" != ""
+X	then
+X		PORTNO=$BOARDBASE
+X
+X		for PORTNO in $MINORS
+X		do
+X			if test ! -c /dev/ttyF$PORTNO ; then
+X				# We got the harware but no device - make it
+X				mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO
+X			fi	
+X		done
+X	fi
+X
+X	if test "$CUAMAJOR" != ""
+X	then
+X		PORTNO=$BOARDBASE
+X
+X		for PORTNO in $MINORS
+X		do
+X			if test ! -c /dev/cuf$PORTNO ; then
+X				# We got the harware but no device - make it
+X				mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO
+X			fi	
+X		done
+X	fi
 done
-
+X
+Xexit 0
+SHAR_EOF
+  $shar_touch -am 1217160599 'ip2mkdev' &&
+  chmod 0755 'ip2mkdev' ||
+  $echo 'restore of' 'ip2mkdev' 'failed'
+  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+    || $echo 'ip2mkdev:' 'MD5 check failed'
+eccd181f4a2005e47a969fc83885df61  ip2mkdev
+SHAR_EOF
+  else
+    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'ip2mkdev'`"
+    test 3300 -eq "$shar_count" ||
+    $echo 'ip2mkdev:' 'original size' '3300,' 'current size' "$shar_count!"
+  fi
+fi
+rm -fr _sh06360
 exit 0
-===== Cut Here ===== 
diff -u --recursive --new-file v2.3.39/linux/Documentation/fb/framebuffer.txt linux/Documentation/fb/framebuffer.txt
--- v2.3.39/linux/Documentation/fb/framebuffer.txt	Fri Jan  7 19:13:21 2000
+++ linux/Documentation/fb/framebuffer.txt	Tue Jan 11 11:53:33 2000
@@ -29,9 +29,9 @@
 minor numbers):
 
       0 = /dev/fb0	First frame buffer
-     32 = /dev/fb1	Second frame buffer
+      1 = /dev/fb1	Second frame buffer
 	  ...
-    224 = /dev/fb7	8th frame buffer
+     31 = /dev/fb31	32nd frame buffer
 
 For backwards compatibility, you may want to create the following symbolic
 links:
diff -u --recursive --new-file v2.3.39/linux/Documentation/filesystems/cramfs.txt linux/Documentation/filesystems/cramfs.txt
--- v2.3.39/linux/Documentation/filesystems/cramfs.txt	Wed Dec 29 13:13:12 1999
+++ linux/Documentation/filesystems/cramfs.txt	Tue Jan 11 10:24:58 2000
@@ -11,3 +11,43 @@
 You can't write to a cramfs filesystem (making it compressible and
 compact also makes it _very_ hard to update on-the-fly), so you have to
 create the disk image with the "mkcramfs" utility in scripts/cramfs.
+
+
+Usage Notes
+-----------
+
+File sizes are limited to less than 16MB.
+
+Maximum filesystem size is a little over 256MB.  (The last file on the
+filesystem is allowed to extend past 256MB.)  (Comments in mkcramfs.c
+suggest that ROM sizes may be limited to 64MB, though that's not a
+limitation in cramfs code.)
+
+Only the low 8 bits of gid are stored.  The current version of
+mkcramfs simply truncates to 8 bits, which is a potential security
+issue.
+
+Hard links are not supported, but symlinks are.  (See also the TODO
+comment in mkcramfs.c at the nlink test.)
+
+Cramfs directories have no `.' or `..' entries.  Directories (like
+every other file on cramfs) always have a link count of 1.  (There's
+no need to use -noleaf in `find', btw.)
+
+No timestamps are stored in a cramfs, so these default to the epoch
+(1970 GMT).  Recently-accessed files may have updated timestamps, but
+the update lasts only as long as the inode is cached in memory, after
+which the timestamp reverts to 1970, i.e. moves backwards in time.
+
+Currently, cramfs must be written and read with architectures of the
+same endianness, and can be read only by kernels with PAGE_CACHE_SIZE
+== 4096.  At least the latter of these is a bug, but it hasn't been
+decided what the best fix is.  For the moment if you have larger pages
+you can just change the #define in mkcramfs.c, so long as you don't
+mind the filesystem becoming unreadable to future kernels.
+
+
+Hacker Notes
+------------
+
+See fs/cramfs/README for filesystem layout and implementation notes.
diff -u --recursive --new-file v2.3.39/linux/Documentation/highuid.txt linux/Documentation/highuid.txt
--- v2.3.39/linux/Documentation/highuid.txt	Tue Jan 11 22:31:36 2000
+++ linux/Documentation/highuid.txt	Wed Jan 12 10:10:10 2000
@@ -17,11 +17,6 @@
   properly with huge UIDs. If it can deal with 64-bit file offsets on all 
   architectures, this should not be a problem.
 
-- Decide on a final layout for the new msqid64_ds, semid64_ds, and
-  shmid64_ds, and shminfo64 structures. The current ones leave pad space
-  for 64-bit time_t and 32-bit pid_t, as well as 4 extra machine words.
-  Perhaps more pad space should be left for future use?
-
 - Decide whether or not to keep backwards compatibility with the system
   accounting file, or if we should break it as the comments suggest
   (currently, the old 16-bit UID and GID are still written to disk, and
@@ -33,7 +28,7 @@
   uses the 32-bit UID system calls properly otherwise.
 
   This affects at least:
-	SunOS emulation - now fixed?
+	SunOS emulation
 	Solaris emulation
 	iBCS on Intel
 
@@ -62,8 +57,8 @@
 
   Other filesystems have not been checked yet.
 
-- The ncpfs and smpfs filesystems can not presently return 32-bit UIDs to
-  all ioctl()s. Some new ioctl()s have been added for 32-bit UIDs, but
+- The ncpfs and smpfs filesystems can not presently use 32-bit UIDs in
+  all ioctl()s. Some new ioctl()s have been added with 32-bit UIDs, but
   more are needed. (as well as new user<->kernel data structures)
 
 - The ELF core dump format only supports 16-bit UIDs on arm, i386, m68k,
@@ -76,3 +71,9 @@
 - make sure that the UID mapping feature of AX25 networking works properly
   (it should be safe because it's always used a 32-bit integer to
   communicate between user and kernel)
+
+
+Chris Wing
+wingc@umich.edu
+
+last updated: January 11, 2000
diff -u --recursive --new-file v2.3.39/linux/Documentation/ide.txt linux/Documentation/ide.txt
--- v2.3.39/linux/Documentation/ide.txt	Tue Dec 14 01:27:23 1999
+++ linux/Documentation/ide.txt	Fri Jan 14 00:50:53 2000
@@ -1,4 +1,4 @@
-ide.txt -- Information regarding the Enhanced IDE drive in Linux 2.1/2.2
+ide.txt -- Information regarding the Enhanced IDE drive in Linux 2.2/2.3/2.4
 ===============================================================================
 
    +-----------------------------------------------------------------+
diff -u --recursive --new-file v2.3.39/linux/Documentation/kernel-docs.txt linux/Documentation/kernel-docs.txt
--- v2.3.39/linux/Documentation/kernel-docs.txt	Mon May 10 13:00:10 1999
+++ linux/Documentation/kernel-docs.txt	Thu Jan 20 10:44:46 2000
@@ -1,15 +1,14 @@
 
-   
- INDEX OF DOCUMENTATION FOR PEOPLE INTERESTED IN WRITING AND/OR UNDERSTANDING
-                               THE LINUX KERNEL.
-                                       
-		Juan-Mariano de Goyeneche <jmseyas@dit.upm.es>
-   
-   
-   /*
-    * The latest version of this document may be found at: 
-    *   http://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
-    */
+       Index of Documentation for People Interested in Writing and/or
+                                      
+                      Understanding the Linux Kernel.
+                                      
+              Juan-Mariano de Goyeneche < jmseyas@dit.upm.es>
+                                      
+/*
+ * The latest version of this document may be found at:
+ *   http://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
+ */
 
    The need for a document like this one became apparent in the
    linux-kernel mailing list as the same questions, asking for pointers
@@ -31,301 +30,409 @@
    corrections, ideas or comments are also welcomed.
    
    The papers that follow are listed in no particular order. All are
-   catalogued with the following fields: the document's "Title", the
-   "Author"/s, the "URL" where they can be found, some "Keywords"
-   helpful when searching for specific topics, and a brief "Description"
-   of the Document.
+   cataloged with the following fields: the document's "Title", the
+   "Author"/s, the "URL" where they can be found, some "Keywords" helpful
+   when searching for specific topics, and a brief "Description" of the
+   Document.
    
    Enjoy!
    
-   
-   ON-LINE DOCS:
-   
-          + Title: "The Linux Kernel"
-            Author: David A. Rusling.
-            URL: http://sunsite.unc.edu/linux/LDP/tlk/tlk.html
-            Keywords: everything!, book.
-            Description: On line, 200 pages book describing most
-            aspects of the Linux Kernel. Probably, the first reference
-            for beginners. Lots of illustrations explaining data
-            structures use and relationships in the purest Richard W.
-            Stevens' style. Contents: "1.-Hardware Basics, 2.-Software
-            Basics, 3.-Memory Management, 4.-Processes, 5.-Interprocess
-            Communication Mechanisms, 6.-PCI, 7.-Interrupts and Interrupt
-            Handling, 8.-Device Drivers, 9.-The File system,
-            10.-Networks, 11.-Kernel Mechanisms, 12.-Modules, 13.-The
-            Linux Kernel Sources, A.-Linux Data Structures, B.-The Alpha
-            AXP Processor, C.-Useful Web and FTP Sites, D.-The GNU
-            General Public License, Glossary". In short: a must have.
-   
-          + Title: "The Linux Kernel Hackers' Guide"
-            Author: Michael K.Johnson and others.
-            URL: http://www.redhat.com:8080/HyperNews/get/khg.html
-            Keywords: everything!
-            Description: No more Postscript book-like version. Only
-            HTML now. Many people have contributed. The interface is
-            similar to web available mailing lists archives. You can find
-            some articles and then some mails asking questions about them
-            and/or complementing previous contributions. A little bit
-            anarchic in this aspect, but with some valuable information
-            in some cases.
-       
-          + Title: "Tour Of the Linux Kernel Source"
-            Author: Vijo Cherian.
-            URL: http://www.svrec.ernet.in/~vijo/tolks/tolks.html
-            Keywords:
-            Description: The name says it all. A tour of the sources,
-            describing directories, files, variables, data structures...
-            It covers general stuff, device drivers, filesystems, IPC and
-            Network Code.
-       
-          + Title: "Overview of the Virtual File System"
-            Author: Richard Gooch.
-            URL: http://www.atnf.csiro.au/~rgooch/linux/vfs.txt
-            Keywords: VFS, File System, mounting filesystems, opening
-            files, dentries,
-            dcache. Description: Brief introduction to the Linux
-            Virtual File System. What is it, how it works, operations
-            taken when opening a file or mounting a file system and
-            description of important data structures explaining the
-            purpose of each of their entries.
-   
-          + Title: "The Linux RAID-1, 4, 5 Code"
-            Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
-            URL: http://www.ssc.com/lj/issue44/2391.html
-            Keywords: RAID, MD driver.
-            Description: Linux Journal Kernel Korner article. Here is
-            it's abstract: "A description of the implementation of the
-            RAID-1, RAID-4 and RAID-5 personalities of the MD device
-            driver in the Linux kernel, providing users with high
-            performance and reliable, secondary-storage capability using
-            software".
-   
-          + Title: "Dynamic Kernels: Modularized Device Drivers"
-            Author: Alessandro Rubini.
-            URL: http://www.ssc.com/lj/issue23/1219.html
-            Keywords: device driver, module, loading/unloading modules,
-            allocating
-            resources. Description: Linux Journal Kernel Korner
-            article. Here is it's abstract: "This is the first of a
-            series of four articles co-authored by Alessandro Rubini and
-            Georg Zezchwitz which present a practical approach to writing
-            Linux device drivers as kernel loadable modules. This
-            installment presents an introduction to the topic, preparing
-            the reader to understand next month's installment".
-   
-          + Title: "Dynamic Kernels: Discovery"
-            Author: Alessandro Rubini.
-            URL: http://www.ssc.com/lj/issue24/kk24.html
-            Keywords: character driver, init_module, clean_up module,
-            autodetection,
-            mayor number, minor number, file operations, open(), close().
-            Description: Linux Journal Kernel Korner article. Here is
-            it's abstract: "This article, the second of four, introduces
-            part of the actual code to create custom module implementing
-            a character device driver. It describes the code for module
-            initialization and cleanup, as well as the open() and close()
-            system calls".
-   
-          + Title: "The Devil's in the Details"
-            Author: Georg v. Zezschwitz and Alessandro Rubini.
-            URL: http://www.ssc.com/lj/issue25/kk25.html
-            Keywords: read(), write(), select(), ioctl(), blocking/non
-            blocking mode,
-            interrupt handler. Description: Linux Journal Kernel Korner
-            article. Here is it's abstract: "This article, the third of
-            four on writing character device drivers, introduces concepts
-            of reading, writing, and using ioctl-calls".
-   
-          + Title: "Dissecting Interrupts and Browsing DMA"
-            Author: Alessandro Rubini and Georg v. Zezschwitz.
-            URL: http://www.ssc.com/lj/issue26/interrupt.html
-            Keywords: interrupts, irqs, DMA, bottom halves, task
-            queues.
-            Description: Linux Journal Kernel Korner article. Here is
-            it's abstract: "This is the fourth in a series of articles
-            about writing character device drivers as loadable kernel
-            modules. This month, we further investigate the field of
-            interrupt handling. Though it is conceptually simple,
-            practical limitations and constraints make this an
-            ``interesting'' part of device driver writing, and several
-            different facilities have been provided for different
-            situations. We also investigate the complex topic of DMA".
-   
-          + Title: "Network Buffers And Memory Management"
-            Author: Alan Cox.
-            URL: http://www.ssc.com/lj/issue30/kk30.html
-            Keywords: sk_buffs, network devices, protocol/link layer
-            variables, network
-            devices flags, transmit, receive, configuration, multicast.
-            Description: Linux Journal Kernel Korner. Here is the
-            abstract: "Writing a network device driver for Linux is
-            fundamentally simple---most of the complexity (other than
-            talking to the hardware) involves managing network packets in
-            memory".
-       
-          + Title: "An Introduction to the Linux 1.3.x Networking Code"
-            Author: Vipul Gupta.
-            URL:
-            http://anchor.cs.binghamton.edu/courses/cs628/linux-net.html
-            Keywords: files, sk_buffs.
-            Description: A short description of files under the net/
-            directory. Each file has a one- or two-line paragraph to
-            describe it. Also, sk_buffs is explained with some
-            beautiful pictures. A little bit outdated.
-   
-          + Title: "Linux ioctl() Primer"
-            Author: Vipul Gupta.
-            URL:
-            http://anchor.cs.binghamton.edu/courses/cs628/ioctl.html
-            Keywords: ioctl, socket.
-            Description: Little description and examples on the use and
-            implementation of the ioctl() system call. A little bit
-            biased towards sockets.
-       
-          + Title: "Writing Linux Device Drivers"
-            Author: Michael K. Johnson.
-            URL: http://www.redhat.com/~johnsonm/devices.html
-            Keywords: files, VFS, file operations, kernel interface,
-            character vs
-            block devices, I/O access, hardware interrupts, DMA, access
-            to user memory, memory allocation, timers. Description:
-            Introductory 50-minutes (sic) tutorial on writing device
-            drivers. 12 pages written by the same author of the "Kernel
-            Hackers' Guide" which give a very good overview of the topic.
-   
-          + Title: "The Venus kernel interface"
-            Author: Peter J. Braam.
-            URL:
-            http://www.coda.cs.cmu.edu/doc/html/kernel-venus-protocol.html
-            Keywords: coda, filesystem, venus, cache manager.
-            Description: "This document describes the communication
-            between Venus and kernel level file system code needed for
-            the operation of the Coda filesystem. This version document
-            is meant to describe the current interface (version 1.0) as
-            well as improvements we envisage".
-       
-          + Title: "Programming PCI-Devices under Linux"
-            Author: Claus Schroeter.
-            URL:
-            ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/pc
-            ip.ps.gz
-            Keywords: PCI, device, busmastering.
-            Description: 6 pages tutorial on PCI programming under
-            Linux. Gives the basic concepts on the architecture of the
-            PCI subsystem, as long as basic functions and macros to
-            read/write the devices and perform busmastering.
-       
-          + Title: "Writing Character Device Driver for Linux"
-            Author: R. Baruch and C. Schroeter.
-            URL:
-            ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/dr
-            ivers.ps.gz
-            Keywords: character device drivers, I/O, signals, DMA,
-            accessing ports in user space, kernel environment.
-            Description: 68 pages paper on writing character drivers. A
-            little bit old (1.993, 1.994) although still useful.
-       
-       
-       
-     * BOOKS: (Not on-line)
-       
-          + Title: "Linux Device Drivers"
-            Author: Alessandro Rubini.
-            Publisher: O'Reilly &Associates.
-            Date: 1998.
-            ISBN: 1-56592-292-1
-       
-          + Title: "Linux Kernel Internals"
-            Author: Michael Beck.
-            Publisher: Addison-Wesley.
-            Date: 1997.
-            ISBN: 0-201-33143-8 (second edition)
-       
-          + Title: "The Design of the UNIX Operating System"
-            Author: Maurice J. Bach.
-            Publisher: Prentice Hall.
-            Date: 1986.
-            ISBN: ???
-   
-          + Title: "The Design and Implementation of the 4.3 BSD UNIX
-            Operating System"
-            Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael
-            J. Karels, John S. Quarterman.
-            Publisher: Addison-Wesley.
-            Date: 1989 (reprinted with corrections on October, 1990).
-            ISBN: 0-201-06196-1
-       
-          + Title: "The Design and Implementation of the 4.4 BSD UNIX
-            Operating System"
-            Author: Marshall Kirk McKusick, Keith Bostic, Michael J.
-            Karels, John S. Quarterman.
-            Publisher: Addison-Wesley.
-            Date: 1996.
-            ISBN: 0-201-54979-4
-   
-          + Title: "Programmation Linux 2.0 API systeme et
-            fonctionnement du noyau"
-            Author: Remy Card, Eric Dumas, Franck Mevel.
-            Publisher: Eyrolles.
-            Date: 1997.
-            Pages: 520. ISBN: 2-212-08932-5
-       
-          + Title: "Unix internals -- the new frontiers"
-            Author: Uresh Vahalia.
-            Publisher: Prentice Hall.
-            Date: 1996.
-            Pages: 600. ISBN: 0-13-101908-2
-   
-       
-     * MISCELLANEOUS:
+     ON-LINE DOCS:
        
-          + Name: Linux Source Driver.
-            URL: http://lsd.linux.cz
-            Keywords: Browsing.
-            Description: "Linux Source Driver (LSD) is an application,
-            which can make browsing source codes of Linux kernel easier
-            than you can imagine. You can select between multiple
-            versions of kernel (e.g. 0.01, 1.0.0, 2.0.33, 2.0.34pre13,
-            2.0.0, 2.1.101 etc.). With LSD you can search Linux kernel
-            (fulltext, macros, types, functions and variables) and LSD
-            can generate patches for you on the fly (files, directories
-            or kernel)".
-       
-          + Name: Linux Weekly News.
-            URL: http://lwn.net
-            Keywords: last kernel news.
-            Description: The title says it all. There's a fixed kernel
-            section summarizing developers' work, bug fixes, new features
-            and versions produced during the week. Published every
-            Thursday.
-       
-          + Name: CuTTiNG.eDGe.LiNuX.
-            URL: http://edge.linuxhq.com
-            Keywords: changelist.
-            Description: Site which provides the changelist for every
-            kernel release. What's new, what's better, what's changed.
-            Myrdraal reads the patchs and describes them. Pointers to the
-            patches are there, too.
+     * Title: "The Linux Kernel"
+       Author: David A. Rusling.
+       URL: http://sunsite.unc.edu/linux/LDP/tlk/tlk.html
+       Keywords: everything!, book.
+       Description: On line, 200 pages book describing most aspects of
+       the Linux Kernel. Probably, the first reference for beginners.
+       Lots of illustrations explaining data structures use and
+       relationships in the purest Richard W. Stevens' style. Contents:
+       "1.-Hardware Basics, 2.-Software Basics, 3.-Memory Management,
+       4.-Processes, 5.-Interprocess Communication Mechanisms, 6.-PCI,
+       7.-Interrupts and Interrupt Handling, 8.-Device Drivers, 9.-The
+       File system, 10.-Networks, 11.-Kernel Mechanisms, 12.-Modules,
+       13.-The Linux Kernel Sources, A.-Linux Data Structures, B.-The
+       Alpha AXP Processor, C.-Useful Web and FTP Sites, D.-The GNU
+       General Public License, Glossary". In short: a must have.
+       
+     * Title: "The Linux Kernel Hackers' Guide"
+       Author: Michael K.Johnson and others.
+       URL: http://khg.redhat.com/HyperNews/get/khg.html
+       Keywords: everything!
+       Description: No more Postscript book-like version. Only HTML now.
+       Many people have contributed. The interface is similar to web
+       available mailing lists archives. You can find some articles and
+       then some mails asking questions about them and/or complementing
+       previous contributions. A little bit anarchic in this aspect, but
+       with some valuable information in some cases.
+       
+     * Title: "Conceptual Architecture of the Linux Kernel"
+       Author: Ivan T. Bowman.
+       URL: http://plg.uwaterloo.ca/~itbowman/papers/CS746G-a1.html
+       Keywords: conceptual software arquitecture, extracted design,
+       reverse engineering, system structure.
+       Description: Conceptual software arquitecture of the Linux kernel,
+       automatically extracted from the source code. Very detailed. Good
+       figures. Gives good overall kernel understanding.
+       
+     * Title: "Concrete Architecture of the Linux Kernel"
+       Author: Ivan T. Bowman, Saheem Siddiqi, and Meyer C. Tanuan.
+       URL: http://plg.uwaterloo.ca/~itbowman/papers/CS746G-a2.html
+       Keywords: concrete arquitecture, extracted design, reverse
+       engineering, system structure, dependencies.
+       Description: Concrete arquitecture of the Linux kernel,
+       automatically extracted from the source code. Very detailed. Good
+       figures. Gives good overall kernel understanding. This papers
+       focus on lower details than its predecessor (files, variables...).
+       
+     * Title: "Linux as a Case Study: Its Extracted Software
+       Architecture"
+       Author: Ivan T. Bowman, Richard C. Holt and Neil V. Brewster.
+       URL: http://plg.uwaterloo.ca/~itbowman/papers/linuxcase.html
+       Keywords: software architecture, architecture recovery,
+       redocumentation.
+       Description: Paper appeared at ICSE'99, Los Angeles, May 16-22,
+       1999. A mixture of the previous two documents from the same
+       author.
+       
+     * Title: "Overview of the Virtual File System"
+       Author: Richard Gooch.
+       URL: http://www.atnf.csiro.au/~rgooch/linux/vfs.txt
+       Keywords: VFS, File System, mounting filesystems, opening files,
+       dentries,
+       dcache. Description: Brief introduction to the Linux Virtual File
+       System. What is it, how it works, operations taken when opening a
+       file or mounting a file system and description of important data
+       structures explaining the purpose of each of their entries.
+       
+     * Title: "The Linux RAID-1, 4, 5 Code"
+       Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
+       URL: http://www.ssc.com/lj/issue44/2391.html
+       Keywords: RAID, MD driver.
+       Description: Linux Journal Kernel Korner article. Here is it's
+       abstract: "A description of the implementation of the RAID-1,
+       RAID-4 and RAID-5 personalities of the MD device driver in the
+       Linux kernel, providing users with high performance and reliable,
+       secondary-storage capability using software".
+       
+     * Title: "Dynamic Kernels: Modularized Device Drivers"
+       Author: Alessandro Rubini.
+       URL: http://www.ssc.com/lj/issue23/1219.html
+       Keywords: device driver, module, loading/unloading modules,
+       allocating resources.
+       Description: Linux Journal Kernel Korner article. Here is it's
+       abstract: "This is the first of a series of four articles
+       co-authored by Alessandro Rubini and Georg Zezchwitz which present
+       a practical approach to writing Linux device drivers as kernel
+       loadable modules. This installment presents an introduction to the
+       topic, preparing the reader to understand next month's
+       installment".
+       
+     * Title: "Dynamic Kernels: Discovery"
+       Author: Alessandro Rubini.
+       URL: http://www.ssc.com/lj/issue24/kk24.html
+       Keywords: character driver, init_module, clean_up module,
+       autodetection,
+       mayor number, minor number, file operations, open(), close().
+       Description: Linux Journal Kernel Korner article. Here is it's
+       abstract: "This article, the second of four, introduces part of
+       the actual code to create custom module implementing a character
+       device driver. It describes the code for module initialization and
+       cleanup, as well as the open() and close() system calls".
+       
+     * Title: "The Devil's in the Details"
+       Author: Georg v. Zezschwitz and Alessandro Rubini.
+       URL: http://www.ssc.com/lj/issue25/kk25.html
+       Keywords: read(), write(), select(), ioctl(), blocking/non
+       blocking mode, interrupt handler.
+       Description: Linux Journal Kernel Korner article. Here is it's
+       abstract: "This article, the third of four on writing character
+       device drivers, introduces concepts of reading, writing, and using
+       ioctl-calls".
+       
+     * Title: "Dissecting Interrupts and Browsing DMA"
+       Author: Alessandro Rubini and Georg v. Zezschwitz.
+       URL: http://www.ssc.com/lj/issue26/interrupt.html
+       Keywords: interrupts, irqs, DMA, bottom halves, task queues.
+       Description: Linux Journal Kernel Korner article. Here is it's
+       abstract: "This is the fourth in a series of articles about
+       writing character device drivers as loadable kernel modules. This
+       month, we further investigate the field of interrupt handling.
+       Though it is conceptually simple, practical limitations and
+       constraints make this an ``interesting'' part of device driver
+       writing, and several different facilities have been provided for
+       different situations. We also investigate the complex topic of
+       DMA".
+       
+     * Title: "Network Buffers And Memory Management"
+       Author: Alan Cox.
+       URL: http://www.ssc.com/lj/issue30/kk30.html
+       Keywords: sk_buffs, network devices, protocol/link layer
+       variables, network devices flags, transmit, receive,
+       configuration, multicast.
+       Description: Linux Journal Kernel Korner. Here is the abstract:
+       "Writing a network device driver for Linux is fundamentally
+       simple---most of the complexity (other than talking to the
+       hardware) involves managing network packets in memory".
+       
+     * Title: "An Introduction to the Linux 1.3.x Networking Code"
+       Author: Vipul Gupta.
+       URL: http://anchor.cs.binghamton.edu/courses/cs628/linux-net.html
+       Keywords: files, sk_buffs.
+       Description: A short description of files under the net/
+       directory. Each file has a one or two lines paragraph description.
+       sk_buffs explained, too, with some beautiful pictures. A little
+       bit outdated.
+       
+     * Title: "Linux ioctl() Primer"
+       Author: Vipul Gupta.
+       URL: http://anchor.cs.binghamton.edu/courses/cs628/ioctl.html
+       Keywords: ioctl, socket.
+       Description: Little description and examples on the use and
+       implementation of the ioctl() system call. A little bit biased
+       towards sockets.
+       
+     * Title: "Writing Linux Device Drivers"
+       Author: Michael K. Johnson.
+       URL: http://www.redhat.com/~johnsonm/devices.html
+       Keywords: files, VFS, file operations, kernel interface, character
+       vs block devices, I/O access, hardware interrupts, DMA, access to
+       user memory, memory allocation, timers.
+       Description: Introductory 50-minutes (sic) tutorial on writing
+       device drivers. 12 pages written by the same author of the "Kernel
+       Hackers' Guide" which give a very good overview of the topic.
+       
+     * Title: "The Venus kernel interface"
+       Author: Peter J. Braam.
+       URL:
+       http://www.coda.cs.cmu.edu/doc/html/kernel-venus-protocol.html
+       Keywords: coda, filesystem, venus, cache manager.
+       Description: "This document describes the communication between
+       Venus and kernel level file system code needed for the operation
+       of the Coda filesystem. This version document is meant to describe
+       the current interface (version 1.0) as well as improvements we
+       envisage".
+       
+     * Title: "Programming PCI-Devices under Linux"
+       Author: Claus Schroeter.
+       URL:
+       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/pcip.ps
+       .gz
+       Keywords: PCI, device, busmastering.
+       Description: 6 pages tutorial on PCI programming under Linux.
+       Gives the basic concepts on the architecture of the PCI subsystem,
+       as long as basic functions and macros to read/write the devices
+       and perform busmastering.
+       
+     * Title: "Writing Character Device Driver for Linux"
+       Author: R. Baruch and C. Schroeter.
+       URL:
+       ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/drivers
+       .ps.gz
+       Keywords: character device drivers, I/O, signals, DMA, accesing
+       ports in user space, kernel environment.
+       Description: 68 pages paper on writing character drivers. A little
+       bit old (1.993, 1.994) although still useful.
+       
+     * Title: "The Second Extended Filesystem"
+       Author: Matthew Wilcox.
+       URL: http://pocket.fluff.org/~mrw/linux/ext2.txt
+       Keywords: ext2, filesystem.
+       Description: Description of ext2's blocks, directories, inodes ...
+       
+     * Title: "Analysis of the Ext2fs structure"
+       Author: Louis-Dominique Dubeau.
+       URL: http://step.polymtl.ca/~ldd/ext2fs/ext2fs_toc.html
+       Keywords: ext2, filesystem, ext2fs.
+       Description: Description of ext2's blocks, directories, inodes,
+       bitmaps, invariants ...
+       
+     * Title: "Kernel API changes from 2.0 to 2.2"
+       Author: Richard Gooch.
+       URL:
+       http://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.2.html
+       Keywords: 2.2, changes.
+       Description: Kernel functions/structures/variables which changed
+       from 2.0.x to 2.2.x.
+       
+     * Title: "Kernel API changes from 2.2 to 2.3"
+       Author: Richard Gooch.
+       URL:
+       http://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.2.html
+       Keywords: 2.3, changes.
+       Description: Kernel functions/structures/variables which changed
+       from 2.2.x to 2.3.x.
+       
+     * Title: "Linux Kernel Module Programming Guide"
+       Author: Ori Pomerantz.
+       URL: http://www.linuxdoc.org/LDP/lkmpg/mpg.html
+       Keywords: modules, GPL book, /proc, ioctls, system calls,
+       interrupt handlers .
+       Description: Very nice 92 pages GPL book on the topic of modules
+       programming. Lots of examples.
+       
+     * Title: "Device File System (devfs) Overview"
+       Author: Richard Gooch.
+       URL: http://www.atnf.csiro.au/~rgooch/linux/docs/devfs.txt
+       Keywords: filesystem, /dev, devfs, dynamic devices, major/minor
+       allocation, device management.
+       Description: Document describing Richard Gooch's controversial
+       devfs, which allows for dynamic devices, only shows present
+       devices in /dev, gets rid of major/minor numbers allocation
+       problems, and allows for hundreds of identical devices (which some
+       USB systems might demand soon).
+       
+     * Title: "I/O Event Handling Under Linux"
+       Author: Richard Gooch.
+       URL: http://www.atnf.csiro.au/~rgooch/linux/docs/io-events.html
+       Keywords: IO, I/O, select(2), poll(2), FDs, aio_read(2), readiness
+       event queues.
+       Description: From the Introduction: "I/O Event handling is about
+       how your Operating System allows you to manage a large number of
+       open files (file descriptors in UNIX/POSIX, or FDs) in your
+       application. You want the OS to notify you when FDs become active
+       (have data ready to be read or are ready for writing). Ideally you
+       want a mechanism that is scalable. This means a large number of
+       inactive FDs cost very little in memory and CPU time to manage".
+       
+     BOOKS: (Not on-line)
+   
+     * Title: "Linux Device Drivers"
+       Author: Alessandro Rubini.
+       Publisher: O'Reilly &Associates.
+       Date: 1998.
+       ISBN: 1-56592-292-1
+       
+     * Title: "Linux Kernel Internals"
+       Author: Michael Beck.
+       Publisher: Addison-Wesley.
+       Date: 1997.
+       ISBN: 0-201-33143-8 (second edition)
+       
+     * Title: "The Design of the UNIX Operating System"
+       Author: Maurice J. Bach.
+       Publisher: Prentice Hall.
+       Date: 1986.
+       Pages: 471.
+       ISBN: 0-13-201757-1
+       
+     * Title: "The Design and Implementation of the 4.3 BSD UNIX
+       Operating System"
+       Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael J.
+       Karels, John S. Quarterman.
+       Publisher: Addison-Wesley.
+       Date: 1989 (reprinted with corrections on October, 1990).
+       ISBN: 0-201-06196-1
+       
+     * Title: "The Design and Implementation of the 4.4 BSD UNIX
+       Operating System"
+       Author: Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
+       John S. Quarterman.
+       Publisher: Addison-Wesley.
+       Date: 1996.
+       ISBN: 0-201-54979-4
+       
+     * Title: "Programmation Linux 2.0 API systeme et fonctionnement du
+       noyau"
+       Author: Remy Card, Eric Dumas, Franck Mevel.
+       Publisher: Eyrolles.
+       Date: 1997.
+       Pages: 520.
+       ISBN: 2-212-08932-5
+       Notes: French.
+       
+     * Title: "The Linux Kernel Book"
+       Author: Remy Card, Eric Dumas, Franck Mevel.
+       Publisher: John Wiley & Sons.
+       Date: 1998.
+       ISBN: 0-471-98141-9
+       Notes: English translation.
+       
+     * Title: "Linux 2.0"
+       Author: Remy Card, Eric Dumas, Franck Mevel.
+       Publisher: Gestión 2000.
+       Date: 1997.
+       Pages: 501.
+       ISBN: 8-480-88208-5
+       Notes: Spanish translation.
+       
+     * Title: "Unix internals -- the new frontiers"
+       Author: Uresh Vahalia.
+       Publisher: Prentice Hall.
+       Date: 1996.
+       Pages: 600.
+       ISBN: 0-13-101908-2
+       
+     * Title: "Linux Core Kernel Commentary. Guide to Insider's Knowledge
+       on the Core Kernel od the Linux Code"
+       Author: Scott Maxwell.
+       Publisher: ???.
+       Date: 1999.
+       Pages: 592.
+       ISBN: 1-57610-469-9
+       Notes: CD-ROM included.
+       
+     MISCELLANEOUS:
+   
+     * Name: Linux Source Driver.
+       URL: http://lsd.linux.cz
+       Keywords: Browsing source code.
+       Description: "Linux Source Driver (LSD) is an application, which
+       can make browsing source codes of Linux kernel easier than you can
+       imagine. You can select between multiple versions of kernel (e.g.
+       0.01, 1.0.0, 2.0.33, 2.0.34pre13, 2.0.0, 2.1.101 etc.). With LSD
+       you can search Linux kernel (fulltext, macros, types, functions
+       and variables) and LSD can generate patches for you on the fly
+       (files, directories or kernel)".
+       
+     * Name: Cross-Referencing Linux.
+       URL: http://lxr.linux.no/source/
+       Keywords: Browsing source code.
+       Description: Another web-based Linux kernel source code browser.
+       Lots of cross references to variables and functions. You can see
+       where they are defined and where they are used.
+       
+     * Name: Linux Weekly News.
+       URL: http://lwn.net
+       Keywords: latest kernel news.
+       Description: The title says it all. There's a fixed kernel section
+       summarizing developers' work, bug fixes, new features and versions
+       produced during the week. Published every Thursday.
+       
+     * Name: Kernel Traffic.
+       URL: http://kt.linuxcare.com
+       Keywords: linux-kernel mailing list, weekly kernel news.
+       Description: Weekly newsletter covering the most relevant
+       discussions of the linux-kernel mailing list.
+       
+     * Name: CuTTiNG.eDGe.LiNuX.
+       URL: http://edge.kernelnotes.org
+       Keywords: changelist.
+       Description: Site which provides the changelist for every kernel
+       release. What's new, what's better, what's changed. Myrdraal reads
+       the patches and describes them. Pointers to the patches are there,
+       too.
+       
+     * Name: New linux-kernel Mailing List FAQ.
+       URL: Original site:
+       http://www.altern.org/andrebalsa/doc/lkml-faq.html
+       URL: U.S. mirror site:
+       http://www.ececs.uc.edu/~rreilova/linux/lkml-faq.html
+       Keywords: linux-kernel mailing list FAQ.
+       Description: linux-kernel is a mailing list for developers to
+       communicate. This FAQ builds on the previous linux-kernel mailing
+       list FAQ maintained by Frohwalt Egerer, who no longer maintains
+       it. Read it to see how to join the mailing list. Dozens of
+       interesting questions regarding the list, Linux, developers (who
+       is ...?), terms (what is...?) are answered here too. Just read it.
+       
+     * Name: "Linux Virtual File System"
+       Author: Peter J. Braam.
+       URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs
+       Keywords: slides, VFS, inode, superblock, dentry, dcache.
+       Description: Set of slides, presumably from a presentation on the
+       Linux VFS layer. Covers version 2.1.x, with dentries and the
+       dcache.
+     _________________________________________________________________
    
-          + Name: New linux-kernel Mailing List FAQ.
-            URL: Original site:
-            http://www.altern.org/andrebalsa/doc/lkml-faq.html
-            URL: U.S. mirror site:
-            http://www.ececs.uc.edu/~rreilova/linux/lkml-faq.html
-            Keywords: linux-kernel mailing list FAQ.
-            Description: linux-kernel is a mailing list for developers
-            to communicate. This FAQ builds on the previous linux-kernel
-            mailing list FAQ maintained by Frohwalt Egerer, who no longer
-            maintains it. Read it to see how to join the mailing list.
-            Dozens of interesting questions regarding the list, Linux,
-            developers (who is ...?), terms (what is...?) are answered
-            here too. Just read it.
-       
-          + Name: "Linux Virtual File System"
-            Author: Peter J. Braam.
-            URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs
-            Keywords: slides, VFS, inode, superblock, dentry, dcache.
-            Description: Set of slides, presumably from a presentation
-            on the Linux VFS layer. Covers version 2.1.x, with dentries
-            and the dcache.
+   Document last updated on Tue Nov 30 11:20:00 CET 1999
diff -u --recursive --new-file v2.3.39/linux/Documentation/kernel-parameters.txt linux/Documentation/kernel-parameters.txt
--- v2.3.39/linux/Documentation/kernel-parameters.txt	Mon Dec 20 18:48:21 1999
+++ linux/Documentation/kernel-parameters.txt	Tue Jan 11 11:32:32 2000
@@ -10,41 +10,41 @@
 restrictions on the kernel for the said kernel parameter to be valid. The
 restrictions referred to are that the relevant option is valid if:
 
-    APIC	APIC support is enabled.
-    APM 	Advanced Power Management support is enabled.
-    AX25	Appropriate AX.25 support is enabled.
-    CD		Appropriate CD support is enabled.
-    EIDE	EIDE/ATAPI support is enabled.
-    FB		The frame buffer device is enabled.
-    HW		Appropriate hardware is enabled.
-    ISDN	Appropriate ISDN support is enabled.
-    JOY 	Appropriate joystick support is enabled.
-    LP		Printer support is enabled.
-    LOOP	Loopback device support is enabled.
-    MCA 	MCA bus support is enabled.
-    MDA 	The MDA console is enabled.
-    MOUSE	Appropriate mouse support is enabled.
-    NET 	Appropriate network support is enabled.
-    NFS 	Appropriate NFS support is enabled.
-    PARIDE	The ParIDE subsystem is enabled.
-    PCI 	PCI bus support is enabled.
-    PCMCIA	The PCMCIA subsystem is enabled.
-    PNP 	Plug & Play support is enabled.
-    PPT		Parallel port support is enabled.
-    PS2 	Appropriate PS/2 support is enabled.
-    RAM 	RAMdisc support is enabled.
-    SCSI	Appropriate SCSI support is enabled.
-    SERIAL	Serial support is enabled.
-    SMP 	The kernel is an SMP kernel.
-    SOUND	Appropriate sound system support is enabled.
-    VGA 	The VGA console has been enabled.
-    VT		Virtual terminal support is enabled.
-    XT		IBM PC/XT MFM hard disk support is enabled.
+	APIC	APIC support is enabled.
+	APM 	Advanced Power Management support is enabled.
+	AX25	Appropriate AX.25 support is enabled.
+	CD	Appropriate CD support is enabled.
+	EIDE	EIDE/ATAPI support is enabled.
+	FB	The frame buffer device is enabled.
+	HW	Appropriate hardware is enabled.
+	ISDN	Appropriate ISDN support is enabled.
+	JOY 	Appropriate joystick support is enabled.
+	LP	Printer support is enabled.
+	LOOP	Loopback device support is enabled.
+	MCA 	MCA bus support is enabled.
+	MDA 	MDA console support is enabled.
+	MOUSE	Appropriate mouse support is enabled.
+	NET 	Appropriate network support is enabled.
+	NFS 	Appropriate NFS support is enabled.
+	PARIDE	The ParIDE subsystem is enabled.
+	PCI 	PCI bus support is enabled.
+	PCMCIA	The PCMCIA subsystem is enabled.
+	PNP 	Plug & Play support is enabled.
+	PPT	Parallel port support is enabled.
+	PS2 	Appropriate PS/2 support is enabled.
+	RAM 	RAM disk support is enabled.
+	SCSI	Appropriate SCSI support is enabled.
+	SERIAL	Serial support is enabled.
+	SMP 	The kernel is an SMP kernel.
+	SOUND	Appropriate sound system support is enabled.
+	VGA 	The VGA console has been enabled.
+	VT	Virtual terminal support is enabled.
+	XT	IBM PC/XT MFM hard disk support is enabled.
 
 In addition, the following text indicates that the option:
 
-    BUGS=	Relates to possible processor bugs on the said processor.
-    KNL 	Is a kernel start-up parameter.
+	BUGS=	Relates to possible processor bugs on the said processor.
+	KNL 	Is a kernel start-up parameter.
 
 Note that ALL kernel parameters listed below are CASE SENSITIVE, and that
 a trailing = on the name of any parameter states that that parameter will
@@ -52,353 +52,353 @@
 it will appear as a kernel argument readable via /proc/cmdline by programs
 running once the system is up.
 
-    53c7xx=		[HW,SCSI] Amiga SCSI controllers
+	53c7xx=		[HW,SCSI] Amiga SCSI controllers.
 
-    adb_buttons=	[HW,MOUSE]
+	adb_buttons=	[HW,MOUSE]
 
-    advansys=		[HW,SCSI]
+	advansys=	[HW,SCSI]
 
-    aha152x=		[HW,SCSI]
+	aha152x=	[HW,SCSI]
 
-    aha1542=		[HW,SCSI]
+	aha1542=	[HW,SCSI]
 
-    aic7xxx=		[HW,SCSI]
+	aic7xxx=	[HW,SCSI]
 
-    AM53C974=		[HW,SCSI]
+	AM53C974=	[HW,SCSI]
 
-    apm=		[APM] Advanced Power Management.
+	apm=		[APM] Advanced Power Management.
 
-    arcrimi=		[HW,NET]
+	arcrimi=	[HW,NET]
 
-	ataflop=		[HW, M68k]
+	ataflop=	[HW, M68k]
 
-    atamouse=		[HW,MOUSE] Atari Mouse.
+	atamouse=	[HW,MOUSE] Atari Mouse.
 
-    atascsi=		[HW,SCSI] Atari SCSI.
+	atascsi=	[HW,SCSI] Atari SCSI.
 
-    aztcd=		[HW,CD] Aztec CD driver.
+	aztcd=		[HW,CD] Aztec CD driver.
 
-    baycom_par= 	[HW,AX25] BayCom Parallel Port AX.25 Modem.
+	baycom_par= 	[HW,AX25] BayCom Parallel Port AX.25 Modem.
 
-    baycom_ser_fdx=	[HW,AX25] BayCom Serial Port AX.25 Modem in Full
+	baycom_ser_fdx=	[HW,AX25] BayCom Serial Port AX.25 Modem in Full
 			Duplex Mode.
 
-    baycom_ser_hdx=	[HW,AX25] BayCom Serial Port AX.25 Modem in Half
+	baycom_ser_hdx=	[HW,AX25] BayCom Serial Port AX.25 Modem in Half
 			Duplex Mode.
 
-    bmouse=		[HW,MOUSE,PS2] Bus mouse.
+	bmouse=		[HW,MOUSE,PS2] Bus mouse.
 
-    BusLogic=		[HW,SCSI]
+	BusLogic=	[HW,SCSI]
 
-    cdu31a=		[HW,CD]
+	cdu31a=		[HW,CD]
 
-    cm206=		[HW,CD]
+	cm206=		[HW,CD]
 
-    com20020=		[HW,NET]
+	com20020=	[HW,NET]
 
-    com90io=		[HW,NET]
+	com90io=	[HW,NET]
 
-    com90xx=		[HW,NET]
+	com90xx=	[HW,NET]
 
-    console=		[KNL] output console + comm spec (speed, control, parity)
+	console=	[KNL] output console + comm spec (speed, control,
+			parity).
 
-    cyclades=		[HW,SERIAL] Cyclades multi-serial port adapter.
+	cyclades=	[HW,SERIAL] Cyclades multi-serial port adapter.
 
-    debug		[KNL] Enable kernel debugging (events log level).
+	debug		[KNL] Enable kernel debugging (events log level).
 
-    decnet=		[HW,NET]
+	decnet=		[HW,NET]
 
-    digi=		[HW,SERIAL] io parameters + enable/disable command
+	digi=		[HW,SERIAL] io parameters + enable/disable command.
 
-    digiepca=		[HW,SERIAL]
+	digiepca=	[HW,SERIAL]
 
-    dmascc=		[HW,AX25,SERIAL] AX.25 Z80SCC driver with DMA
+	dmascc=		[HW,AX25,SERIAL] AX.25 Z80SCC driver with DMA
 			support available.
 
-    dmasound=		[HW,SOUND] (sound subsystem buffers)
+	dmasound=	[HW,SOUND] (sound subsystem buffers).
 
-    dtc3181e=		[HW,SCSI]
+	dtc3181e=	[HW,SCSI]
 
-    eata=		[HW,SCSI]
+	eata=		[HW,SCSI]
 
-    eda=		[HW,PS2]
+	eda=		[HW,PS2]
 
-    edb=		[HW,PS2]
+	edb=		[HW,PS2]
 
-    ether=		[HW,NET] Ethernet cards parameters (iomem,irq,dev_name).
+	ether=		[HW,NET] Ethernet cards parameters (iomem, irq,
+			dev_name).
 
-    fd_mcs=		[HW,SCSI]
+	fd_mcs=		[HW,SCSI]
 
-    fdomain=		[HW,SCSI]
+	fdomain=	[HW,SCSI]
 
-    floppy=		[HW]
+	floppy=		[HW]
 
-    ftape=		[HW] Floppy Tape subsystem debugging options.
+	ftape=		[HW] Floppy Tape subsystem debugging options.
 
-    gdth=		[HW,SCSI]
+	gdth=		[HW,SCSI]
 
-    gscd=		[HW,CD]
+	gscd=		[HW,CD]
 
-    gvp11=		[HW,SCSI]
+	gvp11=		[HW,SCSI]
 
-    hd= 		[EIDE] (E)IDE hard drive subsystem
-                geometry (Cyl/heads/sectors) or tune parameters.
+	hd= 		[EIDE] (E)IDE hard drive subsystem geometry
+			(Cyl/heads/sectors) or tune parameters.
 
-    hfmodem=		[HW,AX25]
+	hfmodem=	[HW,AX25]
 
-    HiSax=		[HW,ISDN]
+	HiSax=		[HW,ISDN]
 
-    hisax=		[HW,ISDN]
+	hisax=		[HW,ISDN]
 
-      in2000=       [HW,SCSI]
+	in2000=		[HW,SCSI]
 
-      init=     [KNL]
+	init=		[KNL]
 
+	ibmmcascsi=	[HW,MCA,SCSI] IBM MicroChannel SCSI adapter.
 
-
-    ibmmcascsi= 	[HW,MCA,SCSI] IBM MicroChannel SCSI adapter.
-
-    icn=		[HW,ISDN]
+	icn=		[HW,ISDN]
 
 	ide?=		[HW] (E)IDE subsystem : config (iomem/irq), tuning or
-				debugging (serialize,reset,no{dma,tune,probe}) or
-				chipset specific parameters
+			debugging (serialize,reset,no{dma,tune,probe}) or
+			chipset specific parameters.
 	
-	idebus=		[HW] (E)IDE subsystem : VLB/PCI bus speed
-
-    in2000=		[HW,SCSI]
+	idebus=		[HW] (E)IDE subsystem : VLB/PCI bus speed.
 
-    init=		[KNL] default init level
+	in2000=		[HW,SCSI]
 
-	initrd=		[KNL] initial ramdisk path
+	init=		[KNL] Default init level.
 
-    ip= 		[PNP]
+	ip=		[PNP]
 
-    isp16=		[HW,CD]
+	isp16=		[HW,CD]
 
-    js_14=		[HW,JOY]
+	js_14=		[HW,JOY]
 
-    js_am=		[HW,JOY]
+	js_am=		[HW,JOY]
 
-    js_an=		[HW,JOY]
+	js_an=		[HW,JOY]
 
-    js_as=		[HW.JOY]
+	js_as=		[HW.JOY]
 
-    js_console= 	[HW,JOY]
+	js_console=	[HW,JOY]
 
-    js_console2=	[HW,JOY]
+	js_console2=	[HW,JOY]
 
-    js_console3=	[HW,JOY]
+	js_console3=	[HW,JOY]
 
-    js_db9=		[HW,JOY]
+	js_db9=		[HW,JOY]
 
-    js_db9_2=		[HW,JOY]
+	js_db9_2=	[HW,JOY]
 
-    js_db9_3=		[HW,JOY]
+	js_db9_3=	[HW,JOY]
 
-    js_tg=		[HW,JOY]
+	js_tg=		[HW,JOY]
 
-    js_tg_2=		[HW,JOY]
+	js_tg_2=	[HW,JOY]
 
-    js_tg_3=		[HW,JOY]
+	js_tg_3=	[HW,JOY]
 
-    kbd-reset		[VT]
+	kbd-reset	[VT]
 
-    load_ramdisk=	[RAM] initrd loading boolean
+	load_ramdisk=	[RAM] List of ramdisks to load from floppy.
 
-    lp=0 		[LP] Specify parallel ports to use, e.g,
-or  lp=port[,port...]	lp=none,parport0 (lp0 not configured, lp1 uses
-or  lp=reset		first parallel port).  'lp=0' disables the printer
-or  lp=auto		driver.  'lp=reset' (which can be specified in
-			addition to the ports) causes attached
-			printers to be reset.  Using
-			lp=port1,port2,... specifies the parallel
-			ports to associate lp devices with, starting
-			with lp0.  A port specification may be 'none'
-			to skip that lp device, or a parport name such
-			as 'parport0'.  Specifying 'lp=auto' instead
-			of a port specification list means that device
-			IDs from each port should be examined, to see
-			if an IEEE 1284-compliant printer is attached;
-			if so, the driver will manage that printer.
+	lp=0		[LP]	Specify parallel ports to use, e.g,
+	lp=port[,port...]	lp=none,parport0 (lp0 not configured, lp1 uses
+	lp=reset		first parallel port). 'lp=0' disables the
+	lp=auto			printer driver. 'lp=reset' (which can be
+				specified in addition to the ports) causes
+				attached printers to be reset. Using
+				lp=port1,port2,... specifies the parallel ports
+				to associate lp devices with, starting with
+				lp0. A port specification may be 'none' to skip
+				that lp device, or a parport name such as
+				'parport0'. Specifying 'lp=auto' instead of a
+				port specification list means that device IDs
+				from each port should be examined, to see if
+				an IEEE 1284-compliant printer is attached; if
+				so, the driver will manage that printer.
 
-    ltpc=		[HW]
+	ltpc=		[HW]
 
-    mac5380=		[HW,SCSI]
+	mac5380=	[HW,SCSI]
 
-    max_loop=[0-255]	[LOOP] States the maximum number of loopback devices
-    			that can be mounted.
+	max_loop=[0-255] [LOOP] Set the maximum number of loopback devices
+				that can be mounted.
 
-    maxcpus=		[SMP] States the maximum number of processors that
+	maxcpus=	[SMP] States the maximum number of processors that
 			an SMP kernel should make use of.
 
-    max_scsi_luns=	[SCSI]
+	max_scsi_luns=	[SCSI]
 
-    mca-pentium 	[BUGS=ix86]
+	mca-pentium	[BUGS=ix86]
 
-    mcd=		[HW,CD]
+	mcd=		[HW,CD]
 
-    mcdx=		[HW,CD]
+	mcdx=		[HW,CD]
 
-    md= 		[HW] RAID subsystems devices and level
+	md=		[HW] RAID subsystems devices and level.
 
-    mdacon=		[MDA]
+	mdacon=		[MDA]
 
-    mem=		[KNL] force use XX Mb of memory when the kernel is not able
-                      to see the whole system memory or for test
+	mem=		[KNL] force use XX Mb of memory when the kernel is not
+			able to see the whole system memory or for test.
 
-    msmouse=		[HW,MOUSE] Microsoft Mouse.
+	msmouse=	[HW,MOUSE] Microsoft Mouse.
 
-    ncr5380=		[HW,SCSI]
+	ncr5380=	[HW,SCSI]
 
-    ncr53c400=		[HW,SCSI]
+	ncr53c400=	[HW,SCSI]
 
-    ncr53c400a= 	[HW,SCSI]
+	ncr53c400a=	[HW,SCSI]
 
-    ncr53c406a= 	[HW,SCSI]
+	ncr53c406a=	[HW,SCSI]
 
-    ncr53c8xx=		[HW,SCSI]
+	ncr53c8xx=	[HW,SCSI]
 
-    nfsaddrs=		[NFS]
+	nfsaddrs=	[NFS]
 
-    nfsroot=		[NFS] nfs root filesystem for disk-less boxes
+	nfsroot=	[NFS] nfs root filesystem for disk-less boxes.
 
-	nmi_watchdog=	[KNL, BUGS=ix86] debugging features for SMP kernels
+	nmi_watchdog=	[KNL, BUGS=ix86] debugging features for SMP kernels.
 
-    no387		[BUGS=ix86] Tells the kernel to use the 387 maths
+	no387		[BUGS=ix86] Tells the kernel to use the 387 maths
 			emulation library even if a 387 maths coprocessor
 			is present.
 
-    noapic		[SMP,APIC] Tells the kernel not to make use of any
+	noapic		[SMP,APIC] Tells the kernel not to make use of any
 			APIC that may be present on the system.
 
-    noasync		[HW, M68K] Disables async and sync negotiation for all devices.
+	noasync		[HW, M68K] Disables async and sync negotiation for
+			all devices.
 
-    nodisconnect	[HW,SCSI, M68K] Disables SCSI disconnects.
+	nodisconnect	[HW,SCSI, M68K] Disables SCSI disconnects.
 
-    no-halt		[BUGS=ix86]
+	no-halt		[BUGS=ix86]
 
-    noinitrd		[RAM] Tells the kernel not to load any configured
-			initial ramdisc.
+	noinitrd	[RAM] Tells the kernel not to load any configured
+			initial RAM disk.
 
-    no-scroll		[VGA]
+	no-scroll	[VGA]
 
-    nosmp		[SMP] Tells an SMP kernel to act as a UP kernel.
+	nosmp		[SMP] Tells an SMP kernel to act as a UP kernel.
 
-    nosync		[HW, M68K] Disables sync negotiation for all devices.
+	nosync		[HW, M68K] Disables sync negotiation for all devices.
 
-    optcd=		[HW,CD]
+	optcd=		[HW,CD]
 
-    panic=		[KNL] kernel behaviour on panic
+	panic=		[KNL] kernel behaviour on panic.
 
-    parport=0			[HW,PPT] Specify parallel ports.  0
-or  parport=auto		disables.  Use 'auto' to force the driver
-or  parport=0xBBB[,IRQ[,DMA]]	to use any IRQ/DMA settings detected
-				(the default is to ignore detected
-				IRQ/DMA settings because of possible
-				conflicts).  You can specify the base
-				address, IRQ, and DMA settings; IRQ
-				and DMA should be numbers, or 'auto'
-				(for using detected settings on that
-				particular port), or 'nofifo' (to
-				avoid using a FIFO even if it is
-				detected).  Parallel ports are
-				assigned in the order they are
-				specified on the command line,
-				starting with parport0.
+	parport=0	[HW,PPT]	Specify parallel ports. 0 disables.
+	parport=auto			Use 'auto' to force the driver to use
+	parport=0xBBB[,IRQ[,DMA]]	any IRQ/DMA settings detected (the
+					default is to ignore detected IRQ/DMA
+					settings because of possible
+					conflicts). You can specify the base
+					address, IRQ, and DMA settings; IRQ and
+					DMA should be numbers, or 'auto' (for
+					using detected settings on that
+					particular port), or 'nofifo' (to avoid
+					using a FIFO even if it is detected).
+					Parallel ports are assigned in the
+					order they are specified on the command
+					line, starting with parport0.
 
-    pas16=		[HW,SCSI]
+	pas16=		[HW,SCSI]
 
-    pcbit=		[HW,ISDN]
+	pcbit=		[HW,ISDN]
 
-    pcd.		[PARIDE]
+	pcd.		[PARIDE]
 
-    pci=		[PCI]
+	pci=		[PCI]
 
-    pd. 		[PARIDE]
+	pd.		[PARIDE]
 
-    pf. 		[PARIDE]
+	pf.		[PARIDE]
 
-    pg. 		[PARIDE]
+	pg.		[PARIDE]
 
-    pirq=		[SMP,APIC] mp-table
+	pirq=		[SMP,APIC] mp-table.
 
-    plip=		[PPT,NET] Parallel port network link.
+	plip=		[PPT,NET] Parallel port network link.
 
-    profile=	[KNL] enable kernel profiling via /proc/profile (param:log level)
+	profile=	[KNL] enable kernel profiling via /proc/profile
+			(param:log level).
 
-    prompt_ramdisk=	[RAM] Whether to prompt for ramdisk before loading
-			its contents into memory.
+	prompt_ramdisk=	[RAM] List of RAM disks to prompt for floppy disk
+			before loading.
 
-    pt. 		[PARIDE]
+	pt.		[PARIDE]
 
-    ramdisk=		[RAM]
+	ramdisk=	[RAM] Sizes of RAM disks in kilobytes [deprecated].
 
-    ramdisk_size=	[RAM]
+	ramdisk_size=	[RAM] New name for the ramdisk parameter.
 
-    ramdisk_start=	[RAM]
+	ramdisk_start=	[RAM] Starting block of RAM disk image (so you can
+			place it after the kernel image on a boot floppy).
 
-    reboot=		[BUGS=ix86]
+	reboot=		[BUGS=ix86]
 
-    reserve=	[KNL,BUGS] force the kernel to ignore some iomem area
+	reserve=	[KNL,BUGS] force the kernel to ignore some iomem area.
 
-    riscom8=		[HW,SERIAL]
+	riscom8=	[HW,SERIAL]
 
-    ro			[KNL] Mount root device read-only on boot.
+	ro		[KNL] Mount root device read-only on boot.
 
-    root=		[KNL] root filesystem
+	root=		[KNL] root filesystem.
 
-    rw			[KNL] Mount root device read-write on boot.
+	rw		[KNL] Mount root device read-write on boot.
 
-    S			[KNL] run init in single mode
+	S		[KNL] run init in single mode.
 
-    sbpcd=		[HW,CD] Soundblaster CD adapter.
+	sbpcd=		[HW,CD] Soundblaster CD adapter.
 
-    scsi_logging=	[SCSI]
+	scsi_logging=	[SCSI]
 
-    sjcd=		[HW,CD]
+	sjcd=		[HW,CD]
 
-    sonycd535=		[HW,CD]
+	sonycd535=	[HW,CD]
 
-    sound=		[SOUND]
+	sound=		[SOUND]
 
-    soundmodem= 	[HW,AX25,SOUND] Sound cards used as AX.25 modems.
+	soundmodem=	[HW,AX25,SOUND] Use sound card as packet radio modem.
 
-    specialix=		[HW,SERIAL] Specialix multi-serial port adapter.
+	specialix=	[HW,SERIAL] Specialix multi-serial port adapter.
 
-    st= 		[HW] SCSI tape parameters (buffers, ..)
+	st=		[HW] SCSI tape parameters (buffers, etc.).
 
-    st0x=		[HW,SCSI]
+	st0x=		[HW,SCSI]
 
-    stram_swap= 	[HW]
+	stram_swap=	[HW]
 
-    switches=		[HW, M68K]
+	switches=	[HW, M68K]
 
-    sym53c416=		[HW,SCSI]
+	sym53c416=	[HW,SCSI]
 
-    sym53c8xx=		[HW,SCSI]
+	sym53c8xx=	[HW,SCSI]
 
-    t128=		[HW,SCSI]
+	t128=		[HW,SCSI]
 
-    tmc8xx=		[HW,SCSI]
+	tmc8xx=		[HW,SCSI]
 
-    tmscsim=		[HW,SCSI]
+	tmscsim=	[HW,SCSI]
 
-    tp720=		[HW,PS2]
+	tp720=		[HW,PS2]
 
-    u14-34f=		[HW,SCSI]
+	u14-34f=	[HW,SCSI]
 
-    video=		[FB]  frame buffer configuration
+	video=		[FB] frame buffer configuration.
 
-    vga=		[KNL]  on ix386, enable to choose a peculiar video mode
-                       vga=ask
+	vga=		[KNL] on ix386, enable to choose a peculiar video mode
+			(use vga=ask for menu).
 
-    wd33c93=		[HW,SCSI]
+	wd33c93=	[HW,SCSI]
 
-    wd7000=		[HW,SCSI]
+	wd7000=		[HW,SCSI]
 
-    wdt=		[HW]
+	wdt=		[HW]
 
-    xd= 		[HW,XT] Original XT pre-IDE (RLL encoded) disks
+	xd=		[HW,XT] Original XT pre-IDE (RLL encoded) disks.
 
-    xd_geo=		[HW,XT]
+	xd_geo=		[HW,XT]
diff -u --recursive --new-file v2.3.39/linux/Documentation/moxa-smartio linux/Documentation/moxa-smartio
--- v2.3.39/linux/Documentation/moxa-smartio	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/moxa-smartio	Thu Jan 20 10:44:46 2000
@@ -0,0 +1,412 @@
+=============================================================================
+
+	MOXA Smartio Family Device Driver Ver 1.1 Installation Guide
+		    for Linux Kernel 2.2.x and 2.0.3x
+	       Copyright (C) 1999, Moxa Technologies Co, Ltd.
+=============================================================================
+Content
+
+1. Introduction
+2. System Requirement
+3. Installation
+4. Utilities
+5. Setserial
+6. Troubleshooting
+
+-----------------------------------------------------------------------------
+1. Introduction
+
+   The Smartio family Linux driver, Ver. 1.1, supports following multiport
+   boards.
+
+    -C104P/H/HS, C104H/PCI, C104HS/PCI, CI-104J 4 port multiport board.
+    -C168P/H/HS, C168H/PCI 8 port multiport board.
+
+   This driver has been modified a little and cleaned up from the Moxa
+   contributed driver code and merged into Linux 2.2.14pre. In paticular
+   official major/minor numbers have been assigned which are different to
+   those the original Moxa supplied driver used.
+
+   This driver and installation procedure have been developed upon Linux Kernel
+   2.2.5 and backward compatible to 2.0.3x. This driver supports Intel x86 and
+   Alpha hardware platform. In order to maintain compatibility, this version
+   has also been properly tested with RedHat, OpenLinux, TurboLinux and
+   S.u.S.E Linux. However, if compatibility problem occurs, please contact
+   Moxa at support@moxa.com.tw.
+
+   In addition to device driver, useful utilities are also provided in this
+   version. They are
+    - msdiag     Diagnostic program for detecting installed Moxa Smartio boards.
+    - msmon      Monitor program to observe data count and line status signals.
+    - msterm     A simple terminal program which is useful in testing serial
+	         ports.
+    - io-irq.exe Configuration program to setup ISA boards. Please note that
+                 this program can only be executed under DOS.
+
+   All the drivers and utilities are published in form of source code under
+   GNU General Public License in this version. Please refer to GNU General
+   Public License announcement in each source code file for more detail.
+
+   In Moxa's ftp sites, you may always find latest driver at
+   ftp://ftp.moxa.com  or ftp://ftp.moxa.com.tw.
+
+   This version of driver can be installed as Loadable Module (Module driver)
+   or built-in into kernel (Static driver). You may refer to following
+   installation procedure for suitable one. Before you install the driver,
+   please refer to hardware installation procedure in the User's Manual.
+
+   We assume the user should be familiar with following documents.
+   - Serial-HOWTO
+   - Kernel-HOWTO
+
+-----------------------------------------------------------------------------
+2. System Requirement
+   - Hardware platform: Intel x86 or Alpha machine
+   - Kernel version: 2.0.3x or 2.2.x
+   - gcc version 2.72 or later
+   - Maximum 4 boards can be installed in combination
+
+-----------------------------------------------------------------------------
+3. Installation
+
+   3.1 Hardware installation
+
+       There are two types of buses, ISA and PCI, for Smartio family multiport
+       board.
+
+       ISA board
+       ---------
+       You'll have to configure CAP address, I/O address, Interrupt Vector
+       as well as IRQ before installing this driver. Please refer to hardware
+       installation procedure in User's Manual before proceed any further.
+       Please make sure the JP1 is open after the ISA board is set properly.
+
+       PCI board
+       ---------
+       You may need to adjust IRQ useage in BIOS to avoid from IRQ conflict
+       with other ISA devices. Please refer to hardware installation
+       procedure in User's Manual in advance.
+
+       IRQ Sharing
+       -----------
+       Each port within the same multiport board shares the same IRQ. Up to
+       4 Moxa Smartio Family multiport boards can be installed together on
+       one system and they can share the same IRQ.
+
+   3.2 Driver files and device naming convention
+
+       The driver file may be obtained from ftp, CD-ROM or floppy disk. The
+       first step, anyway, is to copy driver file "mxser.tgz" into specified
+       directory. e.g. /moxa. The execute commands as below.
+
+       # cd /moxa
+       # tar xvf /dev/fd0 
+       or
+       # cd /moxa
+       # cp /mnt/cdrom/<driver directory>/mxser.tgz .
+       # tar xvfz mxser.tgz
+
+       You may find all the driver and utilities files in /moxa/mxser.
+       Following installation procedure depends on the model you'd like to
+       run the driver. If you prefer module driver, please refer to 3.3.
+       If static driver is required, please refer to 3.4.
+
+       Dialin and callout port
+       -----------------------
+       This driver remains traditional serial device properties. There're
+       two special file name for each serial port. One is dial-in port
+       which is named "ttyMxx". For callout port, the naming convention
+       is "cumxx".
+
+       Device naming when more than 2 boards installed
+       -----------------------------------------------
+       Naming convention for each Smartio multiport board is pre-defined
+       as below.
+
+       Board Num.	 Dial-in Port	      Callout port
+       1st board	ttyM0  - ttyM7	      cum0  - cum7
+       2nd board	ttyM8  - ttyM15       cum8  - cum15
+       3rd board	ttyM16 - ttyM23       cum16 - cum23
+       4th board	ttyM24 - ttym31       cum24 - cum31
+
+       Board sequence
+       --------------
+       This driver will activate ISA boards according to the parameter set
+       in the driver. After all specified ISA board activated, PCI board
+       will be installed in the system automatically driven.
+       Therefore the board number is sorted by the CAP address of ISA boards.
+       For PCI boards, their sequence will be after ISA boards and C168H/PCI
+       has higher priority than C104H/PCI boards.
+
+   3.3 Module driver configuration
+       Module driver is easiest way to install. If you prefer static driver
+       installation, please skip this paragraph.
+       1. Find "Makefile" in /moxa/mxser, then run
+
+	  # make install
+
+	  The driver files "mxser.o" and utilities will be properly compiled
+	  and copied to system directories respectively.Then run
+
+	  # insmod mxser
+
+	  to activate the moduler driver. You may run "lsmod" to check
+	  if "mxser.o" is activated.
+
+       2. Create special files by executing "msmknod".
+	  # cd /moxa/mxser/driver
+	  # ./msmknod
+
+	  Default major numbers for dial-in device and callout device are
+	  174, 175. Msmknod will delete any special files occuping the same
+	  device naming.
+
+       3. Up to now, you may manually execute "insmod mxser" to activate
+	  this driver and run "rmmod mxser" to remove it. However, it's
+	  better to have a boot time configuration to eliminate manual
+	  operation.
+	  Boot time configuration can be achieved by rc file. Run following
+	  command for setting rc files.
+
+	  # cd /moxa/mxser/driver
+	  # cp ./rc.mxser /etc/rc.d
+	  # cd /etc/rc.d
+
+	  You may have to modify part of the content in rc.mxser to specify
+          parameters for ISA board. Please refer to rc.mxser for more detail.
+          Find "rc.serial". If "rc.serial" doesn't exist, create it by vi.
+	  Add "rc.mxser" in last line. Next, open rc.local by vi
+	  and append following content.
+
+	  if [ -f /etc/rc.d/rc.serial ]; then
+	     sh /etc/rc.d/rc.serial
+	  fi
+
+       4. Reboot and check if mxser.o activated by "lsmod" command.
+       5. If you'd like to drive Smartio ISA boards in the system, you'll
+	  have to add parameter to specify CAP address of given board while
+          activating "mxser.o". The format for parameters are as follows.
+
+	  insmod mxser ioaddr=0x???,0x???,0x???,0x???
+				|      |     |	  |
+				|      |     |	  +- 4th ISA board
+				|      |     +------ 3rd ISA board
+				|      +------------ 2nd ISA board
+				+------------------- 1st ISA board
+
+   3.4 Static driver configuration
+
+       1. Create link
+	  # cd /usr/src/linux/drivers/char
+	  # ln -s /moxa/mxser/driver/mxser.c mxser.c
+
+       2. Add CAP address list for ISA boards
+	  In module mode, the CAP address for ISA board is given by
+	  parameter. In static driver configuration, you'll have to
+	  assign it within driver's source code. If you will not
+	  install any ISA boards, you may skip to next portion.
+	  The instructions to modify driver source code are as
+	  below.
+	  a. # cd /moxa/mxser/driver
+	     # vi mxser.c
+	  b. Find the array mxserBoardCAP[] as belows.
+
+	     static int mxserBoardCAP[]
+	     = {0x00, 0x00, 0x00, 0x00};
+
+	  c. Change the address within this array using vi. For
+	     example, to driver 2 ISA boards with CAP address
+	     0x280 and 0x180 as 1st and 2nd board. Just to change
+	     the source code as follows.
+
+	     static int mxserBoardCAP[]
+	     = {0x280, 0x180, 0x00, 0x00};
+
+       3. Modify tty_io.c
+	  # cd /usr/src/linux/drivers/char/
+	  # vi tty_io.c
+	    Find pty_init(), insert "mxser_init()" as
+
+	    pty_init();
+	    mxser_init();
+
+       4. Modify tty.h
+	  # cd /usr/src/linux/include/linux
+	  # vi tty.h
+	    Find extern int tty_init(void), insert "mxser_init()" as
+
+	    extern int tty_init(void);
+	    extern int mxser_init(void);
+     
+       5. Modify Makefile
+	  # cd /usr/src/linux/drivers/char
+	  # vi Makefile
+	    Find L_OBJS := tty_io.o ...... random.o, add
+	    "mxser.o" at last of this line as
+	    L_OBJS := tty_io.o ....... mxser.o
+
+       6. Rebuild kernel
+	  The following are for Linux kernel rebuilding,for your reference only.
+	  For appropriate details, please refer to the Linux document.
+
+	  If 'lilo' utility is installed, please use 'make zlilo' to rebuild
+	  kernel. If 'lilo' is not installed, please follow the following steps.
+
+	   a. cd /usr/src/linux
+	   b. make clean			     /* take a few minutes */
+	   c. make dep				     /* take a few minutes */
+	   d. make bzImage		   /* take probably 10-20 minutes */
+	   e. Backup original boot kernel.		  /* optional step */
+	   f. cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz
+	   g. Please make sure the boot kernel (vmlinuz) is in the
+	      correct position. If you use 'lilo' utility, you should
+	      check /etc/lilo.conf 'image' item specifiedd the path
+	      which is the 'vmlinuz' path, or you will load wrong
+	      (or old) boot kernel image (vmlinuz).
+	   h. chmod 400 /vmlinuz
+	   i. lilo
+	   j. rdev -R /vmlinuz 1
+	   k. sync
+
+	  Note that if the result of "make zImage" is ERROR, then you have to
+	  go back to Linux configuration Setup. Type "make config" in directory
+	  /usr/src/linux or "setup".
+
+	  Since system include file, /usr/src/linux/include/linux/interrupt.h,
+	  is modified each time the MOXA driver is installed, kernel rebuilding
+	  is inevitable. And it takes about 10 to 20 minutes depends on the
+	  machine.
+
+       7. Make utility
+	  # cd /moxa/mxser/utility
+	  # make install
+       
+       8. Make special file
+          # cd /moxa/mxser/driver
+          # ./msmknod
+
+       9. Reboot
+
+   3.5 Custom configuration
+       Although this driver already provides you default configuration, you
+       still can change the device name and major number.The instruction to
+       change these parameters are shown as below.
+
+       Change Device name
+       ------------------
+       If you'd like to use other device names instead of default naming
+       convention, all you have to do is to modify the internal code
+       within the shell script "msmknod". First, you have to open "msmknod"
+       by vi. Locate each line contains "ttyM" and "cum" and change them
+       to the device name you desired. "msmknod" creates the device names
+       you need next time executed.
+
+       Change Major number
+       -------------------
+       If major number 30 and 35 had been occupied, you may have to select
+       2 free major numbers for this driver. There are 3 steps to change
+       major numbers.
+
+       1. Find free major numbers
+	  In /proc/devices, you may find all the major numbers occupied
+	  in the system. Please select 2 major numbers that are available.
+	  e.g. 40, 45.
+       2. Create special files
+	  Run /moxa/mxser/driver/msmknod to create special files with
+	  specified major numbers.
+       3. Modify driver with new major number
+	  Run vi to open /moxa/mxser/driver/mxser.c. Locate the line
+	  contains "MXSERMAJOR". Change the content as below.
+	  #define	  MXSERMAJOR		  40
+	  #define	  MXSERCUMAJOR		  45
+       4. Run # make install in /moxa/mxser/driver.
+
+   3.6 Verify driver installation
+       You may refer to /var/log/messages to check the latest status
+       log reported by this driver whenever it's activated.
+-----------------------------------------------------------------------------
+4. Utilities
+   There are 3 utilities contained in this driver. They are msdiag, msmon and
+   msterm. These 3 utilities are released in form of source code. They should
+   be compiled into executable file and copied into /usr/bin.
+
+   msdiag - Diagnostic
+   --------------------
+   This utility provides the function to detect what Moxa Smartio multiport
+   board exists in the system.
+
+   msmon - Port Monitoring
+   -----------------------
+   This utility gives the user a quick view about all the MOXA ports'
+   activities. One can easily learn each port's total received/transmitted
+   (Rx/Tx) character count since the time when the monitoring is started.
+   Rx/Tx throughputs per second are also reported in interval basis (e.g.
+   the last 5 seconds) and in average basis (since the time the monitoring
+   is started). You can reset all ports' count by <HOME> key. <+> <->
+   (plus/minus) keys to change the displaying time interval. Press <ENTER>
+   on the port, that cursor stay, to view the port's communication
+   parameters, signal status, and input/output queue.
+
+   msterm - Terminal Emulation
+   ---------------------------
+   This utility provides data sending and receiving ability of all tty ports,
+   especially for MOXA ports. It is quite useful for testing simple
+   application, for example, sending AT command to a modem connected to the
+   port or used as a terminal for login purpose. Note that this is only a
+   dumb terminal emulation without handling full screen operation.
+-----------------------------------------------------------------------------
+5. Setserial
+
+   Supported Setserial parameters are listed as below.
+
+   uart 	  set UART type(16450-->disable FIFO, 16550A-->enable FIFO)
+   close_delay	  set the amount of time(in 1/100 of a second) that DTR
+		  should be kept low while being closed.
+   closing_wait   set the amount of time(in 1/100 of a second) that the
+		  serial port should wait for data to be drained while
+		  being closed, before the receiver is disable.
+   spd_hi	  Use  57.6kb  when  the application requests 38.4kb.
+   spd_vhi	  Use  115.2kb	when  the application requests 38.4kb.
+   spd_normal	  Use  38.4kb  when  the application requests 38.4kb.
+
+-----------------------------------------------------------------------------
+6. Troubleshooting
+
+   The boot time error mesages and solutions are stated as clearly as
+   possible. If all the possible solutions fail, please contact our technical
+   support team to get more help.
+
+   Error msg: More than 4 Moxa Smartio family boards found. Fifth board and
+	      after are ignored.
+   Solution:
+   To avoid this problem, please unplug fifth and after board, because Moxa
+   driver supports up to 4 boards.
+
+   Error msg: Request_irq fail, IRQ(?) may be conflict with another device.
+   Solution:
+   Other PCI or ISA devices occupy the assigned IRQ. If you are not sure
+   which device causes the situation,please check /proc/interrupts to find
+   free IRQ and simply change another free IRQ for Moxa board.
+
+   Error msg: Board #: C1xx Series(CAP=xxx) interupt number invalid.
+   Solution:
+   Each port within the same multiport board shares the same IRQ. Please set
+   one IRQ (IRQ doesn't equal to zero) for one Moxa board.
+
+   Error msg: No interrupt vector be set for Moxa ISA board(CAP=xxx).
+   Solution:
+   Moxa ISA board needs an interrupt vector.Please refer to user's manual
+   "Hardware Installation" chapter to set interrupt vector.
+
+   Error msg: Couldn't install MOXA Smartio family driver!
+   Solution:
+   Load Moxa driver fail, the major number may conflict with other devices.
+   Please refer to previous section 3.5 to change a free major number for
+   Moxa driver.
+
+   Error msg: Couldn't install MOXA Smartio family callout driver!
+   Solution:
+   Load Moxa callout driver fail, the callout device major number may
+   conflict with other devices. Please refer to previous section 3.5 to
+   change a free callout device major number for Moxa driver.
+-----------------------------------------------------------------------------
diff -u --recursive --new-file v2.3.39/linux/Documentation/parport.txt linux/Documentation/parport.txt
--- v2.3.39/linux/Documentation/parport.txt	Tue Jan  4 13:57:16 2000
+++ linux/Documentation/parport.txt	Thu Jan 20 12:35:23 2000
@@ -28,8 +28,12 @@
 
 to tell the parport code that you want three PC-style ports, one at
 0x3bc with no IRQ, one at 0x378 using IRQ 7, and one at 0x278 with an
-auto-detected IRQ.  Currently, PC-style (parport_pc), Sun Ultra/AX
-(parport_ax), Amiga, Atari, and MFC3 hardware is supported.
+auto-detected IRQ.  Currently, PC-style (parport_pc), Sun `bpp',
+Amiga, Atari, and MFC3 hardware is supported.
+
+PCI parallel I/O card support comes from parport_pc.  Base I/O
+addresses should not be specified for supported PCI cards since they
+are automatically detected.
 
 
 KMod
diff -u --recursive --new-file v2.3.39/linux/Documentation/sound/Introduction linux/Documentation/sound/Introduction
--- v2.3.39/linux/Documentation/sound/Introduction	Sun Nov  7 16:37:33 1999
+++ linux/Documentation/sound/Introduction	Thu Jan 20 10:44:46 2000
@@ -25,7 +25,8 @@
                    added info on multiple sound cards of similar types,]
                    added more diagnostics info, added info about esd.
                    added info on OSS and ALSA.
-
+1.1.1  19991031	   Added notes on sound-slot- and sound-service.
+			(Alan Cox)
 
 Modular Sound Drivers:
 ======================
@@ -321,6 +322,12 @@
 
 7)  Turn on debug in drivers/sound/sound_config.h (DEB, DDB, MDB).
 
+8)  If the system reports insuffcient DMA memory then you may want to
+    load sound with the "dmabufs=1" option. Or in /etc/conf.modules add
+	
+	preinstall sound dmabufs=1
+
+    This makes the sound system allocate its buffers and hang onto them.
 
 Configuring Sound:
 ==================
@@ -335,7 +342,7 @@
 
 3)  In /etc/modules.conf when using modprobe.
 
-4)  Via Red Hat's /usr/sbin/sndconfig program (text based).
+4)  Via Red Hat's GPL'd /usr/sbin/sndconfig program (text based).
 
 5)  Via the OSS soundconf program (with the commercial version
     of the OSS driver.
@@ -344,6 +351,28 @@
 
 Anyone want to write a linuxconf module for configuring sound?
 
+Module Loading:
+===============
+
+When a sound card is first referenced and sound is modular the sound system
+will ask for the sound devices to be loaded. Initially it requests that
+the driver for the sound system is loaded. It then wwill ask for 
+sound-slot-0, where 0 is the first sound card. (sound-slot-1 the second and
+so on). Thus you can do
+
+alias sound-slot-0 sb
+
+To load a soundblaster at this point. If the slot loading does not provide
+the desired device - for example a soundblaster does not directly provide
+a midi synth in all cases then it will request "sound-service-0-n" where n
+is
+
+0	Mixer
+
+2  	MIDI
+
+3, 4	DSP audio
+
 
 For More Information (RTFM):
 ============================
@@ -373,6 +402,3 @@
 Contact Information:
 ====================
 Wade Hampton:  (whampton@staffnet.com)
-
-
-
diff -u --recursive --new-file v2.3.39/linux/Documentation/sound/MultiSound linux/Documentation/sound/MultiSound
--- v2.3.39/linux/Documentation/sound/MultiSound	Wed Dec 16 12:52:00 1998
+++ linux/Documentation/sound/MultiSound	Thu Jan 20 10:44:46 2000
@@ -4,7 +4,7 @@
 #  -- Andrew Veliath <andrewtv@usa.net>
 #
 #  Last update:                      September 10, 1998
-#  Corresponding msnd driver:        0.8.2
+#  Corresponding msnd driver:        0.8.3
 #
 # ** This file is a README (top part) and shell archive (bottom part).
 #    The corresponding archived utility sources can be unpacked by
diff -u --recursive --new-file v2.3.39/linux/Documentation/sound/PSS linux/Documentation/sound/PSS
--- v2.3.39/linux/Documentation/sound/PSS	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/PSS	Thu Jan 20 10:44:46 2000
@@ -0,0 +1,41 @@
+The PSS cards and other ECHO based cards provide an onboard DSP with 
+downloadable programs and also has an AD1848 "Microsoft Sound System" 
+device. The PSS driver enables MSS and MPU401 modes of the card. SB 
+is not enabled since it doesn't work concurrently with MSS. 
+
+If you build this driver as a module then the driver takes the folowing
+parameters
+
+pss_io. 	The I/O base the PSS card is configured at (normally 0x220
+		or 0x240)
+
+mss_io		The base address of the Microsoft Sound System interface.
+		This is normally 0x530, but may be 0x604 or other addresses.
+
+mss_irq		The interrupt assigned to the Microsoft Sound System
+		emulation. IRQ's 3,5,7,9,10,11 and 12 are available. If you
+		get IRQ errors be sure to check the interrupt is set to 
+		"ISA/Legacy" in the BIOS on modern machines.
+
+mss_dma		The DMA channel used by the Microsoft Sound System.
+		This can be 0, 1, or 3. DMA 0 is not available on older 
+		machines and will cause a crash on them.
+
+mpu_io		The MPU emulation base address. This sets the base of the
+		synthesizer. It is typically 0x330 but can be altered.
+
+mpu_irq		The interrupt to use for the synthesizer. It must differ
+		from the IRQ used by the Microsoft Sound System port.
+
+
+The mpu_io/mpu_irq fields are optional. If they are not specified the 
+synthesizer parts are not configured.
+
+When the module is loaded it looks for a file called 
+/etc/sound/pss_synth. This is the firmware file from the DOS install disks.
+This fil holds a general MIDI emulation. The file expected is called
+genmidi.ld on newer DOS driver install disks and synth.ld on older ones.
+
+You can also load alternative DSP algorithms into the card if you wish. One
+alternative driver can be found at http://www.mpg123.de/
+
diff -u --recursive --new-file v2.3.39/linux/Documentation/sound/SoundPro linux/Documentation/sound/SoundPro
--- v2.3.39/linux/Documentation/sound/SoundPro	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/SoundPro	Thu Jan 20 10:44:46 2000
@@ -0,0 +1,103 @@
+Documentation for the SoundPro CMI8330 extensions in the WSS driver (ad1848.o)
+------------------------------------------------------------------------------
+
+Ion Badulescu, ionut@cs.columbia.edu
+February 24, 1999
+
+(derived from the OPL3-SA2 documentation by Scott Murray)
+
+The SoundPro CMI8330 (ISA) is a chip usually found on some Taiwanese
+motherboards.  The official name in the documentation is CMI8330, SoundPro
+is the nickname and the big inscription on the chip itself.
+
+The chip emulates a WSS as well as a SB16, but it has certain differences
+in the mixer section which require separate support. It also emulates an
+MPU401 and an OPL3 synthesizer, so you probably want to enable support
+for these, too.
+
+The chip identifies itself as an AD1848, but its mixer is significantly
+more advanced than the original AD1848 one. If your system works with
+either WSS or SB16 and you are having problems with some mixer controls
+(no CD audio, no line-in, etc), you might want to give this driver a try.
+Detection should work, but it hasn't been widely tested, so it might still
+mis-identify the chip. You can still force soundpro=1 in the modprobe
+parameters for ad1848. Please let me know if it happens to you, so I can
+adjust the detection routine.
+
+The chip is capable of doing full-duplex, but since the driver sees it as an
+AD1848, it cannot take advantage of this.  Moreover, the full-duplex mode is
+not achievable through the WSS interface, b/c it needs a dma16 line which is
+assigned only to the SB16 subdevice (with isapnp). Windows documentation
+says the user must use WSS Playback and SB16 Recording for full-duplex, so
+it might be possible to do the same thing under Linux. You can try loading
+up both ad1848 and sb then use one for playback and the other for
+recording. I don't know if this works, b/c I haven't tested it. Anyway, if
+you try it, be very careful: the SB16 mixer *mostly* works, but certain
+settings can have unexpected effects. Use the WSS mixer for best results.
+
+There is also a PCI SoundPro chip. I have not seen this chip, so I have
+no idea if the driver will work with it. I suspect it won't.
+
+As with PnP cards, some configuration is required.  There are two ways
+of doing this.  The most common is to use the isapnptools package to
+initialize the card, and use the kernel module form of the sound
+subsystem and sound drivers.  Alternatively, some BIOS's allow manual
+configuration of installed PnP devices in a BIOS menu, which should
+allow using the non-modular sound drivers, i.e. built into the kernel.
+Since in this latter case you cannot use module parameters, you will
+have to enable support for the SoundPro at compile time.
+
+The IRQ and DMA values can be any that are considered acceptable for a
+WSS.  Assuming you've got isapnp all happy, then you should be able to
+do something like the following (which *must* match the isapnp/BIOS
+configuration):
+
+modprobe ad1848 io=0x530 irq=11 dma=0 soundpro=1
+-and maybe-
+modprobe sb io=0x220 irq=5 dma=1 dma16=5
+
+-then-
+modprobe mpu401 io=0x330 irq=9
+modprobe opl3 io=0x388
+
+If all goes well and you see no error messages, you should be able to
+start using the sound capabilities of your system.  If you get an
+error message while trying to insert the module(s), then make
+sure that the values of the various arguments match what you specified
+in your isapnp configuration file, and that there is no conflict with
+another device for an I/O port or interrupt.  Checking the contents of
+/proc/ioports and /proc/interrupts can be useful to see if you're
+butting heads with another device.
+
+If you do not see the chipset version message, and none of the other
+messages present in the system log are helpful, try adding 'debug=1'
+to the ad1848 parameters, email me the syslog results and I'll do
+my best to help. 
+
+Lastly, if you're using modules and want to set up automatic module
+loading with kmod, the kernel module loader, here is the section I
+currently use in my conf.modules file:
+
+# Sound
+post-install sound modprobe -k ad1848; modprobe -k mpu401; modprobe -k opl3
+options ad1848 io=0x530 irq=11 dma=0
+options sb io=0x220 irq=5 dma=1 dma16=5
+options mpu401 io=0x330 irq=9
+options opl3 io=0x388
+
+The above ensures that ad1848 will be loaded whenever the sound system
+is being used.
+
+Good luck.
+
+Ion
+
+NOT REALLY TESTED:
+- recording
+- recording device selection
+- full-duplex
+
+TODO:
+- implement mixer support for surround, loud, digital CD switches.
+- come up with a scheme which allows recording volumes for each subdevice.
+This is a major OSS API change.
diff -u --recursive --new-file v2.3.39/linux/Documentation/usb/CREDITS linux/Documentation/usb/CREDITS
--- v2.3.39/linux/Documentation/usb/CREDITS	Tue Jan 11 22:31:36 2000
+++ linux/Documentation/usb/CREDITS	Mon Jan 17 22:19:12 2000
@@ -6,10 +6,12 @@
 
   Georg Acher <acher@informatik.tu-muenchen.de>
   Alan Cox <alan@lxorguk.ukuu.org.uk>
+  Randy Dunlap <randy.dunlap@intel.com>
   Johannes Erdfelt <jerdfelt@sventech.com>
   Deti Fliegl <deti@fliegl.de>
   ham <ham@unsuave.com>
   Bradley M Keryan <keryan@andrew.cmu.edu>
+  Greg Kroah-Hartman <greg@kroah.com>
   Paul Mackerras <paulus@cs.anu.edu.au>
   David E. Nelson <dnelson@jump.net>
   Vojtech Pavlik <vojtech@suse.cz>
@@ -104,6 +106,9 @@
         - Thanks to Entrega for providing PCI to USB cards, hubs and
           converter products for development. 
 
+	- Thanks to ConnectTech for providing a WhiteHEAT usb to
+	  serial converter, and the documentation for the device to
+	  allow a driver to be written.
 
         And thanks go to (hey! in no particular order :)
 
@@ -160,4 +165,3 @@
           for convincing me USB Standard hubs are not that standard
           and that's good to allow for vendor specific quirks on the
           standard hub driver.
-
diff -u --recursive --new-file v2.3.39/linux/Documentation/usb/dc2xx.txt linux/Documentation/usb/dc2xx.txt
--- v2.3.39/linux/Documentation/usb/dc2xx.txt	Thu Jan  6 12:57:47 2000
+++ linux/Documentation/usb/dc2xx.txt	Thu Jan 20 09:48:48 2000
@@ -1,4 +1,4 @@
-13 November 1999
+19 January 2000
 david-b@pacbell.net
 
 This is an overview of how to use the "dc2xx" USB driver with certain
@@ -15,14 +15,13 @@
 (www.gphoto.org), since version 0.4 and later know how to use it to talk
 to Kodak DC-240 and DC-280 cameras over USB.
 
-In addition the DC-260, DC-265, and DC-290 are currently recognized.
+In addition the DC-220, DC-260, DC-265, and DC-290 are also recognized.
 However, like other cameras using the "Digita OS" (from www.flashpoint.com)
 there is no gPhoto support for this camera.  At this writing the best
 known support for these cameras is a Python script that supports image
 downloading from those cameras.  (See archives of the linux-usb mailing
-list.)  The DC-220 should also work with this driver, given information
-about the USB product IDs.  When it becomes available, the HP PhotoSmart
-C500 should also work ... it's another Digita OS camera with USB support.)
+list.)  When it becomes available, the HP PhotoSmart C500 should also
+work ... it's another Digita OS camera with USB support.
 
 It's likely that other digital still cameras can also use this USB driver,
 even if they're not from Kodak and don't use Digita.  The reason is that
@@ -35,30 +34,33 @@
 
 This has been shown to work on x86 OHCI and UHCI (Intel) chipsets.  OHCI has
 been trouble free; not so with UHCI, which was first seen to be happy with
-2.3.24 kernels, and has not been as fast as OHCI.
+2.3.24 kernels, and has not been as fast as OHCI.  Users on the PowerMac
+platform have had success, although the stock kernel doesn't yet support
+that platform.
 
 Note that in some cases changes in BIOS settings may be needed before
 your USB works.  At least one user has reported a need for SMP-related 
 settings as well.
 
-As yet, no reports have come from Linux users on non-Intel hardware.
-(You could color coordinate your iMac with a DC-240i ... :-)
-
 
 SETUP
 
-Configure in the DC2XX USB driver, and have it in your kernel.  Recently I
-compile it right in, but I've done it as a module in the past.
-
-Create a device, perhaps like this (both read and write):
+Configure in the DC2XX USB driver, and have it in your kernel.  It works
+as a module, or compiled in directly.
 
-    # mknod -m 0666 /dev/kodak c 10 170
+Create at least one device, perhaps like this (both read and write):
 
-That "170" is not formally assigned, and this command may change.  If you're
-using a non-Kodak camera, you may prefer another name.
-
-Don't plug in more than one compatible camera at this time.  One of them
-will be ignored, but I'd not be sure which one!
+    # mknod -m 0666 /dev/kodak00 c 180 80
+    # mknod -m 0666 /dev/kodak01 c 180 81
+    ...
+
+The driver supports multiple device nodes.  The USB framework supports
+a maximum of sixteen device nodes (up to minor device number 96), though
+by default fewer devices are available.
+
+When you plug in one camera, it will use the first device node (kodak00
+in the example above).  A second camera will use the second device node,
+and so on.
 
 
 SANITY TESTING
@@ -66,14 +68,11 @@
 First:  if you've got /proc support, make sure that the driver has hooked
 itself up correctly.
 
-    - you should see an entry in /proc/misc for the a Kodak DC-2xx
-      minor device number
-
-    - you should see an entry in /proc/bus/usb/drivers for "dc2xx",
-      if you also enabled USB /proc support.
+    - You should see an entry in /proc/bus/usb/drivers for "dc2xx",
+      if you enabled USB /proc support.
 
 Second:  when you connect your camera to the computer, does it get recognized
-by the driver?
+by the driver?  (Make sure the camera is powered on!)
 
     - if you've got /proc/bus/usb/devices, you should see an entry
       something like this.  The "ProdID" may be different if you didn't
@@ -87,19 +86,16 @@
 	E:  Ad=01(O) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
 	E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=  0ms
 
-    - if you don't have /proc support for USB, see if "dmesg" output
-      tells you that you plugged in your camera.
+    - see if "dmesg" output tells you that you plugged in your camera.
 
-	USB new device connect, assigned device number 1
 	Manufacturer: Eastman Kodak Company
 	Product: KODAK DC240 Zoom Digital Camera
-	USB Camera is connected
-	usbcore: dc2xx driver claimed interface c3a68600
-	ohci-control thread sleeping
+	Serial Number: ?
+	dc2xx.c: USB Camera #0 connected
 
 Third:  (optional) can you use gPhoto to talk to the camera?
 
-    - When you configure your camera, tell it to use "/dev/kodak" (or
+    - When you configure your camera, tell it to use "/dev/kodak00" (or
       whatever name you used).  Right now, gPhoto emits a diagnostic
       message (non-GUI) saying that it since it didn't act like a TTY,
       it's assuming it's got a USB connection.
@@ -108,3 +104,10 @@
       talk to the camera -- and tell you you're using USB.
 
 If you got that far, you should be able to use everything fine.
+
+
+ADDITIONAL INFORMATION
+
+You may find that you need more driver-specific information, which is
+currently accessible through a link from http://www.linux-usb.org/
+along with other Linux USB resources.
diff -u --recursive --new-file v2.3.39/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt
--- v2.3.39/linux/Documentation/usb/ov511.txt	Tue Jan 11 22:31:36 2000
+++ linux/Documentation/usb/ov511.txt	Mon Jan 17 16:24:48 2000
@@ -2,22 +2,28 @@
 Readme for Linux device driver for the OmniVision OV511 USB to camera bridge IC
 -------------------------------------------------------------------------------
 
+Author: Mark McClelland
+Homepage: http://people.delphi.com/mmcclelland/linux/
+
 INTRODUCTION:
 
 This is a preliminary version of my OV511 Linux device driver. Currently, it can
-grab a frame in black-and-white at 640x480 using the vidcat utility. Color,
-variable image size, and compatibility with other apps are currently under
-development.
+grab a frame in color (YUV420) at 640x480 or 320x240 using either vidcat or
+xawtv. Other utilities may work but have not yet been tested.
+
+NOTE: 320x240 does not work reliably for me, and causes complete system crashes.
+      I recommend not using it until a later version, and if you do, run "sync"
+      first.
 
 SUPPORTED CAMERAS:
 ________________________________________________________
 Manufacturer     | Model          | Custom ID | Status
 -----------------+----------------+-----------+---------
 MediaForte       | MV300          | 0         | Untested
-D-Link           | DSB-C300	      | 3         | Working
+D-Link           | DSB-C300       | 3         | Working
 Creative Labs    | WebCam 3       | 21        | Working
-Lifeview         | RoboCam        |	100       | Untested
-AverMedia        | InterCam Elite | 102       | Untested
+Lifeview         | RoboCam        | 100       | Untested
+AverMedia        | InterCam Elite | 102       | Working
 --------------------------------------------------------
 
 Any camera using the OV511 and the OV7610 CCD should work with this driver. The
@@ -32,9 +38,55 @@
 - If you want to help with the development, get the chip's specification docs at
   http://www.ovt.com/omniusbp.html
 
-- A Video4Linux compatible frame grabber program (I recommend vidcat)
+- A Video4Linux compatible frame grabber program (I recommend vidcat and xawtv)
   (see: http://www.exploits.org/v4l/ )
-  
+
+HOW TO USE IT:
+
+You must have first compiled USB support, support for your specific USB host
+controller (UHCI or OHCI), and Video4Linux support for your kernel (I recommend
+making them modules.) 
+
+Next, (as root) from your appropriate modules directory (lib/modules/2.3.XX):
+
+	insmod usb/usbcore.o
+	insmod usb/usb-uhci.o  <OR>  insmod usb/ohci-hcd.o
+	insmod misc/videodev.o
+	insmod usb/ov511.o
+
+If it is not already there (it usually is), create the video device:
+
+	mknod /dev/video c 81 0
+	
+Now you are ready to run a video app! Both vidcat and xawtv work well for me
+at 640x480.
+	
+[Using vidcat:]
+
+	vidcat -s 640x480 > test.jpg
+	xview test.jpg
+	
+[Using xawtv:]
+
+You must make some modifications to the source and compile it before you use it.
+(Note: this may not be applicable to versions other than 3.06)
+
+In src/Xawtv.ad, change xawtv.tv.width to 640 and xawtv.tv.height to 480. Next,
+in src/grab-v4l.c, change SYNC_TIMEOUT from 1 to 2. Then, from the main xawtv
+directory:
+
+	make clean
+	./configure
+	make
+	make install
+
+Now you should be able to run xawtv. Right click for the options dialog.
+
+WORKING FEATURES:
+ o Color streaming/capture at 640x480 (reliably) and 320x240 (unreliably)
+ o YUV420 color
+ o Setting/getting of saturation, contrast and brightness (no color yet)
+
 WHAT NEEDS TO BE DONE:
 
 The rest of the work will involve implementing support for all the different
@@ -55,4 +107,4 @@
 The code is based in no small part on the CPiA driver by Johannes Erdfelt,
 Randy Dunlap, and others. Big thanks to them for their pioneering work on that
 and the USB stack. Thanks to Bret Wallach for getting camera reg IO , ISOC, and
-preliminary image capture working.
+image capture working.
diff -u --recursive --new-file v2.3.39/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- v2.3.39/linux/Documentation/usb/usb-serial.txt	Thu Jan  6 12:57:47 2000
+++ linux/Documentation/usb/usb-serial.txt	Fri Jan 14 11:25:21 2000
@@ -1,42 +1,115 @@
-This serial driver currently only works with the Belkin and Peracom USB 
-Serial devices. It should also work for the Etek converter, but I do 
-not know the vendor id and device id of that device (if anyone does, 
-please let me know.)
-
-If your device is not compatible with the above models, you can try
-out the "generic" interface. This interface does not provide any type
-of control messages sent to the device, and does not support any kind
-of device flow control. All that is required of your device is that
-it has at least one bulk in endpoint, or one bulk out endpoint.
-To enable the driver to recognize your device, build the driver as
-a module and load it by the following invocation:
-	insmod usb-serial.o vendor=0x#### product=0x####
-where the #### is replaced with the hex representation of your device's
-vendor id and product id.
-
-The driver can handle enumerating the device, and sending and receiving
-data from the converter. However, since I do not have a spec for the Belkin,
-Peracom, and eTek devices, and the raw dumps from the Win98 driver are 
-confusing, and eTek keeps giving me the run around, no control signals are 
-currently handled, and the data will most likely come through on a baud
-rate that you are not expecting. So if you have these devices, do not 
-expect the correct data to show up at either end. 
-
-The major number that the driver uses is 188 so to use the driver, create
-the following nodes:
-mknod /dev/ttyUSB0 c 188 0
-mknod /dev/ttyUSB1 c 188 1
-mknod /dev/ttyUSB2 c 188 2
-mknod /dev/ttyUSB3 c 188 3
-
-then plug in a device and use your friendly terminal program to see what
-happens.
+INTRODUCTION
 
-If anyone has any problems getting the device to enumerate, or data to 
-flow through it, please contact me.
+  The USB serial driver currently supports a number of different USB to
+  serial converter products, as well as some devices that use a serial
+  interface from userspace to talk to the device.
+
+  See the individual product section below for specific information about
+  the different devices.
+
+
+CONFIGURATION
+
+  Currently the driver can handle up to 16 different serial interfaces at
+  one time. Once more of the drivers become stable, this number will be
+  increased to the full 256. 
+
+  The major number that the driver uses is 188 so to use the driver,
+  create the following nodes:
+	mknod /dev/ttyUSB0 c 188 0
+	mknod /dev/ttyUSB1 c 188 1
+	mknod /dev/ttyUSB2 c 188 2
+	mknod /dev/ttyUSB3 c 188 3
+	mknod /dev/ttyUSB4 c 188 4
+	mknod /dev/ttyUSB5 c 188 5
+	mknod /dev/ttyUSB6 c 188 6
+	mknod /dev/ttyUSB7 c 188 7
+	mknod /dev/ttyUSB8 c 188 8
+	mknod /dev/ttyUSB9 c 188 9
+	mknod /dev/ttyUSB10 c 188 10
+	mknod /dev/ttyUSB11 c 188 11
+	mknod /dev/ttyUSB12 c 188 12
+	mknod /dev/ttyUSB13 c 188 13
+	mknod /dev/ttyUSB14 c 188 14
+	mknod /dev/ttyUSB15 c 188 15
+	mknod /dev/ttyUSB16 c 188 16
+
+
+SPECIFIC DEVICES SUPPORTED
+
+
+ConnectTech WhiteHEAT 4 port converter
+
+  ConnectTech has been very forthcoming with information about their
+  device, including providing a unit to test with. This driver will end up
+  being fully supported.
+
+Current status:
+  The device's firmware is downloaded on connection, but the use of a
+  special Anchor Chips extension is currently giving me problems.
+  This driver is not fully operational.
+
+
+HandSpring Visor USB docking station
+
+Current status:
+  Only when the Visor tries to connect to the host, does the docking
+  station show up as a valid USB device. When this happens, the device is
+  properly enumerated, assigned a port, and then communication _should_ be
+  possible. The driver cleans up properly when the device is removed, or
+  the connection is canceled on the Visor.
+  
+  I write _should_ because communication does not seem to work properly at
+  this time. I am in contact with the developers at HandSpring and am
+  working at getting this to work properly.
+
+  There is a webpage for this portion of the driver at 
+  http://milosch.net/visor/ and a project set up with mailing lists for
+  it at :
+  http://sourceforge.net/project/?group_id=1404
+
+
+Belkin single port serial converter
+Peracom single port serial converter
+
+Current status:
+  The driver can handle enumerating the device, and sending and receiving
+  data from the converter. However, since I do not have a spec for the
+  Belkin, Peracom, and eTek devices, and the raw dumps from the Win98
+  driver are confusing, and eTek refuses to provide documentation on their
+  protocol, no control signals are currently handled, and the data will
+  most likely come through on a baud rate that you are not expecting. So
+  if you have these devices, do not expect the correct data to show up at 
+  either end. 
+  
+
+Generic Serial driver
+
+  If your device is not one of the above listed devices, compatible with
+  the above models, you can try out the "generic" interface. This
+  interface does not provide any type of control messages sent to the
+  device, and does not support any kind of device flow control. All that
+  is required of your device is that it has at least one bulk in endpoint,
+  or one bulk out endpoint. 
+  
+  To enable the generic driver to recognize your device, build the driver
+  as a module and load it by the following invocation:
+	insmod usb-serial vendor=0x#### product=0x####
+  where the #### is replaced with the hex representation of your device's
+  vendor id and product id.
+
+  This driver has been successfully used to connect to the NetChip USB
+  development board, providing a way to develop USB firmware without
+  having to write a custom driver.
+
+
+CONTACT:
+
+  If anyone has any problems using this driver, with any of the above
+  specified products, please contact me, or join the Linux-USB mailing
+  list (information on joining the mailing list, as well as a link to its
+  searchable archive is at http://www.linux-usb.org/ )
 
 
-
-greg k-h
+Greg Kroah-Hartman
 greg@kroah.com
-
diff -u --recursive --new-file v2.3.39/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.39/linux/MAINTAINERS	Tue Jan 11 22:31:36 2000
+++ linux/MAINTAINERS	Mon Jan 17 22:19:08 2000
@@ -243,7 +243,7 @@
 
 CYCLADES ASYNC MUX DRIVER
 P:	Ivan Passos
-M:	Ivan Passos <ivan@cyclades.com>
+M:	ivan@cyclades.com
 W:	http://www.cyclades.com/
 S:	Supported
 
diff -u --recursive --new-file v2.3.39/linux/Makefile linux/Makefile
--- v2.3.39/linux/Makefile	Tue Jan 11 22:31:36 2000
+++ linux/Makefile	Mon Jan 17 22:22:52 2000
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 39
+SUBLEVEL = 40
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -158,6 +158,10 @@
 DRIVERS := $(DRIVERS) drivers/scsi/scsi.a
 endif
 
+ifeq ($(CONFIG_IEEE1394),y)
+DRIVERS := $(DRIVERS) drivers/ieee1394/ieee1394.a
+endif
+
 ifneq ($(CONFIG_CD_NO_IDESCSI)$(CONFIG_BLK_DEV_IDECD)$(CONFIG_BLK_DEV_SR)$(CONFIG_PARIDE_PCD),)
 DRIVERS := $(DRIVERS) drivers/cdrom/cdrom.a
 endif
@@ -202,7 +206,7 @@
 DRIVERS := $(DRIVERS) drivers/macintosh/macintosh.a
 endif
 
-ifeq ($(CONFIG_PNP),y)
+ifeq ($(CONFIG_ISAPNP),y)
 DRIVERS := $(DRIVERS) drivers/pnp/isa-pnp.o
 endif
 
@@ -397,6 +401,7 @@
 	if [ -f IRDA_MODULES  ]; then inst_mod IRDA_MODULES  net;   fi; \
 	if [ -f SK98LIN_MODULES ]; then inst_mod SK98LIN_MODULES  net;   fi; \
 	if [ -f USB_MODULES   ]; then inst_mod USB_MODULES   usb;   fi; \
+	if [ -f IEEE1394_MODULES ]; then inst_mod IEEE1394_MODULES ieee1394; fi; \
 	if [ -f PCMCIA_MODULES ]; then inst_mod PCMCIA_MODULES pcmcia; fi; \
 	if [ -f PCMCIA_NET_MODULES ]; then inst_mod PCMCIA_NET_MODULES pcmcia; fi; \
 	if [ -f PCMCIA_CHAR_MODULES ]; then inst_mod PCMCIA_CHAR_MODULES pcmcia; fi; \
@@ -482,7 +487,7 @@
 
 # make checkconfig: Prune 'scripts' directory to avoid "false positives".
 checkconfig:
-	perl -w scripts/checkconfig.pl `find * -path 'scripts' -prune -o -name '*.[hcS]' -print | sort`
+	find * -name '*.[hcS]' -type f -print | grep -v scripts/ | sort | xargs perl -w scripts/checkconfig.pl
 
 checkhelp:
 	perl -w scripts/checkhelp.pl `find * -name [cC]onfig.in -print`
diff -u --recursive --new-file v2.3.39/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.3.39/linux/arch/alpha/config.in	Wed Dec  8 14:11:24 1999
+++ linux/arch/alpha/config.in	Wed Jan 12 09:20:56 2000
@@ -2,6 +2,9 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
+
+define_bool CONFIG_UID16 n
+
 mainmenu_name "Kernel configuration of Linux for Alpha machines"
 
 mainmenu_option next_comment
@@ -180,6 +183,12 @@
 
 source drivers/pci/Config.in
 
+bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+ 
+if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+   source drivers/pcmcia/Config.in
+fi
+
 bool 'Networking support' CONFIG_NET
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
@@ -249,6 +258,10 @@
 endmenu
 
 source drivers/char/Config.in
+
+source drivers/usb/Config.in
+
+source drivers/misc/Config.in
 
 source fs/Config.in
 
diff -u --recursive --new-file v2.3.39/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.3.39/linux/arch/alpha/defconfig	Wed Dec  8 14:11:24 1999
+++ linux/arch/alpha/defconfig	Mon Jan 17 22:22:52 2000
@@ -28,6 +28,7 @@
 # CONFIG_ALPHA_EB64P is not set
 # CONFIG_ALPHA_EB66 is not set
 # CONFIG_ALPHA_EB66P is not set
+# CONFIG_ALPHA_EIGER is not set
 # CONFIG_ALPHA_JENSEN is not set
 # CONFIG_ALPHA_LX164 is not set
 # CONFIG_ALPHA_MIATA is not set
@@ -44,14 +45,15 @@
 # CONFIG_ALPHA_SABLE is not set
 # CONFIG_ALPHA_TAKARA is not set
 CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
 # CONFIG_SMP is not set
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
 CONFIG_KCORE_ELF=y
 # CONFIG_KCORE_AOUT is not set
-CONFIG_SYSCTL=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
@@ -84,6 +86,7 @@
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_IDE_MODES is not set
@@ -92,7 +95,8 @@
 #
 # Networking options
 #
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
@@ -135,6 +139,7 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
+# CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
@@ -148,6 +153,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -164,6 +170,7 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_NCR53C8XX is not set
 # CONFIG_SCSI_SYM53C8XX is not set
@@ -201,6 +208,7 @@
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
 # CONFIG_PCNET32 is not set
@@ -211,16 +219,27 @@
 # CONFIG_DGRS is not set
 # CONFIG_EEXPRESS_PRO100 is not set
 # CONFIG_NE2K_PCI is not set
+# CONFIG_SIS900 is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
 # CONFIG_NET_RADIO is not set
 
 #
-# Token ring devices
+# Token Ring driver support
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -228,13 +247,7 @@
 #
 # Wan interfaces
 #
-# CONFIG_HOSTESS_SV11 is not set
-# CONFIG_COSA is not set
-# CONFIG_SEALEVEL_4021 is not set
-# CONFIG_DLCI is not set
-# CONFIG_WAN_DRIVERS is not set
-# CONFIG_LAPBETHER is not set
-# CONFIG_X25_ASY is not set
+# CONFIG_WAN is not set
 
 #
 # Amateur Radio support
@@ -264,6 +277,11 @@
 CONFIG_UNIX98_PTY_COUNT=256
 
 #
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
@@ -271,7 +289,16 @@
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -280,17 +307,25 @@
 # Video For Linux
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Misc devices
+#
 
 #
 # Filesystems
@@ -298,11 +333,11 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
+# CONFIG_CRAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
@@ -313,6 +348,7 @@
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
@@ -320,6 +356,7 @@
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFSD is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
@@ -329,16 +366,20 @@
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
 CONFIG_OSF_PARTITION=y
-# CONFIG_SMD_DISKLABEL is not set
-# CONFIG_SGI_DISKLABEL is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
 # Console drivers
 #
 CONFIG_VGA_CONSOLE=y
+
+#
+# Frame-buffer support
+#
 # CONFIG_FB is not set
 
 #
diff -u --recursive --new-file v2.3.39/linux/arch/alpha/kernel/core_mcpcia.c linux/arch/alpha/kernel/core_mcpcia.c
--- v2.3.39/linux/arch/alpha/kernel/core_mcpcia.c	Wed Dec 15 10:43:16 1999
+++ linux/arch/alpha/kernel/core_mcpcia.c	Wed Jan 12 11:51:49 2000
@@ -560,12 +560,14 @@
 
 	switch (expected) {
 	case 0:
+	    {
 		/* FIXME: how do we figure out which hose the
 		   error was on?  */	
 		struct pci_controler *hose;
 		for (hose = hose_head; hose; hose = hose->next)
 			mcpcia_pci_clr_err(hose2mid(hose->index));
 		break;
+	    }
 	case 1:
 		mcpcia_pci_clr_err(mcheck_extra(cpu));
 		break;
diff -u --recursive --new-file v2.3.39/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.3.39/linux/arch/alpha/kernel/osf_sys.c	Tue Jan 11 22:31:36 2000
+++ linux/arch/alpha/kernel/osf_sys.c	Tue Jan 11 14:18:38 2000
@@ -439,7 +439,7 @@
 
 	dentry = getdev(tmp.devname, 0);
 	retval = PTR_ERR(dentry);
-	if (IS_ERR(dentry)
+	if (IS_ERR(dentry))
 		goto out;
 	retval = do_mount(dentry->d_inode->i_bdev, tmp.devname, dirname, 
 				"ext2", flags, NULL);
@@ -471,7 +471,6 @@
 
 static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags)
 {
-	int retval;
 	struct procfs_args tmp;
 
 	if (copy_from_user(&tmp, args, sizeof(tmp)))
diff -u --recursive --new-file v2.3.39/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c
--- v2.3.39/linux/arch/alpha/kernel/pci.c	Wed Dec 15 10:43:16 1999
+++ linux/arch/alpha/kernel/pci.c	Tue Jan 11 14:22:31 2000
@@ -251,11 +251,13 @@
 	/* Propogate hose info into the subordinate devices.  */
 
 	struct pci_controler *hose = (struct pci_controler *) bus->sysdata;
-	struct pci_dev *dev;
+	struct list_head *ln;
 
 	bus->resource[0] = hose->io_space;
 	bus->resource[1] = hose->mem_space;
-	for (dev = bus->devices; dev; dev = dev->sibling) {
+
+	for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
+		struct pci_dev *dev = pci_dev_b(ln);
 		if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
 			pcibios_fixup_device_resources(dev, bus);
 	}
@@ -322,6 +324,13 @@
 	ranges->mem_end -= bus->resource[1]->start;
 }
 
+int __init
+pcibios_enable_device(struct pci_dev *dev)
+{
+	/* Not needed, since we enable all devices at startup.  */
+	return 0;
+}
+
 void __init
 common_init_pci(void)
 {
@@ -339,8 +348,7 @@
 		next_busno += 1;
 	}
 
-	pci_assign_unassigned_resources(alpha_mv.min_io_address,
-				        alpha_mv.min_mem_address);
+	pci_assign_unassigned_resources();
 	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
 	pci_set_bus_ranges();
 }
diff -u --recursive --new-file v2.3.39/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c
--- v2.3.39/linux/arch/alpha/mm/init.c	Wed Dec 15 10:43:16 1999
+++ linux/arch/alpha/mm/init.c	Tue Jan 11 14:18:38 2000
@@ -274,7 +274,8 @@
 }
 #endif
 
-static void __init printk_memory_info(void)
+static void __init
+printk_memory_info(void)
 {
 	unsigned long codesize, reservedpages, datasize, initsize, tmp;
 	extern int page_is_ram(unsigned long) __init;
diff -u --recursive --new-file v2.3.39/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.3.39/linux/arch/arm/Makefile	Tue Dec  7 09:32:40 1999
+++ linux/arch/arm/Makefile	Thu Jan 13 13:30:30 2000
@@ -136,7 +136,7 @@
 ARCHDIR		 = nexuspci
 endif
 
-ifeq ($(CONFIG_ARCH_SA1100),u)
+ifeq ($(CONFIG_ARCH_SA1100),y)
 MACHINE		 = sa1100
 ARCHDIR		 = sa1100
 endif
@@ -146,7 +146,7 @@
 SUBDIRS		+= arch/arm/kernel arch/arm/mm arch/arm/lib \
 		   arch/arm/special arch/arm/nwfpe
 CORE_FILES	:= arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
-LIBS		:= arch/arm/lib/lib.a $(LIBS) $(GCCLIB)
+LIBS		:= arch/arm/lib/lib.o arch/arm/lib/lib.a $(LIBS) $(GCCLIB)
 DRIVERS		+= arch/arm/special/special.a
 
 ifeq ($(CONFIG_NWFPE),y)
diff -u --recursive --new-file v2.3.39/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile
--- v2.3.39/linux/arch/arm/boot/compressed/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/arm/boot/compressed/Makefile	Thu Jan 13 13:30:30 2000
@@ -44,9 +44,9 @@
 ZRELADDR	 = 0x40008000
 endif
 
-ifeq ($(CONFIG_ARCH_SA110),y)
+ifeq ($(CONFIG_ARCH_SA1100),y)
+OBJS		+= head-sa1100.o
 ifeq ($(CONFIG_SA1100_VICTOR),y)
-HEAD		 = head-victor.o
 ZTEXTADDR	 = 0x00002000
 ZBSSADDR	 = 0xc0100000
 else
@@ -91,7 +91,7 @@
 vmlinux.lds:	vmlinux.lds.in
 		@sed "$(SEDFLAGS)" < vmlinux.lds.in > $@
 
-clean:;		rm -f vmlinux core piggy*
+clean:;		rm -f vmlinux core piggy* vmlinux.lds
 
 .PHONY:	vmlinux.lds clean
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/boot/compressed/head-sa1100.S linux/arch/arm/boot/compressed/head-sa1100.S
--- v2.3.39/linux/arch/arm/boot/compressed/head-sa1100.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/boot/compressed/head-sa1100.S	Thu Jan 13 13:30:30 2000
@@ -0,0 +1,65 @@
+/* 
+ * linux/arch/arm/boot/compressed/head-sa1100.S
+ * 
+ * Copyright (C) 1999 Nicolas Pitre <nico@cam.org>
+ * 
+ * SA1100 specific tweaks.  This is merged with head.S by the linker.
+ */
+
+#include <linux/config.h>
+
+
+		.section        ".start", #alloc, #execinstr
+
+#ifndef CONFIG_ARCH_SA1100
+#error What am I doing here...
+#endif
+
+#ifdef CONFIG_SA1100_BRUTUS
+@ need to enter SVC mode
+#define angel_SWIreason_EnterSVC 0x17   /* from arm.h, in angel source */
+#define angel_SWI_ARM (0xEF123456 & 0xffffff)
+		mov	r0, #angel_SWIreason_EnterSVC
+		swi	#angel_SWI_ARM
+
+		@ turn off interrupts to prevent the angel from running
+		mrs	r0, cpsr
+		orr	r0, r0, #0xc0
+		msr	cpsr, r0
+#endif
+
+#ifdef CONFIG_SA1100_VICTOR
+		@ Copy cmdline to 0xc0000000
+		mov	r1, #0xc0000000
+		cmp	r0, #0
+		moveq	r2, #0
+1:		ldrneb	r2, [r0], #1
+		cmpne	r2, #0
+		strb	r2, [r1], #1
+		bne	1b
+#endif
+
+		@ Data cache might be active.
+		@ Be sure to flush kernel binary out of the cache,
+		@ whatever state it is, before it is turned off.
+		@ This is done by fetching through currently executed
+		@ memory to be sure we hit the same cache.
+		bic	r2, pc, #0x1f
+		add	r3, r2, #0x4000		@ 16 kb is quite enough...
+1:		ldr	r0, [r2], #32
+		teq	r2, r3
+		bne	1b
+		mcr	p15, 0, r0, c7, c10, 4	@ drain WB
+		mcr	p15, 0, r0, c7, c7, 0	@ flush I & D caches
+
+		@ disabling MMU, enabling I cache
+		mrc	p15, 0, r0, c1, c0, 0	@ read control reg
+		bic	r0, r0, #0x0d		@ clear WB, DC, MMU
+		orr	r0, r0, #0x1000		@ set Icache
+		mcr	p15, 0, r0, c1, c0, 0
+
+		@ set registers for entry
+		mov	r0, #0
+		mov	r1, #16
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/boot/compressed/head-victor.S linux/arch/arm/boot/compressed/head-victor.S
--- v2.3.39/linux/arch/arm/boot/compressed/head-victor.S	Fri Oct 22 13:21:43 1999
+++ linux/arch/arm/boot/compressed/head-victor.S	Wed Dec 31 16:00:00 1969
@@ -1,45 +0,0 @@
-/*
- * linux/arch/arm/boot/compressed/head-victor.S
- *
- * Copyright (C) 1998 Nicolas Pitre <nico@visuaide.com>
- */
-
-#include <linux/linkage.h>
-
-		.text
-		.globl	_start
-_start:
-		@ just in case we still use an a.out loader...
-		nop
-		nop
-		nop
-		nop
-		nop
-		nop
-		nop
-		nop
-
-		@ load different addresses
-		adr	r2, LC0
-		ldmia	r2, {r4, r5, r6, sp}
-
-		@ clear BSS
-		mov	r2, #0
-1:		str	r2, [r5], #4
-		cmp	r5, r6
-		blt	1b
-
-		@ uncompress the kernel
-		mov	r8, r0		@ save cmdline ptr
-		mov	r0, r4		@ where to put uncompressed data
-		add	r1, r6, #31
-		bic	r1, r1, #31	@ free memory space
-		add	r2, r1, #65536	@ end of free mem space
-		bl	SYMBOL_NAME(decompress_kernel)
-		mov	r0, r8		@ retrieve cmdline ptr
-		mov	pc, r4		@ call via EXEC entry
-
-LC0:		.word	_load_addr
-		.word	__bss_start
-		.word	SYMBOL_NAME(_end)
-		.word	SYMBOL_NAME(user_stack)+4096
diff -u --recursive --new-file v2.3.39/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S
--- v2.3.39/linux/arch/arm/boot/compressed/head.S	Mon Nov  1 13:56:26 1999
+++ linux/arch/arm/boot/compressed/head.S	Thu Jan 13 13:30:30 2000
@@ -77,10 +77,10 @@
 		cmp	r2, r3
 		blt	1b
 
-		eor	r1, r6, #0x44 << 24	@ SA-110?
+		eor	r1, r6, #0x44 << 24	@ SA-110 or SA-1100?
 		eor	r1, r1, #0x01 << 16
 		eor	r1, r1, #0xa1 << 8
-		movs	r1, r1, lsr #4
+		movs	r1, r1, lsr #5
 		mcreq	p15, 0, r1, c7, c7, 0	@ flush I & D-cache
 		mcreq	p15, 0, r1, c7, c10, 4	@ drain WB
 		add	pc, r5, r0		@ call relocation code
@@ -144,10 +144,10 @@
 	mov r0, r4
 	bl  memdump
 #endif
-		eor	r0, r6, #0x44 << 24	@ SA-110?
+		eor	r0, r6, #0x44 << 24	@ SA-110 or SA-1100?
 		eor	r0, r0, #0x01 << 16
 		eor	r0, r0, #0xa1 << 8
-		movs	r0, r0, lsr #4
+		movs	r0, r0, lsr #5
 		mcreq	p15, 0, r0, c7, c7, 0	@ flush I cache
 		mcreq	p15, 0, r1, c7, c10, 4	@ drain WB
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.3.39/linux/arch/arm/config.in	Wed Dec  8 14:11:24 1999
+++ linux/arch/arm/config.in	Thu Jan 13 13:30:30 2000
@@ -6,6 +6,8 @@
 
 define_bool CONFIG_ARM y
 
+define_bool CONFIG_UID16 y
+
 mainmenu_option next_comment
 comment 'Code maturity level options'
 bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
@@ -44,7 +46,6 @@
 fi
 
 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
-   define_bool CONFIG_CPU_SA1100 y
    choice 'SA1100 implementation' \
 	   "Brutus		CONFIG_SA1100_BRUTUS \
 	    Empeg		CONFIG_SA1100_EMPEG \
@@ -93,7 +94,11 @@
         "$CONFIG_FOOTBRIDGE" = "y" -o \
         "$CONFIG_ARCH_NEXUSPCI" = "y" ]; then
       define_bool CONFIG_CPU_32v4 y
-      define_bool CONFIG_CPU_SA110 y
+      if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
+         define_bool CONFIG_CPU_SA1100 y
+      else
+         define_bool CONFIG_CPU_SA110 y
+      fi
    else
       if [ "$CONFIG_ARCH_RPC" = "y" ]; then
 	 define_bool CONFIG_CPU_32v3 y
@@ -110,7 +115,7 @@
 if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \
      "$CONFIG_HOST_FOOTBRIDGE" = "y" ]; then
    define_bool CONFIG_PCI y
-   source drivers/pci/Config.h
+   source drivers/pci/Config.in
 fi
 
 #
@@ -123,8 +128,8 @@
    define_bool CONFIG_ISA_DMA n
 fi
 
-if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   bool 'Enable kernel-mode alignment trap handler (EXPERIMENTAL)' CONFIG_ALIGNMENT_TRAP
+if [ "$CONFIG_CPU_32" = "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
+   bool 'Kernel-mode alignment trap handler' CONFIG_ALIGNMENT_TRAP
 fi
 #bool 'Split text into discardable sections' CONFIG_TEXT_SECTIONS
 endmenu
@@ -273,11 +278,10 @@
 bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
 #bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+if [ "$CONFIG_CPU_26" = "y" ]; then
+   bool 'Disable pgtable cache' CONFIG_NO_PGT_CACHE
+fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   if [ "$CONFIG_CPU_26" = "y" ]; then
-      bool 'Disable pgtable cache (EXPERIMENTAL)' CONFIG_NO_PGT_CACHE
-   fi
-
    # These options are only for real kernel hackers
    # who want to get their hands dirty. 
    bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL
diff -u --recursive --new-file v2.3.39/linux/arch/arm/def-configs/a5k linux/arch/arm/def-configs/a5k
--- v2.3.39/linux/arch/arm/def-configs/a5k	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/def-configs/a5k	Mon Jan 17 22:22:52 2000
@@ -4,6 +4,11 @@
 CONFIG_ARM=y
 
 #
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
 # System and processor type
 #
 # CONFIG_ARCH_ARC is not set
@@ -12,22 +17,10 @@
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_FOOTBRIDGE is not set
 CONFIG_ARCH_ACORN=y
-# CONFIG_ISA_DMA is not set
 # CONFIG_CPU_32 is not set
 CONFIG_CPU_26=y
-# CONFIG_CPU_ARM2 is not set
-CONFIG_CPU_ARM3=y
-# CONFIG_CPU_ARM6 is not set
-# CONFIG_CPU_ARM7 is not set
-# CONFIG_CPU_SA110 is not set
-CONFIG_PAGESIZE_32=y
 # CONFIG_PAGESIZE_16 is not set
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_TEXT_SECTIONS is not set
+# CONFIG_ISA_DMA is not set
 
 #
 # Loadable module support
@@ -43,17 +36,38 @@
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_NWFPE is not set
+CONFIG_NWFPE=y
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
 CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_ELF=m
+# CONFIG_BINFMT_ELF is not set
 # CONFIG_BINFMT_MISC is not set
-CONFIG_PARPORT=y
-CONFIG_PARPORT_PC=y
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
 
 #
-# Plug and Play support
+# Plug and Play configuration
 #
 # CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
 
 #
 # Block devices
@@ -66,11 +80,19 @@
 #
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
 # CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDE_ICSIDE=y
+# CONFIG_BLK_DEV_IDEDMA_ICS is not set
+# CONFIG_BLK_DEV_IDE_RAPIDE is not set
 # CONFIG_IDE_CHIPSETS is not set
 
 #
@@ -82,16 +104,14 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
+CONFIG_PARIDE_PARPORT=m
 # CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
 # Acorn-specific block devices
 #
-CONFIG_BLK_DEV_IDE_CARDS=y
-CONFIG_BLK_DEV_IDE_ICSIDE=y
-# CONFIG_BLK_DEV_IDE_RAPIDE is not set
 # CONFIG_BLK_DEV_FD1772 is not set
 CONFIG_BLK_DEV_MFM=m
 CONFIG_BLK_DEV_MFM_AUTODETECT=y
@@ -102,26 +122,33 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_ATOMWIDE_SERIAL is not set
+# CONFIG_DUALSP_SERIAL is not set
 # CONFIG_SERIAL_EXTENDED is not set
-CONFIG_ATOMWIDE_SERIAL=y
-CONFIG_DUALSP_SERIAL=y
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_UNIX98_PTYS is not set
-CONFIG_PRINTER=y
-CONFIG_PRINTER_READBACK=y
-CONFIG_MOUSE=y
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
 
 #
 # Mice
 #
-# CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
 # CONFIG_PSMOUSE is not set
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -130,27 +157,38 @@
 # Video For Linux
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-CONFIG_KBDMOUSE=y
+# CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_AGP is not set
+
+#
+# Support for USB
+#
+# CONFIG_USB is not set
 
 #
 # Console drivers
 #
 CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FB_ACORN=y
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_MFB=y
@@ -158,9 +196,13 @@
 CONFIG_FBCON_CFB4=y
 CONFIG_FBCON_CFB8=y
 # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
-# CONFIG_FBCON_FONTS is not set
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
+CONFIG_FBCON_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
 CONFIG_FONT_ACORN_8x8=y
 
 #
@@ -168,7 +210,7 @@
 #
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -184,15 +226,17 @@
 #
 # (it is safe to leave these untouched)
 #
-# CONFIG_INET_RARP is not set
 # CONFIG_SKB_LARGE is not set
 # CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
@@ -201,7 +245,6 @@
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
 
 #
 # QoS and/or fair queueing
@@ -214,7 +257,7 @@
 # CONFIG_HAMRADIO is not set
 
 #
-# IrDA subsystem support
+# IrDA (infrared) support
 #
 # CONFIG_IRDA is not set
 
@@ -222,9 +265,18 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_NET_ETHERNET=y
 CONFIG_ARM_ETHER1=y
 CONFIG_ARM_ETHER3=y
@@ -234,96 +286,47 @@
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_RTL8139 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_DLCI is not set
 # CONFIG_PLIP is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
 # CONFIG_NET_RADIO is not set
+
+#
+# Token Ring driver support
+#
 # CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-# CONFIG_HOSTESS_SV11 is not set
-# CONFIG_COSA is not set
+# CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
 
 #
-# SCSI support
+# Wan interfaces
 #
-CONFIG_SCSI=y
+# CONFIG_WAN is not set
 
 #
-# SCSI support type (disk, tape, CD-ROM)
+# SCSI support
 #
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-# CONFIG_CHR_DEV_SG is not set
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-# CONFIG_SCSI_MULTI_LUN is not set
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_SCSI_7000FASST is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
-# CONFIG_SCSI_AHA1740 is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_AM53C974 is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_DMA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-CONFIG_SCSI_PPA=m
-# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_IZIP_EPP16 is not set
-# CONFIG_SCSI_IZIP_SLOW_CTR is not set
-# CONFIG_SCSI_NCR53C406A is not set
-# CONFIG_SCSI_SYM53C416 is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_SEAGATE is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
-# CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_ACORNSCSI_3=y
-CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y
-CONFIG_SCSI_ACORNSCSI_SYNC=y
-CONFIG_SCSI_ARXESCSI=m
-# CONFIG_SCSI_CUMANA_2 is not set
-CONFIG_SCSI_EESOXSCSI=y
-# CONFIG_SCSI_POWERTECSCSI is not set
-
-#
-# The following drivers are not fully supported
-#
-# CONFIG_SCSI_CUMANA_1 is not set
-# CONFIG_SCSI_ECOSCSI is not set
-# CONFIG_SCSI_OAK1 is not set
+# CONFIG_SCSI is not set
 
 #
 # Sound
@@ -338,12 +341,14 @@
 CONFIG_ADFS_FS=y
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=m
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -352,6 +357,7 @@
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
@@ -359,8 +365,7 @@
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
-CONFIG_NFSD=y
-# CONFIG_NFSD_SUN is not set
+# CONFIG_NFSD is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
@@ -369,12 +374,10 @@
 #
 # Partition Types
 #
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+# CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
 CONFIG_ACORN_PARTITION=y
 CONFIG_ACORN_PARTITION_ADFS=y
 CONFIG_ACORN_PARTITION_ICS=y
@@ -410,6 +413,7 @@
 # CONFIG_NLS_ISO8859_7 is not set
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
 
@@ -418,8 +422,8 @@
 #
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_INFO is not set
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_NO_PGT_CACHE=y
-# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL=y
diff -u --recursive --new-file v2.3.39/linux/arch/arm/def-configs/footbridge linux/arch/arm/def-configs/footbridge
--- v2.3.39/linux/arch/arm/def-configs/footbridge	Tue Nov 23 22:42:20 1999
+++ linux/arch/arm/def-configs/footbridge	Mon Jan 17 22:22:52 2000
@@ -4,6 +4,11 @@
 CONFIG_ARM=y
 
 #
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
 # System and processor type
 #
 # CONFIG_ARCH_ARC is not set
@@ -23,11 +28,6 @@
 CONFIG_CPU_SA110=y
 CONFIG_PCI=y
 CONFIG_ISA_DMA=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
 # CONFIG_ALIGNMENT_TRAP is not set
 
 #
@@ -45,6 +45,8 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_NWFPE=y
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
@@ -52,7 +54,6 @@
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
 CONFIG_PARPORT_PC_FIFO=y
-# CONFIG_PARPORT_PC_PCMCIA is not set
 # CONFIG_PARPORT_ARC is not set
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
@@ -60,7 +61,7 @@
 # CONFIG_PARPORT_SUNBPP is not set
 # CONFIG_PARPORT_OTHER is not set
 CONFIG_PARPORT_1284=y
-CONFIG_CMDLINE="root=/dev/hda2 ro mem=32M parport=0x378,7 ide0=autotune"
+CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune"
 CONFIG_LEDS=y
 CONFIG_LEDS_TIMER=y
 # CONFIG_LEDS_CPU is not set
@@ -97,15 +98,20 @@
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 CONFIG_IDEDMA_PCI_AUTO=y
-# IDEDMA_NEW_DRIVE_LISTINGS is not set
-IDEDMA_PCI_EXPERIMENTAL=y
+CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y
+CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 CONFIG_BLK_DEV_OFFBOARD=y
 # CONFIG_BLK_DEV_AEC6210 is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_CMD646 is not set
 CONFIG_BLK_DEV_CY82C693=y
 # CONFIG_BLK_DEV_HPT34X is not set
@@ -113,8 +119,8 @@
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_PDC202XX=y
-# PDC202XX_FORCE_BURST_BIT is not set
-# PDC202XX_FORCE_MASTER_MODE is not set
+# CONFIG_PDC202XX_FORCE_BURST_BIT is not set
+# CONFIG_PDC202XX_FORCE_MASTER_MODE is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 CONFIG_BLK_DEV_SL82C105=y
 CONFIG_BLK_DEV_IDEDMA=y
@@ -135,6 +141,7 @@
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_PARIDE_PARPORT=y
 CONFIG_PARIDE=m
 
@@ -176,7 +183,8 @@
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
 CONFIG_PRINTER=m
 # CONFIG_LP_CONSOLE is not set
 # CONFIG_PPDEV is not set
@@ -189,12 +197,17 @@
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
-CONFIG_WATCHDOG=y
 
 #
 # Watchdog Cards
 #
+CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 # CONFIG_WDT is not set
 CONFIG_SOFT_WATCHDOG=y
@@ -212,12 +225,33 @@
 #
 # Video For Linux
 #
-# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_DEV=y
+# CONFIG_I2C_PARPORT is not set
 
 #
-# Joystick support
+# Radio/Video Adapters
 #
-# CONFIG_JOYSTICK is not set
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_BUZ is not set
+# CONFIG_VIDEO_ZR36120 is not set
+CONFIG_VIDEO_CYBERPRO=m
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -226,41 +260,64 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
 
 #
-# USB drivers - not for the faint of heart
+# Support for USB
 #
 CONFIG_USB=m
+
+#
+# USB Controllers
+#
 # CONFIG_USB_UHCI is not set
 CONFIG_USB_OHCI=m
 CONFIG_USB_OHCI_DEBUG=y
 CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_OHCI_VROOTHUB=y
+
+#
+# Miscellaneous USB options
+#
 # CONFIG_USB_DEBUG_ISOC is not set
-CONFIG_USB_HUB=m
+CONFIG_USB_PROC=y
+# CONFIG_USB_EZUSB is not set
+
+#
+# USB Devices
+#
 CONFIG_USB_MOUSE=m
+# CONFIG_USB_HP_SCANNER is not set
 CONFIG_USB_KBD=m
 CONFIG_USB_AUDIO=m
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=m
+# CONFIG_USB_SERIAL is not set
 # CONFIG_USB_CPIA is not set
-CONFIG_USB_SCSI=m
-CONFIG_USB_SCSI_DEBUG=m
-# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_SCSI is not set
 # CONFIG_USB_USS720 is not set
-CONFIG_USB_PROC=y
 
 #
 # Console drivers
 #
 CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
 # CONFIG_FB_CLGEN is not set
 # CONFIG_FB_PM2 is not set
 CONFIG_FB_CYBER2000=y
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
 # CONFIG_FB_VIRTUAL is not set
 CONFIG_FBCON_ADVANCED=y
 # CONFIG_FBCON_MFB is not set
@@ -377,12 +434,13 @@
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_RTL8139 is not set
-# CONFIG_SIS900 is not set
-# CONFIG_YELLOWFIN is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
 # CONFIG_PCNET32 is not set
-# CONFIG_ACENIC is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
@@ -393,27 +451,40 @@
 # CONFIG_LNE390 is not set
 # CONFIG_NE3210 is not set
 CONFIG_NE2K_PCI=y
+# CONFIG_SIS900 is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_ES3210 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
 CONFIG_PPP=m
 CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
 CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
+
+#
+# Wireless LAN (non-hamradio)
+#
 # CONFIG_NET_RADIO is not set
 
 #
-# Token ring devices
+# Token Ring driver support
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -423,10 +494,7 @@
 #
 # Wan interfaces
 #
-# CONFIG_HOSTESS_SV11 is not set
-# CONFIG_COSA is not set
-# CONFIG_SEALEVEL_4021 is not set
-# CONFIG_DLCI is not set
+# CONFIG_WAN is not set
 
 #
 # SCSI support
@@ -441,30 +509,33 @@
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_PAS is not set
-CONFIG_SOUND_SB=m
-CONFIG_SOUND_ADLIB=m
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_CS4232 is not set
 # CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
 # CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SOFTOSS is not set
+CONFIG_SOUND_SB=m
 # CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
 # CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_VIDC is not set
 CONFIG_SOUND_WAVEARTIST=m
@@ -482,10 +553,11 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
 CONFIG_ADFS_FS=y
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
@@ -497,10 +569,12 @@
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
+CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
@@ -510,7 +584,7 @@
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
-# CONFIG_NFSD_SUN is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
diff -u --recursive --new-file v2.3.39/linux/arch/arm/def-configs/rpc linux/arch/arm/def-configs/rpc
--- v2.3.39/linux/arch/arm/def-configs/rpc	Mon Jul 19 09:52:57 1999
+++ linux/arch/arm/def-configs/rpc	Mon Jan 17 22:22:52 2000
@@ -4,6 +4,11 @@
 CONFIG_ARM=y
 
 #
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
 # System and processor type
 #
 # CONFIG_ARCH_ARC is not set
@@ -12,21 +17,14 @@
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_FOOTBRIDGE is not set
 CONFIG_ARCH_ACORN=y
-# CONFIG_ISA_DMA is not set
 CONFIG_CPU_32=y
 # CONFIG_CPU_26 is not set
-# CONFIG_CPU_ARM2 is not set
-# CONFIG_CPU_ARM3 is not set
-# CONFIG_CPU_ARM6 is not set
-# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_32v3=y
+CONFIG_CPU_ARM6=y
+CONFIG_CPU_ARM7=y
 CONFIG_CPU_SA110=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
+# CONFIG_ISA_DMA is not set
 # CONFIG_ALIGNMENT_TRAP is not set
-# CONFIG_TEXT_SECTIONS is not set
 
 #
 # Loadable module support
@@ -43,16 +41,38 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_NWFPE is not set
+CONFIG_KCORE_ELF=y
+# CONFIG_KCORE_AOUT is not set
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
 
 #
-# Plug and Play support
+# Plug and Play configuration
 #
 # CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
 
 #
 # Block devices
@@ -65,11 +85,22 @@
 #
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
 CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_IDETAPE=y
-CONFIG_BLK_DEV_IDEFLOPPY=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
 # CONFIG_BLK_DEV_CMD640 is not set
+CONFIG_BLK_DEV_IDE_ICSIDE=y
+CONFIG_BLK_DEV_IDEDMA_ICS=y
+CONFIG_IDEDMA_ICS_AUTO=y
+CONFIG_BLK_DEV_IDE_RAPIDE=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDE_CHIPSETS is not set
 
 #
@@ -83,14 +114,12 @@
 # CONFIG_BLK_DEV_XD is not set
 CONFIG_PARIDE_PARPORT=y
 # CONFIG_PARIDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
 # Acorn-specific block devices
 #
-CONFIG_BLK_DEV_IDE_CARDS=y
-CONFIG_BLK_DEV_IDE_ICSIDE=y
-CONFIG_BLK_DEV_IDE_RAPIDE=y
 
 #
 # Character devices
@@ -99,25 +128,36 @@
 CONFIG_VT_CONSOLE=y
 CONFIG_SERIAL=y
 # CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
 CONFIG_ATOMWIDE_SERIAL=y
 CONFIG_DUALSP_SERIAL=y
+# CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 # CONFIG_UNIX98_PTYS is not set
 CONFIG_PRINTER=m
-CONFIG_PRINTER_READBACK=y
-CONFIG_MOUSE=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
 
 #
 # Mice
 #
+CONFIG_BUSMOUSE=y
 # CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
+# CONFIG_LOGIBUSMOUSE is not set
 # CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
 # CONFIG_PSMOUSE is not set
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
@@ -126,27 +166,39 @@
 # Video For Linux
 #
 # CONFIG_VIDEO_DEV is not set
-
-#
-# Joystick support
-#
-# CONFIG_JOYSTICK is not set
 # CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_AGP is not set
 CONFIG_RPCMOUSE=y
 
 #
+# Support for USB
+#
+# CONFIG_USB is not set
+
+#
 # Console drivers
 #
 CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FB_ACORN=y
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
 # CONFIG_FB_VIRTUAL is not set
 CONFIG_FBCON_ADVANCED=y
 CONFIG_FBCON_MFB=y
@@ -162,6 +214,7 @@
 # CONFIG_FBCON_IPLAN2P4 is not set
 # CONFIG_FBCON_IPLAN2P8 is not set
 # CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA_PLANES is not set
 # CONFIG_FBCON_VGA is not set
 # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
 CONFIG_FBCON_FONTS=y
@@ -178,7 +231,7 @@
 #
 # CONFIG_PACKET is not set
 # CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -194,15 +247,17 @@
 #
 # (it is safe to leave these untouched)
 #
-# CONFIG_INET_RARP is not set
 CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
@@ -211,7 +266,6 @@
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
 
 #
 # QoS and/or fair queueing
@@ -224,7 +278,7 @@
 # CONFIG_HAMRADIO is not set
 
 #
-# IrDA subsystem support
+# IrDA (infrared) support
 #
 # CONFIG_IRDA is not set
 
@@ -232,39 +286,67 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_NET_ETHERNET=y
 CONFIG_ARM_ETHER1=m
 CONFIG_ARM_ETHER3=m
-CONFIG_ARM_ETHERH=m
+CONFIG_ARM_ETHERH=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_RTL8139 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_DLCI is not set
 # CONFIG_PLIP is not set
 CONFIG_PPP=m
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_SLIP is not set
 
 #
-# CCP compressors for PPP are only built as modules.
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
+
+#
+# Token Ring driver support
+#
 # CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-# CONFIG_HOSTESS_SV11 is not set
-# CONFIG_COSA is not set
+# CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
 
 #
 # SCSI support
@@ -283,6 +365,7 @@
 #
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
+CONFIG_SCSI_DEBUG_QUEUES=y
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
@@ -296,6 +379,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -314,6 +398,7 @@
 # CONFIG_SCSI_IZIP_SLOW_CTR is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_SIM710 is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
@@ -342,32 +427,37 @@
 # Sound
 #
 CONFIG_SOUND=m
+# CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_PAS is not set
-# CONFIG_SOUND_SB is not set
-# CONFIG_SOUND_ADLIB is not set
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_CS4232 is not set
 # CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
 # CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_SB is not set
 # CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
 # CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
 # CONFIG_SOUND_UART6850 is not set
 CONFIG_SOUND_VIDC=m
 # CONFIG_SOUND_WAVEARTIST is not set
@@ -385,10 +475,12 @@
 CONFIG_ADFS_FS=y
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
-CONFIG_VFAT_FS=y
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 # CONFIG_MINIX_FS is not set
@@ -399,6 +491,7 @@
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
@@ -415,12 +508,17 @@
 #
 # Partition Types
 #
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_OSF_PARTITION=y
+CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+CONFIG_SGI_PARTITION=y
+CONFIG_SUN_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
 CONFIG_ACORN_PARTITION=y
 CONFIG_ACORN_PARTITION_ADFS=y
 CONFIG_ACORN_PARTITION_ICS=y
@@ -456,6 +554,7 @@
 CONFIG_NLS_ISO8859_7=m
 CONFIG_NLS_ISO8859_8=m
 CONFIG_NLS_ISO8859_9=m
+# CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 CONFIG_NLS_KOI8_R=m
 
@@ -467,5 +566,4 @@
 # CONFIG_DEBUG_USER is not set
 # CONFIG_DEBUG_INFO is not set
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_ARTHUR is not set
-# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL=y
diff -u --recursive --new-file v2.3.39/linux/arch/arm/defconfig linux/arch/arm/defconfig
--- v2.3.39/linux/arch/arm/defconfig	Wed Dec  8 14:11:24 1999
+++ linux/arch/arm/defconfig	Mon Jan 17 22:22:52 2000
@@ -4,6 +4,11 @@
 CONFIG_ARM=y
 
 #
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
 # System and processor type
 #
 # CONFIG_ARCH_ARC is not set
@@ -17,23 +22,13 @@
 # CONFIG_CATS is not set
 CONFIG_ARCH_NETWINDER=y
 # CONFIG_ARCH_ACORN is not set
-CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
-CONFIG_ISA_DMA=y
 CONFIG_CPU_32=y
 # CONFIG_CPU_26 is not set
-# CONFIG_CPU_ARM2 is not set
-# CONFIG_CPU_ARM3 is not set
-# CONFIG_CPU_ARM6 is not set
-# CONFIG_CPU_ARM7 is not set
+CONFIG_CPU_32v4=y
 CONFIG_CPU_SA110=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
+CONFIG_PCI=y
+CONFIG_ISA_DMA=y
 # CONFIG_ALIGNMENT_TRAP is not set
-# CONFIG_TEXT_SECTIONS is not set
 
 #
 # Loadable module support
@@ -58,15 +53,34 @@
 # CONFIG_ARTHUR is not set
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_FIFO=y
+# CONFIG_PARPORT_ARC is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
+# CONFIG_PARPORT_SUNBPP is not set
+# CONFIG_PARPORT_OTHER is not set
+CONFIG_PARPORT_1284=y
 CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune"
 CONFIG_LEDS=y
 CONFIG_LEDS_TIMER=y
 # CONFIG_LEDS_CPU is not set
 
 #
-# Plug and Play support
+# I2O device support
 #
-# CONFIG_PNP is not set
+# CONFIG_I2O is not set
+# CONFIG_I2O_PCI is not set
+# CONFIG_I2O_BLOCK is not set
+# CONFIG_I2O_LAN is not set
+# CONFIG_I2O_SCSI is not set
+# CONFIG_I2O_PROC is not set
+
+#
+# Plug and Play configuration
+#
+CONFIG_PNP=y
+CONFIG_ISAPNP=y
 
 #
 # Block devices
@@ -79,23 +93,40 @@
 #
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_BLK_DEV_OFFBOARD=y
+CONFIG_BLK_DEV_IDEDMA_PCI=y
 CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y
+CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
+CONFIG_BLK_DEV_OFFBOARD=y
+# CONFIG_BLK_DEV_AEC6210 is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_CMD646 is not set
+CONFIG_BLK_DEV_CY82C693=y
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_PDC202XX=y
+# CONFIG_PDC202XX_FORCE_BURST_BIT is not set
+# CONFIG_PDC202XX_FORCE_MASTER_MODE is not set
 # CONFIG_BLK_DEV_TRM290 is not set
-# CONFIG_BLK_DEV_NS87415 is not set
-# CONFIG_BLK_DEV_VIA82C586 is not set
-# CONFIG_BLK_DEV_CMD646 is not set
 CONFIG_BLK_DEV_SL82C105=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_CPQ_DA is not set
 
 #
 # Additional Block Devices
@@ -110,6 +141,7 @@
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_PARIDE_PARPORT=y
 CONFIG_PARIDE=m
 
@@ -139,6 +171,7 @@
 CONFIG_PARIDE_KTTI=m
 CONFIG_PARIDE_ON20=m
 CONFIG_PARIDE_ON26=m
+CONFIG_BLK_DEV_IDE_MODES=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -150,31 +183,38 @@
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
 CONFIG_PRINTER=m
-CONFIG_PRINTER_READBACK=y
-CONFIG_MOUSE=y
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
 
 #
 # Mice
 #
-# CONFIG_ATIXL_BUSMOUSE is not set
 # CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
+CONFIG_MOUSE=y
 CONFIG_PSMOUSE=y
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
 # CONFIG_QIC02_TAPE is not set
-CONFIG_WATCHDOG=y
 
 #
 # Watchdog Cards
 #
+CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 # CONFIG_WDT is not set
 CONFIG_SOFT_WATCHDOG=y
 # CONFIG_PCWATCHDOG is not set
 # CONFIG_ACQUIRE_WDT is not set
+# CONFIG_21285_WATCHDOG is not set
+CONFIG_977_WATCHDOG=m
 CONFIG_DS1620=y
 CONFIG_NWBUTTON=y
 CONFIG_NWBUTTON_REBOOT=y
@@ -185,29 +225,100 @@
 #
 # Video For Linux
 #
-# CONFIG_VIDEO_DEV is not set
+CONFIG_VIDEO_DEV=y
+# CONFIG_I2C_PARPORT is not set
 
 #
-# Joystick support
+# Radio/Video Adapters
 #
-# CONFIG_JOYSTICK is not set
+# CONFIG_RADIO_CADET is not set
+# CONFIG_RADIO_RTRACK is not set
+# CONFIG_RADIO_RTRACK2 is not set
+# CONFIG_RADIO_AZTECH is not set
+# CONFIG_VIDEO_BT848 is not set
+# CONFIG_RADIO_GEMTEK is not set
+# CONFIG_VIDEO_PMS is not set
+# CONFIG_RADIO_MIROPCM20 is not set
+# CONFIG_VIDEO_BWQCAM is not set
+# CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_RADIO_SF16FMI is not set
+# CONFIG_VIDEO_STRADIS is not set
+# CONFIG_RADIO_TERRATEC is not set
+# CONFIG_RADIO_TRUST is not set
+# CONFIG_RADIO_TYPHOON is not set
+# CONFIG_RADIO_ZOLTRIX is not set
+# CONFIG_VIDEO_ZORAN is not set
+# CONFIG_VIDEO_BUZ is not set
+# CONFIG_VIDEO_ZR36120 is not set
+CONFIG_VIDEO_CYBERPRO=m
 # CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
+# CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
+# CONFIG_AGP is not set
+
+#
+# Support for USB
+#
+CONFIG_USB=m
+
+#
+# USB Controllers
+#
+# CONFIG_USB_UHCI is not set
+CONFIG_USB_OHCI=m
+CONFIG_USB_OHCI_DEBUG=y
+CONFIG_USB_OHCI_HCD=m
+CONFIG_USB_OHCI_VROOTHUB=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEBUG_ISOC is not set
+CONFIG_USB_PROC=y
+# CONFIG_USB_EZUSB is not set
+
+#
+# USB Devices
+#
+CONFIG_USB_MOUSE=m
+# CONFIG_USB_HP_SCANNER is not set
+CONFIG_USB_KBD=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_CPIA is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_SCSI is not set
+# CONFIG_USB_USS720 is not set
 
 #
 # Console drivers
 #
 CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_CLGEN is not set
 # CONFIG_FB_PM2 is not set
 CONFIG_FB_CYBER2000=y
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_3DFX is not set
 # CONFIG_FB_VIRTUAL is not set
 CONFIG_FBCON_ADVANCED=y
 # CONFIG_FBCON_MFB is not set
@@ -223,6 +334,7 @@
 # CONFIG_FBCON_IPLAN2P4 is not set
 # CONFIG_FBCON_IPLAN2P8 is not set
 # CONFIG_FBCON_MAC is not set
+# CONFIG_FBCON_VGA_PLANES is not set
 CONFIG_FBCON_VGA=y
 # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
 CONFIG_FBCON_FONTS=y
@@ -238,8 +350,9 @@
 # Networking options
 #
 CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
 # CONFIG_NETLINK is not set
-# CONFIG_FIREWALL is not set
+# CONFIG_NETFILTER is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -257,15 +370,17 @@
 #
 # (it is safe to leave these untouched)
 #
-# CONFIG_INET_RARP is not set
 CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
 
 #
 #  
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
@@ -274,7 +389,6 @@
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
-# CONFIG_CPU_IS_SLOW is not set
 
 #
 # QoS and/or fair queueing
@@ -287,7 +401,7 @@
 # CONFIG_HAMRADIO is not set
 
 #
-# IrDA subsystem support
+# IrDA (infrared) support
 #
 # CONFIG_IRDA is not set
 
@@ -295,9 +409,18 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
 CONFIG_NET_ETHERNET=y
 # CONFIG_ARM_AM79C961A is not set
 CONFIG_NET_VENDOR_3COM=y
@@ -312,11 +435,13 @@
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_RTL8139 is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
+# CONFIG_DM9102 is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
 # CONFIG_PCNET32 is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
@@ -327,31 +452,50 @@
 # CONFIG_LNE390 is not set
 # CONFIG_NE3210 is not set
 CONFIG_NE2K_PCI=y
+# CONFIG_SIS900 is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_ES3210 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_ZNET is not set
 # CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
+# CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-# CONFIG_DLCI is not set
 # CONFIG_PLIP is not set
 CONFIG_PPP=m
-
-#
-# CCP compressors for PPP are only built as modules.
-#
+CONFIG_PPP_ASYNC=m
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
 CONFIG_SLIP_MODE_SLIP6=y
+
+#
+# Wireless LAN (non-hamradio)
+#
 # CONFIG_NET_RADIO is not set
+
+#
+# Token Ring driver support
+#
 # CONFIG_TR is not set
-# CONFIG_SHAPER is not set
-# CONFIG_HOSTESS_SV11 is not set
-# CONFIG_COSA is not set
+# CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
 
 #
 # SCSI support
@@ -362,32 +506,37 @@
 # Sound
 #
 CONFIG_SOUND=m
+# CONFIG_SOUND_CMPCI is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
 # CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 CONFIG_SOUND_OSS=m
-# CONFIG_SOUND_PAS is not set
-CONFIG_SOUND_SB=m
-CONFIG_SOUND_ADLIB=m
-# CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_MPU401 is not set
-# CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_AD1816 is not set
+# CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_CS4232 is not set
 # CONFIG_SOUND_SSCAPE is not set
+# CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_TRIX is not set
+# CONFIG_SOUND_MSS is not set
+# CONFIG_SOUND_MPU401 is not set
+# CONFIG_SOUND_NM256 is not set
 # CONFIG_SOUND_MAD16 is not set
+# CONFIG_SOUND_PAS is not set
+# CONFIG_SOUND_PSS is not set
+# CONFIG_SOUND_SOFTOSS is not set
+CONFIG_SOUND_SB=m
 # CONFIG_SOUND_WAVEFRONT is not set
-# CONFIG_SOUND_CS4232 is not set
-# CONFIG_SOUND_OPL3SA2 is not set
 # CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_SGALAXY is not set
-# CONFIG_SOUND_AD1816 is not set
-# CONFIG_SOUND_OPL3SA1 is not set
-# CONFIG_SOUND_SOFTOSS is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_YM3812 is not set
-# CONFIG_SOUND_VMIDI is not set
+# CONFIG_SOUND_OPL3SA1 is not set
+# CONFIG_SOUND_OPL3SA2 is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_VIDC is not set
 CONFIG_SOUND_WAVEARTIST=m
@@ -405,24 +554,28 @@
 # Filesystems
 #
 # CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS_FS=y
 CONFIG_ADFS_FS=y
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
 CONFIG_VFAT_FS=m
+# CONFIG_EFS_FS is not set
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
+CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_UDF_FS is not set
 # CONFIG_UFS_FS is not set
 
 #
@@ -432,7 +585,7 @@
 CONFIG_NFS_FS=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
-# CONFIG_NFSD_SUN is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
@@ -441,12 +594,17 @@
 #
 # Partition Types
 #
+CONFIG_PARTITION_ADVANCED=y
 # CONFIG_OSF_PARTITION is not set
 # CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
 CONFIG_ACORN_PARTITION=y
 CONFIG_ACORN_PARTITION_ADFS=y
 # CONFIG_ACORN_PARTITION_ICS is not set
@@ -482,6 +640,7 @@
 # CONFIG_NLS_ISO8859_7 is not set
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_14 is not set
 CONFIG_NLS_ISO8859_15=m
 # CONFIG_NLS_KOI8_R is not set
 
@@ -490,7 +649,7 @@
 #
 CONFIG_FRAME_POINTER=y
 CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_USER is not set
+CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_INFO is not set
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_DEBUG_LL is not set
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/armksyms.c linux/arch/arm/kernel/armksyms.c
--- v2.3.39/linux/arch/arm/kernel/armksyms.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/arm/kernel/armksyms.c	Thu Jan 13 13:30:31 2000
@@ -16,6 +16,7 @@
 #include <asm/dma.h>
 #include <asm/pgalloc.h>
 #include <asm/proc-fns.h>
+#include <asm/processor.h>
 #include <asm/semaphore.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -29,8 +30,6 @@
 extern unsigned int local_bh_count[NR_CPUS];
 extern unsigned int local_irq_count[NR_CPUS];
 
-extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 /*
  * syscalls
  */
@@ -125,7 +124,6 @@
 EXPORT_SYMBOL(__machine_arch_type);
 
 	/* networking */
-EXPORT_SYMBOL(csum_partial_copy);
 EXPORT_SYMBOL(csum_partial_copy_nocheck);
 EXPORT_SYMBOL(__csum_ipv6_magic);
 
@@ -172,8 +170,7 @@
 EXPORT_SYMBOL_NOVERS(strtok);
 EXPORT_SYMBOL_NOVERS(strrchr);
 EXPORT_SYMBOL_NOVERS(strstr);
-EXPORT_SYMBOL_NOVERS(__memset);
-EXPORT_SYMBOL_NOVERS(memset); /* needed for some versions of gcc */
+EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memcpy);
 EXPORT_SYMBOL_NOVERS(memmove);
 EXPORT_SYMBOL_NOVERS(memcmp);
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c
--- v2.3.39/linux/arch/arm/kernel/bios32.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/arm/kernel/bios32.c	Mon Jan 17 22:22:52 2000
@@ -5,6 +5,7 @@
  *
  * Bits taken from various places.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/errno.h>
@@ -33,8 +34,8 @@
 			continue;
 
 		pci_write_config_word(dev, PCI_STATUS, status & 0xf900);
-		printk(KERN_DEBUG "PCI: status %04X on %s\n",
-			status, dev->name);
+		printk(KERN_DEBUG "PCI: %02X:%02X: status %04X on %s\n",
+			dev->bus->number, dev->devfn, status, dev->name);
 	}
 }
 
@@ -162,9 +163,10 @@
  */
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-	struct pci_dev *dev;
+	struct list_head *walk = &bus->devices;
 
-	for (dev = bus->devices; dev; dev = dev->sibling) {
+	for (walk = walk->next; walk != &bus->devices; walk = walk->next) {
+		struct pci_dev *dev = pci_dev_b(walk);
 		u16 cmd;
 
 		/*
@@ -220,6 +222,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_FOOTBRIDGE
 /* ebsa285 host-specific stuff */
 static int irqmap_ebsa285[] __initdata = { IRQ_IN1, IRQ_IN0, IRQ_PCI, IRQ_IN3 };
 
@@ -255,7 +258,7 @@
 static int __init cats_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (dev->irq >= 128)
-		return 16 + (dev->irq & 0x1f);
+		return dev->irq & 0x1f;
 
 	if (dev->irq >= 1 && dev->irq <= 4)
 		return irqmap_cats[dev->irq - 1];
@@ -313,17 +316,53 @@
 	no_swizzle,
 	netwinder_map_irq
 };
+#endif
+
+#ifdef CONFIG_ARCH_NEXUSPCI
+/*
+ * Owing to a PCB cockup, issue A backplanes are wired thus:
+ *
+ * Slot 1    2    3    4    5   Bridge
+ * IRQ  D    C    B    A    A
+ *      A    D    C    B    B
+ *      B    A    D    C    C
+ *      C    B    A    D    D
+ *
+ * ID A31  A30  A29  A28  A27   A26
+ */
+
+static int irqmap_ftv[] __initdata = { IRQ_PCI_A, IRQ_PCI_B, IRQ_PCI_C, IRQ_PCI_D };
+
+static int __init ftv_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return irqmap_ftv[(slot + pin) & 3];
+}
+
+/* ftv host-specific stuff */
+static struct hw_pci ftv_pci __initdata = {
+	plx90x0_init,
+	0x9000,
+	0x00100000,
+	no_swizzle,
+	ftv_map_irq
+};
+#endif
 
 void __init pcibios_init(void)
 {
 	struct hw_pci *hw_pci = NULL;
 
+#ifdef CONFIG_FOOTBRIDGE
 	if (machine_is_ebsa285())
 		hw_pci = &ebsa285_pci;
 	else if (machine_is_cats())
 		hw_pci = &cats_pci;
 	else if (machine_is_netwinder())
 		hw_pci = &netwinder_pci;
+#endif
+#ifdef CONFIG_ARCH_NEXUSPCI
+	hw_pci = &ftv_pci;
+#endif
 
 	if (hw_pci == NULL)
 		return;
@@ -346,12 +385,14 @@
 	pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq);
 	pci_set_bus_ranges();
 
+#ifdef CONFIG_FOOTBRIDGE
 	/*
 	 * Initialise any other hardware after we've got the PCI bus
 	 * initialised.  We may need the PCI bus to talk to this other
 	 * hardware.
 	 */
 	hw_init();
+#endif
 }
 
 char * __init pcibios_setup(char *str)
@@ -363,7 +404,17 @@
 	return str;
 }
 
-void __init
-pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+/*
+ * Assign new address to PCI resource.  We hope our resource information
+ * is complete.
+ *
+ * Expects start=0, end=size-1, flags=resource type.
+ */
+int pci_assign_resource(struct pci_dev *dev, int i)
+{
+	return 0;
+}
+
+void pcibios_align_resource(void *data, struct resource *res, unsigned long size)
 {
 }
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/bios32.h linux/arch/arm/kernel/bios32.h
--- v2.3.39/linux/arch/arm/kernel/bios32.h	Tue Nov 23 22:42:20 1999
+++ linux/arch/arm/kernel/bios32.h	Thu Jan 13 13:30:31 2000
@@ -7,3 +7,4 @@
 };
 
 void __init dc21285_init(void);
+void __init plx90x0_init(void);
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S
--- v2.3.39/linux/arch/arm/kernel/calls.S	Tue Jan 11 22:31:36 2000
+++ linux/arch/arm/kernel/calls.S	Thu Jan 13 13:30:31 2000
@@ -27,17 +27,17 @@
 /* 15 */	.long	SYMBOL_NAME(sys_chmod)
 		.long	SYMBOL_NAME(sys_lchown16)
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_break */
-		.long	SYMBOL_NAME(sys_stat)
+		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_stat */
 		.long	SYMBOL_NAME(sys_lseek)
 /* 20 */	.long	SYMBOL_NAME(sys_getpid)
-		.long	SYMBOL_NAME(sys_mount_wrapper)
+		.long	SYMBOL_NAME(sys_mount)
 		.long	SYMBOL_NAME(sys_oldumount)
 		.long	SYMBOL_NAME(sys_setuid16)
 		.long	SYMBOL_NAME(sys_getuid16)
 /* 25 */	.long	SYMBOL_NAME(sys_stime)
 		.long	SYMBOL_NAME(sys_ptrace)
 		.long	SYMBOL_NAME(sys_alarm)
-		.long	SYMBOL_NAME(sys_fstat)
+		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_fstat */
 		.long	SYMBOL_NAME(sys_pause)
 /* 30 */	.long	SYMBOL_NAME(sys_utime)
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_stty */
@@ -93,7 +93,7 @@
 		.long	SYMBOL_NAME(sys_setgroups16)
 		.long	SYMBOL_NAME(old_select)
 		.long	SYMBOL_NAME(sys_symlink)
-		.long	SYMBOL_NAME(sys_lstat)
+		.long	SYMBOL_NAME(sys_ni_syscall)		/* was sys_lstat */
 /* 85 */	.long	SYMBOL_NAME(sys_readlink)
 		.long	SYMBOL_NAME(sys_uselib)
 		.long	SYMBOL_NAME(sys_swapon)
@@ -132,7 +132,7 @@
 /* 120 */	.long	SYMBOL_NAME(sys_clone_wapper)
 		.long	SYMBOL_NAME(sys_setdomainname)
 		.long	SYMBOL_NAME(sys_newuname)
-		.long	SYMBOL_NAME(sys_ni_syscall)		/* .long	SYMBOL_NAME(sys_modify_ldt) */
+		.long	SYMBOL_NAME(sys_ni_syscall)
 		.long	SYMBOL_NAME(sys_adjtimex)
 /* 125 */	.long	SYMBOL_NAME(sys_mprotect)
 		.long	SYMBOL_NAME(sys_sigprocmask)
@@ -149,7 +149,7 @@
 		.long	SYMBOL_NAME(sys_ni_syscall)		/* .long	_sys_afs_syscall */
 		.long	SYMBOL_NAME(sys_setfsuid16)
 		.long	SYMBOL_NAME(sys_setfsgid16)
-/* 140 */	.long	SYMBOL_NAME(sys_llseek_wrapper)
+/* 140 */	.long	SYMBOL_NAME(sys_llseek)
 		.long	SYMBOL_NAME(sys_getdents)
 		.long	SYMBOL_NAME(sys_select)
 		.long	SYMBOL_NAME(sys_flock)
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/debug-armv.S linux/arch/arm/kernel/debug-armv.S
--- v2.3.39/linux/arch/arm/kernel/debug-armv.S	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/kernel/debug-armv.S	Thu Jan 13 13:30:31 2000
@@ -134,17 +134,24 @@
 #elif defined(CONFIG_ARCH_SA1100)
 		.macro	addruart,rx
 		mov	\rx, #0xf8000000
-		add	\rx, \rx, #0x00050000
+		add	\rx, \rx, #0x00050000	@ Ser3
+		@add	\rx, \rx, #0x00010000	@ Ser1
 		.endm
 
 		.macro	senduart,rd,rx
-		str	\rd, [\rx, #0x14]	@ UARTDR
+		str	\rd, [\rx, #0x14]	@ UTDR
 		.endm
 
-		.macro	busyuart,rd,rx
+		.macro	waituart,rd,rx
 1001:		ldr	\rd, [\rx, #0x20]	@ UTSR1
-		tst	\rd, #1 << 2
+		tst	\rd, #1 << 2		@ UTSR1_TNF
 		beq	1001b
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:		ldr	\rd, [\rx, #0x20]	@ UTSR1
+		tst	\rd, #1 << 0		@ UTSR1_TBY
+		bne	1001b
 		.endm
 
 #else
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c
--- v2.3.39/linux/arch/arm/kernel/dec21285.c	Tue Dec 14 01:27:23 1999
+++ linux/arch/arm/kernel/dec21285.c	Thu Jan 13 13:30:31 2000
@@ -220,7 +220,9 @@
 #ifdef CONFIG_HOST_FOOTBRIDGE
 
 	csrio.flags = IORESOURCE_IO;
+	csrio.name  = "DC21285";
 	csrmem.flags = IORESOURCE_MEM;
+	csrmem.name  = "DC21285";
 
 	allocate_resource(&ioport_resource, &csrio, 128,
 			  0xff00, 0xffff, 128, NULL, NULL);
@@ -244,7 +246,7 @@
 				(1 << 31) | (1 << 29) | (1 << 28) | (1 << 24);
 #endif
 
-	printk(KERN_DEBUG"PCI: DC21285 footbridge, revision %02lX\n",
+	printk(KERN_DEBUG "PCI: DC21285 footbridge, revision %02lX\n",
 		*CSR_CLASSREV & 0xff);
 
 	pci_scan_bus(0, &dc21285_ops, NULL);
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/entry-armo.S linux/arch/arm/kernel/entry-armo.S
--- v2.3.39/linux/arch/arm/kernel/entry-armo.S	Tue Aug 31 17:29:12 1999
+++ linux/arch/arm/kernel/entry-armo.S	Thu Jan 13 13:30:31 2000
@@ -535,7 +535,6 @@
 		mov	r0, r1
 		mov	r1, r4
 		mov	r2, r3
-	mov r3, lr
 		b	baddataabort
 
 Ldata_ldrstr_post:
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- v2.3.39/linux/arch/arm/kernel/entry-armv.S	Tue Dec  7 09:32:40 1999
+++ linux/arch/arm/kernel/entry-armv.S	Thu Jan 13 13:30:31 2000
@@ -429,7 +429,10 @@
 		and	r2, r6, #31			@ int mode
 		b	SYMBOL_NAME(bad_mode)
 
-
+#ifdef CONFIG_NWFPE
+		/* The FPE is always present */
+		.equ	fpe_not_present, 0
+#else
 wfs_mask_data:	.word	0x0e200110			@ WFS/RFS
 		.word	0x0fef0fff
 		.word	0x0d0d0100			@ LDF [sp]/STF [sp]
@@ -466,6 +469,7 @@
 		add	r5, r5, r4, lsl #2
 		str	r5, [sp, r6, lsr #14]		@ Save reg
 		mov	pc, r9
+#endif
 
 /*
  * SVC mode handlers
@@ -685,11 +689,11 @@
 		stmfd	sp!, {r4 - sl, fp, lr}		@ Store most regs on stack
 		mrs	ip, cpsr
 		stmfd	sp!, {ip}			@ Save cpsr_SVC
-		ldr	r2, [r1, #TSS_DOMAIN]
 		str	sp, [r0, #TSS_SAVE]		@ Save sp_SVC
 		ldr	sp, [r1, #TSS_SAVE]		@ Get saved sp_SVC
-		mcr	p15, 0, r2, c3, c0		@ Set domain register
+		ldr	r2, [r1, #TSS_DOMAIN]
 		ldmfd	sp!, {ip}
+		mcr	p15, 0, r2, c3, c0		@ Set domain register
 		msr	spsr, ip			@ Save tasks CPSR into SPSR for this return
 		ldmfd	sp!, {r4 - sl, fp, pc}^		@ Load all regs saved previously
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S
--- v2.3.39/linux/arch/arm/kernel/entry-common.S	Tue Aug 31 17:29:12 1999
+++ linux/arch/arm/kernel/entry-common.S	Thu Jan 13 13:30:31 2000
@@ -3,6 +3,9 @@
  * All exits to user mode from the kernel go through this code.
  */
 
+#define S_OFF		8
+#define SYSCALL_REGS	r4, r5
+
 /*
  * Define to favour ARM8, ARM9 and StrongARM cpus.  This says that it is
  * cheaper to use two LDR instructions than a two-register LDM, if the
@@ -16,9 +19,9 @@
 
 		.align	5
 fast_syscall_return:
-		str	r0, [sp, #S_R0 + 4]		@ returned r0
+		str	r0, [sp, #S_R0 + S_OFF]		@ returned r0
 slow_syscall_return:
-		add	sp, sp, #4
+		add	sp, sp, #S_OFF
 ret_from_sys_call:
 #ifdef HARVARD_CACHE
 		ldr	r0, bh_data
@@ -74,65 +77,71 @@
 /*=============================================================================
  * SWI handler
  *-----------------------------------------------------------------------------
- *
- * We now handle sys-call tracing, and the errno in the task structure.
- * Still have a problem with >4 arguments for functions.  Theres only
- * a couple of functions in the code that have 5 arguments, so Im not
- * too worried.
  */
 
+/*
+ * Create some aliases for some registers.  These should allow
+ * us to have in theory up to 7 arguments to a function.
+ */
+scno		.req	r9			@ syscall number
+tbl		.req	r8			@ syscall table pointer
+tip		.req	r7			@ temporary IP
+
 		.align	5
 vector_swi:	save_user_regs
 		mask_pc	lr, lr
 		mov	fp, #0
-		ldr	r6, [lr, #-4]		@ get SWI instruction
-		arm700_bug_check r6, r7
+		ldr	scno, [lr, #-4]		@ get SWI instruction
+		arm700_bug_check scno, ip
 #ifdef CONFIG_ALIGNMENT_TRAP
-		ldr	r7, .LCswi
-		ldr	r7, [r7]
-		mcr	p15, 0, r7, c1, c0
+		ldr	ip, .LCswi
+		ldr	ip, [ip]
+		mcr	p15, 0, ip, c1, c0
 #endif
-		enable_irqs r7
+		enable_irqs ip
 
-		str	r4, [sp, #-4]!		@ new style: (r0 = arg1, r4 = arg5)
+		stmdb	sp!, {SYSCALL_REGS}	@ new style: (r0 = arg1, r4 = arg5, r5 = arg6)
+						@ Note that we dont have to handle
+						@ sys_syscalls arg7 here
 		adrsvc	al, lr, fast_syscall_return
 
-		bic	r6, r6, #0xff000000	@ mask off SWI op-code
-		eor	r6, r6, #OS_NUMBER<<20	@ check OS number
-		cmp	r6, #NR_syscalls	@ check upper syscall limit
+		bic	scno, scno, #0xff000000	@ mask off SWI op-code
+		eor	scno, scno, #OS_NUMBER<<20	@ check OS number
+		cmp	scno, #NR_syscalls	@ check upper syscall limit
 		bcs	2f
 
-		get_current_task r7
-		ldr	ip, [r7, #TSK_FLAGS]	@ check for syscall tracing
-		adr	r5, SYMBOL_NAME(sys_call_table)
+		get_current_task ip
+		ldr	ip, [ip, #TSK_FLAGS]	@ check for syscall tracing
+		adr	tbl, SYMBOL_NAME(sys_call_table)
 		tst	ip, #PF_TRACESYS
-		ldreq	pc, [r5, r6, lsl #2]	@ call sys routine
+		ldreq	pc, [tbl, scno, lsl #2]	@ call sys routine
 
-		ldr	r7, [sp, #S_IP + 4]	@ save old IP
-		mov	r0, #0
-		str	r0, [sp, #S_IP + 4]	@ trace entry [IP = 0]
+		ldr	tip, [sp, #S_IP + S_OFF]	@ save old IP
+		mov	ip, #0
+		str	ip, [sp, #S_IP + S_OFF]	@ trace entry [IP = 0]
 		bl	SYMBOL_NAME(syscall_trace)
-		str	r7, [sp, #S_IP + 4]
+		str	tip, [sp, #S_IP + S_OFF]
 
-		ldmib	sp, {r0 - r3}		@ have to reload r0 - r3
+		add	ip, sp, #S_OFF
+		ldmia	ip, {r0 - r3}		@ have to reload r0 - r3
 		mov	lr, pc
-		ldr	pc, [r5, r6, lsl #2]	@ call sys routine
-		str	r0, [sp, #S_R0 + 4]	@ returned r0
+		ldr	pc, [tbl, scno, lsl #2]	@ call sys routine
+		str	r0, [sp, #S_R0 + S_OFF]	@ returned r0
 
-		mov	r0, #1
-		str	r0, [sp, #S_IP + 4]	@ trace exit [IP = 1]
+		mov	ip, #1
+		str	ip, [sp, #S_IP + S_OFF]	@ trace exit [IP = 1]
 		bl	SYMBOL_NAME(syscall_trace)
-		str	r7, [sp, #S_IP + 4]
+		str	tip, [sp, #S_IP + S_OFF]
 		b	slow_syscall_return
 
-2:		add	r1, sp, #4
-		tst	r6, #0x00f00000		@ is it a Unix SWI?
+2:		add	r1, sp, #S_OFF
+		tst	scno, #0x00f00000	@ is it a Unix SWI?
 		bne	3f
-		subs	r0, r6, #(KSWI_SYS_BASE - KSWI_BASE)
+		subs	r0, scno, #(KSWI_SYS_BASE - KSWI_BASE)
 		bcs	SYMBOL_NAME(arm_syscall)
 		b	SYMBOL_NAME(sys_ni_syscall) @ not private func
 
-3:		eor	r0, r6, #OS_NUMBER <<20	@ Put OS number back
+3:		eor	r0, scno, #OS_NUMBER <<20	@ Put OS number back
 		adrsvc	al, lr, slow_syscall_return
 		b	SYMBOL_NAME(deferred)
 
@@ -150,67 +159,49 @@
 @ r0 = syscall number
 @ r5 = syscall table
 SYMBOL_NAME(sys_syscall):
-		eor	r6, r0, #OS_NUMBER << 20
-		cmp	r6, #NR_syscalls	@ check range
-		add	ip, sp, #4
-		ldmleib	ip, {r0 - r4}		@ get our args
-		strle	r4, [sp]		@ Put our arg on the stack
-		ldrle	pc, [r5, r6, lsl #2]
+		eor	scno, r0, #OS_NUMBER << 20
+		cmp	scno, #NR_syscalls	@ check range
+		add	ip, sp, #S_OFF
+		ldmleib	ip, {r0 - r3, SYSCALL_REGS}	@ get our args
+		stmleia	sp, {SYSCALL_REGS}	@ Put our arg on the stack
+		ldrle	pc, [tbl, scno, lsl #2]
 		mov	r0, #-ENOSYS
-		mov	pc, lr
+		RETINSTR(mov,pc,lr)
 
 sys_fork_wrapper:
-		add	r0, sp, #4
+		add	r0, sp, #S_OFF
 		b	SYMBOL_NAME(sys_fork)
 
 sys_vfork_wrapper:
-		add	r0, sp, #4
+		add	r0, sp, #S_OFF
 		b	SYMBOL_NAME(sys_vfork)
 
 sys_execve_wrapper:
-		add	r3, sp, #4
+		add	r3, sp, #S_OFF
 		b	SYMBOL_NAME(sys_execve)
 
-sys_mount_wrapper:
-		mov	r6, lr
-		add	r5, sp, #4
-		str	r5, [sp]
-		str	r4, [sp, #-4]!
-		bl	SYMBOL_NAME(sys_compat_mount)
-		add	sp, sp, #4
-		RETINSTR(mov,pc,r6)
-
 sys_clone_wapper:
-		add	r2, sp, #4
+		add	r2, sp, #S_OFF
 		b	SYMBOL_NAME(sys_clone)
 
-sys_llseek_wrapper:
-		mov	r6, lr
-		add	r5, sp, #4
-		str	r5, [sp]
-		str	r4, [sp, #-4]!
-		bl	SYMBOL_NAME(sys_compat_llseek)
-		add	sp, sp, #4
-		RETINSTR(mov,pc,r6)
-
 sys_sigsuspend_wrapper:
-		add	r3, sp, #4
+		add	r3, sp, #S_OFF
 		b	SYMBOL_NAME(sys_sigsuspend)
 
 sys_rt_sigsuspend_wrapper:
-		add	r2, sp, #4
+		add	r2, sp, #S_OFF
 		b	SYMBOL_NAME(sys_rt_sigsuspend)
 
 sys_sigreturn_wrapper:
-		add	r0, sp, #4
+		add	r0, sp, #S_OFF
 		b	SYMBOL_NAME(sys_sigreturn)
 
 sys_rt_sigreturn_wrapper:
-		add	r0, sp, #4
+		add	r0, sp, #S_OFF
 		b	SYMBOL_NAME(sys_rt_sigreturn)
 
 sys_sigaltstack_wrapper:
-		ldr	r2, [sp, #4 + S_SP]
+		ldr	r2, [sp, #S_OFF + S_SP]
 		b	do_sigaltstack
 
 		.data
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S
--- v2.3.39/linux/arch/arm/kernel/head-armv.S	Tue Nov 23 22:42:20 1999
+++ linux/arch/arm/kernel/head-armv.S	Thu Jan 13 13:30:31 2000
@@ -69,7 +69,7 @@
  *  r1 contains the unique architecture number.  See
  * linux/arch/arm/kernel/setup.c machine_desc[] array for the complete
  * list.  If you require a new number, please follow the instructions
- * given in Documentation/ARM-README.
+ * given in Documentation/arm/README.
  */
 __entry:	teq	r0, #0
 		movne	r0, #'i'
@@ -83,7 +83,7 @@
 		moveq	r0, #'a'
 		beq	__error
 		bl	__create_page_tables
-		adr	lr, __aligned_call
+		adr	lr, __ret
 		add	pc, r10, #12			@ flush caches (returns ctrl reg)
 
 __switch_data:	.long	__mmap_switched
@@ -94,16 +94,11 @@
 		.long	SYMBOL_NAME(cr_alignment)
 		.long	SYMBOL_NAME(init_task_union)+8192
 
-		/*
-		 * This needs to be aligned to a cache line.
-		 */
-		.align	5
-__aligned_call:
-		ldr	lr, __switch_data
-#ifdef CONFIG_ALIGNMENT_TRAP
-		orr	r0, r0, #2			@ ...........A.
-#endif
+__ret:		ldr	lr, __switch_data
 		mcr	p15, 0, r0, c1, c0
+		mov	r0, r0
+		mov	r0, r0
+		mov	r0, r0
 		mov	pc, lr
 
 		/*
@@ -126,6 +121,9 @@
 
 		str	r9, [r6]			@ Save processor ID
 		str	r1, [r7]			@ Save machine type
+#ifdef CONFIG_ALIGNMENT_TRAP
+		orr	r0, r0, #2			@ ...........A.
+#endif
 		bic	r2, r0, #2			@ Clear 'A' bit
 		stmia	r8, {r0, r2}			@ Save control register values
 		b	SYMBOL_NAME(start_kernel)
@@ -137,16 +135,16 @@
  * amount which are required to get the kernel running, which
  * generally means mapping in the kernel code.
  *
- * We only map in 2MB of RAM, which should be sufficient in
+ * We only map in 4MB of RAM, which should be sufficient in
  * all cases.
  *
- * r4 = physical address of page tables
  * r5 = physical address of start of RAM
  * r6 = physical IO address
  * r7 = byte offset into page tables for IO
  * r8 = page table flags
  */
 __create_page_tables:
+		add	r4, r5, #SWAPPER_PGDIR_OFFSET
 		mov	r0, r4
 		mov	r3, #0
 		add	r2, r0, #0x4000			@ Clear page table
@@ -157,13 +155,22 @@
 		teq	r0, r2
 		bne	1b
 		/*
-		 * map in two sections (2MB) for kernel.
+		 * Create identity mapping for first MB of kernel.
+		 * map in four sections (4MB) for kernel.
 		 * these are marked cacheable and bufferable.
+		 *
+		 * The identity mapping will be removed by  paging_init()
 		 */
-		add	r0, r4, #(TEXTADDR - 0x8000) >> 18
 		mov	r3, #0x0c
 		orr	r3, r3, r8
 		add	r3, r3, r5
+		add	r0, r4, r5, lsr #18
+		str	r3, [r0]
+		add	r0, r4, #(TEXTADDR - 0x8000) >> 18
+		str	r3, [r0], #4
+		add	r3, r3, #1 << 20
+		str	r3, [r0], #4
+		add	r3, r3, #1 << 20
 		str	r3, [r0], #4
 		add	r3, r3, #1 << 20
 		str	r3, [r0], #4
@@ -174,8 +181,11 @@
 		 * via a serial before paging_init.
 		 */
 		add	r0, r4, r7
+		rsb	r3, r7, #0x4000	@ PTRS_PER_PGD*sizeof(long)
+		cmp	r3, #0x0800
+		addge	r2, r0, #0x0800
+		addlt	r2, r0, r3
 		orr	r3, r6, r8
-		add	r2, r0, #0x0800
 1:		str	r3, [r0], #4
 		add	r3, r3, #1 << 20
 		teq	r0, r2
@@ -273,7 +283,7 @@
  * Lookup machine architecture
  * r1 = machine architecture number
  * Returns:
- *  r4 = physical address of page tables
+ *  r4 = unused word
  *  r5 = physical start address of RAM
  *  r6 = physical address of IO
  *  r7 = byte offset into page tables for IO
@@ -284,7 +294,6 @@
 		adr	r4, __arch_types_start
 		add	r4, r4, r1, lsl #4
 		ldmia	r4, {r4, r5, r6, r7}
-		add	r4, r5, #SWAPPER_PGDIR_OFFSET
 		mov	r7, r7, lsr #18
 		mov	pc, lr
 1:		mov	r7, #0
@@ -330,20 +339,20 @@
 		@ 0x04 - DEC EBSA285
 		.long	0
 		.long	0
-		.long	0x24000000			@ I/O base address (0x42000000 -> 0xfe000000)
-		.long	0xe0000000
+		.long	DC21285_ARMCSR_BASE
+		.long	0xfe000000
 
 		@ 0x05 - Rebel.com NetWinder
 		.long	0
 		.long	0
-		.long	0x24000000			@ I/O base address (0x42000000 -> 0xfe000000)
-		.long	0xe0000000
+		.long	DC21285_ARMCSR_BASE
+		.long	0xfe000000
 
 		@ 0x06 - CATS
 		.long	0
 		.long	0
-		.long	0x24000000			@ I/O base address (0x42000000 -> 0xfe000000)
-		.long	0xe0000000
+		.long	DC21285_ARMCSR_BASE
+		.long	0xfe000000
 
 		@ 0x07 - tbox
 		.long	0
@@ -398,9 +407,16 @@
 		.long	0
 		.long	0
 		.long	0
-__arch_types_end:
-		@ unknown - SA1100
+
+		@ 0x10 - SA1100
 		.long	0
 		.long	0xc0000000
 		.long	0x80000000
-		.long	0xe0000000
+		.long	0xf8000000
+
+		/*
+		 * Don't add anything here unless you have an
+		 * architecture number allocated - see
+		 * Documentation/arm/README
+		 */
+__arch_types_end:
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- v2.3.39/linux/arch/arm/kernel/process.c	Tue Dec  7 09:32:40 1999
+++ linux/arch/arm/kernel/process.c	Thu Jan 13 13:30:31 2000
@@ -50,13 +50,13 @@
 static int __init nohlt_setup(char *__unused)
 {
 	hlt_counter = 1;
-	return 0;
+	return 1;
 }
 
 static int __init hlt_setup(char *__unused)
 {
 	hlt_counter = 0;
-	return 0;
+	return 1;
 }
 
 __setup("nohlt", nohlt_setup);
@@ -114,6 +114,7 @@
 
 void machine_power_off(void)
 {
+	arch_power_off();
 }
 
 void show_regs(struct pt_regs * regs)
@@ -284,7 +285,7 @@
 int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
 {
 	if (current->used_math)
-		memcpy(fp, &current->thread.fpstate.soft, sizeof (fp));
+		memcpy(fp, &current->thread.fpstate.soft, sizeof (*fp));
 
 	return current->used_math;
 }
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.3.39/linux/arch/arm/kernel/setup.c	Tue Dec 14 01:27:23 1999
+++ linux/arch/arm/kernel/setup.c	Thu Jan 13 13:30:31 2000
@@ -54,13 +54,13 @@
 struct machine_desc {
 	const char	*name;		/* architecture name	*/
 	unsigned int	param_offset;	/* parameter page	*/
+	unsigned int	video_start;	/* start of video RAM	*/
+	unsigned int	video_end;	/* end of video RAM	*/
 	unsigned int	reserve_lp0 :1;	/* never has lp0	*/
 	unsigned int	reserve_lp1 :1;	/* never has lp1	*/
 	unsigned int	reserve_lp2 :1;	/* never has lp2	*/
 	unsigned int	broken_hlt  :1;	/* hlt is broken	*/
 	unsigned int	soft_reboot :1;	/* soft reboot		*/
-	unsigned int	video_start;	/* start of video RAM	*/
-	unsigned int	video_end;	/* end of video RAM	*/
 	void		(*fixup)(struct machine_desc *,
 				 struct param_struct *, char **);
 };
@@ -201,7 +201,7 @@
 				meminfo.nr_banks = 0;
 			}
 
-			start = 0;
+			start = PHYS_OFFSET;
 			size  = memparse(from + 4, &from);
 			if (*from == '@')
 				start = memparse(from + 1, &from);
@@ -250,17 +250,18 @@
 }
 
 #define O_PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-#define P_PFN_DOWN(x)	O_PFN_DOWN((x) - PHYS_OFFSET)
 #define V_PFN_DOWN(x)	O_PFN_DOWN(__pa(x))
 
 #define O_PFN_UP(x)	(PAGE_ALIGN(x) >> PAGE_SHIFT)
-#define P_PFN_UP(x)	O_PFN_UP((x) - PHYS_OFFSET)
 #define V_PFN_UP(x)	O_PFN_UP(__pa(x))
 
 #define PFN_SIZE(x)	((x) >> PAGE_SHIFT)
 #define PFN_RANGE(s,e)	PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
 				(((unsigned long)(s)) & PAGE_MASK))
 
+/*
+ * FIXME: These can be removed when Ingo's cleanup patch goes in
+ */
 #define free_bootmem(s,sz)	free_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT)
 #define reserve_bootmem(s,sz)	reserve_bootmem((s)<<PAGE_SHIFT, (sz)<<PAGE_SHIFT)
 
@@ -277,10 +278,10 @@
 	 */
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start) {
-		if (__pa(initrd_end) > (meminfo.end + PHYS_OFFSET)) {
+		if (__pa(initrd_end) > meminfo.end) {
 			printk ("initrd extends beyond end of memory "
 				"(0x%08lx > 0x%08lx) - disabling initrd\n",
-				__pa(initrd_end), meminfo.end + PHYS_OFFSET);
+				__pa(initrd_end), meminfo.end);
 			initrd_start = 0;
 			initrd_end   = 0;
 		}
@@ -373,7 +374,7 @@
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
-		reserve_bootmem(O_PFN_DOWN(initrd_start),
+		reserve_bootmem(V_PFN_DOWN(initrd_start),
 				PFN_RANGE(initrd_start, initrd_end));
 #endif
 }
@@ -528,16 +529,66 @@
 		char **cmdline)
 {
 #if 0
-	if (machine_is_co285()) {
-		extern unsigned long boot_memory_end;
-		extern char boot_command_line[];
-
-		meminfo.nr_banks      = 1;
-		meminfo.bank[0].start = PHYS_OFFSET;
-		meminfo.bank[0].size  = boot_memory_end;
+	extern unsigned long boot_memory_end;
+	extern char boot_command_line[];
 
-		*cmdline = boot_command_line;
+	meminfo.nr_banks      = 1;
+	meminfo.bank[0].start = PHYS_OFFSET;
+	meminfo.bank[0].size  = boot_memory_end;
+
+	*cmdline = boot_command_line;
+#endif
+}
+
+static void __init
+fixup_sa1100(struct machine_desc *desc, struct param_struct *params,
+		char **cmdline)
+{
+#ifdef CONFIG_ARCH_SA1100
+	int i;
+	extern struct mem_desc {
+		unsigned long phys_start;
+		unsigned long length;
+	} mem_desc[];
+	extern unsigned int mem_desc_size;
+
+	for( i = 0; i < mem_desc_size; i++ ) {
+		if( i >= NR_BANKS ) {
+			printk( __FUNCTION__ 
+				": mem_desc too large for meminfo structure\n");
+			break;
+		}
+		meminfo.bank[i].start = mem_desc[i].phys_start;
+		meminfo.bank[i].size = mem_desc[i].length;
 	}
+	meminfo.nr_banks = i;
+
+#if defined(CONFIG_SA1100_BRUTUS)
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	setup_ramdisk( 1, 0, 0, 8192 );
+	setup_initrd( __phys_to_virt(0xd8000000), 0x00400000 );
+#elif defined(CONFIG_SA1100_EMPEG)
+	ROOT_DEV = MKDEV( 3, 1 );  /* /dev/hda1 */
+	setup_ramdisk( 1, 0, 0, 4096 );
+	setup_initrd( 0xd0000000+((1024-320)*1024), (320*1024) );
+#elif defined(CONFIG_SA1100_TIFON)
+	ROOT_DEV = MKDEV(UNNAMED_MAJOR, 0);
+	setup_ramdisk(1, 0, 0, 4096);
+	setup_initrd( 0xd0000000 + 0x1100004, 0x140000 );
+#elif defined(CONFIG_SA1100_VICTOR)
+	ROOT_DEV = MKDEV( 60, 2 );
+
+	/* Get command line parameters passed from the loader (if any) */
+	if( *((char*)0xc0000000) )
+		strcpy( default_command_line, ((char *)0xc0000000) );
+
+	/* power off if any problem */
+	strcat( default_command_line, " panic=1" );
+#elif defined(CONFIG_SA1100_LART)
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR,0);
+	setup_ramdisk(1, 0, 0, 8192);
+	setup_initrd(0xc0400000, 0x00400000);
+#endif
 #endif
 }
 
@@ -565,7 +616,7 @@
 		NO_VIDEO,
 		0, 0, 0, 0, 0,
 		NULL
-	}, { "Nexus-FTV/PCI",	/* Philip Blundell	*/
+	}, { "FTV/PCI",		/* Philip Blundell	*/
 		NO_PARAMS,
 		NO_VIDEO,
 		0, 0, 0, 0, 0,
@@ -627,9 +678,15 @@
 		NULL
 	}, { "Shark",		/* Alexander Schulz	*/
 		NO_PARAMS,
-		NO_VIDEO,
+		/* do you really mean 0x200000? */
+		0x06000000, 0x06000000+0x00200000,
 		0, 0, 0, 0, 0,
 		NULL
+	}, { "SA1100-based",	/* Nicolas Pitre	*/
+		NO_PARAMS,
+		NO_VIDEO,
+		0, 0, 0, 0, 0,
+		fixup_sa1100
 	}
 };
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/signal.c linux/arch/arm/kernel/signal.c
--- v2.3.39/linux/arch/arm/kernel/signal.c	Tue Jan 11 22:31:36 2000
+++ linux/arch/arm/kernel/signal.c	Thu Jan 13 13:30:31 2000
@@ -278,6 +278,7 @@
 
 	err |= __put_user (current->thread.trap_no, &sc->trap_no);
 	err |= __put_user (current->thread.error_code, &sc->error_code);
+	err |= __put_user (current->thread.address, &sc->fault_address);
 	err |= __put_user (mask, &sc->oldmask);
 
 	return err;
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c
--- v2.3.39/linux/arch/arm/kernel/sys_arm.c	Wed Dec  8 14:11:25 1999
+++ linux/arch/arm/kernel/sys_arm.c	Thu Jan 13 13:30:31 2000
@@ -79,12 +79,26 @@
 	return error;
 }
 
+#define PGOFF_SHIFT (PAGE_SHIFT - 12)
+#define PGOFF_MASK  (~((1 << PGOFF_SHIFT) - 1))
+
 /*
- * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. ARM Linux didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
- * block for parameter passing..
+ * Note: off_4k is always units of 4K.  If we can't do the requested
+ * offset, we return EINVAL.
  */
+asmlinkage long
+sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+	  unsigned long flags, unsigned long fd, unsigned long off_4k)
+{
+	unsigned long pgoff;
+
+	if (off_4k & ~PGOFF_MASK)
+		return -EINVAL;
+
+	pgoff = off_4k >> PGOFF_SHIFT;
+
+	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
 
 struct mmap_arg_struct {
 	unsigned long addr;
@@ -112,6 +126,10 @@
 	return error;
 }
 
+/*
+ * Perform the select(nd, in, out, ex, tv) and mmap() system
+ * calls.
+ */
 extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
 
 struct sel_arg_struct {
@@ -251,48 +269,11 @@
 	return error;
 }
 
-/*
- * Detect the old function calling standard
- */
-static inline unsigned long old_calling_standard (struct pt_regs  *regs)
-{
-	unsigned long instr, *pcv = (unsigned long *)(instruction_pointer(regs) - 8);
-	return (!get_user (instr, pcv) && instr == 0xe1a0300d);
-}
-
 /* Compatability functions - we used to pass 5 parameters as r0, r1, r2, *r3, *(r3+4)
  * We now use r0 - r4, and return an error if the old style calling standard is used.
  * Eventually these functions will disappear.
  */
-asmlinkage int
-sys_compat_llseek (unsigned int fd, unsigned long offset_high, unsigned long offset_low,
-		loff_t *result, unsigned int origin, struct pt_regs *regs)
-{
-	extern int sys_llseek (unsigned int, unsigned long, unsigned long, loff_t *, unsigned int);
-
-	if (old_calling_standard (regs)) {
-		printk (KERN_NOTICE "%s (%d): unsupported llseek call standard\n",
-			current->comm, current->pid);
-		return -EINVAL;
-	}
-	return sys_llseek (fd, offset_high, offset_low, result, origin);
-}
-
-asmlinkage int
-sys_compat_mount (char *devname, char *dirname, char *type, unsigned long flags, void *data,
-		  struct pt_regs *regs)
-{
-	extern int sys_mount (char *, char *, char *, unsigned long, void *);
-
-	if (old_calling_standard (regs)) {
-		printk (KERN_NOTICE "%s (%d): unsupported mount call standard\n",
-			current->comm, current->pid);
-		return -EINVAL;
-	}
-	return sys_mount (devname, dirname, type, flags, data);
-}
-
-asmlinkage int sys_uname (struct old_utsname * name)
+asmlinkage int sys_uname(struct old_utsname * name)
 {
 	static int warned = 0;
 	int err;
@@ -331,15 +312,15 @@
 	down(&uts_sem);
 	
 	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-	error -= __put_user(0,name->release+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-	error -= __put_user(0,name->version+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
-	error -= __put_user(0,name->machine+__OLD_UTS_LEN);
+	error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	error |= __put_user(0,name->release+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	error |= __put_user(0,name->version+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	error |= __put_user(0,name->machine+__OLD_UTS_LEN);
 	
 	up(&uts_sem);
 	
@@ -354,4 +335,3 @@
 	schedule();
 	return -ERESTARTNOHAND;
 }
-
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c
--- v2.3.39/linux/arch/arm/kernel/time.c	Tue Aug 31 17:29:12 1999
+++ linux/arch/arm/kernel/time.c	Thu Jan 13 13:30:31 2000
@@ -112,7 +112,7 @@
 
 	/*
 	 * xtime is atomically updated in timer_bh. lost_ticks is
-	 * nonzero if the tiemr bottom half hasnt executed yet.
+	 * nonzero if the timer bottom half hasnt executed yet.
 	 */
 	if (lost_ticks)
 		tv->tv_usec += USECS_PER_JIFFY;
diff -u --recursive --new-file v2.3.39/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.3.39/linux/arch/arm/kernel/traps.c	Tue Dec 14 01:27:23 1999
+++ linux/arch/arm/kernel/traps.c	Thu Jan 13 13:30:31 2000
@@ -187,10 +187,11 @@
 		dump_instr(instruction_pointer(regs), 0);
 	}
 
-	spin_unlock_irq(&die_lock);	
+	spin_unlock_irq(&die_lock);
+	do_exit(SIGSEGV);
 }
 
-static void die_if_kernel(const char *str, struct pt_regs *regs, int err)
+void die_if_kernel(const char *str, struct pt_regs *regs, int err)
 {
 	if (user_mode(regs))
     		return;
@@ -241,11 +242,10 @@
 }
 
 /*
- * bad_mode handles the impossible case in the vectors.
- * If you see one of these, then it's extremely serious,
- * and could mean you have buggy hardware.  It never
- * returns, and never tries to sync.  We hope that we
- * can dump out some state information...
+ * bad_mode handles the impossible case in the vectors.  If you see one of
+ * these, then it's extremely serious, and could mean you have buggy hardware.
+ * It never returns, and never tries to sync.  We hope that we can at least
+ * dump out some state information...
  */
 asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
 {
@@ -255,7 +255,8 @@
 		handler[reason], processor_modes[proc_mode]);
 
 	/*
-	 * Dump out the vectors and stub routines
+	 * Dump out the vectors and stub routines.  Maybe a better solution
+	 * would be to dump them out only if we detect that they are corrupted.
 	 */
 	printk(KERN_CRIT "Vectors:\n");
 	dump_mem(0, 0x40);
@@ -279,6 +280,9 @@
 	current->used_math = 1;
 }
 
+/*
+ * Handle some more esoteric system calls
+ */
 asmlinkage int arm_syscall (int no, struct pt_regs *regs)
 {
 	switch (no) {
@@ -295,7 +299,7 @@
 
 	case 2:	/* sys_cacheflush */
 #ifdef CONFIG_CPU_32
-		/* r0 = start, r1 = length, r2 = flags */
+		/* r0 = start, r1 = end, r2 = flags */
 		cpu_flush_cache_area(regs->ARM_r0, regs->ARM_r1, 1);
 #endif
 		break;
@@ -308,7 +312,7 @@
 		if (no <= 0x7ff)
 			return -ENOSYS;
 #ifdef CONFIG_DEBUG_USER
-		/* experiance shows that these seem to indicate that
+		/* experience shows that these seem to indicate that
 		 * something catastrophic has happened
 		 */
 		printk("[%d] %s: arm syscall %d\n", current->pid, current->comm, no);
@@ -357,16 +361,19 @@
 		function, __builtin_return_address(0), size);
 }
 
-#ifdef CONFIG_CPU_26
-asmlinkage void baddataabort(int code, unsigned long instr, struct pt_regs *regs)
+/*
+ * A data abort trap was taken, but the instruction was not an instruction
+ * which should cause the trap to be taken.  Try to abort it.  Note that
+ * the while(1) is there because we cannot currently handle returning from
+ * this function.
+ */
+asmlinkage void
+baddataabort(int code, unsigned long instr, struct pt_regs *regs)
 {
 	unsigned long phys, addr = instruction_pointer(regs);
 
 #ifdef CONFIG_DEBUG_ERRORS
-	printk("pid=%d\n", current->pid);
-
-	show_regs(regs);
-	dump_instr(instruction_pointer(regs), 1);
+	dump_instr(addr, 1);
 	{
 		pgd_t *pgd;
 
@@ -385,10 +392,10 @@
 		printk ("\n");
 	}
 #endif
-	panic("unknown data abort code %d [pc=%08lx *pc=%08lx lr=%08lx sp=%08lx]",
-		code, regs->ARM_pc, instr, regs->ARM_lr, regs->ARM_sp);
+	force_sig(SIGILL, current);
+	die_if_kernel("unknown data abort code", regs, instr);
+	while (1);
 }
-#endif
 
 void __bug(const char *file, int line, void *data)
 {
@@ -423,6 +430,19 @@
 {
 	printk("Division by zero in kernel.\n");
 	__backtrace();
+}
+
+void abort(void)
+{
+	void *lr = __builtin_return_address(0);
+
+	printk(KERN_CRIT "abort() called from %p!  (Please "
+	       "report to rmk@arm.linux.org.uk)\n", lr);
+
+	*(int *)0 = 0;
+
+	/* if that doesn't kill us, halt */
+	panic("Oops failed to kill thread");
 }
 
 void __init trap_init(void)
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.3.39/linux/arch/arm/lib/Makefile	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/lib/Makefile	Thu Jan 13 13:30:31 2000
@@ -5,8 +5,14 @@
 #
 
 L_TARGET := lib.a
-L_OBJS   := backtrace.o bitops.o checksum.o delay.o \
-	    string.o system.o uaccess.o
+L_OBJS   := changebit.o csumipv6.o csumpartial.o csumpartialcopy.o \
+	    csumpartialcopyuser.o clearbit.o copy_page.o findbit.o \
+	    memchr.o memcpy.o memset.o memzero.o setbit.o strchr.o \
+	    strrchr.o testchangebit.o testclearbit.o testsetbit.o  \
+	    uaccess.o
+
+O_TARGET := lib.o
+O_OBJS   := backtrace.o delay.o
 
 ifeq ($(PROCESSOR),armo)
   L_OBJS += uaccess-armo.o
@@ -25,13 +31,21 @@
 ifeq ($(MACHINE),ebsa110)
   L_OBJS += io-ebsa110.o
 else
-  LX_OBJS += io.o
+  OX_OBJS += io.o
 endif
 
 ifeq ($(MACHINE),footbridge)
   L_OBJS += io-footbridge.o
 endif
 
+#
+# SA1100 IO routines happen to be the
+# same as the footbridge routines
+#
+ifeq ($(MACHINE),sa1100)
+  L_OBJS += io-footbridge.o
+endif
+
 include $(TOPDIR)/Rules.make
 
 .S.o:
@@ -42,5 +56,3 @@
 
 getconsdata.o: getconsdata.c
 	$(CC) $(CFLAGS) -c getconsdata.c
-
-checksum.o string.o: constants.h
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/bitops.S linux/arch/arm/lib/bitops.S
--- v2.3.39/linux/arch/arm/lib/bitops.S	Tue Jan 20 16:39:41 1998
+++ linux/arch/arm/lib/bitops.S	Wed Dec 31 16:00:00 1969
@@ -1,152 +0,0 @@
-/*
- * linux/arch/arm/lib/bitops.S
- *
- * Copyright (C) 1995, 1996 Russell King
- */
-
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-                .text
-
-@ Purpose  : Function to set a bit
-@ Prototype: int set_bit(int bit,int *addr)
-
-ENTRY(set_bit)
-                and     r2, r0, #7
-                mov     r3, #1
-                mov     r3, r3, lsl r2
-		SAVEIRQS(ip)
-		DISABLEIRQS(ip)
-		ldrb	r2, [r1, r0, lsr #3]
-		orr	r2, r2, r3
-		strb	r2, [r1, r0, lsr #3]
-		RESTOREIRQS(ip)
-		RETINSTR(mov,pc,lr)
-
-ENTRY(test_and_set_bit)
-		add	r1, r1, r0, lsr #3	@ Get byte offset
-		and	r3, r0, #7		@ Get bit offset
-		mov	r0, #1
-		SAVEIRQS(ip)
-		DISABLEIRQS(ip)
-		ldrb	r2, [r1]
-		tst	r2, r0, lsl r3
-		orr	r2, r2, r0, lsl r3
-		moveq	r0, #0
-		strb	r2, [r1]
-		RESTOREIRQS(ip)
-		RETINSTR(mov,pc,lr)
-
-@ Purpose  : Function to clear a bit
-@ Prototype: int clear_bit(int bit,int *addr)
-
-ENTRY(clear_bit)
-		and	r2, r0, #7
-		mov	r3, #1
-		mov	r3, r3, lsl r2
-		SAVEIRQS(ip)
-		DISABLEIRQS(ip)
-		ldrb	r2, [r1, r0, lsr #3]
-		bic	r2, r2, r3
-		strb	r2, [r1, r0, lsr #3]
-		RESTOREIRQS(ip)
-		RETINSTR(mov,pc,lr)
-
-ENTRY(test_and_clear_bit)
-		add	r1, r1, r0, lsr #3	@ Get byte offset
-		and	r3, r0, #7	@ Get bit offset
-		mov	r0, #1
-		SAVEIRQS(ip)
-		DISABLEIRQS(ip)
-		ldrb	r2, [r1]
-		tst	r2, r0, lsl r3
-		bic	r2, r2, r0, lsl r3
-		moveq	r0, #0
-		strb	r2, [r1]
-		RESTOREIRQS(ip)
-		RETINSTR(mov,pc,lr)
-
-/* Purpose  : Function to change a bit
- * Prototype: int change_bit(int bit,int *addr)
- */
-ENTRY(change_bit)
-                and     r2, r0, #7
-                mov     r3, #1
-                mov     r3, r3, lsl r2
-		SAVEIRQS(ip)
-		DISABLEIRQS(ip)
-		ldrb	r2, [r1, r0, lsr #3]
-		eor	r2, r2, r3
-		strb	r2, [r1, r0, lsr #3]
-		RESTOREIRQS(ip)
-		RETINSTR(mov,pc,lr)
-
-ENTRY(test_and_change_bit)
-		add	r1, r1, r0, lsr #3
-		and	r3, r0, #7
-		mov	r0, #1
-		SAVEIRQS(ip)
-		DISABLEIRQS(ip)
-		ldrb	r2, [r1]
-		tst	r2, r0, lsl r3
-		eor	r2, r2, r0, lsl r3
-		moveq	r0, #0
-		strb	r2, [r1]
-		RESTOREIRQS(ip)
-		RETINSTR(mov,pc,lr)
-
-@ Purpose  : Find a 'zero' bit
-@ Prototype: int find_first_zero_bit(char *addr,int maxbit);
-
-ENTRY(find_first_zero_bit)
-		mov	r2, #0			@ Initialise bit position
-Lfindzbit1lp:	ldrb	r3, [r0, r2, lsr #3]	@ Check byte, if 0xFF, then all bits set
-		teq	r3, #0xFF
-		bne	Lfoundzbit
-		add	r2, r2, #8
-		cmp	r2, r1			@ Check to see if we have come to the end
-		bcc	Lfindzbit1lp
-		add	r0, r1, #1		@ Make sure that we flag an error
-		RETINSTR(mov,pc,lr)
-Lfoundzbit:	tst	r3, #1			@ Check individual bits
-		moveq	r0, r2
-		RETINSTR(moveq,pc,lr)
-		tst	r3, #2
-		addeq	r0, r2, #1
-		RETINSTR(moveq,pc,lr)
-		tst	r3, #4
-		addeq	r0, r2, #2
-		RETINSTR(moveq,pc,lr)
-		tst	r3, #8
-		addeq	r0, r2, #3
-		RETINSTR(moveq,pc,lr)
-		tst	r3, #16
-		addeq	r0, r2, #4
-		RETINSTR(moveq,pc,lr)
-		tst	r3, #32
-		addeq	r0, r2, #5
-		RETINSTR(moveq,pc,lr)
-		tst	r3, #64
-		addeq	r0, r2, #6
-		RETINSTR(moveq,pc,lr)
-		add	r0, r2, #7
-		RETINSTR(mov,pc,lr)
-
-@ Purpose  : Find next 'zero' bit
-@ Prototype: int find_next_zero_bit(char *addr,int maxbit,int offset)
-
-ENTRY(find_next_zero_bit)
-		tst	r2, #7
-		beq	Lfindzbit1lp		@ If new byte, goto old routine
-		ldrb	r3, [r0, r2, lsr#3]
-		orr	r3, r3, #0xFF00		@ Set top bits so we wont get confused
-		stmfd	sp!, {r4}
-		and	r4, r2, #7
-		mov	r3, r3, lsr r4		@ Shift right by no. of bits
-		ldmfd	sp!, {r4}
-		and	r3, r3, #0xFF
-		teq	r3, #0xFF
-		orreq	r2, r2, #7
-		addeq	r2, r2, #1
-		beq	Lfindzbit1lp		@ If all bits are set, goto old routine
-		b	Lfoundzbit
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/changebit.S linux/arch/arm/lib/changebit.S
--- v2.3.39/linux/arch/arm/lib/changebit.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/changebit.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/lib/changebit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+                .text
+
+/* Purpose  : Function to change a bit
+ * Prototype: int change_bit(int bit,int *addr)
+ */
+ENTRY(change_bit)
+                and     r2, r0, #7
+                mov     r3, #1
+                mov     r3, r3, lsl r2
+		SAVEIRQS(ip)
+		DISABLEIRQS(ip)
+		ldrb	r2, [r1, r0, lsr #3]
+		eor	r2, r2, r3
+		strb	r2, [r1, r0, lsr #3]
+		RESTOREIRQS(ip)
+		RETINSTR(mov,pc,lr)
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/checksum.S linux/arch/arm/lib/checksum.S
--- v2.3.39/linux/arch/arm/lib/checksum.S	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/lib/checksum.S	Wed Dec 31 16:00:00 1969
@@ -1,734 +0,0 @@
-/*
- * linux/arch/arm/lib/checksum.S
- *
- * Copyright (C) 1995, 1996, 1997, 1998 Russell King
- */
-#include <linux/config.h>
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/errno.h>
-#include "constants.h"
-
-		.text
-
-/* Function: __u32 csum_partial(const char *src, int len, __u32)
- * Params  : r0 = buffer, r1 = len, r2 = checksum
- * Returns : r0 = new checksum
- */
-
-ENTRY(csum_partial)
-		tst	r0, #2
-		beq	1f
-		subs	r1, r1, #2
-		addmi	r1, r1, #2
-		bmi	3f
-		bic	r0, r0, #3
-		ldr	r3, [r0], #4
-		adds	r2, r2, r3, lsr #16
-		adcs	r2, r2, #0
-1:		adds	r2, r2, #0
-		bics	ip, r1, #31
-		beq	3f
-		stmfd	sp!, {r4 - r6}
-2:		ldmia	r0!, {r3 - r6}
-		adcs	r2, r2, r3
-		adcs	r2, r2, r4
-		adcs	r2, r2, r5
-		adcs	r2, r2, r6
-		ldmia	r0!, {r3 - r6}
-		adcs	r2, r2, r3
-		adcs	r2, r2, r4
-		adcs	r2, r2, r5
-		adcs	r2, r2, r6
-		sub	ip, ip, #32
-		teq	ip, #0
-		bne	2b
-		adcs	r2, r2, #0
-		ldmfd	sp!, {r4 - r6}
-3:		ands	ip, r1, #0x1c
-		beq	5f
-4:		ldr	r3, [r0], #4
-		adcs	r2, r2, r3
-		sub	ip, ip, #4
-		teq	ip, #0
-		bne	4b
-		adcs	r2, r2, #0
-5:		ands	ip, r1, #3
-		moveq	r0, r2
-		RETINSTR(moveq,pc,lr)
-		mov	ip, ip, lsl #3
-		rsb	ip, ip, #32
-		ldr	r3, [r0]
-		mov	r3, r3, lsl ip
-		adds	r2, r2, r3, lsr ip
-		adc	r0, r2, #0
-		RETINSTR(mov,pc,lr)
-
-/* Function: __u32 csum_partial_copy_from_user (const char *src, char *dst, int len, __u32 sum, int *err_ptr)
- * Params  : r0 = src, r1 = dst, r2 = len, r3 = sum, [sp, #0] = &err
- * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT
- */
-#if defined(CONFIG_CPU_32)
-
-		.macro	save_regs
-		stmfd	sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}
-		.endm
-
-		.macro	load_regs,flags
-		ldm\flags	fp, {r1, r2, r4-r8, fp, sp, pc}
-		.endm
-
-		.macro	load1b,	reg1
-9999:		ldrbt	\reg1, [r0], $1
-		.section __ex_table, "a"
-		.align	3
-		.long	9999b, 6001f
-		.previous
-		.endm
-
-		.macro	load2b, reg1, reg2
-9999:		ldrbt	\reg1, [r0], $1
-9998:		ldrbt	\reg2, [r0], $1
-		.section __ex_table, "a"
-		.long	9999b, 6001f
-		.long	9998b, 6001f
-		.previous
-		.endm
-
-		.macro	load1l, reg1
-9999:		ldrt	\reg1, [r0], $4
-		.section __ex_table, "a"
-		.align	3
-		.long	9999b, 6001f
-		.previous
-		.endm
-
-		.macro	load2l, reg1, reg2
-9999:		ldrt	\reg1, [r0], $4
-9998:		ldrt	\reg2, [r0], $4
-		.section __ex_table, "a"
-		.long	9999b, 6001f
-		.long	9998b, 6001f
-		.previous
-		.endm
-
-		.macro	load4l, reg1, reg2, reg3, reg4
-9999:		ldrt	\reg1, [r0], $4
-9998:		ldrt	\reg2, [r0], $4
-9997:		ldrt	\reg3, [r0], $4
-9996:		ldrt	\reg4, [r0], $4
-		.section __ex_table, "a"
-		.long	9999b, 6001f
-		.long	9998b, 6001f
-		.long	9997b, 6001f
-		.long	9996b, 6001f
-		.previous
-		.endm
-
-#elif defined(CONFIG_CPU_26)
-
-		.macro	save_regs
-		stmfd	sp!, {r1 - r2, r4 - r9, fp, ip, lr, pc}
-		mov	r9, sp, lsr #13
-		mov	r9, r9, lsl #13
-		ldr	r9, [r9, #TSK_ADDR_LIMIT]
-		mov	r9, r9, lsr #24
-		.endm
-
-		.macro	load_regs,flags
-		ldm\flags	fp, {r1, r2, r4-r9, fp, sp, pc}^
-		.endm
-
-		.macro	load1b,	reg1
-		tst	r9, #0x01
-9999:		ldreqbt	\reg1, [r0], #1
-		ldrneb	\reg1, [r0], #1
-		.section __ex_table, "a"
-		.align	3
-		.long	9999b, 6001f
-		.previous
-		.endm
-
-		.macro	load2b, reg1, reg2
-		tst	r9, #0x01
-9999:		ldreqbt	\reg1, [r0], #1
-		ldrneb	\reg1, [r0], #1
-9998:		ldreqbt	\reg2, [r0], #1
-		ldrneb	\reg2, [r0], #1
-		.section __ex_table, "a"
-		.long	9999b, 6001f
-		.long	9998b, 6001f
-		.previous
-		.endm
-
-		.macro	load1l, reg1
-		tst	r9, #0x01
-9999:		ldreqt	\reg1, [r0], #4
-		ldrne	\reg1, [r0], #4
-		.section __ex_table, "a"
-		.align	3
-		.long	9999b, 6001f
-		.previous
-		.endm
-
-		.macro	load2l, reg1, reg2
-		tst	r9, #0x01
-		ldmneia	r0!, {\reg1, \reg2}
-9999:		ldreqt	\reg1, [r0], #4
-9998:		ldreqt	\reg2, [r0], #4
-		.section __ex_table, "a"
-		.long	9999b, 6001f
-		.long	9998b, 6001f
-		.previous
-		.endm
-
-		.macro	load4l, reg1, reg2, reg3, reg4
-		tst	r9, #0x01
-		ldmneia	r0!, {\reg1, \reg2, \reg3, \reg4}
-9999:		ldreqt	\reg1, [r0], #4
-9998:		ldreqt	\reg2, [r0], #4
-9997:		ldreqt	\reg3, [r0], #4
-9996:		ldreqt	\reg4, [r0], #4
-		.section __ex_table, "a"
-		.long	9999b, 6001f
-		.long	9998b, 6001f
-		.long	9997b, 6001f
-		.long	9996b, 6001f
-		.previous
-		.endm
-
-#else
-#error Unknown CPU architecture
-#endif
-
-ENTRY(csum_partial_copy_from_user)
-		mov	ip, sp
-		save_regs
-		sub	fp, ip, #4
-		cmp	r2, #4
-		blt	.too_small_user
-		tst	r1, #2			@ Test destination alignment
-		beq	.dst_aligned_user
-		subs	r2, r2, #2		@ We do not know if SRC is aligned...
-		load2b	ip, r8
-		orr	ip, ip, r8, lsl #8
-		adds	r3, r3, ip
-		adcs	r3, r3, #0
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1		@ Destination now aligned
-.dst_aligned_user:
-		tst	r0, #3
-		bne	.src_not_aligned_user
-		adds	r3, r3, #0
-		bics	ip, r2, #15		@ Routine for src & dst aligned
-		beq	2f
-1:		load4l	r4, r5, r6, r7
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r4, r5
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		tst	ip, #4
-		beq	4f
-3:		load1l	r4
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		load1l	r4
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-.exit:		tst	r2, #1
-		strneb	r4, [r1], #1
-		andne	r4, r4, #255
-		adcnes	r3, r3, r4
-		adcs	r0, r3, #0
-		load_regs	ea
-
-.too_small_user:
-		teq	r2, #0
-		load_regs	eqea
-		cmp	r2, #2
-		blt	.too_small_user1
-		load2b	ip, r8
-		orr	ip, ip, r8, lsl #8
-		adds	r3, r3, ip
-		strb	ip, [r1], #1
-		strb	r8, [r1], #1
-		tst	r2, #1
-.too_small_user1:				@ C = 0
-		beq	.csum_exit
-		load1b	ip
-		strb	ip, [r1], #1
-		adcs	r3, r3, ip
-.csum_exit:	adc	r0, r3, #0
-		load_regs	ea
-
-.src_not_aligned_user:
-		cmp	r2, #4
-		blt	.too_small_user
-		and	ip, r0, #3
-		bic	r0, r0, #3
-		load1l	r4
-		cmp	ip, #2
-		beq	.src2_aligned_user
-		bhi	.src3_aligned_user
-		mov	r4, r4, lsr #8
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
-		mov	r7, r7, lsr #8
-		orr	r7, r7, r8, lsl #24
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #8
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #8
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #24
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #8
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		b	.exit
-
-.src2_aligned_user:
-		mov	r4, r4, lsr #16
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7, lsl #16
-		mov	r7, r7, lsr #16
-		orr	r7, r7, r8, lsl #16
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #16
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #16
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #16
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #16
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		load1b	r4
-		b	.exit
-
-.src3_aligned_user:
-		mov	r4, r4, lsr #24
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		load4l	r5, r6, r7, r8
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
-		mov	r7, r7, lsr #24
-		orr	r7, r7, r8, lsl #8
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #24
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		load2l	r5, r6
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #24
-		tst	ip, #4
-		beq	4f
-3:		load1l	r5
-		orr	r4, r4, r5, lsl #8
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #24
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		load_regs	eqea
-		tst	r2, #2
-		beq	.exit
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		load1l	r4
-		strb	r4, [r1], #1
-		adcs	r3, r3, r4, lsl #24
-		mov	r4, r4, lsr #8
-		b	.exit
-
-#if defined(CONFIG_CPU_32)
-		.section .fixup,"ax"
-#endif
-		.align	4
-6001:		mov	r4, #-EFAULT
-		ldr	r5, [fp, #4]
-		str	r4, [r5]
-		ldmia	sp, {r1, r2}		@ retrieve original arguments
-		add	r2, r2, r1
-		mov	r3, #0			@ zero the buffer
-6002:		teq	r2, r1
-		strneb	r3, [r1], #1
-		bne	6002b
-		load_regs	ea
-#if defined(CONFIG_CPU_32)
-		.previous
-#endif
-
-/* Function: __u32 csum_partial_copy (const char *src, char *dst, int len, __u32 sum)
- * Params  : r0 = src, r1 = dst, r2 = len, r3 = checksum
- * Returns : r0 = new checksum
- */
-ENTRY(csum_partial_copy_nocheck)
-ENTRY(csum_partial_copy)
-		mov	ip, sp
-		stmfd	sp!, {r4 - r8, fp, ip, lr, pc}
-		sub	fp, ip, #4
-		cmp	r2, #4
-		blt	Ltoo_small
-		tst	r1, #2			@ Test destination alignment
-		beq	Ldst_aligned
-		subs	r2, r2, #2		@ We do not know if SRC is aligned...
-		ldrb	ip, [r0], #1
-		ldrb	r8, [r0], #1
-		orr	ip, ip, r8, lsl #8
-		adds	r3, r3, ip
-		adcs	r3, r3, #0
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strb	ip, [r1], #1		@ Destination now aligned
-Ldst_aligned:	tst	r0, #3
-		bne	Lsrc_not_aligned
-		adds	r3, r3, #0
-		bics	ip, r2, #15		@ Routine for src & dst aligned
-		beq	3f
-1:		ldmia	r0!, {r4, r5, r6, r7}
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-3:		ands	ip, r2, #12
-		beq	5f
-		tst	ip, #8
-		beq	4f
-		ldmia	r0!, {r4, r5}
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		tst	ip, #4
-		beq	5f
-4:		ldr	r4, [r0], #4
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-5:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
-		ldr	r4, [r0], #4
-		tst	r2, #2
-		beq	Lexit_r4
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		b	Lexit_r4
-
-Ltoo_small:	teq	r2, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
-		cmp	r2, #2
-		blt	Ltoo_small1
-		ldrb	ip, [r0], #1
-		ldrb	r8, [r0], #1
-		orr	ip, ip, r8, lsl #8
-		adds	r3, r3, ip
-		strb	ip, [r1], #1
-		strb	r8, [r1], #1
-		tst	r2, #1
-Ltoo_small1:	ldrneb	r4, [r0], #1
-Lexit_r4:	tst	r2, #1
-		strneb	r4, [r1], #1
-		andne	r4, r4, #255
-		adcnes	r3, r3, r4
-		adcs	r0, r3, #0
-		LOADREGS(ea,fp,{r4 - r8, fp, sp, pc})
-
-Lsrc_not_aligned:
-		cmp	r2, #4
-		blt	Ltoo_small
-		and	ip, r0, #3
-		bic	r0, r0, #3
-		ldr	r4, [r0], #4
-		cmp	ip, #2
-		beq	Lsrc2_aligned
-		bhi	Lsrc3_aligned
-		mov	r4, r4, lsr #8
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		ldmia	r0!, {r5, r6, r7, r8}
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
-		mov	r7, r7, lsr #8
-		orr	r7, r7, r8, lsl #24
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #8
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		ldmia	r0!, {r5, r6}
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #8
-		tst	ip, #4
-		beq	4f
-3:		ldr	r5, [r0], #4
-		orr	r4, r4, r5, lsl #24
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #8
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
-		tst	r2, #2
-		beq	Lexit_r4
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		b	Lexit_r4
-
-Lsrc2_aligned:	mov	r4, r4, lsr #16
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		ldmia	r0!, {r5, r6, r7, r8}
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7, lsl #16
-		mov	r7, r7, lsr #16
-		orr	r7, r7, r8, lsl #16
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #16
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		ldmia	r0!, {r5, r6}
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #16
-		tst	ip, #4
-		beq	4f
-3:		ldr	r5, [r0], #4
-		orr	r4, r4, r5, lsl #16
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #16
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
-		tst	r2, #2
-		beq	Lexit_r4
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		mov	r4, r4, lsr #8
-		strb	r4, [r1], #1
-		ldrb	r4, [r0], #1
-		b	Lexit_r4
-
-Lsrc3_aligned:	mov	r4, r4, lsr #24
-		adds	r3, r3, #0
-		bics	ip, r2, #15
-		beq	2f
-1:		ldmia	r0!, {r5, r6, r7, r8}
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
-		mov	r7, r7, lsr #24
-		orr	r7, r7, r8, lsl #8
-		stmia	r1!, {r4, r5, r6, r7}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		adcs	r3, r3, r6
-		adcs	r3, r3, r7
-		mov	r4, r8, lsr #24
-		sub	ip, ip, #16
-		teq	ip, #0
-		bne	1b
-2:		ands	ip, r2, #12
-		beq	4f
-		tst	ip, #8
-		beq	3f
-		ldmia	r0!, {r5, r6}
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		stmia	r1!, {r4, r5}
-		adcs	r3, r3, r4
-		adcs	r3, r3, r5
-		mov	r4, r6, lsr #24
-		tst	ip, #4
-		beq	4f
-3:		ldr	r5, [r0], #4
-		orr	r4, r4, r5, lsl #8
-		str	r4, [r1], #4
-		adcs	r3, r3, r4
-		mov	r4, r5, lsr #24
-4:		ands	r2, r2, #3
-		adceq	r0, r3, #0
-		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
-		tst	r2, #2
-		beq	Lexit_r4
-		adcs	r3, r3, r4, lsl #16
-		strb	r4, [r1], #1
-		ldr	r4, [r0], #4
-		strb	r4, [r1], #1
-		adcs	r3, r3, r4, lsl #24
-		mov	r4, r4, lsr #8
-		b	Lexit_r4
-
-ENTRY(__csum_ipv6_magic)
-		stmfd	sp!, {lr}
-		adds	ip, r2, r3
-		ldmia	r1, {r1 - r3, lr}
-		adcs	ip, ip, r1
-		adcs	ip, ip, r2
-		adcs	ip, ip, r3
-		adcs	ip, ip, lr
-		ldmia	r0, {r0 - r3}
-		adcs	r0, ip, r0
-		adcs	r0, r0, r1
-		adcs	r0, r0, r2
-		adcs	r0, r0, r3
-		ldr	r3, [sp, #4]
-		adcs	r0, r0, r3
-		adcs	r0, r0, #0
-		LOADREGS(fd, sp!, {pc})
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/clearbit.S linux/arch/arm/lib/clearbit.S
--- v2.3.39/linux/arch/arm/lib/clearbit.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/clearbit.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/lib/clearbit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+                .text
+
+@ Purpose  : Function to clear a bit
+@ Prototype: int clear_bit(int bit,int *addr)
+
+ENTRY(clear_bit)
+		and	r2, r0, #7
+		mov	r3, #1
+		mov	r3, r3, lsl r2
+		SAVEIRQS(ip)
+		DISABLEIRQS(ip)
+		ldrb	r2, [r1, r0, lsr #3]
+		bic	r2, r2, r3
+		strb	r2, [r1, r0, lsr #3]
+		RESTOREIRQS(ip)
+		RETINSTR(mov,pc,lr)
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/copy_page.S linux/arch/arm/lib/copy_page.S
--- v2.3.39/linux/arch/arm/lib/copy_page.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/copy_page.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,35 @@
+/*
+ * linux/arch/arm/lib/copypage.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ *
+ * ASM optimised string functions
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include "constants.h"
+
+		.text 
+/*
+ * StrongARM optimised copy_page routine
+ * now 1.72bytes/cycle, was 1.60 bytes/cycle
+ * (50MHz bus -> 86MB/s)
+ */
+
+ENTRY(copy_page)
+		stmfd	sp!, {r4, lr}			@	2
+		mov	r2, #PAGE_SZ/64			@	1
+1:		ldmia	r1!, {r3, r4, ip, lr}		@	4
+		subs	r2, r2, #1			@	1
+		stmia	r0!, {r3, r4, ip, lr}		@	4
+		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
+		stmia	r0!, {r3, r4, ip, lr}		@	4
+		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
+		stmia	r0!, {r3, r4, ip, lr}		@	4
+		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
+		stmia	r0!, {r3, r4, ip, lr}		@	4
+		bne	1b				@	1
+		LOADREGS(fd, sp!, {r4, pc})		@	3
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/csumipv6.S linux/arch/arm/lib/csumipv6.S
--- v2.3.39/linux/arch/arm/lib/csumipv6.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/csumipv6.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/arm/lib/csumipv6.S
+ *
+ * Copyright (C) 1995-1998 Russell King
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+		.text
+
+ENTRY(__csum_ipv6_magic)
+		str	lr, [sp, #-4]!
+		adds	ip, r2, r3
+		ldmia	r1, {r1 - r3, lr}
+		adcs	ip, ip, r1
+		adcs	ip, ip, r2
+		adcs	ip, ip, r3
+		adcs	ip, ip, lr
+		ldmia	r0, {r0 - r3}
+		adcs	r0, ip, r0
+		adcs	r0, r0, r1
+		adcs	r0, r0, r2
+		ldr	r2, [sp, #4]
+		adcs	r0, r0, r3
+		adcs	r0, r0, r2
+		adcs	r0, r0, #0
+		LOADREGS(fd, sp!, {pc})
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/csumpartial.S linux/arch/arm/lib/csumpartial.S
--- v2.3.39/linux/arch/arm/lib/csumpartial.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/csumpartial.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,64 @@
+/*
+ * linux/arch/arm/lib/csumpartial.S
+ *
+ * Copyright (C) 1995-1998 Russell King
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+		.text
+
+/* Function: __u32 csum_partial(const char *src, int len, __u32)
+ * Params  : r0 = buffer, r1 = len, r2 = checksum
+ * Returns : r0 = new checksum
+ */
+
+ENTRY(csum_partial)
+		tst	r0, #2
+		beq	1f
+		subs	r1, r1, #2
+		addmi	r1, r1, #2
+		bmi	3f
+		bic	r0, r0, #3
+		ldr	r3, [r0], #4
+		adds	r2, r2, r3, lsr #16
+		adcs	r2, r2, #0
+1:		adds	r2, r2, #0
+		bics	ip, r1, #31
+		beq	3f
+		stmfd	sp!, {r4 - r6}
+2:		ldmia	r0!, {r3 - r6}
+		adcs	r2, r2, r3
+		adcs	r2, r2, r4
+		adcs	r2, r2, r5
+		adcs	r2, r2, r6
+		ldmia	r0!, {r3 - r6}
+		adcs	r2, r2, r3
+		adcs	r2, r2, r4
+		adcs	r2, r2, r5
+		adcs	r2, r2, r6
+		sub	ip, ip, #32
+		teq	ip, #0
+		bne	2b
+		adcs	r2, r2, #0
+		ldmfd	sp!, {r4 - r6}
+3:		ands	ip, r1, #0x1c
+		beq	5f
+4:		ldr	r3, [r0], #4
+		sub	ip, ip, #4
+		adcs	r2, r2, r3
+		teq	ip, #0
+		bne	4b
+		adcs	r2, r2, #0
+5:		ands	ip, r1, #3
+		moveq	r0, r2
+		RETINSTR(moveq,pc,lr)
+		mov	ip, ip, lsl #3
+		ldr	r3, [r0]
+		rsb	ip, ip, #32
+		mov	r3, r3, lsl ip
+		adds	r2, r2, r3, lsr ip
+		adc	r0, r2, #0
+		RETINSTR(mov,pc,lr)
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/csumpartialcopy.S linux/arch/arm/lib/csumpartialcopy.S
--- v2.3.39/linux/arch/arm/lib/csumpartialcopy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/csumpartialcopy.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,257 @@
+/*
+ * linux/arch/arm/lib/csumpartialcopy.S
+ *
+ * Copyright (C) 1995-1998 Russell King
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+		.text
+
+/* Function: __u32 csum_partial_copy_nocheck(const char *src, char *dst, int len, __u32 sum)
+ * Params  : r0 = src, r1 = dst, r2 = len, r3 = checksum
+ * Returns : r0 = new checksum
+ */
+ENTRY(csum_partial_copy_nocheck)
+		mov	ip, sp
+		stmfd	sp!, {r4 - r8, fp, ip, lr, pc}
+		sub	fp, ip, #4
+		cmp	r2, #4
+		blt	Ltoo_small
+		tst	r1, #2			@ Test destination alignment
+		beq	Ldst_aligned
+		ldrb	ip, [r0], #1
+		ldrb	r8, [r0], #1
+		subs	r2, r2, #2		@ We do not know if SRC is aligned...
+		orr	ip, ip, r8, lsl #8
+		adds	r3, r3, ip
+		adcs	r3, r3, #0
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strb	ip, [r1], #1		@ Destination now aligned
+Ldst_aligned:	tst	r0, #3
+		bne	Lsrc_not_aligned
+		adds	r3, r3, #0
+		bics	ip, r2, #15		@ Routine for src & dst aligned
+		beq	3f
+1:		ldmia	r0!, {r4, r5, r6, r7}
+		stmia	r1!, {r4, r5, r6, r7}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		adcs	r3, r3, r6
+		adcs	r3, r3, r7
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+3:		ands	ip, r2, #12
+		beq	5f
+		tst	ip, #8
+		beq	4f
+		ldmia	r0!, {r4, r5}
+		stmia	r1!, {r4, r5}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		tst	ip, #4
+		beq	5f
+4:		ldr	r4, [r0], #4
+		str	r4, [r1], #4
+		adcs	r3, r3, r4
+5:		ands	r2, r2, #3
+		adceq	r0, r3, #0
+		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		ldr	r4, [r0], #4
+		tst	r2, #2
+		beq	Lexit_r4
+		adcs	r3, r3, r4, lsl #16
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		b	Lexit_r4
+
+Ltoo_small:	teq	r2, #0
+		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		cmp	r2, #2
+		blt	Ltoo_small1
+		ldrb	ip, [r0], #1
+		ldrb	r8, [r0], #1
+		orr	ip, ip, r8, lsl #8
+		adds	r3, r3, ip
+		strb	ip, [r1], #1
+		strb	r8, [r1], #1
+		tst	r2, #1
+Ltoo_small1:	ldrneb	r4, [r0], #1
+Lexit_r4:	tst	r2, #1
+		strneb	r4, [r1], #1
+		andne	r4, r4, #255
+		adcnes	r3, r3, r4
+		adcs	r0, r3, #0
+		LOADREGS(ea,fp,{r4 - r8, fp, sp, pc})
+
+Lsrc_not_aligned:
+		cmp	r2, #4
+		blt	Ltoo_small
+		and	ip, r0, #3
+		bic	r0, r0, #3
+		ldr	r4, [r0], #4
+		cmp	ip, #2
+		beq	Lsrc2_aligned
+		bhi	Lsrc3_aligned
+		mov	r4, r4, lsr #8
+		adds	r3, r3, #0
+		bics	ip, r2, #15
+		beq	2f
+1:		ldmia	r0!, {r5, r6, r7, r8}
+		orr	r4, r4, r5, lsl #24
+		mov	r5, r5, lsr #8
+		orr	r5, r5, r6, lsl #24
+		mov	r6, r6, lsr #8
+		orr	r6, r6, r7, lsl #24
+		mov	r7, r7, lsr #8
+		orr	r7, r7, r8, lsl #24
+		stmia	r1!, {r4, r5, r6, r7}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		adcs	r3, r3, r6
+		adcs	r3, r3, r7
+		mov	r4, r8, lsr #8
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, r2, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		ldmia	r0!, {r5, r6}
+		orr	r4, r4, r5, lsl #24
+		mov	r5, r5, lsr #8
+		orr	r5, r5, r6, lsl #24
+		stmia	r1!, {r4, r5}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		mov	r4, r6, lsr #8
+		tst	ip, #4
+		beq	4f
+3:		ldr	r5, [r0], #4
+		orr	r4, r4, r5, lsl #24
+		str	r4, [r1], #4
+		adcs	r3, r3, r4
+		mov	r4, r5, lsr #8
+4:		ands	r2, r2, #3
+		adceq	r0, r3, #0
+		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		tst	r2, #2
+		beq	Lexit_r4
+		adcs	r3, r3, r4, lsl #16
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		b	Lexit_r4
+
+Lsrc2_aligned:	mov	r4, r4, lsr #16
+		adds	r3, r3, #0
+		bics	ip, r2, #15
+		beq	2f
+1:		ldmia	r0!, {r5, r6, r7, r8}
+		orr	r4, r4, r5, lsl #16
+		mov	r5, r5, lsr #16
+		orr	r5, r5, r6, lsl #16
+		mov	r6, r6, lsr #16
+		orr	r6, r6, r7, lsl #16
+		mov	r7, r7, lsr #16
+		orr	r7, r7, r8, lsl #16
+		stmia	r1!, {r4, r5, r6, r7}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		adcs	r3, r3, r6
+		adcs	r3, r3, r7
+		mov	r4, r8, lsr #16
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, r2, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		ldmia	r0!, {r5, r6}
+		orr	r4, r4, r5, lsl #16
+		mov	r5, r5, lsr #16
+		orr	r5, r5, r6, lsl #16
+		stmia	r1!, {r4, r5}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		mov	r4, r6, lsr #16
+		tst	ip, #4
+		beq	4f
+3:		ldr	r5, [r0], #4
+		orr	r4, r4, r5, lsl #16
+		str	r4, [r1], #4
+		adcs	r3, r3, r4
+		mov	r4, r5, lsr #16
+4:		ands	r2, r2, #3
+		adceq	r0, r3, #0
+		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		tst	r2, #2
+		beq	Lexit_r4
+		adcs	r3, r3, r4, lsl #16
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [r1], #1
+		ldrb	r4, [r0], #1
+		b	Lexit_r4
+
+Lsrc3_aligned:	mov	r4, r4, lsr #24
+		adds	r3, r3, #0
+		bics	ip, r2, #15
+		beq	2f
+1:		ldmia	r0!, {r5, r6, r7, r8}
+		orr	r4, r4, r5, lsl #8
+		mov	r5, r5, lsr #24
+		orr	r5, r5, r6, lsl #8
+		mov	r6, r6, lsr #24
+		orr	r6, r6, r7, lsl #8
+		mov	r7, r7, lsr #24
+		orr	r7, r7, r8, lsl #8
+		stmia	r1!, {r4, r5, r6, r7}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		adcs	r3, r3, r6
+		adcs	r3, r3, r7
+		mov	r4, r8, lsr #24
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, r2, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		ldmia	r0!, {r5, r6}
+		orr	r4, r4, r5, lsl #8
+		mov	r5, r5, lsr #24
+		orr	r5, r5, r6, lsl #8
+		stmia	r1!, {r4, r5}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		mov	r4, r6, lsr #24
+		tst	ip, #4
+		beq	4f
+3:		ldr	r5, [r0], #4
+		orr	r4, r4, r5, lsl #8
+		str	r4, [r1], #4
+		adcs	r3, r3, r4
+		mov	r4, r5, lsr #24
+4:		ands	r2, r2, #3
+		adceq	r0, r3, #0
+		LOADREGS(eqea,fp,{r4 - r8, fp, sp, pc})
+		tst	r2, #2
+		beq	Lexit_r4
+		adcs	r3, r3, r4, lsl #16
+		strb	r4, [r1], #1
+		ldr	r4, [r0], #4
+		strb	r4, [r1], #1
+		adcs	r3, r3, r4, lsl #24
+		mov	r4, r4, lsr #8
+		b	Lexit_r4
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/csumpartialcopyuser.S linux/arch/arm/lib/csumpartialcopyuser.S
--- v2.3.39/linux/arch/arm/lib/csumpartialcopyuser.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/csumpartialcopyuser.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,419 @@
+/*
+ * linux/arch/arm/lib/csumpartialcopyuser.S
+ *
+ * Copyright (C) 1995-1998 Russell King
+ */
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+#include "constants.h"
+
+		.text
+
+/* Function: __u32 csum_partial_copy_from_user (const char *src, char *dst, int len, __u32 sum, int *err_ptr)
+ * Params  : r0 = src, r1 = dst, r2 = len, r3 = sum, [sp, #0] = &err
+ * Returns : r0 = checksum, [[sp, #0], #0] = 0 or -EFAULT
+ */
+#if defined(CONFIG_CPU_32)
+
+		.macro	save_regs
+		stmfd	sp!, {r1 - r2, r4 - r8, fp, ip, lr, pc}
+		.endm
+
+		.macro	load_regs,flags
+		ldm\flags	fp, {r1, r2, r4-r8, fp, sp, pc}
+		.endm
+
+		.macro	load1b,	reg1
+9999:		ldrbt	\reg1, [r0], $1
+		.section __ex_table, "a"
+		.align	3
+		.long	9999b, 6001f
+		.previous
+		.endm
+
+		.macro	load2b, reg1, reg2
+9999:		ldrbt	\reg1, [r0], $1
+9998:		ldrbt	\reg2, [r0], $1
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.previous
+		.endm
+
+		.macro	load1l, reg1
+9999:		ldrt	\reg1, [r0], $4
+		.section __ex_table, "a"
+		.align	3
+		.long	9999b, 6001f
+		.previous
+		.endm
+
+		.macro	load2l, reg1, reg2
+9999:		ldrt	\reg1, [r0], $4
+9998:		ldrt	\reg2, [r0], $4
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.previous
+		.endm
+
+		.macro	load4l, reg1, reg2, reg3, reg4
+9999:		ldrt	\reg1, [r0], $4
+9998:		ldrt	\reg2, [r0], $4
+9997:		ldrt	\reg3, [r0], $4
+9996:		ldrt	\reg4, [r0], $4
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.long	9997b, 6001f
+		.long	9996b, 6001f
+		.previous
+		.endm
+
+#elif defined(CONFIG_CPU_26)
+
+		.macro	save_regs
+		stmfd	sp!, {r1 - r2, r4 - r9, fp, ip, lr, pc}
+		mov	r9, sp, lsr #13
+		mov	r9, r9, lsl #13
+		ldr	r9, [r9, #TSK_ADDR_LIMIT]
+		mov	r9, r9, lsr #24
+		.endm
+
+		.macro	load_regs,flags
+		ldm\flags	fp, {r1, r2, r4-r9, fp, sp, pc}^
+		.endm
+
+		.macro	load1b,	reg1
+		tst	r9, #0x01
+9999:		ldreqbt	\reg1, [r0], #1
+		ldrneb	\reg1, [r0], #1
+		.section __ex_table, "a"
+		.align	3
+		.long	9999b, 6001f
+		.previous
+		.endm
+
+		.macro	load2b, reg1, reg2
+		tst	r9, #0x01
+9999:		ldreqbt	\reg1, [r0], #1
+		ldrneb	\reg1, [r0], #1
+9998:		ldreqbt	\reg2, [r0], #1
+		ldrneb	\reg2, [r0], #1
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.previous
+		.endm
+
+		.macro	load1l, reg1
+		tst	r9, #0x01
+9999:		ldreqt	\reg1, [r0], #4
+		ldrne	\reg1, [r0], #4
+		.section __ex_table, "a"
+		.align	3
+		.long	9999b, 6001f
+		.previous
+		.endm
+
+		.macro	load2l, reg1, reg2
+		tst	r9, #0x01
+		ldmneia	r0!, {\reg1, \reg2}
+9999:		ldreqt	\reg1, [r0], #4
+9998:		ldreqt	\reg2, [r0], #4
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.previous
+		.endm
+
+		.macro	load4l, reg1, reg2, reg3, reg4
+		tst	r9, #0x01
+		ldmneia	r0!, {\reg1, \reg2, \reg3, \reg4}
+9999:		ldreqt	\reg1, [r0], #4
+9998:		ldreqt	\reg2, [r0], #4
+9997:		ldreqt	\reg3, [r0], #4
+9996:		ldreqt	\reg4, [r0], #4
+		.section __ex_table, "a"
+		.long	9999b, 6001f
+		.long	9998b, 6001f
+		.long	9997b, 6001f
+		.long	9996b, 6001f
+		.previous
+		.endm
+
+#else
+#error Unknown CPU architecture
+#endif
+
+ENTRY(csum_partial_copy_from_user)
+		mov	ip, sp
+		save_regs
+		sub	fp, ip, #4
+		cmp	r2, #4
+		blt	.too_small_user
+		tst	r1, #2			@ Test destination alignment
+		beq	.dst_aligned_user
+		load2b	ip, r8
+		subs	r2, r2, #2		@ We do not know if SRC is aligned...
+		orr	ip, ip, r8, lsl #8
+		adds	r3, r3, ip
+		adcs	r3, r3, #0
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strb	ip, [r1], #1		@ Destination now aligned
+.dst_aligned_user:
+		tst	r0, #3
+		bne	.src_not_aligned_user
+		adds	r3, r3, #0
+		bics	ip, r2, #15		@ Routine for src & dst aligned
+		beq	2f
+1:		load4l	r4, r5, r6, r7
+		stmia	r1!, {r4, r5, r6, r7}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		adcs	r3, r3, r6
+		adcs	r3, r3, r7
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, r2, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		load2l	r4, r5
+		stmia	r1!, {r4, r5}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		tst	ip, #4
+		beq	4f
+3:		load1l	r4
+		str	r4, [r1], #4
+		adcs	r3, r3, r4
+4:		ands	r2, r2, #3
+		adceq	r0, r3, #0
+		load_regs	eqea
+		load1l	r4
+		tst	r2, #2
+		beq	.exit
+		adcs	r3, r3, r4, lsl #16
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+.exit:		tst	r2, #1
+		strneb	r4, [r1], #1
+		andne	r4, r4, #255
+		adcnes	r3, r3, r4
+		adcs	r0, r3, #0
+		load_regs	ea
+
+.too_small_user:
+		teq	r2, #0
+		load_regs	eqea
+		cmp	r2, #2
+		blt	.too_small_user1
+		load2b	ip, r8
+		orr	ip, ip, r8, lsl #8
+		adds	r3, r3, ip
+		strb	ip, [r1], #1
+		strb	r8, [r1], #1
+		tst	r2, #1
+.too_small_user1:				@ C = 0
+		beq	.csum_exit
+		load1b	ip
+		strb	ip, [r1], #1
+		adcs	r3, r3, ip
+.csum_exit:	adc	r0, r3, #0
+		load_regs	ea
+
+.src_not_aligned_user:
+		cmp	r2, #4
+		blt	.too_small_user
+		and	ip, r0, #3
+		bic	r0, r0, #3
+		load1l	r4
+		cmp	ip, #2
+		beq	.src2_aligned_user
+		bhi	.src3_aligned_user
+		mov	r4, r4, lsr #8
+		adds	r3, r3, #0
+		bics	ip, r2, #15
+		beq	2f
+1:		load4l	r5, r6, r7, r8
+		orr	r4, r4, r5, lsl #24
+		mov	r5, r5, lsr #8
+		orr	r5, r5, r6, lsl #24
+		mov	r6, r6, lsr #8
+		orr	r6, r6, r7, lsl #24
+		mov	r7, r7, lsr #8
+		orr	r7, r7, r8, lsl #24
+		stmia	r1!, {r4, r5, r6, r7}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		adcs	r3, r3, r6
+		adcs	r3, r3, r7
+		mov	r4, r8, lsr #8
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, r2, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		load2l	r5, r6
+		orr	r4, r4, r5, lsl #24
+		mov	r5, r5, lsr #8
+		orr	r5, r5, r6, lsl #24
+		stmia	r1!, {r4, r5}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		mov	r4, r6, lsr #8
+		tst	ip, #4
+		beq	4f
+3:		load1l	r5
+		orr	r4, r4, r5, lsl #24
+		str	r4, [r1], #4
+		adcs	r3, r3, r4
+		mov	r4, r5, lsr #8
+4:		ands	r2, r2, #3
+		adceq	r0, r3, #0
+		load_regs	eqea
+		tst	r2, #2
+		beq	.exit
+		adcs	r3, r3, r4, lsl #16
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		b	.exit
+
+.src2_aligned_user:
+		mov	r4, r4, lsr #16
+		adds	r3, r3, #0
+		bics	ip, r2, #15
+		beq	2f
+1:		load4l	r5, r6, r7, r8
+		orr	r4, r4, r5, lsl #16
+		mov	r5, r5, lsr #16
+		orr	r5, r5, r6, lsl #16
+		mov	r6, r6, lsr #16
+		orr	r6, r6, r7, lsl #16
+		mov	r7, r7, lsr #16
+		orr	r7, r7, r8, lsl #16
+		stmia	r1!, {r4, r5, r6, r7}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		adcs	r3, r3, r6
+		adcs	r3, r3, r7
+		mov	r4, r8, lsr #16
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, r2, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		load2l	r5, r6
+		orr	r4, r4, r5, lsl #16
+		mov	r5, r5, lsr #16
+		orr	r5, r5, r6, lsl #16
+		stmia	r1!, {r4, r5}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		mov	r4, r6, lsr #16
+		tst	ip, #4
+		beq	4f
+3:		load1l	r5
+		orr	r4, r4, r5, lsl #16
+		str	r4, [r1], #4
+		adcs	r3, r3, r4
+		mov	r4, r5, lsr #16
+4:		ands	r2, r2, #3
+		adceq	r0, r3, #0
+		load_regs	eqea
+		tst	r2, #2
+		beq	.exit
+		adcs	r3, r3, r4, lsl #16
+		strb	r4, [r1], #1
+		mov	r4, r4, lsr #8
+		strb	r4, [r1], #1
+		tst	r2, #1
+		adceq	r0, r3, #0
+		load_regs	eqea
+		load1b	r4
+		b	.exit
+
+.src3_aligned_user:
+		mov	r4, r4, lsr #24
+		adds	r3, r3, #0
+		bics	ip, r2, #15
+		beq	2f
+1:		load4l	r5, r6, r7, r8
+		orr	r4, r4, r5, lsl #8
+		mov	r5, r5, lsr #24
+		orr	r5, r5, r6, lsl #8
+		mov	r6, r6, lsr #24
+		orr	r6, r6, r7, lsl #8
+		mov	r7, r7, lsr #24
+		orr	r7, r7, r8, lsl #8
+		stmia	r1!, {r4, r5, r6, r7}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		adcs	r3, r3, r6
+		adcs	r3, r3, r7
+		mov	r4, r8, lsr #24
+		sub	ip, ip, #16
+		teq	ip, #0
+		bne	1b
+2:		ands	ip, r2, #12
+		beq	4f
+		tst	ip, #8
+		beq	3f
+		load2l	r5, r6
+		orr	r4, r4, r5, lsl #8
+		mov	r5, r5, lsr #24
+		orr	r5, r5, r6, lsl #8
+		stmia	r1!, {r4, r5}
+		adcs	r3, r3, r4
+		adcs	r3, r3, r5
+		mov	r4, r6, lsr #24
+		tst	ip, #4
+		beq	4f
+3:		load1l	r5
+		orr	r4, r4, r5, lsl #8
+		str	r4, [r1], #4
+		adcs	r3, r3, r4
+		mov	r4, r5, lsr #24
+4:		ands	r2, r2, #3
+		adceq	r0, r3, #0
+		load_regs	eqea
+		tst	r2, #2
+		beq	.exit
+		adcs	r3, r3, r4, lsl #16
+		strb	r4, [r1], #1
+		load1l	r4
+		strb	r4, [r1], #1
+		adcs	r3, r3, r4, lsl #24
+		mov	r4, r4, lsr #8
+		b	.exit
+
+#if defined(CONFIG_CPU_32)
+		.section .fixup,"ax"
+#endif
+		.align	4
+6001:		mov	r4, #-EFAULT
+		ldr	r5, [fp, #4]
+		str	r4, [r5]
+		ldmia	sp, {r1, r2}		@ retrieve original arguments
+		add	r2, r2, r1
+		mov	r3, #0			@ zero the buffer
+6002:		teq	r2, r1
+		strneb	r3, [r1], #1
+		bne	6002b
+		load_regs	ea
+#if defined(CONFIG_CPU_32)
+		.previous
+#endif
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/findbit.S linux/arch/arm/lib/findbit.S
--- v2.3.39/linux/arch/arm/lib/findbit.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/findbit.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,65 @@
+/*
+ * linux/arch/arm/lib/bitops.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+                .text
+
+@ Purpose  : Find a 'zero' bit
+@ Prototype: int find_first_zero_bit(char *addr,int maxbit);
+
+ENTRY(find_first_zero_bit)
+		mov	r2, #0			@ Initialise bit position
+Lfindzbit1lp:	ldrb	r3, [r0, r2, lsr #3]	@ Check byte, if 0xFF, then all bits set
+		teq	r3, #0xFF
+		bne	Lfoundzbit
+		add	r2, r2, #8
+		cmp	r2, r1			@ Check to see if we have come to the end
+		bcc	Lfindzbit1lp
+		add	r0, r1, #1		@ Make sure that we flag an error
+		RETINSTR(mov,pc,lr)
+Lfoundzbit:	tst	r3, #1			@ Check individual bits
+		moveq	r0, r2
+		RETINSTR(moveq,pc,lr)
+		tst	r3, #2
+		addeq	r0, r2, #1
+		RETINSTR(moveq,pc,lr)
+		tst	r3, #4
+		addeq	r0, r2, #2
+		RETINSTR(moveq,pc,lr)
+		tst	r3, #8
+		addeq	r0, r2, #3
+		RETINSTR(moveq,pc,lr)
+		tst	r3, #16
+		addeq	r0, r2, #4
+		RETINSTR(moveq,pc,lr)
+		tst	r3, #32
+		addeq	r0, r2, #5
+		RETINSTR(moveq,pc,lr)
+		tst	r3, #64
+		addeq	r0, r2, #6
+		RETINSTR(moveq,pc,lr)
+		add	r0, r2, #7
+		RETINSTR(mov,pc,lr)
+
+@ Purpose  : Find next 'zero' bit
+@ Prototype: int find_next_zero_bit(char *addr,int maxbit,int offset)
+
+ENTRY(find_next_zero_bit)
+		tst	r2, #7
+		beq	Lfindzbit1lp		@ If new byte, goto old routine
+		ldrb	r3, [r0, r2, lsr#3]
+		orr	r3, r3, #0xFF00		@ Set top bits so we wont get confused
+		stmfd	sp!, {r4}
+		and	r4, r2, #7
+		mov	r3, r3, lsr r4		@ Shift right by no. of bits
+		ldmfd	sp!, {r4}
+		and	r3, r3, #0xFF
+		teq	r3, #0xFF
+		orreq	r2, r2, #7
+		addeq	r2, r2, #1
+		beq	Lfindzbit1lp		@ If all bits are set, goto old routine
+		b	Lfoundzbit
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/getconsdata.c linux/arch/arm/lib/getconsdata.c
--- v2.3.39/linux/arch/arm/lib/getconsdata.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/lib/getconsdata.c	Thu Jan 13 13:30:31 2000
@@ -10,6 +10,16 @@
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
 
+/*
+ * Make sure that the compiler and target are compatible
+ */
+#if (defined(__APCS_32__) && defined(CONFIG_CPU_26))
+#error Your compiler targets APCS-32 but this kernel requires APCS-26.
+#endif
+#if (defined(__APCS_26__) && defined(CONFIG_CPU_32))
+#error Your compiler targets APCS-26 but this kernel requires APCS-32.
+#endif
+
 #undef PAGE_READONLY
 
 #define OFF_TSK(n) (unsigned long)&(((struct task_struct *)0)->n)
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/io-footbridge.S linux/arch/arm/lib/io-footbridge.S
--- v2.3.39/linux/arch/arm/lib/io-footbridge.S	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/lib/io-footbridge.S	Thu Jan 13 13:30:31 2000
@@ -6,7 +6,9 @@
 
 		.macro	ioaddr, rd,rn
 		add	\rd, \rn, #pcio_high
+		.if	pcio_low
 		add	\rd, \rd, #pcio_low
+		.endif
 		.endm
 
 ENTRY(insl)
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/memchr.S linux/arch/arm/lib/memchr.S
--- v2.3.39/linux/arch/arm/lib/memchr.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/memchr.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/lib/memchr.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ *
+ * ASM optimised string functions
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include "constants.h"
+
+		.text
+ENTRY(memchr)
+		str	lr, [sp, #-4]!
+1:		ldrb	r3, [r0], #1
+		teq	r3, r1
+		beq	2f
+		subs	r2, r2, #1
+		bpl	1b
+2:		movne	r0, #0
+		subeq	r0, r0, #1
+		LOADREGS(fd, sp!, {pc})
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/memcpy.S linux/arch/arm/lib/memcpy.S
--- v2.3.39/linux/arch/arm/lib/memcpy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/memcpy.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,318 @@
+/*
+ * linux/arch/arm/lib/memcpy.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ *
+ * ASM optimised string functions
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include "constants.h"
+
+		.text
+
+#define ENTER	\
+		mov	ip,sp	;\
+		stmfd	sp!,{r4-r9,fp,ip,lr,pc}	;\
+		sub	fp,ip,#4
+
+#define EXIT	\
+		LOADREGS(ea, fp, {r4 - r9, fp, sp, pc})
+
+#define EXITEQ	\
+		LOADREGS(eqea, fp, {r4 - r9, fp, sp, pc})
+
+/*
+ * Prototype: void memcpy(void *to,const void *from,unsigned long n);
+ * ARM3: cant use memcopy here!!!
+ */
+ENTRY(memcpy)
+ENTRY(memmove)
+		ENTER
+		cmp	r1, r0
+		bcc	19f
+		subs	r2, r2, #4
+		blt	6f
+		ands	ip, r0, #3
+		bne	7f
+		ands	ip, r1, #3
+		bne	8f
+
+1:		subs	r2, r2, #8
+		blt	5f
+		subs	r2, r2, #0x14
+		blt	3f
+2:		ldmia	r1!,{r3 - r9, ip}
+		stmia	r0!,{r3 - r9, ip}
+		subs	r2, r2, #32
+		bge	2b
+		cmn	r2, #16
+		ldmgeia	r1!, {r3 - r6}
+		stmgeia	r0!, {r3 - r6}
+		subge	r2, r2, #0x10
+3:		adds	r2, r2, #0x14
+4:		ldmgeia	r1!, {r3 - r5}
+		stmgeia	r0!, {r3 - r5}
+		subges	r2, r2, #12
+		bge	4b
+5:		adds	r2, r2, #8
+		blt	6f
+		subs	r2, r2, #4
+		ldrlt	r3, [r1], #4
+		ldmgeia	r1!, {r4, r5}
+		strlt	r3, [r0], #4
+		stmgeia	r0!, {r4, r5}
+		subge	r2, r2, #4
+
+6:		adds	r2, r2, #4
+		EXITEQ
+		cmp	r2, #2
+		ldrb	r3, [r1], #1
+		ldrgeb	r4, [r1], #1
+		ldrgtb	r5, [r1], #1
+		strb	r3, [r0], #1
+		strgeb	r4, [r0], #1
+		strgtb	r5, [r0], #1
+		EXIT
+
+7:		rsb	ip, ip, #4
+		cmp	ip, #2
+		ldrb	r3, [r1], #1
+		ldrgeb	r4, [r1], #1
+		ldrgtb	r5, [r1], #1
+		strb	r3, [r0], #1
+		strgeb	r4, [r0], #1
+		strgtb	r5, [r0], #1
+		subs	r2, r2, ip
+		blt	6b
+		ands	ip, r1, #3
+		beq	1b
+
+8:		bic	r1, r1, #3
+		ldr	r7, [r1], #4
+		cmp	ip, #2
+		bgt	15f
+		beq	11f
+		cmp	r2, #12
+		blt	10f
+		sub	r2, r2, #12
+9:		mov	r3, r7, lsr #8
+		ldmia	r1!, {r4 - r7}
+		orr	r3, r3, r4, lsl #24
+		mov	r4, r4, lsr #8
+		orr	r4, r4, r5, lsl #24
+		mov	r5, r5, lsr #8
+		orr	r5, r5, r6, lsl #24
+		mov	r6, r6, lsr #8
+		orr	r6, r6, r7, lsl #24
+		stmia	r0!, {r3 - r6}
+		subs	r2, r2, #16
+		bge	9b
+		adds	r2, r2, #12
+		blt	100f
+10:		mov	r3, r7, lsr #8
+		ldr	r7, [r1], #4
+		subs	r2, r2, #4
+		orr	r3, r3, r7, lsl #24
+		str	r3, [r0], #4
+		bge	10b
+100:		sub	r1, r1, #3
+		b	6b
+
+11:		cmp	r2, #12
+		blt	13f		/* */
+		sub	r2, r2, #12
+12:		mov	r3, r7, lsr #16
+		ldmia	r1!, {r4 - r7}
+		orr	r3, r3, r4, lsl #16
+		mov	r4, r4, lsr #16
+		orr	r4, r4, r5, lsl #16
+		mov	r5, r5, lsr #16
+		orr	r5, r5, r6, lsl #16
+		mov	r6, r6, lsr #16
+		orr	r6, r6, r7,LSL#16
+		stmia	r0!, {r3 - r6}
+		subs	r2, r2, #16
+		bge	12b
+		adds	r2, r2, #12
+		blt	14f
+13:		mov	r3, r7, lsr #16
+		ldr	r7, [r1], #4
+		subs	r2, r2, #4
+		orr	r3, r3, r7, lsl #16
+		str	r3, [r0], #4
+		bge	13b
+14:		sub	r1, r1, #2
+		b	6b
+
+15:		cmp	r2, #12
+		blt	17f
+		sub	r2, r2, #12
+16:		mov	r3, r7, lsr #24
+		ldmia	r1!,{r4 - r7}
+		orr	r3, r3, r4, lsl #8
+		mov	r4, r4, lsr #24
+		orr	r4, r4, r5, lsl #8
+		mov	r5, r5, lsr #24
+		orr	r5, r5, r6, lsl #8
+		mov	r6, r6, lsr #24
+		orr	r6, r6, r7, lsl #8
+		stmia	r0!, {r3 - r6}
+		subs	r2, r2, #16
+		bge	16b
+		adds	r2, r2, #12
+		blt	18f
+17:		mov	r3, r7, lsr #24
+		ldr	r7, [r1], #4
+		subs	r2, r2, #4
+		orr	r3, r3, r7, lsl#8
+		str	r3, [r0], #4
+		bge	17b
+18:		sub	r1, r1, #1
+		b	6b
+
+
+19:		add	r1, r1, r2
+		add	r0, r0, r2
+		subs	r2, r2, #4
+		blt	24f
+		ands	ip, r0, #3
+		bne	25f
+		ands	ip, r1, #3
+		bne	26f
+
+20:		subs	r2, r2, #8
+		blt	23f
+		subs	r2, r2, #0x14
+		blt	22f
+21:		ldmdb	r1!, {r3 - r9, ip}
+		stmdb	r0!, {r3 - r9, ip}
+		subs	r2, r2, #32
+		bge	21b
+22:		cmn	r2, #16
+		ldmgedb	r1!, {r3 - r6}
+		stmgedb	r0!, {r3 - r6}
+		subge	r2, r2, #16
+		adds	r2, r2, #20
+		ldmgedb	r1!, {r3 - r5}
+		stmgedb	r0!, {r3 - r5}
+		subge	r2, r2, #12
+23:		adds	r2, r2, #8
+		blt	24f
+		subs	r2, r2, #4
+		ldrlt	r3, [r1, #-4]!
+		ldmgedb	r1!, {r4, r5}
+		strlt	r3, [r0, #-4]!
+		stmgedb	r0!, {r4, r5}
+		subge	r2, r2, #4
+
+24:		adds	r2, r2, #4
+		EXITEQ
+		cmp	r2, #2
+		ldrb	r3, [r1, #-1]!
+		ldrgeb	r4, [r1, #-1]!
+		ldrgtb	r5, [r1, #-1]!
+		strb	r3, [r0, #-1]!
+		strgeb	r4, [r0, #-1]!
+		strgtb	r5, [r0, #-1]!
+		EXIT
+
+25:		cmp	ip, #2
+		ldrb	r3, [r1, #-1]!
+		ldrgeb	r4, [r1, #-1]!
+		ldrgtb	r5, [r1, #-1]!
+		strb	r3, [r0, #-1]!
+		strgeb	r4, [r0, #-1]!
+		strgtb	r5, [r0, #-1]!
+		subs	r2, r2, ip
+		blt	24b
+		ands	ip, r1, #3
+		beq	20b
+
+26:		bic	r1, r1, #3
+		ldr	r3, [r1], #0
+		cmp	ip, #2
+		blt	34f
+		beq	30f
+		cmp	r2, #12
+		blt	28f
+		sub	r2, r2, #12
+27:		mov	r7, r3, lsl #8
+		ldmdb	r1!, {r3, r4, r5, r6}
+		orr	r7, r7, r6, lsr #24
+		mov	r6, r6, lsl #8
+		orr	r6, r6, r5, lsr #24
+		mov	r5, r5, lsl #8
+		orr	r5, r5, r4, lsr #24
+		mov	r4, r4, lsl #8
+		orr	r4, r4, r3, lsr #24
+		stmdb	r0!, {r4, r5, r6, r7}
+		subs	r2, r2, #16
+		bge	27b
+		adds	r2, r2, #12
+		blt	29f
+28:		mov	ip, r3, lsl #8
+		ldr	r3, [r1, #-4]!
+		subs	r2, r2, #4
+		orr	ip, ip, r3, lsr #24
+		str	ip, [r0, #-4]!
+		bge	28b
+29:		add	r1, r1, #3
+		b	24b
+
+30:		cmp	r2, #12
+		blt	32f
+		sub	r2, r2, #12
+31:		mov	r7, r3, lsl #16
+		ldmdb	r1!, {r3, r4, r5, r6}
+		orr	r7, r7, r6, lsr #16
+		mov	r6, r6, lsl #16
+		orr	r6, r6, r5, lsr #16
+		mov	r5, r5, lsl #16
+		orr	r5, r5, r4, lsr #16
+		mov	r4, r4, lsl #16
+		orr	r4, r4, r3, lsr #16
+		stmdb	r0!, {r4, r5, r6, r7}
+		subs	r2, r2, #16
+		bge	31b
+		adds	r2, r2, #12
+		blt	33f
+32:		mov	ip, r3, lsl #16
+		ldr	r3, [r1, #-4]!
+		subs	r2, r2, #4
+		orr	ip, ip, r3, lsr #16
+		str	ip, [r0, #-4]!
+		bge	32b
+33:		add	r1, r1, #2
+		b	24b
+
+34:		cmp	r2, #12
+		blt	36f
+		sub	r2, r2, #12
+35:		mov	r7, r3, lsl #24
+		ldmdb	r1!, {r3, r4, r5, r6}
+		orr	r7, r7, r6, lsr #8
+		mov	r6, r6, lsl #24
+		orr	r6, r6, r5, lsr #8
+		mov	r5, r5, lsl #24
+		orr	r5, r5, r4, lsr #8
+		mov	r4, r4, lsl #24
+		orr	r4, r4, r3, lsr #8
+		stmdb	r0!, {r4, r5, r6, r7}
+		subs	r2, r2, #16
+		bge	35b
+		adds	r2, r2, #12
+		blt	37f
+36:		mov	ip, r3, lsl #24
+		ldr	r3, [r1, #-4]!
+		subs	r2, r2, #4
+		orr	ip, ip, r3, lsr #8
+		str	ip, [r0, #-4]!
+		bge	36b
+37:		add	r1, r1, #1
+		b	24b
+
+		.align
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/memset.S linux/arch/arm/lib/memset.S
--- v2.3.39/linux/arch/arm/lib/memset.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/memset.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,88 @@
+/*
+ * linux/arch/arm/lib/memset.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ *
+ * ASM optimised string functions
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include "constants.h"
+
+		.text
+		.align	5
+ENTRY(memset)
+		mov	r3, r0
+		cmp	r2, #16
+		blt	6f
+		ands	ip, r3, #3
+		beq	1f
+		cmp	ip, #2
+		strltb	r1, [r3], #1			@ Align destination
+		strleb	r1, [r3], #1
+		strb	r1, [r3], #1
+		rsb	ip, ip, #4
+		sub	r2, r2, ip
+1:		orr	r1, r1, r1, lsl #8
+		orr	r1, r1, r1, lsl #16
+		cmp	r2, #256
+		blt	4f
+		stmfd	sp!, {r4, r5, lr}
+		mov	r4, r1
+		mov	r5, r1
+		mov	lr, r1
+		mov	ip, r2, lsr #6
+		sub	r2, r2, ip, lsl #6
+2:		stmia	r3!, {r1, r4, r5, lr}		@ 64 bytes at a time.
+		stmia	r3!, {r1, r4, r5, lr}
+		stmia	r3!, {r1, r4, r5, lr}
+		stmia	r3!, {r1, r4, r5, lr}
+		subs	ip, ip, #1
+		bne	2b
+		teq	r2, #0
+		LOADREGS(eqfd, sp!, {r4, r5, pc})	@ Now <64 bytes to go.
+		tst	r2, #32
+		stmneia	r3!, {r1, r4, r5, lr}
+		stmneia	r3!, {r1, r4, r5, lr}
+		tst	r2, #16
+		stmneia	r3!, {r1, r4, r5, lr}
+		ldmia	sp!, {r4, r5}
+3:		tst	r2, #8
+		stmneia	r3!, {r1, lr}
+		tst	r2, #4
+		strne	r1, [r3], #4
+		tst	r2, #2
+		strneb	r1, [r3], #1
+		strneb	r1, [r3], #1
+		tst	r2, #1
+		strneb	r1, [r3], #1
+		LOADREGS(fd, sp!, {pc})
+
+4:		movs	ip, r2, lsr #3
+		beq	3b
+		sub	r2, r2, ip, lsl #3
+		str	lr, [sp, #-4]!		
+		mov	lr, r1
+		subs	ip, ip, #4
+5:		stmgeia	r3!, {r1, lr}
+		stmgeia	r3!, {r1, lr}
+		stmgeia	r3!, {r1, lr}
+		stmgeia	r3!, {r1, lr}
+		subges	ip, ip, #4
+		bge	5b
+		tst	ip, #2
+		stmneia	r3!, {r1, lr}
+		stmneia	r3!, {r1, lr}
+		tst	ip, #1
+		stmneia	r3!, {r1, lr}
+		teq	r2, #0
+		LOADREGS(eqfd, sp!, {pc})
+		b	3b
+
+6:		subs	r2, r2, #1
+		strgeb	r1, [r3], #1
+		bgt	6b
+		RETINSTR(mov, pc, lr)
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/memzero.S linux/arch/arm/lib/memzero.S
--- v2.3.39/linux/arch/arm/lib/memzero.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/memzero.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/arm/lib/memzero.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include "constants.h"
+
+		.text
+
+/*
+ * Prototype: void memzero(void *d, size_t n)
+ */
+1:		@ 4 <= r1
+		cmp	ip, #2				@	1
+		strltb	r2, [r0], #1			@	1
+		strleb	r2, [r0], #1			@	1
+		strb	r2, [r0], #1			@	1
+		rsb	ip, ip, #4			@	1
+		sub	r1, r1, ip			@	1
+		cmp	r1, #3				@	1
+		bgt	2f				@	1	@ +8
+		b	4f				@	1	@ +9
+
+		.align	5
+
+ENTRY(__memzero)
+		mov	r2, #0				@	1
+		cmp	r1, #4				@	1
+		blt	4f				@	1	@ = 3
+
+		@ r1 >= 4
+
+		ands	ip, r0, #3			@	1
+		bne	1b				@	1	@ = 5
+
+2:		@ r1 >= 4 && (r0 & 3) = 0				@ = 5 or 11
+
+		str	lr, [sp, #-4]!			@	1
+		mov	r3, #0				@	1
+		mov	ip, #0				@	1
+		mov	lr, #0				@	1
+
+		@ 4 <= r1 <= 32						@ = 9 or 15
+
+3:		subs	r1, r1, #32			@	1
+		stmgeia	r0!, {r2, r3, ip, lr}		@	4
+		stmgeia	r0!, {r2, r3, ip, lr}		@	4
+		bgt	3b				@	1
+		LOADREGS(eqfd, sp!, {pc})		@	1/2
+
+		@ -28 <= r1 <= -1
+
+		cmp	r1, #-16			@	1
+		stmgeia	r0!, {r2, r3, ip, lr}		@	4
+		ldr	lr, [sp], #4			@	1
+		addlts	r1, r1, #16			@	1
+		RETINSTR(moveq,pc,lr)			@	1
+
+		@ -12 <= r1 <= -1
+
+		cmp	r1, #-8				@	1
+		stmgeia	r0!, {r2, r3}			@	2
+		addlts	r1, r1, #8			@	1
+		RETINSTR(moveq,pc,lr)			@	1
+
+		@ -4 <= r1 <= -1
+
+		cmp	r1, #-4				@	1
+		strge	r2, [r0], #4			@	1
+		adds	r1, r1, #4			@	1
+		RETINSTR(moveq,pc,lr)			@	1
+
+4:		@ 1 <= r1 <= 3
+		cmp	r1, #2				@	1
+		strgtb	r2, [r0], #1			@	1
+		strgeb	r2, [r0], #1			@	1
+		strb	r2, [r0], #1			@	1
+		RETINSTR(mov,pc,lr)			@	1
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/setbit.S linux/arch/arm/lib/setbit.S
--- v2.3.39/linux/arch/arm/lib/setbit.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/setbit.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/lib/setbit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+                .text
+
+@ Purpose  : Function to set a bit
+@ Prototype: int set_bit(int bit,int *addr)
+
+ENTRY(set_bit)
+                and     r2, r0, #7
+                mov     r3, #1
+                mov     r3, r3, lsl r2
+		SAVEIRQS(ip)
+		DISABLEIRQS(ip)
+		ldrb	r2, [r1, r0, lsr #3]
+		orr	r2, r2, r3
+		strb	r2, [r1, r0, lsr #3]
+		RESTOREIRQS(ip)
+		RETINSTR(mov,pc,lr)
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/strchr.S linux/arch/arm/lib/strchr.S
--- v2.3.39/linux/arch/arm/lib/strchr.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/strchr.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/lib/strchr.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ *
+ * ASM optimised string functions
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include "constants.h"
+
+		.text
+ENTRY(strchr)
+		str	lr, [sp, #-4]!
+		mov	r3, #0
+1:		ldrb	r2, [r0], #1
+		teq	r2, r1
+		teqne	r2, #0
+		bne	1b
+		teq	r2, #0
+		moveq	r0, #0
+		subne	r0, r0, #1
+		LOADREGS(fd, sp!, {pc})
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/string.S linux/arch/arm/lib/string.S
--- v2.3.39/linux/arch/arm/lib/string.S	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/lib/string.S	Wed Dec 31 16:00:00 1969
@@ -1,519 +0,0 @@
-/*
- * linux/arch/arm/lib/string.S
- *
- * Copyright (C) 1995-1999 Russell King
- *
- * ASM optimised string functions
- *
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include "constants.h"
-
-		.text
-
-/*
- * Prototype: void memzero(void *d, size_t n)
- */
-1:		@ 4 <= r1
-		cmp	ip, #2				@	1
-		strltb	r2, [r0], #1			@	1
-		strleb	r2, [r0], #1			@	1
-		strb	r2, [r0], #1			@	1
-		rsb	ip, ip, #4			@	1
-		sub	r1, r1, ip			@	1
-		cmp	r1, #3				@	1
-		bgt	2f				@	1	@ +8
-		b	4f				@	1	@ +9
-
-		.align	5
-
-ENTRY(__memzero)
-		mov	r2, #0				@	1
-		cmp	r1, #4				@	1
-		blt	4f				@	1	@ = 3
-
-		@ r1 >= 4
-
-		ands	ip, r0, #3			@	1
-		bne	1b				@	1	@ = 5
-
-2:		@ r1 >= 4 && (r0 & 3) = 0				@ = 5 or 11
-
-		str	lr, [sp, #-4]!			@	1
-		mov	r3, #0				@	1
-		mov	ip, #0				@	1
-		mov	lr, #0				@	1
-
-		@ 4 <= r1 <= 32						@ = 9 or 15
-
-3:		subs	r1, r1, #32			@	1
-		stmgeia	r0!, {r2, r3, ip, lr}		@	4
-		stmgeia	r0!, {r2, r3, ip, lr}		@	4
-		bgt	3b				@	1
-		LOADREGS(eqfd, sp!, {pc})		@	1/2
-
-		@ -28 <= r1 <= -1
-
-		cmp	r1, #-16			@	1
-		stmgeia	r0!, {r2, r3, ip, lr}		@	4
-		ldr	lr, [sp], #4			@	1
-		addlts	r1, r1, #16			@	1
-		RETINSTR(moveq,pc,lr)			@	1
-
-		@ -12 <= r1 <= -1
-
-		cmp	r1, #-8				@	1
-		stmgeia	r0!, {r2, r3}			@	2
-		addlts	r1, r1, #8			@	1
-		RETINSTR(moveq,pc,lr)			@	1
-
-		@ -4 <= r1 <= -1
-
-		cmp	r1, #-4				@	1
-		strge	r2, [r0], #4			@	1
-		adds	r1, r1, #4			@	1
-		RETINSTR(moveq,pc,lr)			@	1
-
-4:		@ 1 <= r1 <= 3
-		cmp	r1, #2				@	1
-		strgtb	r2, [r0], #1			@	1
-		strgeb	r2, [r0], #1			@	1
-		strb	r2, [r0], #1			@	1
-		RETINSTR(mov,pc,lr)			@	1
-
-/*
- * StrongARM optimised copy_page routine
- * now 1.72bytes/cycle, was 1.60 bytes/cycle
- * (50MHz bus -> 86MB/s)
- */
-
-ENTRY(copy_page)
-		stmfd	sp!, {r4, lr}			@	2
-		mov	r2, #PAGE_SZ/64			@	1
-1:		ldmia	r1!, {r3, r4, ip, lr}		@	4
-		subs	r2, r2, #1			@	1
-		stmia	r0!, {r3, r4, ip, lr}		@	4
-		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
-		stmia	r0!, {r3, r4, ip, lr}		@	4
-		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
-		stmia	r0!, {r3, r4, ip, lr}		@	4
-		ldmia	r1!, {r3, r4, ip, lr}		@	4+1
-		stmia	r0!, {r3, r4, ip, lr}		@	4
-		bne	1b				@	1
-		LOADREGS(fd, sp!, {r4, pc})		@	3
-
-		.align	5
-ENTRY(memset)		/* needed for some versions of gcc */
-ENTRY(__memset)
-		mov	r3, r0
-		cmp	r2, #16
-		blt	6f
-		ands	ip, r3, #3
-		beq	1f
-		cmp	ip, #2
-		strltb	r1, [r3], #1			@ Align destination
-		strleb	r1, [r3], #1
-		strb	r1, [r3], #1
-		rsb	ip, ip, #4
-		sub	r2, r2, ip
-1:		orr	r1, r1, r1, lsl #8
-		orr	r1, r1, r1, lsl #16
-		cmp	r2, #256
-		blt	4f
-		stmfd	sp!, {r4, r5, lr}
-		mov	r4, r1
-		mov	r5, r1
-		mov	lr, r1
-		mov	ip, r2, lsr #6
-		sub	r2, r2, ip, lsl #6
-2:		stmia	r3!, {r1, r4, r5, lr}		@ 64 bytes at a time.
-		stmia	r3!, {r1, r4, r5, lr}
-		stmia	r3!, {r1, r4, r5, lr}
-		stmia	r3!, {r1, r4, r5, lr}
-		subs	ip, ip, #1
-		bne	2b
-		teq	r2, #0
-		LOADREGS(eqfd, sp!, {r4, r5, pc})	@ Now <64 bytes to go.
-		tst	r2, #32
-		stmneia	r3!, {r1, r4, r5, lr}
-		stmneia	r3!, {r1, r4, r5, lr}
-		tst	r2, #16
-		stmneia	r3!, {r1, r4, r5, lr}
-		ldmia	sp!, {r4, r5}
-3:		tst	r2, #8
-		stmneia	r3!, {r1, lr}
-		tst	r2, #4
-		strne	r1, [r3], #4
-		tst	r2, #2
-		strneb	r1, [r3], #1
-		strneb	r1, [r3], #1
-		tst	r2, #1
-		strneb	r1, [r3], #1
-		LOADREGS(fd, sp!, {pc})
-
-4:		movs	ip, r2, lsr #3
-		beq	3b
-		sub	r2, r2, ip, lsl #3
-		stmfd	sp!, {lr}
-		mov	lr, r1
-		subs	ip, ip, #4
-5:		stmgeia	r3!, {r1, lr}
-		stmgeia	r3!, {r1, lr}
-		stmgeia	r3!, {r1, lr}
-		stmgeia	r3!, {r1, lr}
-		subges	ip, ip, #4
-		bge	5b
-		tst	ip, #2
-		stmneia	r3!, {r1, lr}
-		stmneia	r3!, {r1, lr}
-		tst	ip, #1
-		stmneia	r3!, {r1, lr}
-		teq	r2, #0
-		LOADREGS(eqfd, sp!, {pc})
-		b	3b
-
-6:		subs	r2, r2, #1
-		strgeb	r1, [r3], #1
-		bgt	6b
-		RETINSTR(mov, pc, lr)
-
-ENTRY(strrchr)
-		stmfd	sp!, {lr}
-		mov	r3, #0
-1:		ldrb	r2, [r0], #1
-		teq	r2, r1
-		moveq	r3, r0
-		teq	r2, #0
-		bne	1b
-		mov	r0, r3
-		LOADREGS(fd, sp!, {pc})
-
-ENTRY(strchr)
-		stmfd	sp!,{lr}
-		mov	r3, #0
-1:		ldrb	r2, [r0], #1
-		teq	r2, r1
-		teqne	r2, #0
-		bne	1b
-		teq	r2, #0
-		moveq	r0, #0
-		subne	r0, r0, #1
-		LOADREGS(fd, sp!, {pc})
-
-ENTRY(memchr)
-		stmfd	sp!, {lr}
-1:		ldrb	r3, [r0], #1
-		teq	r3, r1
-		beq	2f
-		subs	r2, r2, #1
-		bpl	1b
-2:		movne	r0, #0
-		subeq	r0, r0, #1
-		LOADREGS(fd, sp!, {pc})
-
-
-#define ENTER	\
-		mov	ip,sp	;\
-		stmfd	sp!,{r4-r9,fp,ip,lr,pc}	;\
-		sub	fp,ip,#4
-
-#define EXIT	\
-		LOADREGS(ea, fp, {r4 - r9, fp, sp, pc})
-
-#define EXITEQ	\
-		LOADREGS(eqea, fp, {r4 - r9, fp, sp, pc})
-
-/*
- * Prototype: void memcpy(void *to,const void *from,unsigned long n);
- * ARM3: cant use memcopy here!!!
- */
-ENTRY(memcpy)
-ENTRY(memmove)
-		ENTER
-		cmp	r1, r0
-		bcc	19f
-		subs	r2, r2, #4
-		blt	6f
-		ands	ip, r0, #3
-		bne	7f
-		ands	ip, r1, #3
-		bne	8f
-
-1:		subs	r2, r2, #8
-		blt	5f
-		subs	r2, r2, #0x14
-		blt	3f
-2:		ldmia	r1!,{r3 - r9, ip}
-		stmia	r0!,{r3 - r9, ip}
-		subs	r2, r2, #32
-		bge	2b
-		cmn	r2, #16
-		ldmgeia	r1!, {r3 - r6}
-		stmgeia	r0!, {r3 - r6}
-		subge	r2, r2, #0x10
-3:		adds	r2, r2, #0x14
-4:		ldmgeia	r1!, {r3 - r5}
-		stmgeia	r0!, {r3 - r5}
-		subges	r2, r2, #12
-		bge	4b
-5:		adds	r2, r2, #8
-		blt	6f
-		subs	r2, r2, #4
-		ldrlt	r3, [r1], #4
-		strlt	r3, [r0], #4
-		ldmgeia	r1!, {r3, r4}
-		stmgeia	r0!, {r3, r4}
-		subge	r2, r2, #4
-
-6:		adds	r2, r2, #4
-		EXITEQ
-		cmp	r2, #2
-		ldrb	r3, [r1], #1
-		strb	r3, [r0], #1
-		ldrgeb	r3, [r1], #1
-		strgeb	r3, [r0], #1
-		ldrgtb	r3, [r1], #1
-		strgtb	r3, [r0], #1
-		EXIT
-
-7:		rsb	ip, ip, #4
-		cmp	ip, #2
-		ldrb	r3, [r1], #1
-		strb	r3, [r0], #1
-		ldrgeb	r3, [r1], #1
-		strgeb	r3, [r0], #1
-		ldrgtb	r3, [r1], #1
-		strgtb	r3, [r0], #1
-		subs	r2, r2, ip
-		blt	6b
-		ands	ip, r1, #3
-		beq	1b
-
-8:		bic	r1, r1, #3
-		ldr	r7, [r1], #4
-		cmp	ip, #2
-		bgt	15f
-		beq	11f
-		cmp	r2, #12
-		blt	10f
-		sub	r2, r2, #12
-9:		mov	r3, r7, lsr #8
-		ldmia	r1!, {r4 - r7}
-		orr	r3, r3, r4, lsl #24
-		mov	r4, r4, lsr #8
-		orr	r4, r4, r5, lsl #24
-		mov	r5, r5, lsr #8
-		orr	r5, r5, r6, lsl #24
-		mov	r6, r6, lsr #8
-		orr	r6, r6, r7, lsl #24
-		stmia	r0!, {r3 - r6}
-		subs	r2, r2, #16
-		bge	9b
-		adds	r2, r2, #12
-		blt	100f
-10:		mov	r3, r7, lsr #8
-		ldr	r7, [r1], #4
-		orr	r3, r3, r7, lsl #24
-		str	r3, [r0], #4
-		subs	r2, r2, #4
-		bge	10b
-100:		sub	r1, r1, #3
-		b	6b
-
-11:		cmp	r2, #12
-		blt	13f		/* */
-		sub	r2, r2, #12
-12:		mov	r3, r7, lsr #16
-		ldmia	r1!, {r4 - r7}
-		orr	r3, r3, r4, lsl #16
-		mov	r4, r4, lsr #16
-		orr	r4, r4, r5, lsl #16
-		mov	r5, r5, lsr #16
-		orr	r5, r5, r6, lsl #16
-		mov	r6, r6, lsr #16
-		orr	r6, r6, r7,LSL#16
-		stmia	r0!, {r3 - r6}
-		subs	r2, r2, #16
-		bge	12b
-		adds	r2, r2, #12
-		blt	14f
-13:		mov	r3, r7, lsr #16
-		ldr	r7, [r1], #4
-		orr	r3, r3, r7, lsl #16
-		str	r3, [r0], #4
-		subs	r2, r2, #4
-		bge	13b
-14:		sub	r1, r1, #2
-		b	6b
-
-15:		cmp	r2, #12
-		blt	17f
-		sub	r2, r2, #12
-16:		mov	r3, r7, lsr #24
-		ldmia	r1!,{r4 - r7}
-		orr	r3, r3, r4, lsl #8
-		mov	r4, r4, lsr #24
-		orr	r4, r4, r5, lsl #8
-		mov	r5, r5, lsr #24
-		orr	r5, r5, r6, lsl #8
-		mov	r6, r6, lsr #24
-		orr	r6, r6, r7, lsl #8
-		stmia	r0!, {r3 - r6}
-		subs	r2, r2, #16
-		bge	16b
-		adds	r2, r2, #12
-		blt	18f
-17:		mov	r3, r7, lsr #24
-		ldr	r7, [r1], #4
-		orr	r3, r3, r7, lsl#8
-		str	r3, [r0], #4
-		subs	r2, r2, #4
-		bge	17b
-18:		sub	r1, r1, #1
-		b	6b
-
-
-19:		add	r1, r1, r2
-		add	r0, r0, r2
-		subs	r2, r2, #4
-		blt	24f
-		ands	ip, r0, #3
-		bne	25f
-		ands	ip, r1, #3
-		bne	26f
-
-20:		subs	r2, r2, #8
-		blt	23f
-		subs	r2, r2, #0x14
-		blt	22f
-21:		ldmdb	r1!, {r3 - r9, ip}
-		stmdb	r0!, {r3 - r9, ip}
-		subs	r2, r2, #32
-		bge	21b
-22:		cmn	r2, #16
-		ldmgedb	r1!, {r3 - r6}
-		stmgedb	r0!, {r3 - r6}
-		subge	r2, r2, #16
-		adds	r2, r2, #20
-		ldmgedb	r1!, {r3 - r5}
-		stmgedb	r0!, {r3 - r5}
-		subge	r2, r2, #12
-23:		adds	r2, r2, #8
-		blt	24f
-		subs	r2, r2, #4
-		ldrlt	r3, [r1, #-4]!
-		strlt	r3, [r0, #-4]!
-		ldmgedb	r1!, {r3, r4}
-		stmgedb	r0!, {r3, r4}
-		subge	r2, r2, #4
-
-24:		adds	r2, r2, #4
-		EXITEQ
-		cmp	r2, #2
-		ldrb	r3, [r1, #-1]!
-		strb	r3, [r0, #-1]!
-		ldrgeb	r3, [r1, #-1]!
-		strgeb	r3, [r0, #-1]!
-		ldrgtb	r3, [r1, #-1]!
-		strgtb	r3, [r0, #-1]!
-		EXIT
-
-25:		cmp	ip, #2
-		ldrb	r3, [r1, #-1]!
-		strb	r3, [r0, #-1]!
-		ldrgeb	r3, [r1, #-1]!
-		strgeb	r3, [r0, #-1]!
-		ldrgtb	r3, [r1, #-1]!
-		strgtb	r3, [r0, #-1]!
-		subs	r2, r2, ip
-		blt	24b
-		ands	ip, r1, #3
-		beq	20b
-
-26:		bic	r1, r1, #3
-		ldr	r3, [r1], #0
-		cmp	ip, #2
-		blt	34f
-		beq	30f
-		cmp	r2, #12
-		blt	28f
-		sub	r2, r2, #12
-27:		mov	r7, r3, lsl #8
-		ldmdb	r1!, {r3, r4, r5, r6}
-		orr	r7, r7, r6, lsr #24
-		mov	r6, r6, lsl #8
-		orr	r6, r6, r5, lsr #24
-		mov	r5, r5, lsl #8
-		orr	r5, r5, r4, lsr #24
-		mov	r4, r4, lsl #8
-		orr	r4, r4, r3, lsr #24
-		stmdb	r0!, {r4, r5, r6, r7}
-		subs	r2, r2, #16
-		bge	27b
-		adds	r2, r2, #12
-		blt	29f
-28:		mov	ip, r3, lsl #8
-		ldr	r3, [r1, #-4]!
-		orr	ip, ip, r3, lsr #24
-		str	ip, [r0, #-4]!
-		subs	r2, r2, #4
-		bge	28b
-29:		add	r1, r1, #3
-		b	24b
-
-30:		cmp	r2, #12
-		blt	32f
-		sub	r2, r2, #12
-31:		mov	r7, r3, lsl #16
-		ldmdb	r1!, {r3, r4, r5, r6}
-		orr	r7, r7, r6, lsr #16
-		mov	r6, r6, lsl #16
-		orr	r6, r6, r5, lsr #16
-		mov	r5, r5, lsl #16
-		orr	r5, r5, r4, lsr #16
-		mov	r4, r4, lsl #16
-		orr	r4, r4, r3, lsr #16
-		stmdb	r0!, {r4, r5, r6, r7}
-		subs	r2, r2, #16
-		bge	31b
-		adds	r2, r2, #12
-		blt	33f
-32:		mov	ip, r3, lsl #16
-		ldr	r3, [r1, #-4]!
-		orr	ip, ip, r3, lsr #16
-		str	ip, [r0, #-4]!
-		subs	r2, r2, #4
-		bge	32b
-33:		add	r1, r1, #2
-		b	24b
-
-34:		cmp	r2, #12
-		blt	36f
-		sub	r2, r2, #12
-35:		mov	r7, r3, lsl #24
-		ldmdb	r1!, {r3, r4, r5, r6}
-		orr	r7, r7, r6, lsr #8
-		mov	r6, r6, lsl #24
-		orr	r6, r6, r5, lsr #8
-		mov	r5, r5, lsl #24
-		orr	r5, r5, r4, lsr #8
-		mov	r4, r4, lsl #24
-		orr	r4, r4, r3, lsr #8
-		stmdb	r0!, {r4, r5, r6, r7}
-		subs	r2, r2, #16
-		bge	35b
-		adds	r2, r2, #12
-		blt	37f
-36:		mov	ip, r3, lsl #24
-		ldr	r3, [r1, #-4]!
-		orr	ip, ip, r3, lsr #8
-		str	ip, [r0, #-4]!
-		subs	r2, r2, #4
-		bge	36b
-37:		add	r1, r1, #1
-		b	24b
-
-		.align
-
-
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/strrchr.S linux/arch/arm/lib/strrchr.S
--- v2.3.39/linux/arch/arm/lib/strrchr.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/strrchr.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,25 @@
+/*
+ * linux/arch/arm/lib/strrchr.S
+ *
+ * Copyright (C) 1995-1999 Russell King
+ *
+ * ASM optimised string functions
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include "constants.h"
+
+		.text
+ENTRY(strrchr)
+		stmfd	sp!, {lr}
+		mov	r3, #0
+1:		ldrb	r2, [r0], #1
+		teq	r2, r1
+		moveq	r3, r0
+		teq	r2, #0
+		bne	1b
+		mov	r0, r3
+		LOADREGS(fd, sp!, {pc})
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/system.c linux/arch/arm/lib/system.c
--- v2.3.39/linux/arch/arm/lib/system.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/lib/system.c	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-/*
- * linux/arch/arm/lib/system.c
- *
- * Copyright (C) 1999 Russell King
- *
- * Converted from ASM version 04/09/1999
- */
-#include <linux/kernel.h>
-
-extern void abort(void)
-{
-	void *lr = __builtin_return_address(0);
-
-	printk(KERN_CRIT "kernel abort from %p!  (Please report to rmk@arm.linux.org.uk)\n",
-		lr);
-
-	/* force an oops */
-	*(int *)0 = 0;
-
-	/* if that doesn't kill us, halt */
-	panic("Oops failed to kill thread");
-}
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/testchangebit.S linux/arch/arm/lib/testchangebit.S
--- v2.3.39/linux/arch/arm/lib/testchangebit.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/testchangebit.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,25 @@
+/*
+ * linux/arch/arm/lib/testchangebit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+                .text
+
+ENTRY(test_and_change_bit)
+		add	r1, r1, r0, lsr #3
+		and	r3, r0, #7
+		mov	r0, #1
+		SAVEIRQS(ip)
+		DISABLEIRQS(ip)
+		ldrb	r2, [r1]
+		tst	r2, r0, lsl r3
+		eor	r2, r2, r0, lsl r3
+		moveq	r0, #0
+		strb	r2, [r1]
+		RESTOREIRQS(ip)
+		RETINSTR(mov,pc,lr)
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/testclearbit.S linux/arch/arm/lib/testclearbit.S
--- v2.3.39/linux/arch/arm/lib/testclearbit.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/testclearbit.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,25 @@
+/*
+ * linux/arch/arm/lib/testclearbit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+                .text
+
+ENTRY(test_and_clear_bit)
+		add	r1, r1, r0, lsr #3	@ Get byte offset
+		and	r3, r0, #7	@ Get bit offset
+		mov	r0, #1
+		SAVEIRQS(ip)
+		DISABLEIRQS(ip)
+		ldrb	r2, [r1]
+		tst	r2, r0, lsl r3
+		bic	r2, r2, r0, lsl r3
+		moveq	r0, #0
+		strb	r2, [r1]
+		RESTOREIRQS(ip)
+		RETINSTR(mov,pc,lr)
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/testsetbit.S linux/arch/arm/lib/testsetbit.S
--- v2.3.39/linux/arch/arm/lib/testsetbit.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/testsetbit.S	Thu Jan 13 13:30:31 2000
@@ -0,0 +1,25 @@
+/*
+ * linux/arch/arm/lib/testsetbit.S
+ *
+ * Copyright (C) 1995-1996 Russell King
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+                .text
+
+ENTRY(test_and_set_bit)
+		add	r1, r1, r0, lsr #3	@ Get byte offset
+		and	r3, r0, #7		@ Get bit offset
+		mov	r0, #1
+		SAVEIRQS(ip)
+		DISABLEIRQS(ip)
+		ldrb	r2, [r1]
+		tst	r2, r0, lsl r3
+		orr	r2, r2, r0, lsl r3
+		moveq	r0, #0
+		strb	r2, [r1]
+		RESTOREIRQS(ip)
+		RETINSTR(mov,pc,lr)
+
+
diff -u --recursive --new-file v2.3.39/linux/arch/arm/lib/uaccess.S linux/arch/arm/lib/uaccess.S
--- v2.3.39/linux/arch/arm/lib/uaccess.S	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/lib/uaccess.S	Thu Jan 13 13:30:31 2000
@@ -12,21 +12,13 @@
 #include <asm/errno.h>
 
 		.text
-#ifdef ENTRY
+
 #define USER(x...)					\
 9999:		x;					\
 		.section __ex_table,"a";		\
 		.align	3;				\
 		.long	9999b,9001f;			\
 		.previous
-#else
-#define USER(x...)					\
-		x
-#define ENTRY(x...)					\
-		.globl	_##x;				\
-_##x:
-#define TESTING
-#endif
 
 #define PAGE_SHIFT 12
 
@@ -285,12 +277,10 @@
 USER(		strgtbt	r3, [r0], #1)			@ May fault
 		b	.c2u_finished
 
-#ifndef TESTING
 		.section .fixup,"ax"
 		.align	0
 9001:		LOADREGS(fd,sp!, {r0, r4 - r7, pc})
 		.previous
-#endif
 
 /* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
  * Purpose  : copy a block from user memory to kernel memory
@@ -546,7 +536,6 @@
 		strgtb	r3, [r0], #1
 		b	.cfu_finished
 
-#ifndef TESTING
 		.section .fixup,"ax"
 		.align	0
 		/* We took an exception.  Zero out the buffer and pretend no
@@ -557,7 +546,6 @@
 		blne	SYMBOL_NAME(__memzero)
 		LOADREGS(fd,sp!, {r0, r4 - r7, pc})
 		.previous
-#endif
 
 /* Prototype: int __arch_clear_user(void *addr, size_t sz)
  * Purpose  : clear some user memory
@@ -592,7 +580,6 @@
 		mov	r0, #0
 		LOADREGS(fd,sp!, {r1, pc})
 
-#ifndef TESTING
 		.section .fixup,"ax"
 		.align	0
 9001:		LOADREGS(fd,sp!, {r0, pc})
@@ -656,5 +643,4 @@
 		.previous
 
 		.align
-#endif
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.3.39/linux/arch/arm/mm/fault-armv.c	Mon Nov  1 13:56:26 1999
+++ linux/arch/arm/mm/fault-armv.c	Thu Jan 13 13:30:31 2000
@@ -29,6 +29,8 @@
 #define DO_COW(m)		(!((m) & FAULT_CODE_READ))
 #define READ_FAULT(m)		((m) & FAULT_CODE_READ)
 
+extern void die_if_kernel(const char *str, struct pt_regs *regs, int err);
+
 #include "fault-common.c"
 
 #ifdef DEBUG
@@ -118,17 +120,18 @@
  * This needs to be done after sysctl_init, otherwise sys/
  * will be overwritten.
  */
-void __init alignment_init(void)
+static int __init alignment_init(void)
 {
 	create_proc_read_entry("sys/debug/alignment", 0, NULL,
-				proc_alignment_read);
+				proc_alignment_read, NULL);
+	return 0;
 }
 
 __initcall(alignment_init);
 #endif /* CONFIG_SYSCTL */
 
 static int
-do_alignment_exception(struct pt_regs *regs)
+do_alignment(unsigned long addr, int error_code, struct pt_regs *regs)
 {
 	unsigned int instr, rd, rn, correction, nr_regs, regbits;
 	unsigned long eaddr;
@@ -308,116 +311,99 @@
 	return 0;
 }
 
+#else
+
+#define do_alignment NULL
+
 #endif
 
-#define BUG_PROC_MSG \
-  "Buggy processor (%08X), trying to continue.\n" \
-  "Please read http://www.arm.linux.org.uk/state.html for more information"
+#ifdef CONFIG_DEBUG_USER
 
-asmlinkage void
-do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
+static int
+do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
 {
 	if (user_mode(regs)) {
-		if (addr == regs->ARM_pc) {
-			static int first = 1;
-			if (first) {
-				/*
-				 * I want statistical information on this problem!
-				 */
-				printk(KERN_ERR BUG_PROC_MSG, fsr);
-				first = 0;
+		printk("%s: permission fault on section, "
+		       "address=0x%08lx, code %d\n",
+		       current->comm, addr, error_code);
+#ifdef DEBUG
+		{
+			unsigned int i, j;
+			unsigned long *sp;
+
+			sp = (unsigned long *) (regs->ARM_sp - 128);
+			for (j = 0; j < 20 && sp_valid(sp); j++) {
+				printk("%p: ", sp);
+				for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++)
+					printk("%08lx ", *sp);
+				printk("\n");
 			}
-			return;
+			show_regs(regs);
+			c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
 		}
+#endif
 	}
+	return 1;	/* not fixed up */
+}
+#else
 
-#define DIE(signr,nam)\
-		force_sig(signr, current);\
-		die(nam, regs, fsr);\
-		do_exit(signr);\
-		break
-
-	switch (fsr & 15) {
-	/*
-	 *  0 - vector exception
-	 */
-	case 0:
-		force_sig(SIGSEGV, current);
-		if (!user_mode(regs)) {
-			die("vector exception", regs, fsr);
-			do_exit(SIGSEGV);
-		}
-		break;
+#define do_sect_fault NULL
 
-	/*
-	 * 15 - permission fault on page
-	 *  5 - page-table entry descriptor fault
-	 *  7 - first-level descriptor fault
-	 */
-	case 15: case 5: case 7:
-		do_page_fault(addr, error_code, regs);
-		break;
-
-	/*
-	 * 13 - permission fault on section
-	 */
-	case 13:
-		force_sig(SIGSEGV, current);
-		if (!user_mode(regs)) {
-			die("section permission fault", regs, fsr);
-			do_exit(SIGSEGV);
-		} else {
-#ifdef CONFIG_DEBUG_USER
-			printk("%s: permission fault on section, "
-			       "address=0x%08lx, code %d\n",
-			       current->comm, addr, error_code);
-#ifdef DEBUG
-			{
-				unsigned int i, j;
-				unsigned long *sp;
-
-				sp = (unsigned long *) (regs->ARM_sp - 128);
-				for (j = 0; j < 20 && sp_valid(sp); j++) {
-					printk("%p: ", sp);
-					for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++)
-						printk("%08lx ", *sp);
-					printk("\n");
-				}
-				show_regs(regs);
-				c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
-			}
-#endif
 #endif
+
+static struct fsr_info {
+	int	(*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
+	int	sig;
+	char	*name;
+} fsr_info[] = {
+	{ NULL,			SIGSEGV, "vector exception"		   },
+	{ do_alignment,		SIGBUS,	 "alignment exception"		   },
+	{ NULL,			SIGKILL, "terminal exception"		   },
+	{ do_alignment,		SIGBUS,	 "alignment exception"		   },
+	{ NULL,			SIGBUS,	 "external abort on linefetch"	   },
+	{ do_page_fault,	SIGSEGV, "page fault"			   },
+	{ NULL,			SIGBUS,	 "external abort on linefetch"	   },
+	{ do_page_fault,	SIGSEGV, "page fault"			   },
+	{ NULL,			SIGBUS,	 "external abort on non-linefetch" },
+	{ NULL,			SIGSEGV, "domain fault"			   },
+	{ NULL,			SIGBUS,	 "external abort on non-linefetch" },
+	{ NULL,			SIGSEGV, "domain fault"			   },
+	{ NULL,			SIGBUS,	 "external abort on translation"   },
+	{ do_sect_fault,	SIGSEGV, "section permission fault"	   },
+	{ NULL,			SIGBUS,	 "external abort on translation"   },
+	{ do_page_fault,	SIGSEGV, "page permission fault"	   }
+};
+
+/*
+ * Currently dropped down to debug level
+ */
+#define BUG_PROC_MSG \
+  KERN_DEBUG "Weird data abort (%08X).\n" \
+  KERN_DEBUG "Please see http://www.arm.linux.org.uk/state.html for more information"
+
+asmlinkage void
+do_DataAbort(unsigned long addr, int fsr, int error_code, struct pt_regs *regs)
+{
+	struct fsr_info *inf;
+
+	if (user_mode(regs) && addr == regs->ARM_pc) {
+		static int first = 1;
+		if (first) {
+			/*
+			 * I want statistical information on this problem,
+			 * but we don't want to hastle the users too much.
+			 */
+			printk(BUG_PROC_MSG, fsr);
+			first = 0;
 		}
-		break;
+		return;
+	}
 
-	case 1:
-	case 3:
-#ifdef CONFIG_ALIGNMENT_TRAP
-		if (!do_alignment_exception(regs))
-			break;
-#endif
-		/*
-		 * this should never happen
-		 */
-		DIE(SIGBUS, "Alignment exception");
-		break;
+	inf = fsr_info + (fsr & 15);
 
-	case 2:
-		DIE(SIGKILL, "Terminal exception");
-	case 12:
-	case 14:
-		DIE(SIGBUS, "External abort on translation");
-	case 9:
-	case 11:
-		DIE(SIGSEGV, "Domain fault");
-
-	case 4:
-	case 6:
-		DIE(SIGBUS, "External abort on linefetch");
-	case 8:
-	case 10:
-		DIE(SIGBUS, "External abort on non-linefetch");
+	if (!inf->fn || inf->fn(addr, error_code, regs)) {
+		force_sig(inf->sig, current);
+		die_if_kernel(inf->name, regs, fsr);
 	}
 }
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/fault-common.c linux/arch/arm/mm/fault-common.c
--- v2.3.39/linux/arch/arm/mm/fault-common.c	Mon Nov  1 13:56:26 1999
+++ linux/arch/arm/mm/fault-common.c	Thu Jan 13 13:30:31 2000
@@ -6,7 +6,7 @@
  */
 #include <linux/config.h>
 
-extern void die(char *msg, struct pt_regs *regs, unsigned int err);
+extern void die(const char *msg, struct pt_regs *regs, unsigned int err);
 
 /*
  * This is useful to dump out the page tables associated with
@@ -79,7 +79,7 @@
 	do_exit(SIGKILL);
 }
 
-static void do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
+static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
 {
 	struct task_struct *tsk;
 	struct mm_struct *mm;
@@ -127,7 +127,7 @@
 		goto do_sigbus;
 
 	up(&mm->mmap_sem);
-	return;
+	return 0;
 
 	/*
 	 * Something tried to access memory that isn't in our memory map..
@@ -138,6 +138,7 @@
 
 	/* User mode accesses just cause a SIGSEGV */
 	if (user_mode(regs)) {
+		tsk->thread.address = addr;
 		tsk->thread.error_code = mode;
 		tsk->thread.trap_no = 14;
 #ifdef CONFIG_DEBUG_USER
@@ -145,7 +146,7 @@
 			tsk->comm, regs->ARM_pc, regs->ARM_lr, addr, mode);
 #endif
 		force_sig(SIGSEGV, tsk);
-		return;
+		return 0;
 	}
 
 no_context:
@@ -156,11 +157,11 @@
 			tsk->comm, regs->ARM_pc, addr, fixup);
 #endif
 		regs->ARM_pc = fixup;
-		return;
+		return 0;
 	}
 
 	kernel_page_fault(addr, mode, regs, tsk, mm);
-	return;
+	return 0;
 
 do_sigbus:
 	/*
@@ -173,6 +174,7 @@
 	 * Send a sigbus, regardless of whether we were in kernel
 	 * or user mode.
 	 */
+	tsk->thread.address = addr;
 	tsk->thread.error_code = mode;
 	tsk->thread.trap_no = 14;
 	force_sig(SIGBUS, tsk);
@@ -180,6 +182,7 @@
 	/* Kernel mode? Handle exceptions or die */
 	if (!user_mode(regs))
 		goto no_context;
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- v2.3.39/linux/arch/arm/mm/init.c	Tue Dec 14 01:27:23 1999
+++ linux/arch/arm/mm/init.c	Thu Jan 13 13:30:31 2000
@@ -168,7 +168,8 @@
 void __init paging_init(void)
 {
 	void *zero_page, *bad_page, *bad_table;
-	unsigned int zone_size[3];
+	unsigned int zone_size[MAX_NR_ZONES];
+	int i;
 
 #ifdef CONFIG_CPU_32
 #define TABLE_OFFSET	(PTRS_PER_PTE)
@@ -193,7 +194,24 @@
 	/*
 	 * Initialise the zones and mem_map
 	 */
-	zonesize_init(zone_size);
+	for (i = 0; i < MAX_NR_ZONES; i++)
+		zone_size[i] = 0;
+
+	/*
+	 * Calculate the size of the zones.  On ARM, we don't have
+	 * any problems with DMA or highmem, so all memory is
+	 * allocated to the DMA zone.
+	 */
+	for (i = 0; i < meminfo.nr_banks; i++) {
+		if (meminfo.bank[i].size) {
+			unsigned int end;
+
+			end = (meminfo.bank[i].start - PHYS_OFFSET +
+			       meminfo.bank[i].size) >> PAGE_SHIFT;
+			if (zone_size[0] < end)
+				zone_size[0] = end;
+		}
+	}
 	free_area_init(zone_size);
 
 	/*
@@ -339,10 +357,11 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(mem_map + MAP_NR(start));
-		set_page_count(mem_map+MAP_NR(start), 1);
-		free_page(start);
+	unsigned long addr;
+	for (addr = start; addr < end; addr += PAGE_SIZE) {
+		ClearPageReserved(mem_map + MAP_NR(addr));
+		set_page_count(mem_map+MAP_NR(addr), 1);
+		free_page(addr);
 		totalram_pages++;
 	}
 	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/mm-armo.c linux/arch/arm/mm/mm-armo.c
--- v2.3.39/linux/arch/arm/mm/mm-armo.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/arm/mm/mm-armo.c	Thu Jan 13 13:30:31 2000
@@ -135,20 +135,6 @@
 }
 
 /*
- * Calculate the size of the DMA, normal and highmem zones.
- * On 26-bit ARMs, we don't have any real DMA or highmem,
- * so we allocate the whole memory as being DMA-capable.
- */
-void __init zonesize_init(unsigned int *zone_size)
-{
-	int i;
-
-	zone_size[0] = max_low_pfn;
-	zone_size[1] = 0;
-	zone_size[2] = 0;
-}
-
-/*
  * This contains the code to setup the memory map on an ARM2/ARM250/ARM3
  * machine. This is both processor & architecture specific, and requires
  * some more work to get it to fit into our separate processor and
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- v2.3.39/linux/arch/arm/mm/mm-armv.c	Tue Dec 14 01:27:23 1999
+++ linux/arch/arm/mm/mm-armv.c	Thu Jan 13 13:30:31 2000
@@ -46,6 +46,15 @@
 	return 1;
 }
 
+static int __init noalign_setup(char *__unused)
+{
+	cr_alignment &= ~2;
+	cr_no_alignment &= ~2;
+	set_cr(cr_alignment);
+	return 1;
+}
+
+__setup("noalign", noalign_setup);
 __setup("nocache", nocache_setup);
 __setup("nowb", nowrite_setup);
 
@@ -218,7 +227,7 @@
  * the clearance is done by the middle-level functions (pmd)
  * rather than the top-level (pgd) functions.
  */
-static inline void free_init_section(unsigned long virt)
+static inline void clear_mapping(unsigned long virt)
 {
 	pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
 }
@@ -273,73 +282,76 @@
 	}
 }
 
-/*
- * Initial boot-time mapping.  This covers just the zero page, kernel and
- * the flush area.  NB: it must be sorted by virtual address, and no
- * virtual address overlaps.
- *  init_map[2..4] are for architectures with banked memory.
- */
-static struct map_desc init_map[] __initdata = {
-	{ 0, 0, PAGE_SIZE,  DOMAIN_USER,   0, 0, 1, 0 }, /* zero page     */
-	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 }, /* kernel memory */
-	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 }, /* (4 banks)	  */
-	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 },
-	{ 0, 0, 0,          DOMAIN_KERNEL, 0, 1, 1, 1 },
-	{ 0, 0, PGDIR_SIZE, DOMAIN_KERNEL, 1, 0, 1, 1 }, /* cache flush 1 */
-	{ 0, 0, 0,          DOMAIN_KERNEL, 1, 0, 1, 0 }  /* cache flush 2 */
-};
-
-#define NR_INIT_MAPS (sizeof(init_map) / sizeof(init_map[0]))
-
-/*
- * Calculate the size of the DMA, normal and highmem zones.
- * On ARM, we don't have any problems with DMA, so all memory
- * is allocated to the DMA zone.  We also don't have any
- * highmem either.
- */
-void __init zonesize_init(unsigned int *zone_size)
+void __init pagetable_init(void)
 {
+	struct map_desc *init_maps, *p;
+	unsigned long address = 0;
 	int i;
 
-	zone_size[0] = 0;
-	zone_size[1] = 0;
-	zone_size[2] = 0;
+	/*
+	 * Setup initial mappings.  We use the page we allocated
+	 * for zero page to hold the mappings, which will get
+	 * overwritten by the vectors in traps_init().  The
+	 * mappings must be in virtual address order.
+	 */
+	init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE);
+
+	p->physical   = virt_to_phys(init_maps);
+	p->virtual    = 0;
+	p->length     = PAGE_SIZE;
+	p->domain     = DOMAIN_USER;
+	p->prot_read  = 0;
+	p->prot_write = 0;
+	p->cacheable  = 1;
+	p->bufferable = 0;
+
+	p ++;
 
 	for (i = 0; i < meminfo.nr_banks; i++) {
-		if (meminfo.bank[i].size) {
-			unsigned int end;
+		if (meminfo.bank[i].size == 0)
+			continue;
 
-			end = (meminfo.bank[i].start - PHYS_OFFSET +
-				meminfo.bank[i].size) >> PAGE_SHIFT;
-			if (end > zone_size[0])
-				zone_size[0] = end;
-		}
-	}
-}
+		p->physical   = meminfo.bank[i].start;
+		p->virtual    = __phys_to_virt(p->physical);
+		p->length     = meminfo.bank[i].size;
+		p->domain     = DOMAIN_KERNEL;
+		p->prot_read  = 0;
+		p->prot_write = 1;
+		p->cacheable  = 1;
+		p->bufferable = 1;
+
+		p ++;
+	}
+
+	p->physical   = FLUSH_BASE_PHYS;
+	p->virtual    = FLUSH_BASE;
+	p->length     = PGDIR_SIZE;
+	p->domain     = DOMAIN_KERNEL;
+	p->prot_read  = 1;
+	p->prot_write = 0;
+	p->cacheable  = 1;
+	p->bufferable = 1;
 
-void __init pagetable_init(void)
-{
-	unsigned long address = 0;
-	int i;
+	p ++;
 
-	/*
-	 * Setup the above mappings
-	 */
-	init_map[0].physical = virt_to_phys(alloc_bootmem_low_pages(PAGE_SIZE));
-	init_map[5].physical = FLUSH_BASE_PHYS;
-	init_map[5].virtual  = FLUSH_BASE;
 #ifdef FLUSH_BASE_MINICACHE
-	init_map[6].physical = FLUSH_BASE_PHYS + PGDIR_SIZE;
-	init_map[6].virtual  = FLUSH_BASE_MINICACHE;
-	init_map[6].length   = PGDIR_SIZE;
+	p->physical   = FLUSH_BASE_PHYS + PGDIR_SIZE;
+	p->virtual    = FLUSH_BASE_MINICACHE;
+	p->length     = PGDIR_SIZE;
+	p->domain     = DOMAIN_KERNEL;
+	p->prot_read  = 1;
+	p->prot_write = 0;
+	p->cacheable  = 1;
+	p->bufferable = 0;
+
+	p ++;
 #endif
 
-	for (i = 0; i < meminfo.nr_banks; i++) {
-		init_map[i+1].physical = meminfo.bank[i].start;
-		init_map[i+1].virtual  = meminfo.bank[i].start +
-					 PAGE_OFFSET - PHYS_OFFSET;
-		init_map[i+1].length   = meminfo.bank[i].size;
-	}
+	/*
+	 * We may have a mapping in virtual address 0.
+	 * Clear it out.
+	 */
+	clear_mapping(0);
 
 	/*
 	 * Go through the initial mappings, but clear out any
@@ -347,18 +359,16 @@
 	 */
 	i = 0;
 	do {
-		if (address < init_map[i].virtual || i == NR_INIT_MAPS) {
-			free_init_section(address);
+		if (address < init_maps->virtual || init_maps == p) {
+			clear_mapping(address);
 			address += PGDIR_SIZE;
 		} else {
-			create_mapping(init_map + i);
+			create_mapping(init_maps);
 
-			address = init_map[i].virtual + init_map[i].length;
+			address = init_maps->virtual + init_maps->length;
 			address = (address + PGDIR_SIZE - 1) & PGDIR_MASK;
 
-			do {
-				i += 1;
-			} while (init_map[i].length == 0 && i < NR_INIT_MAPS);
+			init_maps ++;
 		}
 	} while (address != 0);
 
@@ -382,6 +392,7 @@
 	unsigned int i;
 
 #define PFN(x)	(((x) - PHYS_OFFSET) >> PAGE_SHIFT)
+#define free_bootmem(s,sz)  free_bootmem(((s)<<PAGE_SHIFT)+PHYS_OFFSET, (sz)<<PAGE_SHIFT)
 
 	for (i = 0; i < meminfo.nr_banks; i++) {
 		if (meminfo.bank[i].size == 0)
@@ -409,7 +420,7 @@
 
 		end_pfn = PFN(meminfo.bank[i].start + meminfo.bank[i].size);
 
-		if (end_pfn != meminfo.end >> PAGE_SHIFT)
+		if (end_pfn != PFN(meminfo.end))
 			pg = mem_map + end_pfn;
 	}
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/mm-sa1100.c linux/arch/arm/mm/mm-sa1100.c
--- v2.3.39/linux/arch/arm/mm/mm-sa1100.c	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/mm/mm-sa1100.c	Thu Jan 13 13:30:31 2000
@@ -6,11 +6,11 @@
  * Copyright (C) 1998-1999 Russell King
  * Copyright (C) 1999 Hugo Fiennes
  *
- * 1999/09/12 Nicolas Pitre <nico@visuaide.com>
- *	Specific RAM implementation details are in
- *	linux/include/asm/arch-sa1100/memory.h now.
- *	Allows for better macro optimisations when possible.
+ * 1999/12/04 Nicolas Pitre <nico@cam.org>
+ *	Converted memory definition for struct meminfo initialisations.
+ *	Memory is listed physically now.
  */
+
 #include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/init.h>
@@ -22,39 +22,44 @@
  
 #define SIZE(x) (sizeof(x) / sizeof(x[0]))
 
+
 /*
- * These are the memory size mappings for the
- * SA1100.  Note that LART is a special case -
- * it doesn't use physical address A23 on the
- * DRAM, so we effectively have 4 * 8MB in
- * two banks.
+ * These are the RAM memory mappings for SA1100 implementations.
+ * Note that LART is a special case - it doesn't use physical 
+ * address line A23 on the DRAM, so we effectively have 4 * 8MB
+ * in two banks.
  */
-struct mem_desc mem_desc[] __initdata = {
-	/* virt start virt end */
+struct mem_desc { 
+	unsigned long phys_start;
+	unsigned long length;
+} mem_desc[] __initdata = {
 #if defined(CONFIG_SA1100_BRUTUS)
-	{ 0xc0000000, 0xc0400000 },	/* 4MB */
-	{ 0xc1000000, 0xc1400000 },	/* 4MB */
-	{ 0xc2000000, 0xc2400000 },	/* 4MB */
-	{ 0xc3000000, 0xc3400000 }	/* 4MB */
+	{ 0xc0000000, 0x00400000 },	/* 4MB */
+	{ 0xc8000000, 0x00400000 },	/* 4MB */
+#if 0	/* only two banks until the bootmem stuff is fixed... */
+	{ 0xd0000000, 0x00400000 },	/* 4MB */
+	{ 0xd8000000, 0x00400000 }	/* 4MB */
+#endif
 #elif defined(CONFIG_SA1100_EMPEG)
-	{ 0xc0000000, 0xc0400000 },	/* 4MB */
-	{ 0xc1000000, 0xc1400000 }	/* 4MB */
+	{ 0xc0000000, 0x00400000 },	/* 4MB */
+	{ 0xc8000000, 0x00400000 }	/* 4MB */
 #elif defined(CONFIG_SA1100_LART)
-	{ 0xc0000000, 0xc0800000 },	/* 16MB */
-	{ 0xc1000000, 0xc1800000 },
-	{ 0xc2000000, 0xc2800000 },	/* 16MB */
-	{ 0xc3000000, 0xc3800000 }
+	{ 0xc0000000, 0x00800000 },	/* 8MB */
+	{ 0xc1000000, 0x00800000 },	/* 8MB */
+	{ 0xc8000000, 0x00800000 },	/* 8MB */
+	{ 0xc9000000, 0x00800000 }	/* 8MB */
 #elif defined(CONFIG_SA1100_VICTOR)
-	{ 0xc0000000, 0xc0400000 }	/* 4MB */
+	{ 0xc0000000, 0x00400000 }	/* 4MB */
 #elif defined(CONFIG_SA1100_TIFON)
-	{ 0xc0000000, 0xc1000000 },	/* 16MB */
-	{ 0xc1000000, 0xc2000000 }	/* 16MB */
+	{ 0xc0000000, 0x01000000 },	/* 16MB */
+	{ 0xc8000000, 0x01000000 }	/* 16MB */
 #else
 #error missing memory configuration
 #endif
 };
 
 unsigned int __initdata mem_desc_size = SIZE(mem_desc);
+
 
 struct map_desc io_desc[] __initdata = {
 	/* virtual           physical     length     domain    r  w  c  b */
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S
--- v2.3.39/linux/arch/arm/mm/proc-arm6,7.S	Tue Dec  7 09:32:40 1999
+++ linux/arch/arm/mm/proc-arm6,7.S	Thu Jan 13 13:30:31 2000
@@ -134,14 +134,10 @@
 		b	Ldata_simple			@ ldc	rd, [rn, #m]
 		b	Ldata_unknown
 Ldata_unknown:	@ Part of jumptable
-		ldr	r3, [sp, #15 * 4]		@ Get PC
-		str	r3, [sp, #-4]!
-		mov	r1, r1, lsr #2
-		mov	r3, r4
-		mov	r2, r0
-		adr	r0, Lukabttxt
-		bl	SYMBOL_NAME(panic)
-Lstop:		b	Lstop
+		mov	r0, r1
+		mov	r1, r4
+		mov	r2, r3
+		b	baddataabort
 
 Ldata_ldmstm:	tst	r4, #1 << 21			@ check writeback bit
 		beq	Ldata_simple
@@ -468,7 +464,7 @@
 		.word	cpu_arm6_cache_wback_area
 		.word	cpu_arm6_cache_purge_area
 		.word	cpu_arm6_flush_tlb_page
-		.word	cpu_arm7_do_idle
+		.word	cpu_arm6_do_idle
 		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
diff -u --recursive --new-file v2.3.39/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S
--- v2.3.39/linux/arch/arm/mm/proc-sa110.S	Tue Dec  7 09:32:40 1999
+++ linux/arch/arm/mm/proc-sa110.S	Thu Jan 13 13:30:31 2000
@@ -16,6 +16,7 @@
  * is larger than this, then we flush the whole cache
  */
 #define MAX_AREA_SIZE	32768
+#define FLUSH_OFFSET	32768
 
 		.macro flush_110_dcache	rd, ra, re
 		add	\re, \ra, #16384		@ only necessary for 16k
@@ -56,7 +57,7 @@
 		ands	r1, r1, #1
 		eor	r1, r1, #1
 		str	r1, [r3]
-		addne	ip, ip, #32768
+		addne	ip, ip, #FLUSH_OFFSET
 		flush_110_dcache	r3, ip, r1
 		mov	ip, #0
 		teq	r2, #0
@@ -74,7 +75,7 @@
 		ands	r1, r1, #1
 		eor	r1, r1, #1
 		str	r1, [r3]
-		addne	ip, ip, #32768
+		addne	ip, ip, #FLUSH_OFFSET
 		flush_1100_dcache	r3, ip, r1
 		mov	ip, #0
 		teq	r2, #0
@@ -321,7 +322,7 @@
 		ands	r2, r2, #1
 		eor	r2, r2, #1
 		str	r2, [r3]
-		addne	ip, ip, #32768
+		addne	ip, ip, #FLUSH_OFFSET
 		flush_110_dcache	r3, ip, r1
 		mov	r1, #0
 		mcr	p15, 0, r1, c7, c5, 0		@ flush I cache
@@ -338,7 +339,7 @@
 		ands	r2, r2, #1
 		eor	r2, r2, #1
 		str	r2, [r3]
-		addne	ip, ip, #32768
+		addne	ip, ip, #FLUSH_OFFSET
 		flush_1100_dcache	r3, ip, r1
 		mov	r1, #0
 		mcr	p15, 0, r1, c7, c5, 0		@ flush I cache
@@ -430,8 +431,12 @@
 ENTRY(cpu_sa1100_do_idle)
 		mov	r0, #0
 		mcr	p15, 0, r0, c15, c2, 2		@ Disable clock switching
-							@ load from uncacheable loc?
-		mcr	p15, 0, r0, c15, c8, 2		@ Wait for interrupt
+		ldr	r1, =FLUSH_BASE+FLUSH_OFFSET*2	@ load from uncacheable loc
+		ldr	r1, [r1, #0]
+		b	1f
+
+		.align	5
+1:		mcr	p15, 0, r0, c15, c8, 2		@ Wait for interrupt
 		mcr	p15, 0, r0, c15, c1, 2		@ Enable clock switching
 		mov	pc, lr
 
diff -u --recursive --new-file v2.3.39/linux/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in
--- v2.3.39/linux/arch/arm/vmlinux-armv.lds.in	Fri Oct 22 13:21:44 1999
+++ linux/arch/arm/vmlinux-armv.lds.in	Thu Jan 13 13:30:31 2000
@@ -6,82 +6,84 @@
 ENTRY(stext)
 SECTIONS
 {
-  . = TEXTADDR;
-  .text : { }			/* Set text start address	*/
+	. = TEXTADDR;
+	.init : {			/* Init code and data		*/
+		__init_begin = .;
+			*(.text.init)
+		__proc_info_begin = .;
+			*(.proc.info)
+		__proc_info_end = .;
+			*(.data.init)
+		. = ALIGN(16);
+		__setup_start = .;
+			*(.setup.init)
+		__setup_end = .;
+		__initcall_start = .;
+			*(.initcall.init)
+		__initcall_end = .;
+		. = ALIGN(4096);
+		__init_end = .;
+	}
+
+	.ebsa285 : {
+		__ebsa285_begin = .;
+			*(.text.ebsa285)
+			*(.data.ebsa285)
+		. = ALIGN(4096);
+		__ebsa285_end = .;
+	}
+
+	.netwinder : {
+		__netwinder_begin = .;
+	  		*(.text.netwinder)
+			*(.data.netwinder)
+		. = ALIGN(4096);
+		__netwinder_end = .;
+	}
+
+	.text : {			/* Real text segment		*/
+		_text = .;		/* Text and read-only data	*/
+			*(.text)
+			*(.fixup)
+			*(.gnu.warning)
+			*(.text.lock)	/* out-of-line lock text */
+			*(.rodata)
+			*(.kstrtab)
+		. = ALIGN(16);		/* Exception table		*/
+		__start___ex_table = .;
+			*(__ex_table)
+		__stop___ex_table = .;
+
+		__start___ksymtab = .;	/* Kernel symbol table		*/
+			*(__ksymtab)
+		__stop___ksymtab = .;
+
+		*(.got)			/* Global offset table		*/
 
-  __init_begin = .;		/* Init code and data		*/
-  .text.init : { *(.text.init) }
-  __proc_info_begin = .;
-  .proc.info : { *(.proc.info) }
-  __proc_info_end = .;
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);
-  __init_end = .;
-
-  __ebsa285_begin = .;
-  .text.ebsa285 : { *(.text.ebsa285) }
-  .data.ebsa285 : { *(.data.ebsa285) }
-  . = ALIGN(4096);
-  __ebsa285_end = .;
-
-  __netwinder_begin = .;
-  .text.netwinder : { *(.text.netwinder) }
-  .data.netwinder : { *(.data.netwinder) }
-  . = ALIGN(4096);
-  __netwinder_end = .;
-
-  _text = .;			/* Text and read-only data	*/
-  .text.real : {		/* Real text segment		*/
-	*(.text)
-	*(.fixup)
-	*(.gnu.warning)
-	}
-
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
-  .kstrtab : { *(.kstrtab) }
-
-  . = ALIGN(16);		/* Exception table		*/
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  __start___ksymtab = .;	/* Kernel symbol table		*/
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-
-  .got : { *(.got) }		/* Global offset table		*/
-
-  _etext = .;			/* End of text section		*/
-
-  . = ALIGN(8192);
-  .data : {			/* Data				*/
-	*(.init.task)
-	*(.data)
-	CONSTRUCTORS
-	}
-
-  _edata = .;			/* End of data section		*/
-
-  __bss_start = .;		/* BSS				*/
-  .bss : {
-	*(.bss)
-	}
-  _end = . ;
-
-				/* Stabs debugging sections.	*/
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  .stab.excl 0 : { *(.stab.excl) }
-  .stab.exclstr 0 : { *(.stab.exclstr) }
-  .stab.index 0 : { *(.stab.index) }
-  .stab.indexstr 0 : { *(.stab.indexstr) }
-  .comment 0 : { *(.comment) }
+		_etext = .;		/* End of text section		*/
+	}
+
+	. = ALIGN(8192);
+
+	.data : {			/* Data				*/
+		*(.init.task)
+		*(.data)
+		CONSTRUCTORS
+		_edata = .;		/* End of data section		*/
+	}
+
+	.bss : {
+		__bss_start = .;	/* BSS				*/
+		*(.bss)
+		*(COMMON)
+		_end = . ;
+	}
+					/* Stabs debugging sections.	*/
+	.stab 0 : { *(.stab) }
+	.stabstr 0 : { *(.stabstr) }
+	.stab.excl 0 : { *(.stab.excl) }
+	.stab.exclstr 0 : { *(.stab.exclstr) }
+	.stab.index 0 : { *(.stab.index) }
+	.stab.indexstr 0 : { *(.stab.indexstr) }
+	.comment 0 : { *(.comment) }
 }
diff -u --recursive --new-file v2.3.39/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.39/linux/arch/i386/config.in	Fri Jan  7 19:13:21 2000
+++ linux/arch/i386/config.in	Thu Jan 20 09:51:42 2000
@@ -7,6 +7,8 @@
 define_bool CONFIG_X86 y
 define_bool CONFIG_ISA y
 
+define_bool CONFIG_UID16 y
+
 mainmenu_option next_comment
 comment 'Code maturity level options'
 bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
@@ -35,6 +37,7 @@
 fi
 if [ "$CONFIG_M686" = "y" ]; then
    define_bool CONFIG_X86_GOOD_APIC y
+   define_bool CONFIG_X86_PGE y
 fi
 if [ "$CONFIG_MK7" = "y" ]; then
    define_bool CONFIG_X86_TSC y
@@ -57,6 +60,13 @@
 bool 'Math emulation' CONFIG_MATH_EMULATION
 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
 bool 'Symmetric multi-processing support' CONFIG_SMP
+if [ "$CONFIG_SMP" != "y" ]; then
+    bool 'APIC and IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC
+    if [ "$CONFIG_X86_UP_IOAPIC" = "y" ]; then
+       define_bool CONFIG_X86_IO_APIC y
+       define_bool CONFIG_X86_LOCAL_APIC y
+    fi
+fi
 endmenu
 
 mainmenu_option next_comment
@@ -103,7 +113,11 @@
    bool 'MCA support' CONFIG_MCA
 fi
 
-source drivers/pcmcia/Config.in
+bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+
+if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+   source drivers/pcmcia/Config.in
+fi
 
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
@@ -162,6 +176,8 @@
    source drivers/scsi/Config.in
 fi
 endmenu
+
+source drivers/ieee1394/Config.in
 
 source drivers/i2o/Config.in
 
diff -u --recursive --new-file v2.3.39/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.39/linux/arch/i386/defconfig	Tue Jan 11 22:31:36 2000
+++ linux/arch/i386/defconfig	Thu Jan 20 16:00:45 2000
@@ -3,6 +3,7 @@
 #
 CONFIG_X86=y
 CONFIG_ISA=y
+CONFIG_UID16=y
 
 #
 # Code maturity level options
@@ -24,6 +25,7 @@
 CONFIG_X86_POPAD_OK=y
 CONFIG_X86_TSC=y
 CONFIG_X86_GOOD_APIC=y
+CONFIG_X86_PGE=y
 CONFIG_NOHIGHMEM=y
 # CONFIG_HIGHMEM4G is not set
 # CONFIG_HIGHMEM64G is not set
@@ -53,6 +55,7 @@
 CONFIG_PCI_DIRECT=y
 CONFIG_PCI_NAMES=y
 # CONFIG_MCA is not set
+CONFIG_HOTPLUG=y
 
 #
 # PCMCIA/CardBus support
@@ -101,11 +104,13 @@
 #
 CONFIG_BLK_DEV_CMD640=y
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
 CONFIG_BLK_DEV_RZ1000=y
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_BLK_DEV_IDEDMA_PCI is not set
 # CONFIG_BLK_DEV_OFFBOARD is not set
 # CONFIG_BLK_DEV_AEC6210 is not set
+# CONFIG_BLK_DEV_CMD64X is not set
 # CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_CPQ_DA is not set
 
@@ -397,11 +402,11 @@
 CONFIG_DRM=y
 CONFIG_DRM_TDFX=y
 # CONFIG_DRM_GAMMA is not set
+CONFIG_PCMCIA_SERIAL=y
 
 #
 # PCMCIA character device support
 #
-CONFIG_PCMCIA_SERIAL=y
 # CONFIG_PCMCIA_SERIAL_CS is not set
 # CONFIG_PCMCIA_SERIAL_CB is not set
 
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.3.39/linux/arch/i386/kernel/Makefile	Wed Dec 29 13:13:12 1999
+++ linux/arch/i386/kernel/Makefile	Thu Jan 20 09:51:42 2000
@@ -55,8 +55,12 @@
 O_OBJS += smp.o smpboot.o trampoline.o
 endif
 
+ifdef CONFIG_X86_LOCAL_APIC
+O_OBJS += apic.o
+endif
+
 ifdef CONFIG_X86_IO_APIC
-O_OBJS += io_apic.o
+O_OBJS += io_apic.o mpparse.o
 endif
 
 ifdef CONFIG_X86_VISWS_APIC
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c
--- v2.3.39/linux/arch/i386/kernel/acpi.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/i386/kernel/acpi.c	Thu Jan 20 09:51:42 2000
@@ -172,6 +172,14 @@
 	 &acpi_p_lvl3_lat, sizeof(acpi_p_lvl3_lat),
 	 0644, NULL, &acpi_do_ulong},
 
+	{ACPI_P_LVL2_LAT, "enter_lvl2_lat",
+	 &acpi_enter_lvl2_lat, sizeof(acpi_enter_lvl2_lat),
+	 0644, NULL, &acpi_do_ulong},
+
+	{ACPI_ENTER_LVL3_LAT, "enter_lvl3_lat",
+	 &acpi_enter_lvl3_lat, sizeof(acpi_enter_lvl3_lat),
+	 0644, NULL, &acpi_do_ulong},
+
 	{ACPI_S0_SLP_TYP, "s0_slp_typ",
 	 &acpi_slp_typ[ACPI_S0], sizeof(acpi_slp_typ[ACPI_S0]),
 	 0600, NULL, &acpi_do_ulong},
@@ -195,6 +203,17 @@
 	{0}
 };
 
+static u32 FASTCALL(acpi_read_pm1_control(struct acpi_facp *));
+static u32 FASTCALL(acpi_read_pm1_status(struct acpi_facp *));
+static u32 FASTCALL(acpi_read_pm1_enable(struct acpi_facp *));
+static u32 FASTCALL(acpi_read_gpe_status(struct acpi_facp *));
+static u32 FASTCALL(acpi_read_gpe_enable(struct acpi_facp *));
+
+static void FASTCALL(acpi_write_pm1_control(struct acpi_facp *, u32));
+static void FASTCALL(acpi_write_pm1_status(struct acpi_facp *, u32));
+static void FASTCALL(acpi_write_pm1_enable(struct acpi_facp *, u32));
+static void FASTCALL(acpi_write_gpe_status(struct acpi_facp *, u32));
+static void FASTCALL(acpi_write_gpe_enable(struct acpi_facp *, u32));
 
 /*
  * Get the value of the PM1 control register (SCI_EN, ...)
@@ -643,43 +662,49 @@
 	return 0;
 }
 
-static inline int bm_activity(void)
+static inline int bm_activity(struct acpi_facp *facp)
 {
-	return 0 && acpi_read_pm1_status(acpi_facp) & ACPI_BM;
+	return acpi_read_pm1_status(facp) & ACPI_BM;
 }
 
-static inline void clear_bm_activity(void)
+static inline void clear_bm_activity(struct acpi_facp *facp)
 {
-	acpi_write_pm1_status(acpi_facp, ACPI_BM);
+	acpi_write_pm1_status(facp, ACPI_BM);
 }
 
-static void sleep_on_busmaster(void)
+static void sleep_on_busmaster(struct acpi_facp *facp)
 {
-	u32 pm1_cntr = acpi_read_pm1_control(acpi_facp);
+	u32 pm1_cntr = acpi_read_pm1_control(facp);
 	if (pm1_cntr & ACPI_BM_RLD) {
 		pm1_cntr &= ~ACPI_BM_RLD;
-		acpi_write_pm1_control(acpi_facp, pm1_cntr);
+		acpi_write_pm1_control(facp, pm1_cntr);
 	}
 }
 
-static void wake_on_busmaster(void)
+static void wake_on_busmaster(struct acpi_facp *facp)
 {
-	u32 pm1_cntr = acpi_read_pm1_control(acpi_facp);
+	u32 pm1_cntr = acpi_read_pm1_control(facp);
 	if (!(pm1_cntr & ACPI_BM_RLD)) {
 		pm1_cntr |= ACPI_BM_RLD;
-		acpi_write_pm1_control(acpi_facp, pm1_cntr);
+		acpi_write_pm1_control(facp, pm1_cntr);
 	}
-	clear_bm_activity();
+	clear_bm_activity(facp);
 }
 
+/* The ACPI timer is just the low 24 bits */
+#define TIME_BEGIN(tmr)			inl(tmr)
+#define TIME_END(tmr, begin) 		((inl(tmr) - (begin)) & 0x00ffffff)
+
+
 /*
  * Idle loop (uniprocessor only)
  */
 static void acpi_idle_handler(void)
 {
 	static int sleep_level = 1;
+	struct acpi_facp *facp = acpi_facp;
 
-	if (!acpi_facp->pm_tmr || !acpi_p_blk)
+	if (!facp || !facp->pm_tmr || !acpi_p_blk)
 		goto not_initialized;
 
 	/*
@@ -687,7 +712,7 @@
 	 */
 	if (sleep_level == 1)
 		goto sleep1;
-	if (sleep_level == 2 || bm_activity())
+	if (sleep_level == 2)
 		goto sleep2;
 sleep3:
 	sleep_level = 3;
@@ -695,37 +720,53 @@
 		printk("ACPI C3 works\n");
 		acpi_p_lvl3_tested = 1;
 	}
-	wake_on_busmaster();
-	if (acpi_facp->pm2_cnt)
+	wake_on_busmaster(facp);
+	if (facp->pm2_cnt)
 		goto sleep3_with_arbiter;
 
 	for (;;) {
 		unsigned long time;
+		unsigned int pm_tmr = facp->pm_tmr;
+
 		__cli();
 		if (current->need_resched)
 			goto out;
-		time = inl(acpi_facp->pm_tmr);
+		if (bm_activity(facp))
+			goto sleep2;
+
+		time = TIME_BEGIN(pm_tmr);
 		inb(acpi_p_blk + ACPI_P_LVL3);
-		time = inl(acpi_facp->pm_tmr) - time;
+		inl(pm_tmr);					/* Dummy read, force synchronization with the PMU */
+		time = TIME_END(pm_tmr, time);
+
 		__sti();
-		if (time > acpi_p_lvl3_lat || bm_activity())
+		if (time < acpi_p_lvl3_lat)
 			goto sleep2;
 	}
 
 sleep3_with_arbiter:
 	for (;;) {
 		unsigned long time;
-		unsigned int pm2_cntr = acpi_facp->pm2_cnt;
+		u8 arbiter;
+		unsigned int pm2_cntr = facp->pm2_cnt;
+		unsigned int pm_tmr = facp->pm_tmr;
+
 		__cli();
 		if (current->need_resched)
 			goto out;
-		time = inl(acpi_facp->pm_tmr);
-		outb(inb(pm2_cntr) | ACPI_ARB_DIS, pm2_cntr);
+		if (bm_activity(facp))
+			goto sleep2;
+
+		time = TIME_BEGIN(pm_tmr);
+		arbiter = inb(pm2_cntr) & ~ACPI_ARB_DIS;
+		outb(arbiter | ACPI_ARB_DIS, pm2_cntr);		/* Disable arbiter, park on CPU */
 		inb(acpi_p_blk + ACPI_P_LVL3);
-		outb(inb(pm2_cntr) & ~ACPI_ARB_DIS, pm2_cntr);
-		time = inl(acpi_facp->pm_tmr) - time;
+		inl(pm_tmr);					/* Dummy read, force synchronization with the PMU */
+		time = TIME_END(pm_tmr, time);
+		outb(arbiter, pm2_cntr);			/* Enable arbiter again.. */
+
 		__sti();
-		if (time > acpi_p_lvl3_lat || bm_activity())
+		if (time < acpi_p_lvl3_lat)
 			goto sleep2;
 	}
 
@@ -735,38 +776,45 @@
 		printk("ACPI C2 works\n");
 		acpi_p_lvl2_tested = 1;
 	}
-	wake_on_busmaster();	/* Required to track BM activity.. */
+	wake_on_busmaster(facp);	/* Required to track BM activity.. */
 	for (;;) {
 		unsigned long time;
+		unsigned int pm_tmr = facp->pm_tmr;
+
 		__cli();
 		if (current->need_resched)
 			goto out;
-		time = inl(acpi_facp->pm_tmr);
+
+		time = TIME_BEGIN(pm_tmr);
 		inb(acpi_p_blk + ACPI_P_LVL2);
-		time = inl(acpi_facp->pm_tmr) - time;
+		inl(pm_tmr);					/* Dummy read, force synchronization with the PMU */
+		time = TIME_END(pm_tmr, time);
+
 		__sti();
-		if (time > acpi_p_lvl2_lat)
+		if (time < acpi_p_lvl2_lat)
 			goto sleep1;
-		if (bm_activity()) {
-			clear_bm_activity();
+		if (bm_activity(facp)) {
+			clear_bm_activity(facp);
 			continue;
 		}
-		if (time < acpi_enter_lvl3_lat)
+		if (time > acpi_enter_lvl3_lat)
 			goto sleep3;
 	}
 
 sleep1:
 	sleep_level = 1;
-	sleep_on_busmaster();
+	sleep_on_busmaster(facp);
 	for (;;) {
 		unsigned long time;
+		unsigned int pm_tmr = facp->pm_tmr;
+
 		__cli();
 		if (current->need_resched)
 			goto out;
-		time = inl(acpi_facp->pm_tmr);
+		time = TIME_BEGIN(pm_tmr);
 		__asm__ __volatile__("sti ; hlt": : :"memory");
-		time = inl(acpi_facp->pm_tmr) - time;
-		if (time < acpi_enter_lvl2_lat)
+		time = TIME_END(pm_tmr, time);
+		if (time > acpi_enter_lvl2_lat)
 			goto sleep2;
 	}
 
@@ -1221,7 +1269,7 @@
 	 * do this with multiple CPU's, we'd need a per-CPU ACPI
 	 * device..
 	 */
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 	if (smp_num_cpus > 1)
 		return 0;
 #endif
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- v2.3.39/linux/arch/i386/kernel/apic.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/apic.c	Thu Jan 20 09:51:42 2000
@@ -0,0 +1,656 @@
+/*
+ *	Local APIC handling, local APIC timers
+ *
+ *	(c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/mc146818rtc.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/smp.h>
+#include <asm/mtrr.h>
+#include <asm/mpspec.h>
+#include <asm/pgalloc.h>
+
+int prof_multiplier[NR_CPUS] = { 1, };
+int prof_old_multiplier[NR_CPUS] = { 1, };
+int prof_counter[NR_CPUS] = { 1, };
+
+/*
+ * IA s/w dev Vol 3, Section 7.4
+ */
+#define APIC_DEFAULT_PHYS_BASE 0xfee00000
+
+int get_maxlvt(void)
+{
+	unsigned int v, ver, maxlvt;
+
+	v = apic_read(APIC_LVR);
+	ver = GET_APIC_VERSION(v);
+	/* 82489DXs do not report # of LVT entries. */
+	maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2;
+	return maxlvt;
+}
+
+void disable_local_APIC (void)
+{
+	unsigned long value;
+        int maxlvt;
+
+	/*
+	 * Disable APIC
+	 */
+ 	value = apic_read(APIC_SPIV);
+ 	value &= ~(1<<8);
+ 	apic_write(APIC_SPIV,value);
+
+	/*
+	 * Clean APIC state for other OSs:
+	 */
+ 	value = apic_read(APIC_SPIV);
+ 	value &= ~(1<<8);
+ 	apic_write(APIC_SPIV,value);
+	maxlvt = get_maxlvt();
+	apic_write_around(APIC_LVTT, 0x00010000);
+	apic_write_around(APIC_LVT0, 0x00010000);
+	apic_write_around(APIC_LVT1, 0x00010000);
+	if (maxlvt >= 3)
+		apic_write_around(APIC_LVTERR, 0x00010000);
+	if (maxlvt >= 4)
+		apic_write_around(APIC_LVTPC, 0x00010000);
+}
+
+extern void __error_in_apic_c (void);
+
+void __init setup_local_APIC (void)
+{
+	unsigned long value, ver, maxlvt;
+
+	if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
+		__error_in_apic_c();
+
+	/*
+	 * Double-check wether this APIC is really registered.
+	 */
+	if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map))
+		BUG();
+
+ 	value = apic_read(APIC_SPIV);
+	/*
+	 * Enable APIC
+	 */
+ 	value |= (1<<8);
+
+	/*
+	 * Some unknown Intel IO/APIC (or APIC) errata is biting us with
+	 * certain networking cards. If high frequency interrupts are
+	 * happening on a particular IOAPIC pin, plus the IOAPIC routing
+	 * entry is masked/unmasked at a high rate as well then sooner or
+	 * later IOAPIC line gets 'stuck', no more interrupts are received
+	 * from the device. If focus CPU is disabled then the hang goes
+	 * away, oh well :-(
+	 *
+	 * [ This bug can be reproduced easily with a level-triggered
+	 *   PCI Ne2000 networking cards and PII/PIII processors, dual
+	 *   BX chipset. ]
+	 */
+#if 0
+	/* Enable focus processor (bit==0) */
+ 	value &= ~(1<<9);
+#else
+	/* Disable focus processor (bit==1) */
+	value |= (1<<9);
+#endif
+	/*
+	 * Set spurious IRQ vector
+	 */
+	value |= SPURIOUS_APIC_VECTOR;
+ 	apic_write(APIC_SPIV,value);
+
+	/*
+	 * Set up LVT0, LVT1:
+	 *
+	 * set up through-local-APIC on the BP's LINT0. This is not
+	 * strictly necessery in pure symmetric-IO mode, but sometimes
+	 * we delegate interrupts to the 8259A.
+	 */
+	if (!smp_processor_id()) {
+		value = 0x00000700;
+		printk("enabled ExtINT on CPU#%d\n", smp_processor_id());
+	} else {
+		value = 0x00010700;
+		printk("masked ExtINT on CPU#%d\n", smp_processor_id());
+	}
+ 	apic_write_around(APIC_LVT0,value);
+
+	/*
+	 * only the BP should see the LINT1 NMI signal, obviously.
+	 */
+	if (!smp_processor_id())
+		value = 0x00000400;		// unmask NMI
+	else
+		value = 0x00010400;		// mask NMI
+ 	apic_write_around(APIC_LVT1,value);
+
+	value = apic_read(APIC_LVR);
+	ver = GET_APIC_VERSION(value);
+	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
+		maxlvt = get_maxlvt();
+		/*
+		 * Due to the Pentium erratum 3AP.
+		 */
+		if (maxlvt > 3) {
+			apic_readaround(APIC_SPIV); // not strictly necessery
+			apic_write(APIC_ESR, 0);
+		}
+		value = apic_read(APIC_ESR);
+		printk("ESR value before enabling vector: %08lx\n", value);
+
+		value = apic_read(APIC_LVTERR);
+		value = ERROR_APIC_VECTOR;      // enables sending errors
+		apic_write(APIC_LVTERR,value);
+		/*
+		 * spec says clear errors after enabling vector.
+		 */
+		if (maxlvt != 3) {
+			apic_readaround(APIC_SPIV);
+			apic_write(APIC_ESR, 0);
+		}
+		value = apic_read(APIC_ESR);
+		printk("ESR value after enabling vector: %08lx\n", value);
+	} else
+		printk("No ESR for 82489DX.\n");
+
+	/*
+	 * Set Task Priority to 'accept all'. We never change this
+	 * later on.
+	 */
+ 	value = apic_read(APIC_TASKPRI);
+ 	value &= ~APIC_TPRI_MASK;
+ 	apic_write(APIC_TASKPRI,value);
+
+	/*
+	 * Set up the logical destination ID and put the
+	 * APIC into flat delivery mode.
+	 */
+ 	value = apic_read(APIC_LDR);
+	value &= ~APIC_LDR_MASK;
+	value |= (1<<(smp_processor_id()+24));
+ 	apic_write(APIC_LDR,value);
+
+ 	value = apic_read(APIC_DFR);
+	value |= SET_APIC_DFR(0xf);
+ 	apic_write(APIC_DFR, value);
+}
+
+void __init init_apic_mappings(void)
+{
+	unsigned long apic_phys;
+
+	if (smp_found_config) {
+		apic_phys = mp_lapic_addr;
+	} else {
+		/*
+		 * set up a fake all zeroes page to simulate the
+		 * local APIC and another one for the IO-APIC. We
+		 * could use the real zero-page, but it's safer
+		 * this way if some buggy code writes to this page ...
+		 */
+		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
+		apic_phys = __pa(apic_phys);
+	}
+	set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
+	Dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
+
+#ifdef CONFIG_X86_IO_APIC
+	{
+		unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+		int i;
+
+		for (i = 0; i < nr_ioapics; i++) {
+			if (smp_found_config) {
+				ioapic_phys = mp_ioapics[i].mpc_apicaddr;
+			} else {
+				ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
+				ioapic_phys = __pa(ioapic_phys);
+			}
+			set_fixmap_nocache(idx, ioapic_phys);
+			Dprintk("mapped IOAPIC to %08lx (%08lx)\n",
+					__fix_to_virt(idx), ioapic_phys);
+			idx++;
+		}
+	}
+#endif
+}
+
+/*
+ * This part sets up the APIC 32 bit clock in LVTT1, with HZ interrupts
+ * per second. We assume that the caller has already set up the local
+ * APIC.
+ *
+ * The APIC timer is not exactly sync with the external timer chip, it
+ * closely follows bus clocks.
+ */
+
+/*
+ * The timer chip is already set up at HZ interrupts per second here,
+ * but we do not accept timer interrupts yet. We only allow the BP
+ * to calibrate.
+ */
+static unsigned int __init get_8254_timer_count(void)
+{
+	extern rwlock_t xtime_lock;
+	unsigned long flags;
+
+	unsigned int count;
+
+	write_lock_irqsave(&xtime_lock, flags);
+
+	outb_p(0x00, 0x43);
+	count = inb_p(0x40);
+	count |= inb_p(0x40) << 8;
+
+	write_unlock_irqrestore(&xtime_lock, flags);
+
+	return count;
+}
+
+void __init wait_8254_wraparound(void)
+{
+	unsigned int curr_count, prev_count=~0;
+	int delta;
+
+	curr_count = get_8254_timer_count();
+
+	do {
+		prev_count = curr_count;
+		curr_count = get_8254_timer_count();
+		delta = curr_count-prev_count;
+
+	/*
+	 * This limit for delta seems arbitrary, but it isn't, it's
+	 * slightly above the level of error a buggy Mercury/Neptune
+	 * chipset timer can cause.
+	 */
+
+	} while (delta<300);
+}
+
+/*
+ * This function sets up the local APIC timer, with a timeout of
+ * 'clocks' APIC bus clock. During calibration we actually call
+ * this function twice on the boot CPU, once with a bogus timeout
+ * value, second time for real. The other (noncalibrating) CPUs
+ * call this function only once, with the real, calibrated value.
+ *
+ * We do reads before writes even if unnecessary, to get around the
+ * P5 APIC double write bug.
+ */
+
+#define APIC_DIVISOR 16
+
+void __setup_APIC_LVTT(unsigned int clocks)
+{
+	unsigned int lvtt1_value, tmp_value;
+
+	tmp_value = apic_read(APIC_LVTT);
+	lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) |
+			APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
+	apic_write(APIC_LVTT, lvtt1_value);
+
+	/*
+	 * Divide PICLK by 16
+	 */
+	tmp_value = apic_read(APIC_TDCR);
+	apic_write(APIC_TDCR, (tmp_value
+				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
+				| APIC_TDR_DIV_16);
+
+	tmp_value = apic_read(APIC_TMICT);
+	apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
+}
+
+void setup_APIC_timer(void * data)
+{
+	unsigned int clocks = (unsigned int) data, slice, t0, t1;
+	unsigned long flags;
+	int delta;
+
+	__save_flags(flags);
+	__sti();
+	/*
+	 * ok, Intel has some smart code in their APIC that knows
+	 * if a CPU was in 'hlt' lowpower mode, and this increases
+	 * its APIC arbitration priority. To avoid the external timer
+	 * IRQ APIC event being in synchron with the APIC clock we
+	 * introduce an interrupt skew to spread out timer events.
+	 *
+	 * The number of slices within a 'big' timeslice is smp_num_cpus+1
+	 */
+
+	slice = clocks / (smp_num_cpus+1);
+	printk("cpu: %d, clocks: %d, slice: %d\n",
+		smp_processor_id(), clocks, slice);
+
+	/*
+	 * Wait for IRQ0's slice:
+	 */
+	wait_8254_wraparound();
+
+	__setup_APIC_LVTT(clocks);
+
+	t0 = apic_read(APIC_TMCCT)*APIC_DIVISOR;
+	do {
+		t1 = apic_read(APIC_TMCCT)*APIC_DIVISOR;
+		delta = (int)(t0 - t1 - slice*(smp_processor_id()+1));
+	} while (delta < 0);
+
+	__setup_APIC_LVTT(clocks);
+
+	printk("CPU%d<C0:%d,C:%d,D:%d,S:%d,C:%d>\n",
+			smp_processor_id(), t0, t1, delta, slice, clocks);
+
+	__restore_flags(flags);
+}
+
+/*
+ * In this function we calibrate APIC bus clocks to the external
+ * timer. Unfortunately we cannot use jiffies and the timer irq
+ * to calibrate, since some later bootup code depends on getting
+ * the first irq? Ugh.
+ *
+ * We want to do the calibration only once since we
+ * want to have local timer irqs syncron. CPUs connected
+ * by the same APIC bus have the very same bus frequency.
+ * And we want to have irqs off anyways, no accidental
+ * APIC irq that way.
+ */
+
+int __init calibrate_APIC_clock(void)
+{
+	unsigned long long t1 = 0, t2 = 0;
+	long tt1, tt2;
+	long result;
+	int i;
+	const int LOOPS = HZ/10;
+
+	printk("calibrating APIC timer ... ");
+
+	/*
+	 * Put whatever arbitrary (but long enough) timeout
+	 * value into the APIC clock, we just want to get the
+	 * counter running for calibration.
+	 */
+	__setup_APIC_LVTT(1000000000);
+
+	/*
+	 * The timer chip counts down to zero. Let's wait
+	 * for a wraparound to start exact measurement:
+	 * (the current tick might have been already half done)
+	 */
+
+	wait_8254_wraparound();
+
+	/*
+	 * We wrapped around just now. Let's start:
+	 */
+	if (cpu_has_tsc)
+		rdtscll(t1);
+	tt1 = apic_read(APIC_TMCCT);
+
+	/*
+	 * Let's wait LOOPS wraprounds:
+	 */
+	for (i = 0; i < LOOPS; i++)
+		wait_8254_wraparound();
+
+	tt2 = apic_read(APIC_TMCCT);
+	if (cpu_has_tsc)
+		rdtscll(t2);
+
+	/*
+	 * The APIC bus clock counter is 32 bits only, it
+	 * might have overflown, but note that we use signed
+	 * longs, thus no extra care needed.
+	 *
+	 * underflown to be exact, as the timer counts down ;)
+	 */
+
+	result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
+
+	if (cpu_has_tsc)
+		printk("\n..... CPU clock speed is %ld.%04ld MHz.\n",
+			((long)(t2-t1)/LOOPS)/(1000000/HZ),
+			((long)(t2-t1)/LOOPS)%(1000000/HZ));
+
+	printk("..... host bus clock speed is %ld.%04ld MHz.\n",
+		result/(1000000/HZ),
+		result%(1000000/HZ));
+
+	return result;
+}
+
+static unsigned int calibration_result;
+
+void __init setup_APIC_clocks (void)
+{
+	__cli();
+
+	calibration_result = calibrate_APIC_clock();
+	/*
+	 * Now set up the timer for real.
+	 */
+	setup_APIC_timer((void *)calibration_result);
+
+	__sti();
+
+	/* and update all other cpus */
+	smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1);
+}
+
+/*
+ * the frequency of the profiling timer can be changed
+ * by writing a multiplier value into /proc/profile.
+ */
+int setup_profiling_timer(unsigned int multiplier)
+{
+	int i;
+
+	/*
+	 * Sanity check. [at least 500 APIC cycles should be
+	 * between APIC interrupts as a rule of thumb, to avoid
+	 * irqs flooding us]
+	 */
+	if ( (!multiplier) || (calibration_result/multiplier < 500))
+		return -EINVAL;
+
+	/* 
+	 * Set the new multiplier for each CPU. CPUs don't start using the
+	 * new values until the next timer interrupt in which they do process
+	 * accounting. At that time they also adjust their APIC timers
+	 * accordingly.
+	 */
+	for (i = 0; i < NR_CPUS; ++i)
+		prof_multiplier[i] = multiplier;
+
+	return 0;
+}
+
+#undef APIC_DIVISOR
+
+/*
+ * Local timer interrupt handler. It does both profiling and
+ * process statistics/rescheduling.
+ *
+ * We do profiling in every local tick, statistics/rescheduling
+ * happen only every 'profiling multiplier' ticks. The default
+ * multiplier is 1 and it can be changed by writing the new multiplier
+ * value into /proc/profile.
+ */
+
+inline void smp_local_timer_interrupt(struct pt_regs * regs)
+{
+	int user = (user_mode(regs) != 0);
+	int cpu = smp_processor_id();
+
+	/*
+	 * The profiling function is SMP safe. (nothing can mess
+	 * around with "current", and the profiling counters are
+	 * updated with atomic operations). This is especially
+	 * useful with a profiling multiplier != 1
+	 */
+	if (!user)
+		x86_do_profile(regs->eip);
+
+	if (--prof_counter[cpu] <= 0) {
+		int system = 1 - user;
+		struct task_struct * p = current;
+
+		/*
+		 * The multiplier may have changed since the last time we got
+		 * to this point as a result of the user writing to
+		 * /proc/profile. In this case we need to adjust the APIC
+		 * timer accordingly.
+		 *
+		 * Interrupts are already masked off at this point.
+		 */
+		prof_counter[cpu] = prof_multiplier[cpu];
+		if (prof_counter[cpu] != prof_old_multiplier[cpu]) {
+			__setup_APIC_LVTT(calibration_result/prof_counter[cpu]);
+			prof_old_multiplier[cpu] = prof_counter[cpu];
+		}
+
+		/*
+		 * After doing the above, we need to make like
+		 * a normal interrupt - otherwise timer interrupts
+		 * ignore the global interrupt lock, which is the
+		 * WrongThing (tm) to do.
+		 */
+
+ 		irq_enter(cpu, 0);
+		update_one_process(p, 1, user, system, cpu);
+		if (p->pid) {
+			p->counter -= 1;
+			if (p->counter <= 0) {
+				p->counter = 0;
+				p->need_resched = 1;
+			}
+			if (p->priority < DEF_PRIORITY) {
+				kstat.cpu_nice += user;
+				kstat.per_cpu_nice[cpu] += user;
+			} else {
+				kstat.cpu_user += user;
+				kstat.per_cpu_user[cpu] += user;
+			}
+			kstat.cpu_system += system;
+			kstat.per_cpu_system[cpu] += system;
+
+		}
+		irq_exit(cpu, 0);
+	}
+
+	/*
+	 * We take the 'long' return path, and there every subsystem
+	 * grabs the apropriate locks (kernel lock/ irq lock).
+	 *
+	 * we might want to decouple profiling from the 'long path',
+	 * and do the profiling totally in assembly.
+	 *
+	 * Currently this isn't too much of an issue (performance wise),
+	 * we can take more than 100K local irqs per second on a 100 MHz P5.
+	 */
+}
+
+/*
+ * Local APIC timer interrupt. This is the most natural way for doing
+ * local interrupts, but local timer interrupts can be emulated by
+ * broadcast interrupts too. [in case the hw doesnt support APIC timers]
+ *
+ * [ if a single-CPU system runs an SMP kernel then we call the local
+ *   interrupt as well. Thus we cannot inline the local irq ... ]
+ */
+unsigned int apic_timer_irqs [NR_CPUS] = { 0, };
+
+void smp_apic_timer_interrupt(struct pt_regs * regs)
+{
+	/*
+	 * the NMI deadlock-detector uses this.
+	 */
+	apic_timer_irqs[smp_processor_id()]++;
+
+	/*
+	 * NOTE! We'd better ACK the irq immediately,
+	 * because timer handling can be slow.
+	 */
+	ack_APIC_irq();
+	smp_local_timer_interrupt(regs);
+}
+
+/*
+ * This interrupt should _never_ happen with our APIC/SMP architecture
+ */
+asmlinkage void smp_spurious_interrupt(void)
+{
+	ack_APIC_irq();
+	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
+	printk("spurious APIC interrupt on CPU#%d, should never happen.\n",
+			smp_processor_id());
+}
+
+/*
+ * This interrupt should never happen with our APIC/SMP architecture
+ */
+
+static spinlock_t err_lock = SPIN_LOCK_UNLOCKED;
+
+asmlinkage void smp_error_interrupt(void)
+{
+	unsigned long v;
+
+	spin_lock(&err_lock);
+
+	v = apic_read(APIC_ESR);
+	printk("APIC error interrupt on CPU#%d, should never happen.\n",
+			smp_processor_id());
+	printk("... APIC ESR0: %08lx\n", v);
+
+	apic_write(APIC_ESR, 0);
+	v |= apic_read(APIC_ESR);
+	printk("... APIC ESR1: %08lx\n", v);
+	/*
+	 * Be a bit more verbose. (multiple bits can be set)
+	 */
+	if (v & 0x01)
+		printk("... bit 0: APIC Send CS Error (hw problem).\n");
+	if (v & 0x02)
+		printk("... bit 1: APIC Receive CS Error (hw problem).\n");
+	if (v & 0x04)
+		printk("... bit 2: APIC Send Accept Error.\n");
+	if (v & 0x08)
+		printk("... bit 3: APIC Receive Accept Error.\n");
+	if (v & 0x10)
+		printk("... bit 4: Reserved!.\n");
+	if (v & 0x20)
+		printk("... bit 5: Send Illegal Vector (kernel bug).\n");
+	if (v & 0x40)
+		printk("... bit 6: Received Illegal Vector.\n");
+	if (v & 0x80)
+		printk("... bit 7: Illegal Register Address.\n");
+
+	ack_APIC_irq();
+
+	irq_err_count++;
+
+	spin_unlock(&err_lock);
+}
+
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.3.39/linux/arch/i386/kernel/i386_ksyms.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/i386/kernel/i386_ksyms.c	Thu Jan 20 09:51:42 2000
@@ -23,7 +23,7 @@
 extern void dump_thread(struct pt_regs *, struct user *);
 extern int dump_fpu(elf_fpregset_t *);
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
 extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
 #endif
@@ -92,13 +92,10 @@
 EXPORT_SYMBOL(mmx_copy_page);
 #endif
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_data);
 EXPORT_SYMBOL(kernel_flag);
-EXPORT_SYMBOL(cpu_number_map);
-EXPORT_SYMBOL(__cpu_logical_map);
 EXPORT_SYMBOL(smp_num_cpus);
-EXPORT_SYMBOL(cpu_present_map);
 EXPORT_SYMBOL(cpu_online_map);
 EXPORT_SYMBOL_NOVERS(__write_lock_failed);
 EXPORT_SYMBOL_NOVERS(__read_lock_failed);
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c
--- v2.3.39/linux/arch/i386/kernel/i8259.c	Sat Oct  9 11:47:50 1999
+++ linux/arch/i386/kernel/i8259.c	Thu Jan 20 09:51:42 2000
@@ -71,17 +71,16 @@
 #undef BI
 
 
-#ifdef __SMP__
 /*
  * The following vectors are part of the Linux architecture, there
  * is no hardware IRQ pin equivalent for them, they are triggered
  * through the ICC by us (IPIs)
  */
+#ifdef CONFIG_SMP
 BUILD_SMP_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
 BUILD_SMP_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
 BUILD_SMP_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
-BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
-BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
+#endif
 
 /*
  * every pentium local APIC has two 'local interrupts', with a
@@ -90,8 +89,10 @@
  * overflow. Linux uses the local APIC timer interrupt to get
  * a much simpler SMP time architecture:
  */
+#ifdef CONFIG_X86_LOCAL_APIC
 BUILD_SMP_TIMER_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR)
-
+BUILD_SMP_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR)
+BUILD_SMP_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR)
 #endif
 
 #define IRQ(x,y) \
@@ -428,8 +429,7 @@
 			set_intr_gate(vector, interrupt[i]);
 	}
 
-#ifdef __SMP__	
-
+#ifdef CONFIG_SMP
 	/*
 	 * IRQ0 must be given a fixed assignment and initialized,
 	 * because it's used before the IO-APIC is set up.
@@ -445,16 +445,18 @@
 	/* IPI for invalidation */
 	set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
 
-	/* self generated IPI for local APIC timer */
-	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
 	/* IPI for generic function call */
 	set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
+#endif	
+
+#ifdef CONFIG_X86_LOCAL_APIC
+	/* self generated IPI for local APIC timer */
+	set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
 
 	/* IPI vectors for APIC spurious and error interrupts */
 	set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
 	set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-#endif	
+#endif
 
 	/*
 	 * Set the clock to HZ Hz, we already have a valid
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.3.39/linux/arch/i386/kernel/io_apic.c	Tue Dec  7 09:32:40 1999
+++ linux/arch/i386/kernel/io_apic.c	Thu Jan 20 09:51:42 2000
@@ -1,7 +1,7 @@
 /*
  *	Intel IO-APIC support for multi-Pentium hosts.
  *
- *	Copyright (C) 1997, 1998, 1999 Ingo Molnar, Hajnalka Szabo
+ *	Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar, Hajnalka Szabo
  *
  *	Many thanks to Stig Venaas for trying out countless experimental
  *	patches and reporting/debugging problems patiently!
@@ -13,105 +13,42 @@
  *	and Ingo Molnar <mingo@redhat.com>
  */
 
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
+#include <linux/mm.h>
+#include <linux/irq.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/config.h>
+#include <linux/smp_lock.h>
+
 #include <asm/io.h>
+#include <asm/smp.h>
 #include <asm/desc.h>
 
-#include <linux/irq.h>
-
-#undef __init
-#define __init
-
-/*
- * volatile is justified in this case, IO-APIC register contents
- * might change spontaneously, GCC should not cache it
- */
-#define IO_APIC_BASE(idx) ((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx))
-
-extern int nmi_watchdog;
-
-/*
- * The structure of the IO-APIC:
- */
-
-struct IO_APIC_reg_00 {
-	__u32	__reserved_2	: 24,
-		ID		:  4,
-		__reserved_1	:  4;
-} __attribute__ ((packed));
-
-struct IO_APIC_reg_01 {
-	__u32	version		:  8,
-		__reserved_2	:  8,
-		entries		:  8,
-		__reserved_1	:  8;
-} __attribute__ ((packed));
-
-struct IO_APIC_reg_02 {
-	__u32	__reserved_2	: 24,
-		arbitration	:  4,
-		__reserved_1	:  4;
-} __attribute__ ((packed));
-
 /*
  * # of IO-APICs and # of IRQ routing registers
  */
 int nr_ioapics = 0;
 int nr_ioapic_registers[MAX_IO_APICS];
 
-enum ioapic_irq_destination_types {
-	dest_Fixed = 0,
-	dest_LowestPrio = 1,
-	dest_SMI = 2,
-	dest__reserved_1 = 3,
-	dest_NMI = 4,
-	dest_INIT = 5,
-	dest__reserved_2 = 6,
-	dest_ExtINT = 7
-};
+/* I/O APIC entries */
+struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
 
-struct IO_APIC_route_entry {
-	__u32	vector		:  8,
-		delivery_mode	:  3,	/* 000: FIXED
-					 * 001: lowest prio
-					 * 111: ExtINT
-					 */
-		dest_mode	:  1,	/* 0: physical, 1: logical */
-		delivery_status	:  1,
-		polarity	:  1,
-		irr		:  1,
-		trigger		:  1,	/* 0: edge, 1: level */
-		mask		:  1,	/* 0: enabled, 1: disabled */
-		__reserved_2	: 15;
-
-	union {		struct { __u32
-					__reserved_1	: 24,
-					physical_dest	:  4,
-					__reserved_2	:  4;
-			} physical;
-
-			struct { __u32
-					__reserved_1	: 24,
-					logical_dest	:  8;
-			} logical;
-	} dest;
+/* # of MP IRQ source entries */
+struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
 
-} __attribute__ ((packed));
+/* MP IRQ source entries */
+int mp_irq_entries = 0;
+
+/* non-0 if default (table-less) MP configuration */
+int mpc_default_type = 0;
 
 /*
- * MP-BIOS irq configuration table structures:
+ * Rough estimation of how many shared IRQs there are, can
+ * be changed anytime.
  */
-
-struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];/* I/O APIC entries */
-int mp_irq_entries = 0;				/* # of MP IRQ source entries */
-struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
-						/* MP IRQ source entries */
-int mpc_default_type = 0;			/* non-0 if default (table-less)
-						   MP configuration */
-
+#define MAX_PLUS_SHARED_IRQS NR_IRQS
+#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
 
 /*
  * This is performance-critical, we want to do it O(1)
@@ -120,43 +57,6 @@
  * between pins and IRQs.
  */
 
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
-{
-	*IO_APIC_BASE(apic) = reg;
-	return *(IO_APIC_BASE(apic)+4);
-}
-
-static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
-{
-	*IO_APIC_BASE(apic) = reg;
-	*(IO_APIC_BASE(apic)+4) = value;
-}
-
-/*
- * Re-write a value: to be used for read-modify-write
- * cycles where the read already set up the index register.
- */
-static inline void io_apic_modify(unsigned int apic, unsigned int value)
-{
-	*(IO_APIC_BASE(apic)+4) = value;
-}
-
-/*
- * Synchronize the IO-APIC and the CPU by doing
- * a dummy read from the IO-APIC
- */
-static inline void io_apic_sync(unsigned int apic)
-{
-	(void) *(IO_APIC_BASE(apic)+4);
-}
-
-/*
- * Rough estimation of how many shared IRQs there are, can
- * be changed anytime.
- */
-#define MAX_PLUS_SHARED_IRQS NR_IRQS
-#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
-
 static struct irq_pin_list {
 	int apic, pin, next;
 } irq_2_pin[PIN_MAP_SIZE];
@@ -239,6 +139,7 @@
 #define MAX_PIRQS 8
 int pirq_entries [MAX_PIRQS];
 int pirqs_enabled;
+int skip_ioapic_setup = 0;
 
 static int __init ioapic_setup(char *str)
 {
@@ -997,7 +898,7 @@
 	}
 }
 
-static void __init setup_ioapic_id(void)
+static void __init setup_ioapic_default_id(void)
 {
 	struct IO_APIC_reg_00 reg_00;
 
@@ -1012,7 +913,7 @@
 	 * system must have a unique ID or we get lots of nice
 	 * 'stuck on smp_invalidate_needed IPI wait' messages.
 	 */
-	if (cpu_present_map & (1<<0x2))
+	if (phys_cpu_present_map & (1<<0x2))
 		panic("APIC ID 2 already used");
 
 	/*
@@ -1031,6 +932,47 @@
 		panic("could not set ID");
 }
 
+/*
+ * function to set the IO-APIC physical IDs based on the
+ * values stored in the MPC table.
+ *
+ * by Matt Domsch <Matt_Domsch@dell.com>  Tue Dec 21 12:25:05 CST 1999
+ */
+
+static void __init setup_ioapic_ids_from_mpc (void)
+{
+	struct IO_APIC_reg_00 reg_00;
+	int apic;
+
+	/*
+	 * Set the IOAPIC ID to the value stored in the MPC table.
+	 */
+	for (apic = 0; apic < nr_ioapics; apic++) {
+
+		/* Read the register 0 value */
+		*(int *)&reg_00 = io_apic_read(apic, 0);
+		
+		/*
+		 * Read the right value from the MPC table and
+		 * write it into the ID register.
+	 	 */
+		printk("...changing IO-APIC physical APIC ID to %d ...",
+					mp_ioapics[apic].mpc_apicid);
+
+		reg_00.ID = mp_ioapics[apic].mpc_apicid;
+		io_apic_write(apic, 0, *(int *)&reg_00);
+
+		/*
+		 * Sanity check
+		 */
+		*(int *)&reg_00 = io_apic_read(apic, 0);
+		if (reg_00.ID != mp_ioapics[apic].mpc_apicid)
+			panic("could not set ID!\n");
+		else
+			printk(" ok.\n");
+	}
+}
+
 static void __init construct_default_ISA_mptable(void)
 {
 	int i, pos = 0;
@@ -1071,7 +1013,7 @@
 			mp_irqs[0].mpc_dstirq = 2;
 	}
 
-	setup_ioapic_id();
+	setup_ioapic_default_id();
 }
 
 /*
@@ -1320,6 +1262,8 @@
 	pin1 = find_timer_pin(mp_INT);
 	pin2 = find_timer_pin(mp_ExtINT);
 
+	printk("..TIMER: vector=%d pin1=%d pin2=%d\n", vector, pin1, pin2);
+
 	/*
 	 * Ok, does IRQ0 through the IOAPIC work?
 	 */
@@ -1405,8 +1349,8 @@
 {
 	enable_IO_APIC();
 
-	printk("ENABLING IO-APIC IRQs\n");
 	io_apic_irqs = ~PIC_IRQS;
+	printk("ENABLING IO-APIC IRQs\n");
 
 	/*
 	 * If there are no explicit MP IRQ entries, it's either one of the
@@ -1422,8 +1366,25 @@
 	 * Set up the IO-APIC IRQ routing table by parsing the MP-BIOS
 	 * mptable:
 	 */
+	setup_ioapic_ids_from_mpc();
 	setup_IO_APIC_irqs();
 	init_IO_APIC_traps();
 	check_timer();
 	print_IO_APIC();
 }
+
+#ifndef CONFIG_SMP
+/*
+ * This initializes the IO-APIC and APIC hardware if this is
+ * a UP kernel.
+ */
+void IO_APIC_init_uniprocessor (void)
+{
+	if (!smp_found_config)
+		return;
+	phys_cpu_present_map = 0xff;
+	setup_local_APIC();
+	setup_IO_APIC();
+	setup_APIC_clocks();
+}
+#endif
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.3.39/linux/arch/i386/kernel/irq.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/i386/kernel/irq.c	Thu Jan 20 09:51:42 2000
@@ -1,8 +1,3 @@
-/* mostly architecture independent
-   some moved to i8259.c
-   the beautiful visws architecture code needs to be updated too.
-   and, finally, the BUILD_IRQ and SMP_BUILD macros in irq.h need fixed.
-   */
 /*
  *	linux/arch/i386/kernel/irq.c
  *
@@ -16,6 +11,8 @@
  */
 
 /*
+ * (mostly architecture independent, will move to kernel/irq.c in 2.5.)
+ *
  * IRQs are in fact implemented a bit like signal handlers for the kernel.
  * Naturally it's not a 1:1 relation, but there are similarities.
  */
@@ -33,15 +30,16 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
+#include <linux/irq.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/system.h>
 #include <asm/bitops.h>
 #include <asm/pgalloc.h>
 #include <asm/delay.h>
 #include <asm/desc.h>
 #include <asm/irq.h>
-#include <linux/irq.h>
 
 
 unsigned int local_bh_count[NR_CPUS];
@@ -99,7 +97,7 @@
  */
 #if CONFIG_X86
 	printk("unexpected IRQ trap at vector %02x\n", irq);
-#ifdef __SMP__
+#ifdef CONFIG_X86_LOCAL_APIC
 	/*
 	 * Currently unexpected vectors happen only on SMP and APIC.
 	 * We _must_ ack these because every local APIC has only N
@@ -149,7 +147,7 @@
 		if (!action) 
 			continue;
 		p += sprintf(p, "%3d: ",i);
-#ifndef __SMP__
+#ifndef CONFIG_SMP
 		p += sprintf(p, "%10u ", kstat_irqs(i));
 #else
 		for (j = 0; j < smp_num_cpus; j++)
@@ -186,7 +184,7 @@
  */
 spinlock_t i386_bh_lock = SPIN_LOCK_UNLOCKED;
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 unsigned char global_irq_holder = NO_PROC_ID;
 unsigned volatile int global_irq_lock;
 atomic_t global_irq_count;
@@ -707,7 +705,7 @@
 			}
 			spin_unlock_irqrestore(&irq_controller_lock,flags);
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 			/* Wait to make sure it's not being used on another CPU */
 			while (irq_desc[irq].status & IRQ_INPROGRESS)
 				barrier();
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/ls linux/arch/i386/kernel/ls
--- v2.3.39/linux/arch/i386/kernel/ls	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/ls	Mon Jan 17 14:37:56 2000
@@ -0,0 +1 @@
+
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c
--- v2.3.39/linux/arch/i386/kernel/mpparse.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/mpparse.c	Thu Jan 20 09:51:42 2000
@@ -0,0 +1,514 @@
+/*
+ *	Intel Multiprocessor Specificiation 1.1 and 1.4
+ *	compliant MP-table parsing routines.
+ *
+ *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
+ *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
+ *
+ *	Fixes
+ *		Erich Boleyn	:	MP v1.4 and additional changes.
+ *		Alan Cox	:	Added EBDA scanning
+ *		Ingo Molnar	:	various cleanups and rewrites
+ *	Maciej W. Rozycki	:	Bits for genuine 82489DX timers
+ */
+
+#include <linux/mm.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/bootmem.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/smp.h>
+#include <asm/mtrr.h>
+#include <asm/mpspec.h>
+#include <asm/pgalloc.h>
+
+/* Have we found an MP table */
+int smp_found_config = 0;
+
+/*
+ * Various Linux-internal data structures created from the
+ * MP-table.
+ */
+int apic_version [NR_CPUS];
+int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
+int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
+int mp_current_pci_id = 0;
+int pic_mode;
+unsigned long mp_lapic_addr = 0;
+
+/* Processor that is doing the boot up */
+unsigned int boot_cpu_id = 0;
+/* Internal processor count */
+static unsigned int num_processors = 1;
+
+/* Bitmask of physically existing CPUs */
+unsigned long phys_cpu_present_map = 0;
+
+/*
+ * IA s/w dev Vol 3, Section 7.4
+ */
+#define APIC_DEFAULT_PHYS_BASE 0xfee00000
+
+/*
+ * Intel MP BIOS table parsing routines:
+ */
+
+#ifndef CONFIG_X86_VISWS_APIC
+/*
+ * Checksum an MP configuration block.
+ */
+
+static int __init mpf_checksum(unsigned char *mp, int len)
+{
+	int sum=0;
+	while(len--)
+		sum+=*mp++;
+	return sum&0xFF;
+}
+
+/*
+ * Processor encoding in an MP configuration block
+ */
+
+static char __init *mpc_family(int family,int model)
+{
+	static char n[32];
+	static char *model_defs[]=
+	{
+		"80486DX","80486DX",
+		"80486SX","80486DX/2 or 80487",
+		"80486SL","80486SX/2",
+		"Unknown","80486DX/2-WB",
+		"80486DX/4","80486DX/4-WB"
+	};
+
+	switch (family) {
+		case 0x04:
+			if (model < 10)
+				return model_defs[model];
+			break;
+
+		case 0x05:
+			return("Pentium(tm)");
+
+		case 0x06:
+			return("Pentium(tm) Pro");
+
+		case 0x0F:
+			if (model == 0x0F)
+				return("Special controller");
+	}
+	sprintf(n,"Unknown CPU [%d:%d]",family, model);
+	return n;
+}
+
+static void __init MP_processor_info (struct mpc_config_processor *m)
+{
+	int ver;
+
+	if (!(m->mpc_cpuflag & CPU_ENABLED))
+		return;
+
+	printk("Processor #%d %s APIC version %d\n",
+		m->mpc_apicid,
+		mpc_family(	(m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
+				(m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
+		m->mpc_apicver);
+
+	if (m->mpc_featureflag&(1<<0))
+		Dprintk("    Floating point unit present.\n");
+	if (m->mpc_featureflag&(1<<7))
+		Dprintk("    Machine Exception supported.\n");
+	if (m->mpc_featureflag&(1<<8))
+		Dprintk("    64 bit compare & exchange supported.\n");
+	if (m->mpc_featureflag&(1<<9))
+		Dprintk("    Internal APIC present.\n");
+
+	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+		Dprintk("    Bootup CPU\n");
+		boot_cpu_id = m->mpc_apicid;
+	} else
+		/* Boot CPU already counted */
+		num_processors++;
+
+	if (m->mpc_apicid > NR_CPUS) {
+		printk("Processor #%d unused. (Max %d processors).\n",
+			m->mpc_apicid, NR_CPUS);
+		return;
+	}
+	ver = m->mpc_apicver;
+
+	phys_cpu_present_map |= 1 << m->mpc_apicid;
+	/*
+	 * Validate version
+	 */
+	if (ver == 0x0) {
+		printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
+		ver = 0x10;
+	}
+	apic_version[m->mpc_apicid] = ver;
+}
+
+static void __init MP_bus_info (struct mpc_config_bus *m)
+{
+	char str[7];
+
+	memcpy(str, m->mpc_bustype, 6);
+	str[6] = 0;
+	Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
+
+	if (strncmp(str, "ISA", 3) == 0) {
+		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
+	} else {
+	if (strncmp(str, "EISA", 4) == 0) {
+		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
+	} else {
+	if (strncmp(str, "PCI", 3) == 0) {
+		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
+		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
+		mp_current_pci_id++;
+	} else {
+		printk("Unknown bustype %s\n", str);
+		panic("cannot handle bus - mail to linux-smp@vger.rutgers.edu");
+	} } }
+}
+
+static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
+{
+	if (!(m->mpc_flags & MPC_APIC_USABLE))
+		return;
+
+	printk("I/O APIC #%d Version %d at 0x%lX.\n",
+		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
+	if (nr_ioapics >= MAX_IO_APICS) {
+		printk("Max # of I/O APICs (%d) exceeded (found %d).\n",
+			MAX_IO_APICS, nr_ioapics);
+		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
+	}
+	mp_ioapics[nr_ioapics] = *m;
+	nr_ioapics++;
+}
+
+static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
+{
+	mp_irqs [mp_irq_entries] = *m;
+	if (++mp_irq_entries == MAX_IRQ_SOURCES)
+		panic("Max # of irq sources exceeded!!\n");
+}
+
+static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
+{
+	/*
+	 * Well it seems all SMP boards in existence
+	 * use ExtINT/LVT1 == LINT0 and
+	 * NMI/LVT2 == LINT1 - the following check
+	 * will show us if this assumptions is false.
+	 * Until then we do not have to add baggage.
+	 */
+	if ((m->mpc_irqtype == mp_ExtINT) &&
+		(m->mpc_destapiclint != 0))
+			BUG();
+	if ((m->mpc_irqtype == mp_NMI) &&
+		(m->mpc_destapiclint != 1))
+			BUG();
+}
+
+/*
+ * Read/parse the MPC
+ */
+
+static int __init smp_read_mpc(struct mp_config_table *mpc)
+{
+	char str[16];
+	int count=sizeof(*mpc);
+	unsigned char *mpt=((unsigned char *)mpc)+count;
+
+	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4))
+	{
+		panic("SMP mptable: bad signature [%c%c%c%c]!\n",
+			mpc->mpc_signature[0],
+			mpc->mpc_signature[1],
+			mpc->mpc_signature[2],
+			mpc->mpc_signature[3]);
+		return 1;
+	}
+	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length))
+	{
+		panic("SMP mptable: checksum error!\n");
+		return 1;
+	}
+	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04)
+	{
+		printk("Bad Config Table version (%d)!!\n",mpc->mpc_spec);
+		return 1;
+	}
+	memcpy(str,mpc->mpc_oem,8);
+	str[8]=0;
+	printk("OEM ID: %s ",str);
+
+	memcpy(str,mpc->mpc_productid,12);
+	str[12]=0;
+	printk("Product ID: %s ",str);
+
+	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
+
+	/* save the local APIC address, it might be non-default */
+	mp_lapic_addr = mpc->mpc_lapic;
+
+	/*
+	 *	Now process the configuration blocks.
+	 */
+	while (count < mpc->mpc_length) {
+		switch(*mpt) {
+			case MP_PROCESSOR:
+			{
+				struct mpc_config_processor *m=
+					(struct mpc_config_processor *)mpt;
+				MP_processor_info(m);
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+			case MP_BUS:
+			{
+				struct mpc_config_bus *m=
+					(struct mpc_config_bus *)mpt;
+				MP_bus_info(m);
+				mpt += sizeof(*m);
+				count += sizeof(*m);
+				break;
+			}
+			case MP_IOAPIC:
+			{
+				struct mpc_config_ioapic *m=
+					(struct mpc_config_ioapic *)mpt;
+				MP_ioapic_info(m);
+				mpt+=sizeof(*m);
+				count+=sizeof(*m);
+				break;
+			}
+			case MP_INTSRC:
+			{
+				struct mpc_config_intsrc *m=
+					(struct mpc_config_intsrc *)mpt;
+
+				MP_intsrc_info(m);
+				mpt+=sizeof(*m);
+				count+=sizeof(*m);
+				break;
+			}
+			case MP_LINTSRC:
+			{
+				struct mpc_config_lintsrc *m=
+					(struct mpc_config_lintsrc *)mpt;
+				MP_lintsrc_info(m);
+				mpt+=sizeof(*m);
+				count+=sizeof(*m);
+				break;
+			}
+		}
+	}
+	return num_processors;
+}
+
+/*
+ * Scan the memory blocks for an SMP configuration block.
+ */
+static int __init smp_get_mpf(struct intel_mp_floating *mpf)
+{
+	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
+	if (mpf->mpf_feature2 & (1<<7)) {
+		printk("    IMCR and PIC compatibility mode.\n");
+		pic_mode = 1;
+	} else {
+		printk("    Virtual Wire compatibility mode.\n");
+		pic_mode = 0;
+	}
+	smp_found_config = 1;
+	/*
+	 * default CPU id - if it's different in the mptable
+	 * then we change it before first using it.
+	 */
+	boot_cpu_id = 0;
+	/*
+	 * Now see if we need to read further.
+	 */
+	if (mpf->mpf_feature1 != 0) {
+		/*
+		 * local APIC has default address
+		 */
+		mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+
+		/*
+		 * 2 CPUs, numbered 0 & 1.
+		 */
+		phys_cpu_present_map = 3;
+		num_processors = 2;
+
+		nr_ioapics = 1;
+		mp_ioapics[0].mpc_apicaddr = 0xFEC00000;
+		/*
+		 * Save the default type number, we
+		 * need it later to set the IO-APIC
+		 * up properly:
+		 */
+		mpc_default_type = mpf->mpf_feature1;
+
+		printk("Bus #0 is ");
+	}
+
+	switch (mpf->mpf_feature1) {
+		case 1:
+		case 5:
+			printk("ISA\n");
+			break;
+		case 2:
+			printk("EISA with no IRQ0 and no IRQ13 DMA chaining\n");
+			break;
+		case 6:
+		case 3:
+			printk("EISA\n");
+			break;
+		case 4:
+		case 7:
+			printk("MCA\n");
+			break;
+		case 0:
+			if (!mpf->mpf_physptr)
+				BUG();
+			break;
+		default:
+			printk("???\nUnknown standard configuration %d\n",
+				mpf->mpf_feature1);
+			return 1;
+	}
+	if (mpf->mpf_feature1 > 4) {
+		printk("Bus #1 is PCI\n");
+
+		/*
+		 * Set local APIC version to the integrated form.
+		 * It's initialized to zero otherwise, representing
+		 * a discrete 82489DX.
+		 */
+		apic_version[0] = 0x10;
+		apic_version[1] = 0x10;
+	}
+	/*
+	 * Read the physical hardware table. Anything here will override the
+	 * defaults.
+	 */
+	if (mpf->mpf_physptr)
+		smp_read_mpc((void *)mpf->mpf_physptr);
+
+	printk("Processors: %d\n", num_processors);
+	/*
+	 * Only use the first configuration found.
+	 */
+	return 1;
+}
+
+static int __init smp_scan_config(unsigned long base, unsigned long length)
+{
+	unsigned long *bp = phys_to_virt(base);
+	struct intel_mp_floating *mpf;
+
+	Dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
+	if (sizeof(*mpf) != 16)
+		printk("Error: MPF size\n");
+
+	while (length > 0) {
+		mpf = (struct intel_mp_floating *)bp;
+		if ((*bp == SMP_MAGIC_IDENT) &&
+			(mpf->mpf_length == 1) &&
+			!mpf_checksum((unsigned char *)bp, 16) &&
+			((mpf->mpf_specification == 1)
+				|| (mpf->mpf_specification == 4)) ) {
+
+			printk("found SMP MP-table at %08ld\n",
+						virt_to_phys(mpf));
+			smp_get_mpf(mpf);
+			return 1;
+		}
+		bp += 4;
+		length -= 16;
+	}
+	return 0;
+}
+
+void __init init_intel_smp (void)
+{
+	unsigned int address;
+
+	/*
+	 * FIXME: Linux assumes you have 640K of base ram..
+	 * this continues the error...
+	 *
+	 * 1) Scan the bottom 1K for a signature
+	 * 2) Scan the top 1K of base RAM
+	 * 3) Scan the 64K of bios
+	 */
+	if (smp_scan_config(0x0,0x400) ||
+		smp_scan_config(639*0x400,0x400) ||
+			smp_scan_config(0xF0000,0x10000))
+		return;
+	/*
+	 * If it is an SMP machine we should know now, unless the
+	 * configuration is in an EISA/MCA bus machine with an
+	 * extended bios data area.
+	 *
+	 * there is a real-mode segmented pointer pointing to the
+	 * 4K EBDA area at 0x40E, calculate and scan it here.
+	 *
+	 * NOTE! There are Linux loaders that will corrupt the EBDA
+	 * area, and as such this kind of SMP config may be less
+	 * trustworthy, simply because the SMP table may have been
+	 * stomped on during early boot. These loaders are buggy and
+	 * should be fixed.
+	 */
+
+	address = *(unsigned short *)phys_to_virt(0x40E);
+	address <<= 4;
+	smp_scan_config(address, 0x1000);
+	if (smp_found_config)
+		printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");
+}
+
+#else
+
+/*
+ * The Visual Workstation is Intel MP compliant in the hardware
+ * sense, but it doesnt have a BIOS(-configuration table).
+ * No problem for Linux.
+ */
+void __init init_visws_smp(void)
+{
+	smp_found_config = 1;
+
+	phys_cpu_present_map |= 2; /* or in id 1 */
+	apic_version[1] |= 0x10; /* integrated APIC */
+	apic_version[0] |= 0x10;
+
+	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
+}
+
+#endif
+
+/*
+ * - Intel MP Configuration Table
+ * - or SGI Visual Workstation configuration
+ */
+void __init init_smp_config (void)
+{
+#ifdef CONFIG_X86_IO_APIC
+	init_intel_smp();
+#endif
+#ifdef CONFIG_VISWS
+	init_visws_smp();
+#endif
+}
+
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/pci-i386.c linux/arch/i386/kernel/pci-i386.c
--- v2.3.39/linux/arch/i386/kernel/pci-i386.c	Thu Jan  6 12:57:47 2000
+++ linux/arch/i386/kernel/pci-i386.c	Wed Jan 12 09:21:23 2000
@@ -94,58 +94,55 @@
 
 #include "pci-i386.h"
 
-/*
- * Assign new address to PCI resource.  We hope our resource information
- * is complete.  On the PC, we don't re-assign resources unless we are
- * forced to do so.
- *
- * Expects start=0, end=size-1, flags=resource type.
- */
-
-int pci_assign_resource(struct pci_dev *dev, int i)
+void
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			struct resource *res, int resource)
 {
-	struct resource *r = &dev->resource[i];
-	struct resource *pr = pci_find_parent_resource(dev, r);
-	unsigned long size = r->end + 1;
 	u32 new, check;
+	int reg;
 
-	if (!pr) {
-		printk(KERN_ERR "PCI: Cannot find parent resource for device %s\n", dev->slot_name);
-		return -EINVAL;
-	}
-	if (r->flags & IORESOURCE_IO) {
-		/*
-		 * We need to avoid collisions with `mirrored' VGA ports and other strange
-		 * ISA hardware, so we always want the addresses kilobyte aligned.
-		 */
-		if (size > 0x100) {
-			printk(KERN_ERR "PCI: I/O Region %s/%d too large (%ld bytes)\n", dev->slot_name, i, size);
-			return -EFBIG;
-		}
-		if (allocate_resource(pr, r, size, 0x1000, ~0, 1024, NULL, NULL)) {
-			printk(KERN_ERR "PCI: Allocation of I/O region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size);
-			return -EBUSY;
-		}
+	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+	if (resource < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+	} else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
 	} else {
-		if (allocate_resource(pr, r, size, 0x10000000, ~0, size, NULL, NULL)) {
-			printk(KERN_ERR "PCI: Allocation of memory region %s/%d (%ld bytes) failed\n", dev->slot_name, i, size);
-			return -EBUSY;
-		}
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
+	
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       new, check);
 	}
-	if (i < 6) {
-		int reg = PCI_BASE_ADDRESS_0 + 4*i;
-		new = r->start | (r->flags & PCI_REGION_FLAG_MASK);
-		pci_write_config_dword(dev, reg, new);
-		pci_read_config_dword(dev, reg, &check);
-		if (new != check)
-			printk(KERN_ERR "PCI: Error while updating region %s/%d (%08x != %08x)\n", dev->slot_name, i, new, check);
-	} else if (i == PCI_ROM_RESOURCE) {
-		r->flags |= PCI_ROM_ADDRESS_ENABLE;
-		pci_write_config_dword(dev, dev->rom_base_reg, r->start | (r->flags & PCI_REGION_FLAG_MASK));
+}
+
+void
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+	struct pci_dev *dev = data;
+
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		/* We need to avoid collisions with `mirrored' VGA ports
+		   and other strange ISA hardware, so we always want the
+		   addresses kilobyte aligned.  */
+		if (size >= 0x100) {
+			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+			       " (%ld bytes)\n", dev->slot_name,
+			       dev->resource - res, size);
+		}
+
+		start = (start + 1024 - 1) & ~(1024 - 1);
+		res->start = start;
 	}
-	printk("PCI: Assigned addresses %08lx-%08lx to region %s/%d\n", r->start, r->end, dev->slot_name, i);
-	return 0;
 }
+
 
 /*
  *  Handle resources of PCI devices.  If the world were perfect, we could
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.3.39/linux/arch/i386/kernel/pci-pc.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/i386/kernel/pci-pc.c	Tue Jan 11 19:12:38 2000
@@ -23,6 +23,7 @@
 unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2;
 
 static struct pci_bus *pci_root_bus;
+static struct pci_ops *pci_root_ops;
 
 /*
  * IRQ routing table provided by the BIOS
@@ -876,9 +877,9 @@
 		pci_read_config_byte(d, reg++, &subb);
 		DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
 		if (busno)
-			pci_scan_bus(busno, pci_root_bus->ops, NULL);	/* Bus A */
+			pci_scan_bus(busno, pci_root_ops, NULL);	/* Bus A */
 		if (suba < subb)
-			pci_scan_bus(suba+1, pci_root_bus->ops, NULL);	/* Bus B */
+			pci_scan_bus(suba+1, pci_root_ops, NULL);	/* Bus B */
 	}
 }
 
@@ -891,7 +892,7 @@
 	u8 busno;
 	pci_read_config_byte(d, 0x44, &busno);
 	printk("PCI: RCC host bridge: secondary bus %02x\n", busno);
-	pci_scan_bus(busno, pci_root_bus->ops, NULL);
+	pci_scan_bus(busno, pci_root_ops, NULL);
 }
 
 static void __init pci_fixup_compaq(struct pci_dev *d)
@@ -903,7 +904,7 @@
 	u8 busno;
 	pci_read_config_byte(d, 0xc8, &busno);
 	printk("PCI: Compaq host bridge: secondary bus %02x\n", busno);
-	pci_scan_bus(busno, pci_root_bus->ops, NULL);
+	pci_scan_bus(busno, pci_root_ops, NULL);
 }
 
 static void __init pci_fixup_umc_ide(struct pci_dev *d)
@@ -1189,7 +1190,6 @@
 {
 	struct pci_ops *bios = NULL;
 	struct pci_ops *dir = NULL;
-	struct pci_ops *ops;
 
 #ifdef CONFIG_PCI_BIOS
 	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
@@ -1202,16 +1202,16 @@
 		dir = pci_check_direct();
 #endif
 	if (dir)
-		ops = dir;
+		pci_root_ops = dir;
 	else if (bios)
-		ops = bios;
+		pci_root_ops = bios;
 	else {
 		printk("PCI: No PCI bus detected\n");
 		return;
 	}
 
 	printk("PCI: Probing PCI hardware\n");
-	pci_root_bus = pci_scan_bus(0, ops, NULL);
+	pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
 
 	pcibios_fixup_irqs();
 	if (pci_probe & PCI_PEER_FIXUP)
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/ptrace.c linux/arch/i386/kernel/ptrace.c
--- v2.3.39/linux/arch/i386/kernel/ptrace.c	Fri Oct 15 15:25:13 1999
+++ linux/arch/i386/kernel/ptrace.c	Sat Jan 15 11:04:17 2000
@@ -198,259 +198,242 @@
 
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
-		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-		case PTRACE_PEEKDATA: {
-			unsigned long tmp;
-			int copied;
-
-			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-			ret = -EIO;
-			if (copied != sizeof(tmp))
-				goto out;
-			ret = put_user(tmp,(unsigned long *) data);
-			goto out;
-		}
+	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+	case PTRACE_PEEKDATA: {
+		unsigned long tmp;
+		int copied;
+
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		ret = -EIO;
+		if (copied != sizeof(tmp))
+			break;
+		ret = put_user(tmp,(unsigned long *) data);
+		break;
+	}
 
 	/* read the word at location addr in the USER area. */
-		case PTRACE_PEEKUSR: {
-			unsigned long tmp;
-
-			ret = -EIO;
-			if ((addr & 3) || addr < 0 || 
-			    addr > sizeof(struct user) - 3)
-				goto out;
-
-			tmp = 0;  /* Default return condition */
-			if(addr < 17*sizeof(long))
-				tmp = getreg(child, addr);
-			if(addr >= (long) &dummy->u_debugreg[0] &&
-			   addr <= (long) &dummy->u_debugreg[7]){
-				addr -= (long) &dummy->u_debugreg[0];
-				addr = addr >> 2;
-				tmp = child->thread.debugreg[addr];
-			};
-			ret = put_user(tmp,(unsigned long *) data);
-			goto out;
-		}
-
-      /* when I and D space are separate, this will have to be fixed. */
-		case PTRACE_POKETEXT: /* write the word at location addr. */
-		case PTRACE_POKEDATA:
-			ret = 0;
-			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-				goto out;
-			ret = -EIO;
-			goto out;
+	case PTRACE_PEEKUSR: {
+		unsigned long tmp;
 
-		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-			ret = -EIO;
-			if ((addr & 3) || addr < 0 || 
-			    addr > sizeof(struct user) - 3)
-				goto out;
-
-			if (addr < 17*sizeof(long)) {
-				ret = putreg(child, addr, data);
-				goto out;
-			}
-
-		  /* We need to be very careful here.  We implicitly
-		     want to modify a portion of the task_struct, and we
-		     have to be selective about what portions we allow someone
-		     to modify. */
+		ret = -EIO;
+		if ((addr & 3) || addr < 0 || 
+		    addr > sizeof(struct user) - 3)
+			break;
+
+		tmp = 0;  /* Default return condition */
+		if(addr < 17*sizeof(long))
+			tmp = getreg(child, addr);
+		if(addr >= (long) &dummy->u_debugreg[0] &&
+		   addr <= (long) &dummy->u_debugreg[7]){
+			addr -= (long) &dummy->u_debugreg[0];
+			addr = addr >> 2;
+			tmp = child->thread.debugreg[addr];
+		}
+		ret = put_user(tmp,(unsigned long *) data);
+		break;
+	}
+
+	/* when I and D space are separate, this will have to be fixed. */
+	case PTRACE_POKETEXT: /* write the word at location addr. */
+	case PTRACE_POKEDATA:
+		ret = 0;
+		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+			break;
+		ret = -EIO;
+		break;
+
+	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+		ret = -EIO;
+		if ((addr & 3) || addr < 0 || 
+		    addr > sizeof(struct user) - 3)
+			break;
+
+		if (addr < 17*sizeof(long)) {
+			ret = putreg(child, addr, data);
+			break;
+		}
+		/* We need to be very careful here.  We implicitly
+		   want to modify a portion of the task_struct, and we
+		   have to be selective about what portions we allow someone
+		   to modify. */
 
+		  ret = -EIO;
 		  if(addr >= (long) &dummy->u_debugreg[0] &&
 		     addr <= (long) &dummy->u_debugreg[7]){
 
-			  if(addr == (long) &dummy->u_debugreg[4]) return -EIO;
-			  if(addr == (long) &dummy->u_debugreg[5]) return -EIO;
+			  if(addr == (long) &dummy->u_debugreg[4]) break;
+			  if(addr == (long) &dummy->u_debugreg[5]) break;
 			  if(addr < (long) &dummy->u_debugreg[4] &&
-			     ((unsigned long) data) >= TASK_SIZE-3) return -EIO;
+			     ((unsigned long) data) >= TASK_SIZE-3) break;
 			  
-			  ret = -EIO;
 			  if(addr == (long) &dummy->u_debugreg[7]) {
 				  data &= ~DR_CONTROL_RESERVED;
 				  for(i=0; i<4; i++)
 					  if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
 						  goto out;
-			  };
+			  }
 
 			  addr -= (long) &dummy->u_debugreg;
 			  addr = addr >> 2;
 			  child->thread.debugreg[addr] = data;
 			  ret = 0;
-			  goto out;
-		  };
-		  ret = -EIO;
-		  goto out;
+		  }
+		  break;
 
-		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-		case PTRACE_CONT: { /* restart after signal. */
-			long tmp;
-
-			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
-				goto out;
-			if (request == PTRACE_SYSCALL)
-				child->flags |= PF_TRACESYS;
-			else
-				child->flags &= ~PF_TRACESYS;
-			child->exit_code = data;
+	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+	case PTRACE_CONT: { /* restart after signal. */
+		long tmp;
+
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			child->flags |= PF_TRACESYS;
+		else
+			child->flags &= ~PF_TRACESYS;
+		child->exit_code = data;
 	/* make sure the single step bit is not set. */
-			tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
-			put_stack_long(child, EFL_OFFSET,tmp);
-			wake_up_process(child);
-			ret = 0;
-			goto out;
-		}
+		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+		put_stack_long(child, EFL_OFFSET,tmp);
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
 
 /*
  * make the child exit.  Best I can do is send it a sigkill. 
  * perhaps it should be put in the status that it wants to 
  * exit.
  */
-		case PTRACE_KILL: {
-			long tmp;
-
-			ret = 0;
-			if (child->state == TASK_ZOMBIE)	/* already dead */
-				goto out;
-			child->exit_code = SIGKILL;
-	/* make sure the single step bit is not set. */
-			tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
-			put_stack_long(child, EFL_OFFSET, tmp);
-			wake_up_process(child);
-			goto out;
-		}
-
-		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-			long tmp;
-
-			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
-				goto out;
-			child->flags &= ~PF_TRACESYS;
-			if ((child->flags & PF_DTRACE) == 0) {
-				/* Spurious delayed TF traps may occur */
-				child->flags |= PF_DTRACE;
-			}
-			tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
-			put_stack_long(child, EFL_OFFSET, tmp);
-			child->exit_code = data;
-	/* give it a chance to run. */
-			wake_up_process(child);
-			ret = 0;
-			goto out;
-		}
+	case PTRACE_KILL: {
+		long tmp;
 
-		case PTRACE_DETACH: { /* detach a process that was attached. */
-			long tmp;
-
-			ret = -EIO;
-			if ((unsigned long) data > _NSIG)
-				goto out;
-			child->flags &= ~(PF_PTRACED|PF_TRACESYS);
-			child->exit_code = data;
-			write_lock_irqsave(&tasklist_lock, flags);
-			REMOVE_LINKS(child);
-			child->p_pptr = child->p_opptr;
-			SET_LINKS(child);
-			write_unlock_irqrestore(&tasklist_lock, flags);
-	/* make sure the single step bit is not set. */
-			tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
-			put_stack_long(child, EFL_OFFSET, tmp);
-			wake_up_process(child);
-			ret = 0;
-			goto out;
+		ret = 0;
+		if (child->state == TASK_ZOMBIE)	/* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		/* make sure the single step bit is not set. */
+		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+		put_stack_long(child, EFL_OFFSET, tmp);
+		wake_up_process(child);
+		break;
+	}
+
+	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
+		long tmp;
+
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		child->flags &= ~PF_TRACESYS;
+		if ((child->flags & PF_DTRACE) == 0) {
+			/* Spurious delayed TF traps may occur */
+			child->flags |= PF_DTRACE;
+		}
+		tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG;
+		put_stack_long(child, EFL_OFFSET, tmp);
+		child->exit_code = data;
+		/* give it a chance to run. */
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
+
+	case PTRACE_DETACH: { /* detach a process that was attached. */
+		long tmp;
+
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+		child->exit_code = data;
+		write_lock_irqsave(&tasklist_lock, flags);
+		REMOVE_LINKS(child);
+		child->p_pptr = child->p_opptr;
+		SET_LINKS(child);
+		write_unlock_irqrestore(&tasklist_lock, flags);
+		/* make sure the single step bit is not set. */
+		tmp = get_stack_long(child, EFL_OFFSET) & ~TRAP_FLAG;
+		put_stack_long(child, EFL_OFFSET, tmp);
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
+
+	case PTRACE_GETREGS: { /* Get all gp regs from the child. */
+	  	if (!access_ok(VERIFY_WRITE, (unsigned *)data, 17*sizeof(long))) {
+			ret = -EIO;
+			break;
+		}
+		for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) {
+			__put_user(getreg(child, i),(unsigned long *) data);
+			data += sizeof(long);
+		}
+		ret = 0;
+		break;
+	}
+
+	case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+		unsigned long tmp;
+	  	if (!access_ok(VERIFY_READ, (unsigned *)data, 17*sizeof(long))) {
+			ret = -EIO;
+			break;
+		}
+		for ( i = 0; i < 17*sizeof(long); i += sizeof(long) ) {
+			__get_user(tmp, (unsigned long *) data);
+			putreg(child, i, tmp);
+			data += sizeof(long);
+		}
+		ret = 0;
+		break;
+	}
+
+	case PTRACE_GETFPREGS: { /* Get the child FPU state. */
+		if (!access_ok(VERIFY_WRITE, (unsigned *)data, sizeof(struct user_i387_struct))) {
+			ret = -EIO;
+			break;
+		}
+		ret = 0;
+		if ( !child->used_math ) {
+			/* Simulate an empty FPU. */
+			child->thread.i387.hard.cwd = 0xffff037f;
+			child->thread.i387.hard.swd = 0xffff0000;
+			child->thread.i387.hard.twd = 0xffffffff;
 		}
-
-		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
-		  	if (!access_ok(VERIFY_WRITE, (unsigned *)data,
-				       17*sizeof(long)))
-			  {
-			    ret = -EIO;
-			    goto out;
-			  }
-			for ( i = 0; i < 17*sizeof(long); i += sizeof(long) )
-			  {
-			    __put_user(getreg(child, i),(unsigned long *) data);
-			    data += sizeof(long);
-			  }
-			ret = 0;
-			goto out;
-		  };
-
-		case PTRACE_SETREGS: { /* Set all gp regs in the child. */
-			unsigned long tmp;
-		  	if (!access_ok(VERIFY_READ, (unsigned *)data,
-				       17*sizeof(long)))
-			  {
-			    ret = -EIO;
-			    goto out;
-			  }
-			for ( i = 0; i < 17*sizeof(long); i += sizeof(long) )
-			  {
-			    __get_user(tmp, (unsigned long *) data);
-			    putreg(child, i, tmp);
-			    data += sizeof(long);
-			  }
-			ret = 0;
-			goto out;
-		  };
-
-		case PTRACE_GETFPREGS: { /* Get the child FPU state. */
-			if (!access_ok(VERIFY_WRITE, (unsigned *)data,
-				       sizeof(struct user_i387_struct)))
-			  {
-			    ret = -EIO;
-			    goto out;
-			  }
-			ret = 0;
-			if ( !child->used_math ) {
-			  /* Simulate an empty FPU. */
-			  child->thread.i387.hard.cwd = 0xffff037f;
-			  child->thread.i387.hard.swd = 0xffff0000;
-			  child->thread.i387.hard.twd = 0xffffffff;
-			}
 #ifdef CONFIG_MATH_EMULATION
-			if ( boot_cpu_data.hard_math ) {
+		if ( boot_cpu_data.hard_math ) {
 #endif
-				__copy_to_user((void *)data, &child->thread.i387.hard,
-						sizeof(struct user_i387_struct));
+			__copy_to_user((void *)data, &child->thread.i387.hard, sizeof(struct user_i387_struct));
 #ifdef CONFIG_MATH_EMULATION
-			} else {
-			  save_i387_soft(&child->thread.i387.soft,
-					 (struct _fpstate *)data);
-			}
+		} else {
+			save_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data);
+		}
 #endif
-			goto out;
-		  };
+		break;
+	}
 
-		case PTRACE_SETFPREGS: { /* Set the child FPU state. */
-			if (!access_ok(VERIFY_READ, (unsigned *)data,
-				       sizeof(struct user_i387_struct)))
-			  {
-			    ret = -EIO;
-			    goto out;
-			  }
-			child->used_math = 1;
+	case PTRACE_SETFPREGS: { /* Set the child FPU state. */
+		if (!access_ok(VERIFY_READ, (unsigned *)data, sizeof(struct user_i387_struct))) {
+			ret = -EIO;
+			break;
+		}
+		child->used_math = 1;
 #ifdef CONFIG_MATH_EMULATION
-			if ( boot_cpu_data.hard_math ) {
+		if ( boot_cpu_data.hard_math ) {
 #endif
-			  __copy_from_user(&child->thread.i387.hard, (void *)data,
-					   sizeof(struct user_i387_struct));
+			__copy_from_user(&child->thread.i387.hard, (void *)data, sizeof(struct user_i387_struct));
 #ifdef CONFIG_MATH_EMULATION
-			} else {
-			  restore_i387_soft(&child->thread.i387.soft,
-					    (struct _fpstate *)data);
-			}
+		} else {
+			restore_i387_soft(&child->thread.i387.soft, (struct _fpstate *)data);
+		}
 #endif
-			ret = 0;
-			goto out;
-		  };
-
-		default:
-			ret = -EIO;
-			goto out;
+		ret = 0;
+		break;
+	}
+
+	default:
+		ret = -EIO;
+		break;
 	}
 out:
 	unlock_kernel();
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.39/linux/arch/i386/kernel/setup.c	Tue Jan 11 22:31:36 2000
+++ linux/arch/i386/kernel/setup.c	Thu Jan 20 09:51:42 2000
@@ -74,6 +74,7 @@
 #include <asm/desc.h>
 #include <asm/e820.h>
 #include <asm/dma.h>
+#include <asm/mpspec.h>
 
 /*
  * Machine setup..
@@ -82,7 +83,7 @@
 char ignore_irq13 = 0;		/* set if exception 16 works */
 struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 
-unsigned long mmu_cr4_features __initdata = 0;
+unsigned long mmu_cr4_features = 0;
 
 /*
  * Bus types ..
@@ -696,7 +697,7 @@
 	 */
 	reserve_bootmem(0, PAGE_SIZE);
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 	/*
 	 * But first pinch a few for the stack/trampoline stuff
 	 * FIXME: Don't need the extra page at 4K, but need to fix
@@ -706,7 +707,7 @@
 	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
 #endif
 
-#ifdef __SMP__
+#ifdef CONFIG_X86_IO_APIC
 	/*
 	 *	Save possible boot-time SMP configuration:
 	 */
@@ -1406,8 +1407,8 @@
 	struct cpuinfo_x86 *c = cpu_data;
 	int i, n;
 
-	for(n=0; n<NR_CPUS; n++, c++) {
-#ifdef __SMP__
+	for (n = 0; n < NR_CPUS; n++, c++) {
+#ifdef CONFIG_SMP
 		if (!(cpu_online_map & (1<<n)))
 			continue;
 #endif
@@ -1519,14 +1520,14 @@
 	int nr = smp_processor_id();
 	struct tss_struct * t = &init_tss[nr];
 
-	if (test_and_set_bit(nr,&cpu_initialized)) {
+	if (test_and_set_bit(nr, &cpu_initialized)) {
 		printk("CPU#%d already initialized!\n", nr);
 		for (;;) __sti();
 	}
 	cpus_initialized++;
 	printk("Initializing CPU#%d\n", nr);
 
-	if (boot_cpu_data.x86_capability & X86_FEATURE_PSE)
+	if (cpu_has_pse)
 		clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
 
 	__asm__ __volatile__("lgdt %0": "=m" (gdt_descr));
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.3.39/linux/arch/i386/kernel/smp.c	Tue Jan 11 22:31:36 2000
+++ linux/arch/i386/kernel/smp.c	Thu Jan 20 09:51:42 2000
@@ -2,7 +2,7 @@
  *	Intel SMP support routines.
  *
  *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
- *	(c) 1998-99 Ingo Molnar <mingo@redhat.com>
+ *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
  *
  *	This code is released under the GNU public license version 2 or
  *	later.
@@ -11,18 +11,18 @@
 #include <linux/init.h>
 
 #include <linux/mm.h>
-#include <linux/spinlock.h>
-#include <linux/kernel_stat.h>
-#include <linux/smp_lock.h>
 #include <linux/irq.h>
-
 #include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
+
 #include <asm/mtrr.h>
 #include <asm/pgalloc.h>
 
 /*
- *	Some notes on processor bugs:
+ *	Some notes on x86 processor bugs affecting SMP operation:
  *
  *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
  *	The Linux implications for SMP are handled as follows:
@@ -381,7 +381,7 @@
 
 static inline void do_flush_tlb_all_local(void)
 {
-	local_flush_tlb();
+	__flush_tlb_all();
 	if (!current->mm && current->active_mm) {
 		unsigned long cpu = smp_processor_id();
 
@@ -448,7 +448,6 @@
 	struct call_data_struct data;
 	int ret, cpus = smp_num_cpus-1;
 	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
-	unsigned long timeout;
 
 	if(cpus == 0)
 		return 0;
@@ -550,430 +549,5 @@
 	(*func)(info);
 	if (wait)
 		atomic_inc(&call_data->finished);
-}
-
-/*
- * This interrupt should _never_ happen with our APIC/SMP architecture
- */
-asmlinkage void smp_spurious_interrupt(void)
-{
-	ack_APIC_irq();
-	/* see sw-dev-man vol 3, chapter 7.4.13.5 */
-	printk("spurious APIC interrupt on CPU#%d, should never happen.\n",
-			smp_processor_id());
-}
-
-/*
- * This interrupt should never happen with our APIC/SMP architecture
- */
-
-static spinlock_t err_lock = SPIN_LOCK_UNLOCKED;
-
-asmlinkage void smp_error_interrupt(void)
-{
-	unsigned long v;
-
-	spin_lock(&err_lock);
-
-	v = apic_read(APIC_ESR);
-	printk("APIC error interrupt on CPU#%d, should never happen.\n",
-			smp_processor_id());
-	printk("... APIC ESR0: %08lx\n", v);
-
-	apic_write(APIC_ESR, 0);
-	v |= apic_read(APIC_ESR);
-	printk("... APIC ESR1: %08lx\n", v);
-	/*
-	 * Be a bit more verbose. (multiple bits can be set)
-	 */
-	if (v & 0x01)
-		printk("... bit 0: APIC Send CS Error (hw problem).\n");
-	if (v & 0x02)
-		printk("... bit 1: APIC Receive CS Error (hw problem).\n");
-	if (v & 0x04)
-		printk("... bit 2: APIC Send Accept Error.\n");
-	if (v & 0x08)
-		printk("... bit 3: APIC Receive Accept Error.\n");
-	if (v & 0x10)
-		printk("... bit 4: Reserved!.\n");
-	if (v & 0x20)
-		printk("... bit 5: Send Illegal Vector (kernel bug).\n");
-	if (v & 0x40)
-		printk("... bit 6: Received Illegal Vector.\n");
-	if (v & 0x80)
-		printk("... bit 7: Illegal Register Address.\n");
-
-	ack_APIC_irq();
-
-	irq_err_count++;
-
-	spin_unlock(&err_lock);
-}
-
-/*
- * This part sets up the APIC 32 bit clock in LVTT1, with HZ interrupts
- * per second. We assume that the caller has already set up the local
- * APIC.
- *
- * The APIC timer is not exactly sync with the external timer chip, it
- * closely follows bus clocks.
- */
-
-int prof_multiplier[NR_CPUS] = { 1, };
-int prof_old_multiplier[NR_CPUS] = { 1, };
-int prof_counter[NR_CPUS] = { 1, };
-
-/*
- * The timer chip is already set up at HZ interrupts per second here,
- * but we do not accept timer interrupts yet. We only allow the BP
- * to calibrate.
- */
-static unsigned int __init get_8254_timer_count(void)
-{
-	extern rwlock_t xtime_lock;
-	unsigned long flags;
-
-	unsigned int count;
-
-	write_lock_irqsave(&xtime_lock, flags);
-
-	outb_p(0x00, 0x43);
-	count = inb_p(0x40);
-	count |= inb_p(0x40) << 8;
-
-	write_unlock_irqrestore(&xtime_lock, flags);
-
-	return count;
-}
-
-void __init wait_8254_wraparound(void)
-{
-	unsigned int curr_count, prev_count=~0;
-	int delta;
-
-	curr_count = get_8254_timer_count();
-
-	do {
-		prev_count = curr_count;
-		curr_count = get_8254_timer_count();
-		delta = curr_count-prev_count;
-
-	/*
-	 * This limit for delta seems arbitrary, but it isn't, it's
-	 * slightly above the level of error a buggy Mercury/Neptune
-	 * chipset timer can cause.
-	 */
-
-	} while (delta<300);
-}
-
-/*
- * This function sets up the local APIC timer, with a timeout of
- * 'clocks' APIC bus clock. During calibration we actually call
- * this function twice on the boot CPU, once with a bogus timeout
- * value, second time for real. The other (noncalibrating) CPUs
- * call this function only once, with the real, calibrated value.
- *
- * We do reads before writes even if unnecessary, to get around the
- * P5 APIC double write bug.
- */
-
-#define APIC_DIVISOR 16
-
-void __setup_APIC_LVTT(unsigned int clocks)
-{
-	unsigned int lvtt1_value, tmp_value;
-
-	tmp_value = apic_read(APIC_LVTT);
-	lvtt1_value = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) |
-			APIC_LVT_TIMER_PERIODIC | LOCAL_TIMER_VECTOR;
-	apic_write(APIC_LVTT, lvtt1_value);
-
-	/*
-	 * Divide PICLK by 16
-	 */
-	tmp_value = apic_read(APIC_TDCR);
-	apic_write(APIC_TDCR, (tmp_value
-				& ~(APIC_TDR_DIV_1 | APIC_TDR_DIV_TMBASE))
-				| APIC_TDR_DIV_16);
-
-	tmp_value = apic_read(APIC_TMICT);
-	apic_write(APIC_TMICT, clocks/APIC_DIVISOR);
-}
-
-void setup_APIC_timer(void * data)
-{
-	unsigned int clocks = (unsigned int) data, slice, t0, t1, nr;
-	unsigned long flags;
-	int delta;
-
-	__save_flags(flags);
-	__sti();
-	/*
-	 * ok, Intel has some smart code in their APIC that knows
-	 * if a CPU was in 'hlt' lowpower mode, and this increases
-	 * its APIC arbitration priority. To avoid the external timer
-	 * IRQ APIC event being in synchron with the APIC clock we
-	 * introduce an interrupt skew to spread out timer events.
-	 *
-	 * The number of slices within a 'big' timeslice is smp_num_cpus+1
-	 */
-
-	slice = clocks / (smp_num_cpus+1);
-	nr = cpu_number_map[smp_processor_id()] + 1;
-	printk("cpu: %d, clocks: %d, slice: %d, nr: %d.\n",
-		smp_processor_id(), clocks, slice, nr);
-	/*
-	 * Wait for IRQ0's slice:
-	 */
-	wait_8254_wraparound();
-
-	__setup_APIC_LVTT(clocks);
-
-	t0 = apic_read(APIC_TMCCT)*APIC_DIVISOR;
-	do {
-		t1 = apic_read(APIC_TMCCT)*APIC_DIVISOR;
-		delta = (int)(t0 - t1 - slice*nr);
-	} while (delta < 0);
-
-	__setup_APIC_LVTT(clocks);
-
-	printk("CPU%d<C0:%d,C:%d,D:%d,S:%d,C:%d>\n",
-			smp_processor_id(), t0, t1, delta, slice, clocks);
-
-	__restore_flags(flags);
-}
-
-/*
- * In this function we calibrate APIC bus clocks to the external
- * timer. Unfortunately we cannot use jiffies and the timer irq
- * to calibrate, since some later bootup code depends on getting
- * the first irq? Ugh.
- *
- * We want to do the calibration only once since we
- * want to have local timer irqs syncron. CPUs connected
- * by the same APIC bus have the very same bus frequency.
- * And we want to have irqs off anyways, no accidental
- * APIC irq that way.
- */
-
-int __init calibrate_APIC_clock(void)
-{
-	unsigned long long t1 = 0, t2 = 0;
-	long tt1, tt2;
-	long result;
-	int i;
-	const int LOOPS = HZ/10;
-
-	printk("calibrating APIC timer ... ");
-
-	/*
-	 * Put whatever arbitrary (but long enough) timeout
-	 * value into the APIC clock, we just want to get the
-	 * counter running for calibration.
-	 */
-	__setup_APIC_LVTT(1000000000);
-
-	/*
-	 * The timer chip counts down to zero. Let's wait
-	 * for a wraparound to start exact measurement:
-	 * (the current tick might have been already half done)
-	 */
-
-	wait_8254_wraparound();
-
-	/*
-	 * We wrapped around just now. Let's start:
-	 */
-	if (cpu_has_tsc)
-		rdtscll(t1);
-	tt1 = apic_read(APIC_TMCCT);
-
-	/*
-	 * Let's wait LOOPS wraprounds:
-	 */
-	for (i = 0; i < LOOPS; i++)
-		wait_8254_wraparound();
-
-	tt2 = apic_read(APIC_TMCCT);
-	if (cpu_has_tsc)
-		rdtscll(t2);
-
-	/*
-	 * The APIC bus clock counter is 32 bits only, it
-	 * might have overflown, but note that we use signed
-	 * longs, thus no extra care needed.
-	 *
-	 * underflown to be exact, as the timer counts down ;)
-	 */
-
-	result = (tt1-tt2)*APIC_DIVISOR/LOOPS;
-
-	if (cpu_has_tsc)
-		printk("\n..... CPU clock speed is %ld.%04ld MHz.\n",
-			((long)(t2-t1)/LOOPS)/(1000000/HZ),
-			((long)(t2-t1)/LOOPS)%(1000000/HZ));
-
-	printk("..... host bus clock speed is %ld.%04ld MHz.\n",
-		result/(1000000/HZ),
-		result%(1000000/HZ));
-
-	return result;
-}
-
-static unsigned int calibration_result;
-
-void __init setup_APIC_clocks(void)
-{
-	__cli();
-
-	calibration_result = calibrate_APIC_clock();
-	/*
-	 * Now set up the timer for real.
-	 */
-	setup_APIC_timer((void *)calibration_result);
-
-	__sti();
-
-	/* and update all other cpus */
-	smp_call_function(setup_APIC_timer, (void *)calibration_result, 1, 1);
-}
-
-/*
- * the frequency of the profiling timer can be changed
- * by writing a multiplier value into /proc/profile.
- */
-int setup_profiling_timer(unsigned int multiplier)
-{
-	int i;
-
-	/*
-	 * Sanity check. [at least 500 APIC cycles should be
-	 * between APIC interrupts as a rule of thumb, to avoid
-	 * irqs flooding us]
-	 */
-	if ( (!multiplier) || (calibration_result/multiplier < 500))
-		return -EINVAL;
-
-	/* 
-	 * Set the new multiplier for each CPU. CPUs don't start using the
-	 * new values until the next timer interrupt in which they do process
-	 * accounting. At that time they also adjust their APIC timers
-	 * accordingly.
-	 */
-	for (i = 0; i < NR_CPUS; ++i)
-		prof_multiplier[i] = multiplier;
-
-	return 0;
-}
-
-#undef APIC_DIVISOR
-
-/*
- * Local timer interrupt handler. It does both profiling and
- * process statistics/rescheduling.
- *
- * We do profiling in every local tick, statistics/rescheduling
- * happen only every 'profiling multiplier' ticks. The default
- * multiplier is 1 and it can be changed by writing the new multiplier
- * value into /proc/profile.
- */
-
-inline void smp_local_timer_interrupt(struct pt_regs * regs)
-{
-	int user = (user_mode(regs) != 0);
-	int cpu = smp_processor_id();
-
-	/*
-	 * The profiling function is SMP safe. (nothing can mess
-	 * around with "current", and the profiling counters are
-	 * updated with atomic operations). This is especially
-	 * useful with a profiling multiplier != 1
-	 */
-	if (!user)
-		x86_do_profile(regs->eip);
-
-	if (--prof_counter[cpu] <= 0) {
-		int system = 1 - user;
-		struct task_struct * p = current;
-
-		/*
-		 * The multiplier may have changed since the last time we got
-		 * to this point as a result of the user writing to
-		 * /proc/profile. In this case we need to adjust the APIC
-		 * timer accordingly.
-		 *
-		 * Interrupts are already masked off at this point.
-		 */
-		prof_counter[cpu] = prof_multiplier[cpu];
-		if (prof_counter[cpu] != prof_old_multiplier[cpu]) {
-			__setup_APIC_LVTT(calibration_result/prof_counter[cpu]);
-			prof_old_multiplier[cpu] = prof_counter[cpu];
-		}
-
-		/*
-		 * After doing the above, we need to make like
-		 * a normal interrupt - otherwise timer interrupts
-		 * ignore the global interrupt lock, which is the
-		 * WrongThing (tm) to do.
-		 */
-
- 		irq_enter(cpu, 0);
-		update_one_process(p, 1, user, system, cpu);
-		if (p->pid) {
-			p->counter -= 1;
-			if (p->counter <= 0) {
-				p->counter = 0;
-				p->need_resched = 1;
-			}
-			if (p->priority < DEF_PRIORITY) {
-				kstat.cpu_nice += user;
-				kstat.per_cpu_nice[cpu] += user;
-			} else {
-				kstat.cpu_user += user;
-				kstat.per_cpu_user[cpu] += user;
-			}
-			kstat.cpu_system += system;
-			kstat.per_cpu_system[cpu] += system;
-
-		}
-		irq_exit(cpu, 0);
-	}
-
-	/*
-	 * We take the 'long' return path, and there every subsystem
-	 * grabs the apropriate locks (kernel lock/ irq lock).
-	 *
-	 * we might want to decouple profiling from the 'long path',
-	 * and do the profiling totally in assembly.
-	 *
-	 * Currently this isn't too much of an issue (performance wise),
-	 * we can take more than 100K local irqs per second on a 100 MHz P5.
-	 */
-}
-
-/*
- * Local APIC timer interrupt. This is the most natural way for doing
- * local interrupts, but local timer interrupts can be emulated by
- * broadcast interrupts too. [in case the hw doesnt support APIC timers]
- *
- * [ if a single-CPU system runs an SMP kernel then we call the local
- *   interrupt as well. Thus we cannot inline the local irq ... ]
- */
-unsigned int apic_timer_irqs [NR_CPUS] = { 0, };
-
-void smp_apic_timer_interrupt(struct pt_regs * regs)
-{
-	/*
-	 * the NMI deadlock-detector uses this.
-	 */
-	apic_timer_irqs[smp_processor_id()]++;
-
-	/*
-	 * NOTE! We'd better ACK the irq immediately,
-	 * because timer handling can be slow.
-	 */
-	ack_APIC_irq();
-	smp_local_timer_interrupt(regs);
 }
 
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- v2.3.39/linux/arch/i386/kernel/smpboot.c	Tue Jan 11 22:31:36 2000
+++ linux/arch/i386/kernel/smpboot.c	Thu Jan 20 09:51:42 2000
@@ -1,8 +1,8 @@
 /*
- *	Intel MP v1.1/v1.4 specification compliant parsing routines.
+ *	x86 SMP booting functions
  *
  *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
- *	(c) 1998, 1999 Ingo Molnar <mingo@redhat.com>
+ *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
  *
  *	Much of the core SMP work is based on previous work by Thomas Radke, to
  *	whom a great many thanks are extended.
@@ -26,10 +26,8 @@
  *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
  *		Ingo Molnar	:	Added APIC timers, based on code
  *					from Jose Renau
- *		Alan Cox	:	Added EBDA scanning
  *		Ingo Molnar	:	various cleanups and rewrites
  *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
- *	Maciej W. Rozycki	:	Bits for genuine 82489DX timers
  */
 
 #include <linux/config.h>
@@ -51,70 +49,28 @@
 
 /* Setup configured maximum number of CPUs to activate */
 static int max_cpus = -1;
-/* 1 if "noapic" boot option passed */
-int skip_ioapic_setup = 0;
 
 /* Total count of live CPUs */
 int smp_num_cpus = 1;
-/* Internal processor count */
-static unsigned int num_processors = 1;
 
-/* Have we found an SMP box */
-int smp_found_config = 0;
-
-/* Bitmask of physically existing CPUs */
-unsigned long cpu_present_map = 0;
 /* Bitmask of currently online CPUs */
 unsigned long cpu_online_map = 0;
 
-/* which CPU maps to which logical number */
-volatile int cpu_number_map[NR_CPUS];
-/* which logical number maps to which CPU */
-volatile int __cpu_logical_map[NR_CPUS];
+/* which CPU (physical APIC ID) maps to which logical CPU number */
+volatile int x86_apicid_to_cpu[NR_CPUS];
+/* which logical CPU number maps to which CPU (physical APIC ID) */
+volatile int x86_cpu_to_apicid[NR_CPUS];
 
 static volatile unsigned long cpu_callin_map = 0;
 static volatile unsigned long cpu_callout_map = 0;
 
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS];
-/* Processor that is doing the boot up */
-static unsigned int boot_cpu_id = 0;
 
 /* Set when the idlers are all forked */
 int smp_threads_ready = 0;
 
 /*
- * Various Linux-internal data structures created from the
- * MP-table.
- */
-int apic_version [NR_CPUS];
-int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
-extern int nr_ioapics;
-extern struct mpc_config_ioapic mp_ioapics [MAX_IO_APICS];
-extern int mp_irq_entries;
-extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
-extern int mpc_default_type;
-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
-int mp_current_pci_id = 0;
-unsigned long mp_lapic_addr = 0;
-int pic_mode;
-
-extern void cache_APIC_registers (void);
-
-#define SMP_DEBUG 1
-
-#if SMP_DEBUG
-#define dprintk(x...) printk(##x)
-#else
-#define dprintk(x...)
-#endif
-
-/*
- * IA s/w dev Vol 3, Section 7.4
- */
-#define APIC_DEFAULT_PHYS_BASE 0xfee00000
-
-/*
  * Setup routine for controlling SMP activation
  *
  * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
@@ -142,471 +98,6 @@
 __setup("maxcpus=", maxcpus);
 
 /*
- * Intel MP BIOS table parsing routines:
- */
-
-#ifndef CONFIG_X86_VISWS_APIC
-/*
- * Checksum an MP configuration block.
- */
-
-static int __init mpf_checksum(unsigned char *mp, int len)
-{
-	int sum=0;
-	while(len--)
-		sum+=*mp++;
-	return sum&0xFF;
-}
-
-/*
- * Processor encoding in an MP configuration block
- */
-
-static char __init *mpc_family(int family,int model)
-{
-	static char n[32];
-	static char *model_defs[]=
-	{
-		"80486DX","80486DX",
-		"80486SX","80486DX/2 or 80487",
-		"80486SL","80486SX/2",
-		"Unknown","80486DX/2-WB",
-		"80486DX/4","80486DX/4-WB"
-	};
-
-	switch (family) {
-		case 0x04:
-			if (model < 10)
-				return model_defs[model];
-			break;
-
-		case 0x05:
-			return("Pentium(tm)");
-
-		case 0x06:
-			return("Pentium(tm) Pro");
-
-		case 0x0F:
-			if (model == 0x0F)
-				return("Special controller");
-	}
-	sprintf(n,"Unknown CPU [%d:%d]",family, model);
-	return n;
-}
-
-static void __init MP_processor_info (struct mpc_config_processor *m)
-{
-	int ver;
-
-	if (!(m->mpc_cpuflag & CPU_ENABLED))
-		return;
-
-	printk("Processor #%d %s APIC version %d\n",
-		m->mpc_apicid,
-		mpc_family(	(m->mpc_cpufeature & CPU_FAMILY_MASK)>>8 ,
-				(m->mpc_cpufeature & CPU_MODEL_MASK)>>4),
-		m->mpc_apicver);
-
-#ifdef SMP_DEBUG
-	if (m->mpc_featureflag&(1<<0))
-		printk("    Floating point unit present.\n");
-	if (m->mpc_featureflag&(1<<7))
-		printk("    Machine Exception supported.\n");
-	if (m->mpc_featureflag&(1<<8))
-		printk("    64 bit compare & exchange supported.\n");
-	if (m->mpc_featureflag&(1<<9))
-		printk("    Internal APIC present.\n");
-#endif
-
-	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
-		dprintk("    Bootup CPU\n");
-		boot_cpu_id = m->mpc_apicid;
-	} else
-		/* Boot CPU already counted */
-		num_processors++;
-
-	if (m->mpc_apicid > NR_CPUS) {
-		printk("Processor #%d unused. (Max %d processors).\n",
-			m->mpc_apicid, NR_CPUS);
-		return;
-	}
-	ver = m->mpc_apicver;
-
-	cpu_present_map |= (1<<m->mpc_apicid);
-	/*
-	 * Validate version
-	 */
-	if (ver == 0x0) {
-		printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
-		ver = 0x10;
-	}
-	apic_version[m->mpc_apicid] = ver;
-}
-
-static void __init MP_bus_info (struct mpc_config_bus *m)
-{
-	char str[7];
-
-	memcpy(str, m->mpc_bustype, 6);
-	str[6] = 0;
-	dprintk("Bus #%d is %s\n", m->mpc_busid, str);
-
-	if (strncmp(str, "ISA", 3) == 0) {
-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
-	} else {
-	if (strncmp(str, "EISA", 4) == 0) {
-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
-	} else {
-	if (strncmp(str, "PCI", 3) == 0) {
-		mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
-		mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
-		mp_current_pci_id++;
-	} else {
-		printk("Unknown bustype %s\n", str);
-		panic("cannot handle bus - mail to linux-smp@vger.rutgers.edu");
-	} } }
-}
-
-static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
-{
-	if (!(m->mpc_flags & MPC_APIC_USABLE))
-		return;
-
-	printk("I/O APIC #%d Version %d at 0x%lX.\n",
-		m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
-	if (nr_ioapics >= MAX_IO_APICS) {
-		printk("Max # of I/O APICs (%d) exceeded (found %d).\n",
-			MAX_IO_APICS, nr_ioapics);
-		panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
-	}
-	mp_ioapics[nr_ioapics] = *m;
-	nr_ioapics++;
-}
-
-static void __init MP_intsrc_info (struct mpc_config_intsrc *m)
-{
-	mp_irqs [mp_irq_entries] = *m;
-	if (++mp_irq_entries == MAX_IRQ_SOURCES)
-		panic("Max # of irq sources exceeded!!\n");
-}
-
-static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
-{
-	/*
-	 * Well it seems all SMP boards in existence
-	 * use ExtINT/LVT1 == LINT0 and
-	 * NMI/LVT2 == LINT1 - the following check
-	 * will show us if this assumptions is false.
-	 * Until then we do not have to add baggage.
-	 */
-	if ((m->mpc_irqtype == mp_ExtINT) &&
-		(m->mpc_destapiclint != 0))
-			BUG();
-	if ((m->mpc_irqtype == mp_NMI) &&
-		(m->mpc_destapiclint != 1))
-			BUG();
-}
-
-/*
- * Read/parse the MPC
- */
-
-static int __init smp_read_mpc(struct mp_config_table *mpc)
-{
-	char str[16];
-	int count=sizeof(*mpc);
-	unsigned char *mpt=((unsigned char *)mpc)+count;
-
-	if (memcmp(mpc->mpc_signature,MPC_SIGNATURE,4))
-	{
-		panic("SMP mptable: bad signature [%c%c%c%c]!\n",
-			mpc->mpc_signature[0],
-			mpc->mpc_signature[1],
-			mpc->mpc_signature[2],
-			mpc->mpc_signature[3]);
-		return 1;
-	}
-	if (mpf_checksum((unsigned char *)mpc,mpc->mpc_length))
-	{
-		panic("SMP mptable: checksum error!\n");
-		return 1;
-	}
-	if (mpc->mpc_spec!=0x01 && mpc->mpc_spec!=0x04)
-	{
-		printk("Bad Config Table version (%d)!!\n",mpc->mpc_spec);
-		return 1;
-	}
-	memcpy(str,mpc->mpc_oem,8);
-	str[8]=0;
-	printk("OEM ID: %s ",str);
-
-	memcpy(str,mpc->mpc_productid,12);
-	str[12]=0;
-	printk("Product ID: %s ",str);
-
-	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
-
-	/* save the local APIC address, it might be non-default */
-	mp_lapic_addr = mpc->mpc_lapic;
-
-	/*
-	 *	Now process the configuration blocks.
-	 */
-	while (count < mpc->mpc_length) {
-		switch(*mpt) {
-			case MP_PROCESSOR:
-			{
-				struct mpc_config_processor *m=
-					(struct mpc_config_processor *)mpt;
-				MP_processor_info(m);
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
-			case MP_BUS:
-			{
-				struct mpc_config_bus *m=
-					(struct mpc_config_bus *)mpt;
-				MP_bus_info(m);
-				mpt += sizeof(*m);
-				count += sizeof(*m);
-				break;
-			}
-			case MP_IOAPIC:
-			{
-				struct mpc_config_ioapic *m=
-					(struct mpc_config_ioapic *)mpt;
-				MP_ioapic_info(m);
-				mpt+=sizeof(*m);
-				count+=sizeof(*m);
-				break;
-			}
-			case MP_INTSRC:
-			{
-				struct mpc_config_intsrc *m=
-					(struct mpc_config_intsrc *)mpt;
-
-				MP_intsrc_info(m);
-				mpt+=sizeof(*m);
-				count+=sizeof(*m);
-				break;
-			}
-			case MP_LINTSRC:
-			{
-				struct mpc_config_lintsrc *m=
-					(struct mpc_config_lintsrc *)mpt;
-				MP_lintsrc_info(m);
-				mpt+=sizeof(*m);
-				count+=sizeof(*m);
-				break;
-			}
-		}
-	}
-	return num_processors;
-}
-
-/*
- * Scan the memory blocks for an SMP configuration block.
- */
-static int __init smp_get_mpf(struct intel_mp_floating *mpf)
-{
-	printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
-	if (mpf->mpf_feature2 & (1<<7)) {
-		printk("    IMCR and PIC compatibility mode.\n");
-		pic_mode = 1;
-	} else {
-		printk("    Virtual Wire compatibility mode.\n");
-		pic_mode = 0;
-	}
-	smp_found_config = 1;
-	/*
-	 * default CPU id - if it's different in the mptable
-	 * then we change it before first using it.
-	 */
-	boot_cpu_id = 0;
-	/*
-	 * Now see if we need to read further.
-	 */
-	if (mpf->mpf_feature1 != 0) {
-		/*
-		 * local APIC has default address
-		 */
-		mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-
-		/*
-		 * 2 CPUs, numbered 0 & 1.
-		 */
-		cpu_present_map = 3;
-		num_processors = 2;
-
-		nr_ioapics = 1;
-		mp_ioapics[0].mpc_apicaddr = 0xFEC00000;
-		/*
-		 * Save the default type number, we
-		 * need it later to set the IO-APIC
-		 * up properly:
-		 */
-		mpc_default_type = mpf->mpf_feature1;
-
-		printk("Bus #0 is ");
-	}
-
-	switch (mpf->mpf_feature1) {
-		case 1:
-		case 5:
-			printk("ISA\n");
-			break;
-		case 2:
-			printk("EISA with no IRQ0 and no IRQ13 DMA chaining\n");
-			break;
-		case 6:
-		case 3:
-			printk("EISA\n");
-			break;
-		case 4:
-		case 7:
-			printk("MCA\n");
-			break;
-		case 0:
-			if (!mpf->mpf_physptr)
-				BUG();
-			break;
-		default:
-			printk("???\nUnknown standard configuration %d\n",
-				mpf->mpf_feature1);
-			return 1;
-	}
-	if (mpf->mpf_feature1 > 4) {
-		printk("Bus #1 is PCI\n");
-
-		/*
-		 * Set local APIC version to the integrated form.
-		 * It's initialized to zero otherwise, representing
-		 * a discrete 82489DX.
-		 */
-		apic_version[0] = 0x10;
-		apic_version[1] = 0x10;
-	}
-	/*
-	 * Read the physical hardware table. Anything here will override the
-	 * defaults.
-	 */
-	if (mpf->mpf_physptr)
-		smp_read_mpc((void *)mpf->mpf_physptr);
-
-	__cpu_logical_map[0] = boot_cpu_id;
-	global_irq_holder = boot_cpu_id;
-	current->processor = boot_cpu_id;
-
-	printk("Processors: %d\n", num_processors);
-	/*
-	 * Only use the first configuration found.
-	 */
-	return 1;
-}
-
-static int __init smp_scan_config(unsigned long base, unsigned long length)
-{
-	unsigned long *bp = phys_to_virt(base);
-	struct intel_mp_floating *mpf;
-
-	dprintk("Scan SMP from %p for %ld bytes.\n", bp,length);
-	if (sizeof(*mpf) != 16)
-		printk("Error: MPF size\n");
-
-	while (length > 0) {
-		mpf = (struct intel_mp_floating *)bp;
-		if ((*bp == SMP_MAGIC_IDENT) &&
-			(mpf->mpf_length == 1) &&
-			!mpf_checksum((unsigned char *)bp, 16) &&
-			((mpf->mpf_specification == 1)
-				|| (mpf->mpf_specification == 4)) ) {
-
-			printk("found SMP MP-table at %08ld\n",
-						virt_to_phys(mpf));
-			smp_get_mpf(mpf);
-			return 1;
-		}
-		bp += 4;
-		length -= 16;
-	}
-	return 0;
-}
-
-void __init init_intel_smp (void)
-{
-	unsigned int address;
-
-	/*
-	 * FIXME: Linux assumes you have 640K of base ram..
-	 * this continues the error...
-	 *
-	 * 1) Scan the bottom 1K for a signature
-	 * 2) Scan the top 1K of base RAM
-	 * 3) Scan the 64K of bios
-	 */
-	if (smp_scan_config(0x0,0x400) ||
-		smp_scan_config(639*0x400,0x400) ||
-			smp_scan_config(0xF0000,0x10000))
-		return;
-	/*
-	 * If it is an SMP machine we should know now, unless the
-	 * configuration is in an EISA/MCA bus machine with an
-	 * extended bios data area.
-	 *
-	 * there is a real-mode segmented pointer pointing to the
-	 * 4K EBDA area at 0x40E, calculate and scan it here.
-	 *
-	 * NOTE! There are Linux loaders that will corrupt the EBDA
-	 * area, and as such this kind of SMP config may be less
-	 * trustworthy, simply because the SMP table may have been
-	 * stomped on during early boot. These loaders are buggy and
-	 * should be fixed.
-	 */
-
-	address = *(unsigned short *)phys_to_virt(0x40E);
-	address <<= 4;
-	smp_scan_config(address, 0x1000);
-	if (smp_found_config)
-		printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");
-}
-
-#else
-
-/*
- * The Visual Workstation is Intel MP compliant in the hardware
- * sense, but it doesnt have a BIOS(-configuration table).
- * No problem for Linux.
- */
-void __init init_visws_smp(void)
-{
-	smp_found_config = 1;
-
-	cpu_present_map |= 2; /* or in id 1 */
-	apic_version[1] |= 0x10; /* integrated APIC */
-	apic_version[0] |= 0x10;
-
-	mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
-}
-
-#endif
-
-/*
- * - Intel MP Configuration Table
- * - or SGI Visual Workstation configuration
- */
-void __init init_smp_config (void)
-{
-#ifndef CONFIG_VISWS
-	init_intel_smp();
-#else
-	init_visws_smp();
-#endif
-}
-
-
-
-/*
  * Trampoline 80x86 program as an array.
  */
 
@@ -686,209 +177,12 @@
 	/*
 	 * Lets the callins below out of their loop.
 	 */
-	dprintk("Setting commenced=1, go go go\n");
+	Dprintk("Setting commenced=1, go go go\n");
 
 	wmb();
 	atomic_set(&smp_commenced,1);
 }
 
-extern void __error_in_io_apic_c(void);
-
-
-int get_maxlvt(void)
-{
-	unsigned int v, ver, maxlvt;
-
-	v = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(v);
-	/* 82489DXs do not report # of LVT entries. */
-	maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(v) : 2;
-	return maxlvt;
-}
-
-void disable_local_APIC (void)
-{
-	unsigned long value;
-        int maxlvt;
-
-	/*
-	 * Disable APIC
-	 */
- 	value = apic_read(APIC_SPIV);
- 	value &= ~(1<<8);
- 	apic_write(APIC_SPIV,value);
-
-	/*
-	 * Clean APIC state for other OSs:
-	 */
- 	value = apic_read(APIC_SPIV);
- 	value &= ~(1<<8);
- 	apic_write(APIC_SPIV,value);
-	maxlvt = get_maxlvt();
-	apic_write_around(APIC_LVTT, 0x00010000);
-	apic_write_around(APIC_LVT0, 0x00010000);
-	apic_write_around(APIC_LVT1, 0x00010000);
-	if (maxlvt >= 3)
-		apic_write_around(APIC_LVTERR, 0x00010000);
-	if (maxlvt >= 4)
-		apic_write_around(APIC_LVTPC, 0x00010000);
-}
-
-void __init setup_local_APIC (void)
-{
-	unsigned long value, ver, maxlvt;
-
-	if ((SPURIOUS_APIC_VECTOR & 0x0f) != 0x0f)
-		__error_in_io_apic_c();
-
- 	value = apic_read(APIC_SPIV);
-	/*
-	 * Enable APIC
-	 */
- 	value |= (1<<8);
-
-	/*
-	 * Some unknown Intel IO/APIC (or APIC) errata is biting us with
-	 * certain networking cards. If high frequency interrupts are
-	 * happening on a particular IOAPIC pin, plus the IOAPIC routing
-	 * entry is masked/unmasked at a high rate as well then sooner or
-	 * later IOAPIC line gets 'stuck', no more interrupts are received
-	 * from the device. If focus CPU is disabled then the hang goes
-	 * away, oh well :-(
-	 *
-	 * [ This bug can be reproduced easily with a level-triggered
-	 *   PCI Ne2000 networking cards and PII/PIII processors, dual
-	 *   BX chipset. ]
-	 */
-#if 0
-	/* Enable focus processor (bit==0) */
- 	value &= ~(1<<9);
-#else
-	/* Disable focus processor (bit==1) */
-	value |= (1<<9);
-#endif
-	/*
-	 * Set spurious IRQ vector
-	 */
-	value |= SPURIOUS_APIC_VECTOR;
- 	apic_write(APIC_SPIV,value);
-
-	/*
-	 * Set up LVT0, LVT1:
-	 *
-	 * set up through-local-APIC on the BP's LINT0. This is not
-	 * strictly necessery in pure symmetric-IO mode, but sometimes
-	 * we delegate interrupts to the 8259A.
-	 */
-	if (hard_smp_processor_id() == boot_cpu_id) {
-		value = 0x00000700;
-		printk("enabled ExtINT on CPU#%d\n", hard_smp_processor_id());
-	} else {
-		value = 0x00010700;
-		printk("masked ExtINT on CPU#%d\n", hard_smp_processor_id());
-	}
- 	apic_write_around(APIC_LVT0,value);
-
-	/*
-	 * only the BP should see the LINT1 NMI signal, obviously.
-	 */
-	if (hard_smp_processor_id() == boot_cpu_id)
-		value = 0x00000400;		// unmask NMI
-	else
-		value = 0x00010400;		// mask NMI
- 	apic_write_around(APIC_LVT1,value);
-
-	value = apic_read(APIC_LVR);
-	ver = GET_APIC_VERSION(value);
-	if (APIC_INTEGRATED(ver)) {		/* !82489DX */
-		maxlvt = get_maxlvt();
-		/*
-		 * Due to the Pentium erratum 3AP.
-		 */
-		if (maxlvt > 3) {
-			apic_readaround(APIC_SPIV); // not strictly necessery
-			apic_write(APIC_ESR, 0);
-		}
-		value = apic_read(APIC_ESR);
-		printk("ESR value before enabling vector: %08lx\n", value);
-
-		value = apic_read(APIC_LVTERR);
-		value = ERROR_APIC_VECTOR;      // enables sending errors
-		apic_write(APIC_LVTERR,value);
-		/*
-		 * spec says clear errors after enabling vector.
-		 */
-		if (maxlvt != 3) {
-			apic_readaround(APIC_SPIV);
-			apic_write(APIC_ESR, 0);
-		}
-		value = apic_read(APIC_ESR);
-		printk("ESR value after enabling vector: %08lx\n", value);
-	} else
-		printk("No ESR for 82489DX.\n");
-
-	/*
-	 * Set Task Priority to 'accept all'. We never change this
-	 * later on.
-	 */
- 	value = apic_read(APIC_TASKPRI);
- 	value &= ~APIC_TPRI_MASK;
- 	apic_write(APIC_TASKPRI,value);
-
-	/*
-	 * Set up the logical destination ID and put the
-	 * APIC into flat delivery mode.
-	 */
- 	value = apic_read(APIC_LDR);
-	value &= ~APIC_LDR_MASK;
-	value |= (1<<(smp_processor_id()+24));
- 	apic_write(APIC_LDR,value);
-
- 	value = apic_read(APIC_DFR);
-	value |= SET_APIC_DFR(0xf);
- 	apic_write(APIC_DFR, value);
-}
-
-void __init init_smp_mappings(void)
-{
-	unsigned long apic_phys;
-
-	if (smp_found_config) {
-		apic_phys = mp_lapic_addr;
-	} else {
-		/*
-		 * set up a fake all zeroes page to simulate the
-		 * local APIC and another one for the IO-APIC. We
-		 * could use the real zero-page, but it's safer
-		 * this way if some buggy code writes to this page ...
-		 */
-		apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-		apic_phys = __pa(apic_phys);
-	}
-	set_fixmap(FIX_APIC_BASE, apic_phys);
-	dprintk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
-
-#ifdef CONFIG_X86_IO_APIC
-	{
-		unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
-		int i;
-
-		for (i = 0; i < nr_ioapics; i++) {
-			if (smp_found_config) {
-				ioapic_phys = mp_ioapics[i].mpc_apicaddr;
-			} else {
-				ioapic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
-				ioapic_phys = __pa(ioapic_phys);
-			}
-			set_fixmap(idx,ioapic_phys);
-			dprintk("mapped IOAPIC to %08lx (%08lx)\n",
-					__fix_to_virt(idx), ioapic_phys);
-			idx++;
-		}
-	}
-#endif
-}
-
 /*
  * TSC synchronization.
  *
@@ -988,20 +282,14 @@
 	}
 
 	sum = 0;
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!(cpu_online_map & (1 << i)))
-			continue;
-
+	for (i = 0; i < smp_num_cpus; i++) {
 		t0 = tsc_values[i];
 		sum += t0;
 	}
 	avg = div64(sum, smp_num_cpus);
 
 	sum = 0;
-	for (i = 0; i < NR_CPUS; i++) {
-		if (!(cpu_online_map & (1 << i)))
-			continue;
-
+	for (i = 0; i < smp_num_cpus; i++) {
 		delta = tsc_values[i] - avg;
 		if (delta < 0)
 			delta = -delta;
@@ -1057,15 +345,20 @@
 
 void __init smp_callin(void)
 {
-	int cpuid;
+	int cpuid, phys_id;
 	unsigned long timeout;
 
 	/*
 	 * (This works even if the APIC is not enabled.)
 	 */
-	cpuid = GET_APIC_ID(apic_read(APIC_ID));
-
-	dprintk("CPU#%d waiting for CALLOUT\n", cpuid);
+	phys_id = GET_APIC_ID(apic_read(APIC_ID));
+	cpuid = current->processor;
+	if (test_and_set_bit(cpuid, &cpu_online_map)) {
+		printk("huh, phys CPU#%d, CPU#%d already present??\n",
+					phys_id, cpuid);
+		BUG();
+	}
+	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
 
 	/*
 	 * STARTUP IPIs are fragile beasts as they might sometimes
@@ -1100,7 +393,7 @@
 	 * boards)
 	 */
 
-	dprintk("CALLIN, before setup_local_APIC().\n");
+	Dprintk("CALLIN, before setup_local_APIC().\n");
 	setup_local_APIC();
 
 	sti();
@@ -1115,7 +408,7 @@
 	 * Get our bogomips.
 	 */
 	calibrate_delay();
-	dprintk("Stack at about %p\n",&cpuid);
+	Dprintk("Stack at about %p\n",&cpuid);
 
 	/*
 	 * Save our processor parameters
@@ -1131,7 +424,7 @@
 	 *      Synchronize the TSC with the BP
 	 */
 	if (cpu_has_tsc)
-		synchronize_tsc_ap ();
+		synchronize_tsc_ap();
 }
 
 int cpucount = 0;
@@ -1196,21 +489,21 @@
 	return do_fork(CLONE_VM|CLONE_PID, 0, &regs);
 }
 
-static void __init do_boot_cpu(int i)
+static void __init do_boot_cpu (int apicid)
 {
 	unsigned long cfg;
 	struct task_struct *idle;
 	unsigned long send_status, accept_status;
-	int timeout, num_starts, j;
+	int timeout, num_starts, j, cpu;
 	unsigned long start_eip;
 
-	cpucount++;
+	cpu = ++cpucount;
 	/*
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
 	 */
 	if (fork_by_hand() < 0)
-		panic("failed fork for CPU %d", i);
+		panic("failed fork for CPU %d", cpu);
 
 	/*
 	 * We remove it from the pidhash and the runqueue
@@ -1218,23 +511,23 @@
 	 */
 	idle = init_task.prev_task;
 	if (!idle)
-		panic("No idle process for CPU %d", i);
+		panic("No idle process for CPU %d", cpu);
 
-	idle->processor = i;
-	__cpu_logical_map[cpucount] = i;
-	cpu_number_map[i] = cpucount;
+	idle->processor = cpu;
+	x86_cpu_to_apicid[cpu] = apicid;
+	x86_apicid_to_cpu[apicid] = cpu;
 	idle->has_cpu = 1; /* we schedule the first task manually */
 	idle->thread.eip = (unsigned long) start_secondary;
 
 	del_from_runqueue(idle);
 	unhash_process(idle);
-	init_tasks[cpucount] = idle;
+	init_tasks[cpu] = idle;
 
 	/* start_eip had better be page-aligned! */
 	start_eip = setup_trampoline();
 
 	/* So we see what's up   */
-	printk("Booting processor %d eip %lx\n", i, start_eip);
+	printk("Booting processor %d eip %lx\n", cpu, start_eip);
 	stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
 
 	/*
@@ -1242,21 +535,20 @@
 	 * the targeted processor.
 	 */
 
-	dprintk("Setting warm reset code and vector.\n");
+	Dprintk("Setting warm reset code and vector.\n");
 
 	CMOS_WRITE(0xa, 0xf);
 	local_flush_tlb();
-	dprintk("1.\n");
+	Dprintk("1.\n");
 	*((volatile unsigned short *) phys_to_virt(0x469)) = start_eip >> 4;
-	dprintk("2.\n");
+	Dprintk("2.\n");
 	*((volatile unsigned short *) phys_to_virt(0x467)) = start_eip & 0xf;
-	dprintk("3.\n");
+	Dprintk("3.\n");
 
 	/*
 	 * Be paranoid about clearing APIC errors.
 	 */
-
-	if (APIC_INTEGRATED(apic_version[i])) {
+	if (APIC_INTEGRATED(apic_version[apicid])) {
 		apic_readaround(APIC_SPIV);
 		apic_write(APIC_ESR, 0);
 		accept_status = (apic_read(APIC_ESR) & 0xEF);
@@ -1272,7 +564,7 @@
 	 * Starting actual IPI sequence...
 	 */
 
-	dprintk("Asserting INIT.\n");
+	Dprintk("Asserting INIT.\n");
 
 	/*
 	 * Turn INIT on
@@ -1283,7 +575,7 @@
 	/*
 	 * Target chip
 	 */
-	apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(i));
+	apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid));
 
 	/*
 	 * Send IPI
@@ -1294,12 +586,12 @@
 	apic_write(APIC_ICR, cfg);
 
 	udelay(200);
-	dprintk("Deasserting INIT.\n");
+	Dprintk("Deasserting INIT.\n");
 
 	/* Target chip */
 	cfg = apic_read(APIC_ICR2);
 	cfg &= 0x00FFFFFF;
-	apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i));
+	apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(apicid));
 
 	/* Send IPI */
 	cfg = apic_read(APIC_ICR);
@@ -1314,8 +606,7 @@
 	 * If we don't have an integrated APIC, don't
 	 * send the STARTUP IPIs.
 	 */
-
-	if (APIC_INTEGRATED(apic_version[i]))
+	if (APIC_INTEGRATED(apic_version[apicid]))
 		num_starts = 2;
 	else
 		num_starts = 0;
@@ -1323,13 +614,14 @@
 	/*
 	 * Run STARTUP IPI loop.
 	 */
+	Dprintk("#startup loops: %d.\n", num_starts);
 
 	for (j = 1; j <= num_starts; j++) {
-		dprintk("Sending STARTUP #%d.\n",j);
+		Dprintk("Sending STARTUP #%d.\n",j);
 		apic_readaround(APIC_SPIV);
 		apic_write(APIC_ESR, 0);
 		apic_read(APIC_ESR);
-		dprintk("After apic_write.\n");
+		Dprintk("After apic_write.\n");
 
 		/*
 		 * STARTUP IPI
@@ -1338,7 +630,7 @@
 		/* Target chip */
 		cfg = apic_read(APIC_ICR2);
 		cfg &= 0x00FFFFFF;
-		apic_write(APIC_ICR2, cfg|SET_APIC_DEST_FIELD(i));
+		apic_write(APIC_ICR2, cfg | SET_APIC_DEST_FIELD(apicid));
 
 		/* Boot on the stack */
 		cfg = apic_read(APIC_ICR);
@@ -1348,12 +640,12 @@
 		/* Kick the second */
 		apic_write(APIC_ICR, cfg);
 
-		dprintk("Startup point 1.\n");
+		Dprintk("Startup point 1.\n");
 
-		dprintk("Waiting for send to finish...\n");
+		Dprintk("Waiting for send to finish...\n");
 		timeout = 0;
 		do {
-			dprintk("+");
+			Dprintk("+");
 			udelay(100);
 			send_status = apic_read(APIC_ICR) & 0x1000;
 		} while (send_status && (timeout++ < 1000));
@@ -1366,7 +658,7 @@
 		if (send_status || accept_status)
 			break;
 	}
-	dprintk("After Startup.\n");
+	Dprintk("After Startup.\n");
 
 	if (send_status)
 		printk("APIC never delivered???\n");
@@ -1377,24 +669,24 @@
 		/*
 		 * allow APs to start initializing.
 		 */
-		dprintk("Before Callout %d.\n", i);
-		set_bit(i, &cpu_callout_map);
-		dprintk("After Callout %d.\n", i);
+		Dprintk("Before Callout %d.\n", cpu);
+		set_bit(cpu, &cpu_callout_map);
+		Dprintk("After Callout %d.\n", cpu);
 
 		/*
 		 * Wait 5s total for a response
 		 */
-		for (timeout = 0; timeout < 50000; timeout++) {
-			if (test_bit(i, &cpu_callin_map))
+		for (timeout = 0; timeout < 1000000000; timeout++) {
+			if (test_bit(cpu, &cpu_callin_map))
 				break;	/* It has booted */
 			udelay(100);
 		}
 
-		if (test_bit(i, &cpu_callin_map)) {
+		if (test_bit(cpu, &cpu_callin_map)) {
 			/* number CPUs logically, starting from 1 (BSP is 0) */
-			printk("OK.\n");
-			printk("CPU%d: ", i);
-			print_cpu_info(&cpu_data[i]);
+			Dprintk("OK.\n");
+			printk("CPU%d: ", cpu);
+			print_cpu_info(&cpu_data[cpu]);
 		} else {
 			if (*((volatile unsigned char *)phys_to_virt(8192))
 					== 0xA5) /* trampoline code not run */
@@ -1402,10 +694,10 @@
 			else
 				printk("CPU booted but not responding.\n");
 		}
-		dprintk("CPU has booted.\n");
+		Dprintk("CPU has booted.\n");
 	} else {
-		__cpu_logical_map[cpucount] = -1;
-		cpu_number_map[i] = -1;
+		x86_cpu_to_apicid[cpu] = -1;
+		x86_apicid_to_cpu[apicid] = -1;
 		cpucount--;
 	}
 
@@ -1460,7 +752,7 @@
 
 void __init smp_boot_cpus(void)
 {
-	int i;
+	int apicid, cpu;
 
 #ifdef CONFIG_MTRR
 	/*  Must be done before other processors booted  */
@@ -1471,58 +763,63 @@
 	 * and the per-CPU profiling counter/multiplier
 	 */
 
-	for (i = 0; i < NR_CPUS; i++) {
-		cpu_number_map[i] = -1;
-		prof_counter[i] = 1;
-		prof_old_multiplier[i] = 1;
-		prof_multiplier[i] = 1;
+	for (apicid = 0; apicid < NR_CPUS; apicid++) {
+		x86_apicid_to_cpu[apicid] = -1;
+		prof_counter[apicid] = 1;
+		prof_old_multiplier[apicid] = 1;
+		prof_multiplier[apicid] = 1;
 	}
 
 	/*
 	 * Setup boot CPU information
 	 */
-
-	smp_store_cpu_info(boot_cpu_id); /* Final full version of the data */
-	smp_tune_scheduling();
-	printk("CPU%d: ", boot_cpu_id);
-	print_cpu_info(&cpu_data[boot_cpu_id]);
+	smp_store_cpu_info(0); /* Final full version of the data */
+	printk("CPU%d: ", 0);
+	print_cpu_info(&cpu_data[0]);
 
 	/*
-	 * not necessary because the MP table should list the boot
-	 * CPU too, but we do it for the sake of robustness anyway.
-	 * (and for the case when a non-SMP board boots an SMP kernel)
-	 */
-	cpu_present_map |= (1 << hard_smp_processor_id());
-
-	cpu_number_map[boot_cpu_id] = 0;
-
+	 * We have the boot CPU online for sure.
+	 */
+	set_bit(0, &cpu_online_map);
+	x86_apicid_to_cpu[boot_cpu_id] = 0;
+	x86_cpu_to_apicid[0] = boot_cpu_id;
+	global_irq_holder = 0;
+	current->processor = 0;
 	init_idle();
+	smp_tune_scheduling();
 
 	/*
 	 * If we couldnt find an SMP configuration at boot time,
 	 * get out of here now!
 	 */
-
 	if (!smp_found_config) {
 		printk(KERN_NOTICE "SMP motherboard not detected. Using dummy APIC emulation.\n");
 #ifndef CONFIG_VISWS
 		io_apic_irqs = 0;
 #endif
-		cpu_online_map = cpu_present_map;
+		cpu_online_map = phys_cpu_present_map = 1;
 		smp_num_cpus = 1;
 		goto smp_done;
 	}
 
 	/*
-	 * If SMP should be disabled, then really disable it!
+	 * Should not be necessary because the MP table should list the boot
+	 * CPU too, but we do it for the sake of robustness anyway.
 	 */
+	if (!test_bit(boot_cpu_id, &phys_cpu_present_map)) {
+		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
+								 boot_cpu_id);
+		phys_cpu_present_map |= (1 << hard_smp_processor_id());
+	}
 
+	/*
+	 * If SMP should be disabled, then really disable it!
+	 */
 	if (!max_cpus) {
 		smp_found_config = 0;
 		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
 	}
 
-#ifdef SMP_DEBUG
 	{
 		int reg;
 
@@ -1534,11 +831,11 @@
 		 */
 
 		reg = apic_read(APIC_LVR);
-		dprintk("Getting VERSION: %x\n", reg);
+		Dprintk("Getting VERSION: %x\n", reg);
 
 		apic_write(APIC_LVR, 0);
 		reg = apic_read(APIC_LVR);
-		dprintk("Getting VERSION: %x\n", reg);
+		Dprintk("Getting VERSION: %x\n", reg);
 
 		/*
 		 * The two version reads above should print the same
@@ -1551,14 +848,12 @@
 		 * compatibility mode, but most boxes are anymore.
 		 */
 
-
 		reg = apic_read(APIC_LVT0);
-		dprintk("Getting LVT0: %x\n", reg);
+		Dprintk("Getting LVT0: %x\n", reg);
 
 		reg = apic_read(APIC_LVT1);
-		dprintk("Getting LVT1: %x\n", reg);
+		Dprintk("Getting LVT1: %x\n", reg);
 	}
-#endif
 
 	setup_local_APIC();
 
@@ -1568,42 +863,33 @@
 	/*
 	 * Now scan the CPU present map and fire up the other CPUs.
 	 */
+	Dprintk("CPU present map: %lx\n", phys_cpu_present_map);
 
-	/*
-	 * Add all detected CPUs. (later on we can down individual
-	 * CPUs which will change cpu_online_map but not necessarily
-	 * cpu_present_map. We are pretty much ready for hot-swap CPUs.)
-	 */
-	cpu_online_map = cpu_present_map;
-	mb();
-
-	dprintk("CPU map: %lx\n", cpu_present_map);
-
-	for (i = 0; i < NR_CPUS; i++) {
+	for (apicid = 0; apicid < NR_CPUS; apicid++) {
 		/*
 		 * Don't even attempt to start the boot CPU!
 		 */
-		if (i == boot_cpu_id)
+		if (apicid == boot_cpu_id)
 			continue;
 
-		if ((cpu_online_map & (1 << i))
-		    && (max_cpus < 0 || max_cpus > cpucount+1)) {
-			do_boot_cpu(i);
-		}
+		if (!(phys_cpu_present_map & (1 << apicid)))
+			continue;
+		if ((max_cpus >= 0) && (max_cpus < cpucount+1))
+			continue;
+
+		do_boot_cpu(apicid);
 
 		/*
 		 * Make sure we unmap all failed CPUs
 		 */
-		if (cpu_number_map[i] == -1 && (cpu_online_map & (1 << i))) {
-			printk("CPU #%d not responding - cannot use it.\n",i);
-			cpu_online_map &= ~(1 << i);
-		}
+		if ((x86_apicid_to_cpu[apicid] == -1) &&
+				(phys_cpu_present_map & (1 << apicid)))
+			printk("phys CPU #%d not responding - cannot use it.\n",apicid);
 	}
 
 	/*
 	 * Cleanup possible dangling ends...
 	 */
-
 #ifndef CONFIG_VISWS
 	{
 		/*
@@ -1625,26 +911,25 @@
 	 * Allow the user to impress friends.
 	 */
 
-	dprintk("Before bogomips.\n");
+	Dprintk("Before bogomips.\n");
 	if (!cpucount) {
 		printk(KERN_ERR "Error: only one processor found.\n");
-		cpu_online_map = (1<<hard_smp_processor_id());
 	} else {
 		unsigned long bogosum = 0;
-		for(i = 0; i < 32; i++)
-			if (cpu_online_map&(1<<i))
-				bogosum+=cpu_data[i].loops_per_sec;
+		for (cpu = 0; cpu < NR_CPUS; cpu++)
+			if (cpu_online_map & (1<<cpu))
+				bogosum += cpu_data[cpu].loops_per_sec;
 		printk(KERN_INFO "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 			cpucount+1,
 			(bogosum+2500)/500000,
 			((bogosum+2500)/5000)%100);
-		dprintk("Before bogocount - setting activated=1.\n");
+		Dprintk("Before bogocount - setting activated=1.\n");
 	}
 	smp_num_cpus = cpucount + 1;
 
 	if (smp_b_stepping)
 		printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
-	dprintk("Boot done.\n");
+	Dprintk("Boot done.\n");
 
 	cache_APIC_registers();
 #ifndef CONFIG_VISWS
@@ -1657,12 +942,6 @@
 #endif
 
 smp_done:
-	/*
-	 * now we know the other CPUs have fired off and we know our
-	 * APIC ID, so we can go init the TSS and stuff:
-	 */
-	cpu_init();
-
 	/*
 	 * Set up all local APIC timers in the system:
 	 */
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.3.39/linux/arch/i386/kernel/time.c	Wed Dec  8 14:11:25 1999
+++ linux/arch/i386/kernel/time.c	Thu Jan 20 09:51:42 2000
@@ -42,12 +42,14 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 
-#include <asm/processor.h>
-#include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/smp.h>
 #include <asm/irq.h>
-#include <asm/delay.h>
 #include <asm/msr.h>
+#include <asm/delay.h>
+#include <asm/mpspec.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
 
 #include <linux/mc146818rtc.h>
 #include <linux/timex.h>
@@ -368,7 +370,7 @@
  * profiling, except when we simulate SMP mode on a uniprocessor
  * system, in that case we have to call the local interrupt handler.
  */
-#ifndef __SMP__
+#ifndef CONFIG_X86_LOCAL_APIC
 	if (!user_mode(regs))
 		x86_do_profile(regs->eip);
 #else
diff -u --recursive --new-file v2.3.39/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.3.39/linux/arch/i386/kernel/traps.c	Tue Dec 14 01:27:23 1999
+++ linux/arch/i386/kernel/traps.c	Thu Jan 20 09:51:42 2000
@@ -138,7 +138,7 @@
 	unsigned short ss;
 	unsigned long *stack, addr, module_start, module_end;
 
-	esp = (unsigned long) (1+regs);
+	esp = (unsigned long) (&regs->esp);
 	ss = __KERNEL_DS;
 	if (regs->xcs & 3) {
 		in_kernel = 0;
@@ -337,7 +337,7 @@
 
 atomic_t nmi_counter[NR_CPUS];
 
-#if CONFIG_SMP
+#if CONFIG_X86_IO_APIC
 
 int nmi_watchdog = 1;
 
@@ -388,7 +388,12 @@
 		alert_counter[cpu]++;
 		if (alert_counter[cpu] == 5*HZ) {
 			spin_lock(&nmi_print_lock);
-			console_lock.lock = 0;	// we are in trouble anyway
+			/*
+			 * We are in trouble anyway, lets at least try
+			 * to get a message out.
+			 */
+			spin_trylock(&console_lock);
+			spin_unlock(&console_lock);
 			printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu);
 			show_registers(regs);
 			printk("console shuts up ...\n");
@@ -409,7 +414,7 @@
 
 	atomic_inc(nmi_counter+smp_processor_id());
 	if (!(reason & 0xc0)) {
-#if CONFIG_SMP
+#if CONFIG_X86_IO_APIC
 		/*
 		 * Ok, so this is none of the documented NMI sources,
 		 * so it must be the NMI watchdog.
@@ -600,7 +605,10 @@
 	pte = pte_offset(pmd, page);
 	__free_page(pte_page(*pte));
 	*pte = mk_pte_phys(__pa(&idt_table), PAGE_KERNEL_RO);
-	local_flush_tlb();
+	/*
+	 * Not that any PGE-capable kernel should have the f00f bug ...
+	 */
+	__flush_tlb_all();
 
 	/*
 	 * "idt" is magic - it overlaps the idt_descr
@@ -806,13 +814,9 @@
 	set_call_gate(&default_ldt[4],lcall27);
 
 	/*
-	 * on SMP we do not yet know which CPU is on which TSS,
-	 * so we delay this until smp_init(). (the CPU is already
-	 * in a reasonable state, otherwise we wouldnt have gotten so far :)
+	 * Should be a barrier for any external CPU state.
 	 */
-#ifndef __SMP__
 	cpu_init();
-#endif
 
 #ifdef CONFIG_X86_VISWS_APIC
 	superio_init();
diff -u --recursive --new-file v2.3.39/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.3.39/linux/arch/i386/mm/fault.c	Tue Nov 23 22:42:20 1999
+++ linux/arch/i386/mm/fault.c	Thu Jan 20 09:51:42 2000
@@ -16,6 +16,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -76,7 +77,7 @@
 	return 0;
 }
 
-static inline void handle_wp_test (void)
+static void __init handle_wp_test (void)
 {
 	const unsigned long vaddr = PAGE_OFFSET;
 	pgd_t *pgd;
@@ -91,7 +92,7 @@
 	pmd = pmd_offset(pgd, vaddr);
 	pte = pte_offset(pmd, vaddr);
 	*pte = mk_pte_phys(0, PAGE_KERNEL);
-	local_flush_tlb();
+	__flush_tlb_all();
 
 	boot_cpu_data.wp_works_ok = 1;
 	/*
@@ -123,6 +124,7 @@
 	unsigned long page;
 	unsigned long fixup;
 	int write;
+	int si_code = SEGV_MAPERR;
 
 	/* get the address */
 	__asm__("movl %%cr2,%0":"=r" (address));
@@ -164,6 +166,8 @@
  */
 good_area:
 	write = 0;
+	si_code = SEGV_ACCERR;
+
 	switch (error_code & 3) {
 		default:	/* 3: write, present */
 #ifdef TEST_VERIFY_AREA
@@ -216,10 +220,14 @@
 
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & 4) {
+		struct siginfo si;
 		tsk->thread.cr2 = address;
 		tsk->thread.error_code = error_code;
 		tsk->thread.trap_no = 14;
-		force_sig(SIGSEGV, tsk);
+		si.si_signo = SIGSEGV;
+		si.si_code = si_code;
+		si.si_addr = (void*) address;
+		force_sig_info(SIGSEGV, &si, tsk);
 		return;
 	}
 
diff -u --recursive --new-file v2.3.39/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.3.39/linux/arch/i386/mm/init.c	Tue Dec  7 09:32:41 1999
+++ linux/arch/i386/mm/init.c	Thu Jan 20 09:51:42 2000
@@ -34,6 +34,7 @@
 #include <asm/dma.h>
 #include <asm/fixmap.h>
 #include <asm/e820.h>
+#include <asm/apic.h>
 
 unsigned long highstart_pfn, highend_pfn;
 static unsigned long totalram_pages = 0;
@@ -194,8 +195,6 @@
 	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
 
 	kmap_prot = PAGE_KERNEL;
-	if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
-		pgprot_val(kmap_prot) |= _PAGE_GLOBAL;
 }
 #endif
 
@@ -239,7 +238,8 @@
 extern char _text, _etext, _edata, __bss_start, _end;
 extern char __init_begin, __init_end;
 
-static void set_pte_phys (unsigned long vaddr, unsigned long phys)
+static inline void set_pte_phys (unsigned long vaddr,
+			unsigned long phys, pgprot_t flags)
 {
 	pgprot_t prot;
 	pgd_t *pgd;
@@ -249,26 +249,25 @@
 	pgd = swapper_pg_dir + __pgd_offset(vaddr);
 	pmd = pmd_offset(pgd, vaddr);
 	pte = pte_offset(pmd, vaddr);
-	prot = PAGE_KERNEL;
-	if (boot_cpu_data.x86_capability & X86_FEATURE_PGE)
-		pgprot_val(prot) |= _PAGE_GLOBAL;
+	pgprot_val(prot) = pgprot_val(PAGE_KERNEL) | pgprot_val(flags);
 	set_pte(pte, mk_pte_phys(phys, prot));
 
 	/*
 	 * It's enough to flush this one mapping.
+	 * (PGE mappings get flushed as well)
 	 */
 	__flush_tlb_one(vaddr);
 }
 
-void set_fixmap (enum fixed_addresses idx, unsigned long phys)
+void __set_fixmap (enum fixed_addresses idx, unsigned long phys, pgprot_t flags)
 {
 	unsigned long address = __fix_to_virt(idx);
 
 	if (idx >= __end_of_fixed_addresses) {
-		printk("Invalid set_fixmap\n");
+		printk("Invalid __set_fixmap\n");
 		return;
 	}
-	set_pte_phys(address,phys);
+	set_pte_phys(address, phys, flags);
 }
 
 static void __init fixrange_init (unsigned long start, unsigned long end, pgd_t *pgd_base)
@@ -439,10 +438,10 @@
 		set_in_cr4(X86_CR4_PAE);
 #endif
 
-	__flush_tlb();
+	__flush_tlb_all();
 
-#ifdef __SMP__
-	init_smp_mappings();
+#ifdef CONFIG_X86_LOCAL_APIC
+	init_apic_mappings();
 #endif
 
 #ifdef CONFIG_HIGHMEM
diff -u --recursive --new-file v2.3.39/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds
--- v2.3.39/linux/arch/i386/vmlinux.lds	Fri Oct 22 13:21:45 1999
+++ linux/arch/i386/vmlinux.lds	Tue Jan 11 14:26:21 2000
@@ -64,6 +64,12 @@
 	}
   _end = . ;
 
+  /* Sections to be discarded */
+  /DISCARD/ : {
+	*(.text.exit)
+	*(.data.exit)
+	}
+
   /* Stabs debugging sections.  */
   .stab 0 : { *(.stab) }
   .stabstr 0 : { *(.stabstr) }
diff -u --recursive --new-file v2.3.39/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c
--- v2.3.39/linux/arch/m68k/atari/stram.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/m68k/atari/stram.c	Tue Jan 18 18:54:20 2000
@@ -1255,6 +1255,8 @@
     blksize_size[STRAM_MAJOR] = stram_blocksizes;
 	stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024;
     blk_size[STRAM_MAJOR] = stram_sizes;
+	register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops,
+			(swap_end-swap_start)>>9);
 	do_z2_request(); /* to avoid warning */
 	return( 0 );
 }
diff -u --recursive --new-file v2.3.39/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.3.39/linux/arch/m68k/config.in	Wed Dec  8 14:11:25 1999
+++ linux/arch/m68k/config.in	Wed Jan 12 09:20:56 2000
@@ -2,6 +2,9 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
+
+define_bool CONFIG_UID16 y
+
 mainmenu_name "Linux/68k Kernel Configuration"
 
 mainmenu_option next_comment
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.3.39/linux/arch/ppc/config.in	Tue Jan 11 22:31:36 2000
+++ linux/arch/ppc/config.in	Sat Jan 15 22:08:29 2000
@@ -2,6 +2,8 @@
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
+define_bool CONFIG_UID16 n
+
 mainmenu_name "Linux/PowerPC Kernel Configuration"
 
 mainmenu_option next_comment
@@ -91,10 +93,9 @@
 fi
 if [ "$CONFIG_8xx" = "y" ]; then
     bool 'QSpan PCI' CONFIG_PCI
-else
-  if [ "$CONFIG_APUS" != "y" ]; then
+fi
+if [ "$CONFIG_6xx" = "y" -a "$CONFIG_APUS" != "y" ]; then
     define_bool CONFIG_PCI y
-  fi
 fi
 
 bool 'Networking support' CONFIG_NET
@@ -112,7 +113,11 @@
 
 source drivers/pci/Config.in
 
-source drivers/pcmcia/Config.in
+bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+
+if [ "$CONFIG_HOTPLUG" = "y" ]; then
+   source drivers/pcmcia/Config.in
+fi
 
 source drivers/parport/Config.in
 
@@ -187,6 +192,8 @@
   source drivers/scsi/Config.in
 fi
 endmenu
+
+source drivers/ieee1394/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
   mainmenu_option next_comment
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig
--- v2.3.39/linux/arch/ppc/configs/common_defconfig	Tue Dec 14 01:27:23 1999
+++ linux/arch/ppc/configs/common_defconfig	Thu Jan 13 11:54:37 2000
@@ -45,11 +45,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_HOTPLUG is not set
 # CONFIG_PARPORT is not set
 CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig
--- v2.3.39/linux/arch/ppc/configs/gemini_defconfig	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/configs/gemini_defconfig	Thu Jan 13 11:54:37 2000
@@ -47,11 +47,7 @@
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_PCI_NAMES is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_HOTPLUG is not set
 # CONFIG_PARPORT is not set
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_FB is not set
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig
--- v2.3.39/linux/arch/ppc/configs/oak_defconfig	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/configs/oak_defconfig	Thu Jan 13 11:54:37 2000
@@ -40,11 +40,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_HOTPLUG is not set
 # CONFIG_PARPORT is not set
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_FB is not set
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/configs/pmac_defconfig linux/arch/ppc/configs/pmac_defconfig
--- v2.3.39/linux/arch/ppc/configs/pmac_defconfig	Tue Dec  7 09:32:41 1999
+++ linux/arch/ppc/configs/pmac_defconfig	Thu Jan 13 11:54:37 2000
@@ -35,6 +35,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 CONFIG_BINFMT_MISC=m
+CONFIG_HOTPLUG=y
 
 #
 # PCMCIA/Cardbus support
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig
--- v2.3.39/linux/arch/ppc/configs/walnut_defconfig	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/configs/walnut_defconfig	Thu Jan 13 11:54:37 2000
@@ -40,11 +40,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_HOTPLUG is not set
 # CONFIG_PARPORT is not set
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_FB is not set
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.39/linux/arch/ppc/defconfig	Tue Dec 14 01:27:23 1999
+++ linux/arch/ppc/defconfig	Sat Jan 15 22:08:29 2000
@@ -35,8 +35,8 @@
 #
 # General setup
 #
+# CONFIG_PCI is not set
 CONFIG_PCI=y
-CONFIG_PCI_NAMES=y
 CONFIG_NET=y
 CONFIG_SYSCTL=y
 CONFIG_SYSVIPC=y
@@ -45,11 +45,7 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_KERNEL_ELF=y
 # CONFIG_BINFMT_MISC is not set
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
+# CONFIG_HOTPLUG is not set
 # CONFIG_PARPORT is not set
 CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- v2.3.39/linux/arch/ppc/kernel/entry.S	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/entry.S	Thu Jan 13 18:03:57 2000
@@ -265,30 +265,20 @@
 	SYNC
 	rfi
 
-/*
- * ret_from_int():
- *
- * Return from an interrupt (external interrupt and
- * decrementer).  This checks the first argument so
- * we know if rtl_intercept wants us to check for
- * a bottom half, signals and so on (normal return) or
- * we're returning from a real-time interrupt or have
- * interrupts soft disabled so we cannot enter Linux.
- *   -- Cort
- */
-	.globl	ret_from_int
-ret_from_int:
-	cmpi	0,r3,0
-	beq	10f
-	/* we're allowed to do signal/bh checks */
-	b	ret_from_syscall
 #ifdef __SMP__	
 	.globl	ret_from_smpfork
 ret_from_smpfork:
 	bl	schedule_tail
+	b	ret_from_except
 #endif
-	.globl	ret_from_syscall
-ret_from_syscall:
+	.globl	ret_from_intercept
+ret_from_intercept:
+	/*
+	 * We may be returning from RTL and cannot do the normal checks
+	 * -- Cort
+	 */
+	cmpi	0,r3,0
+	beq	10f
 	.globl	ret_from_except
 ret_from_except:
 0:	/* disable interrupts */	
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.3.39/linux/arch/ppc/kernel/head.S	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/head.S	Thu Jan 13 18:03:57 2000
@@ -375,7 +375,7 @@
 	.globl do_IRQ_intercept
 do_IRQ_intercept:
 	.long	do_IRQ;
-	.long	ret_from_int
+	.long	ret_from_intercept
 #else
 	bl	apus_interrupt_entry
 #endif /* CONFIG_APUS */
@@ -425,7 +425,7 @@
 	.globl timer_interrupt_intercept
 timer_interrupt_intercept:
 	.long	timer_interrupt
-	.long	ret_from_int
+	.long	ret_from_intercept
 
 	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
 	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/head_4xx.S linux/arch/ppc/kernel/head_4xx.S
--- v2.3.39/linux/arch/ppc/kernel/head_4xx.S	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/head_4xx.S	Thu Jan 13 18:03:58 2000
@@ -266,7 +266,7 @@
 	bl	transfer_to_handler
 _GLOBAL(do_IRQ_intercept)
 	.long	do_IRQ
-	.long	ret_from_except
+	.long	ret_from_intercept
 
 ### 0x0600 - Alignment Exception
 	
@@ -320,7 +320,7 @@
 	bl	transfer_to_handler
 _GLOBAL(timer_interrupt_intercept)
 	.long	timer_interrupt
-	.long	ret_from_except
+	.long	ret_from_intercept
 
 #if 0
 ### 0x1010 - Fixed Interval Timer (FIT) Exception
@@ -474,7 +474,7 @@
 	
 _GLOBAL(abort)
 	mfspr	r13,SPRN_DBCR
-	oris	r13,r13,DBCR_RST(SYSTEM)@h
+	oris	r13,r13,DBCR_RST(DBCR_RST_SYSTEM)@h
 	mtspr	SPRN_DBCR,r13
 
 
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S
--- v2.3.39/linux/arch/ppc/kernel/head_8xx.S	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/head_8xx.S	Thu Jan 13 18:03:58 2000
@@ -266,34 +266,6 @@
 	. = 0x500;
 HardwareInterrupt:
 	EXCEPTION_PROLOG;
-#ifdef CONFIG_APUS
-	/* This is horrible, but there's no way around it. Enable the
-	data cache so the IRQ hardware register can be accessed
-	without cache intervention. Then disable interrupts and get
-	the current emulated m68k IPL value. */
-	
-	mfmsr	20
-	xori	r20,r20,MSR_DR
-	sync
-	mtmsr	r20
-	sync
-
-	lis	r3,APUS_IPL_EMU@h
-
-	li	r20,(IPLEMU_SETRESET|IPLEMU_DISABLEINT)
-	stb	r20,APUS_IPL_EMU@l(r3)
-	eieio
-
-	lbz	r3,APUS_IPL_EMU@l(r3)
-
-	mfmsr	r20
-	xori	r20,r20,MSR_DR
-	sync
-	mtmsr	r20
-	sync
-
-	stw	r3,(_CCR+4)(r21);
-#endif
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	li	r20,MSR_KERNEL
 	li	r4,0
@@ -301,7 +273,7 @@
 	.globl do_IRQ_intercept
 do_IRQ_intercept:
 	.long	do_IRQ;
-	.long	ret_from_except
+	.long	ret_from_intercept
 	
 
 /* Alignment exception */
@@ -343,7 +315,7 @@
 	.globl timer_interrupt_intercept
 timer_interrupt_intercept:
 	.long	timer_interrupt
-	.long	ret_from_except
+	.long	ret_from_intercept
 
 	STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
 	STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/ppc4xx_pic.c linux/arch/ppc/kernel/ppc4xx_pic.c
--- v2.3.39/linux/arch/ppc/kernel/ppc4xx_pic.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/ppc4xx_pic.c	Tue Jan 11 21:49:26 2000
@@ -22,7 +22,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.3.39/linux/arch/ppc/kernel/ppc_ksyms.c	Wed Dec 29 13:13:13 1999
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Sat Jan 15 22:08:29 2000
@@ -260,10 +260,8 @@
 #endif
 
 EXPORT_SYMBOL(int_control);
-#if !defined(CONFIG_4xx)
 EXPORT_SYMBOL(timer_interrupt_intercept);
 EXPORT_SYMBOL(timer_interrupt);
-#endif
 extern unsigned long do_IRQ_intercept;
 EXPORT_SYMBOL(do_IRQ_intercept);
 EXPORT_SYMBOL(irq_desc);
@@ -272,3 +270,4 @@
 EXPORT_SYMBOL(decrementer_count);
 EXPORT_SYMBOL(get_wchan);
 EXPORT_SYMBOL(console_drivers);
+EXPORT_SYMBOL(do_bottom_half);
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.3.39/linux/arch/ppc/kernel/process.c	Tue Jan 11 22:31:37 2000
+++ linux/arch/ppc/kernel/process.c	Thu Jan 13 18:03:58 2000
@@ -292,7 +292,7 @@
 #ifdef __SMP__
 	extern void ret_from_smpfork(void);
 #else
-	extern void ret_from_syscall(void);
+	extern void ret_from_except(void);
 #endif
 	/* Copy registers */
 	childregs = ((struct pt_regs *)
@@ -309,7 +309,7 @@
 #ifdef __SMP__
 	kregs->nip = (unsigned long)ret_from_smpfork;
 #else	
-	kregs->nip = (unsigned long)ret_from_syscall;
+	kregs->nip = (unsigned long)ret_from_except;
 #endif	
 	asm volatile("mfmsr %0" : "=r" (msr):);
 	kregs->msr = msr;
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.3.39/linux/arch/ppc/kernel/setup.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/ppc/kernel/setup.c	Sat Jan 15 22:08:29 2000
@@ -716,25 +716,25 @@
 	id->word72         = __le16_to_cpu(id->word72);
 	id->word73         = __le16_to_cpu(id->word73);
 	id->word74         = __le16_to_cpu(id->word74);
-	id->word75         = __le16_to_cpu(id->word75);
+	id->queue_depth	   = __le16_to_cpu(id->queue_depth);
 	id->word76         = __le16_to_cpu(id->word76);
 	id->word77         = __le16_to_cpu(id->word77);
 	id->word78         = __le16_to_cpu(id->word78);
 	id->word79         = __le16_to_cpu(id->word79);
-	id->word80         = __le16_to_cpu(id->word80);
-	id->word81         = __le16_to_cpu(id->word81);
-	id->command_sets   = __le16_to_cpu(id->command_sets);
-	id->word83         = __le16_to_cpu(id->word83);
-	id->word84         = __le16_to_cpu(id->word84);
-	id->word85         = __le16_to_cpu(id->word85);
-	id->word86         = __le16_to_cpu(id->word86);
-	id->word87         = __le16_to_cpu(id->word87);
+	id->major_rev_num  = __le16_to_cpu(id->major_rev_num);
+	id->minor_rev_num  = __le16_to_cpu(id->minor_rev_num);
+	id->command_set_1  = __le16_to_cpu(id->command_set_1);
+	id->command_set_2  = __le16_to_cpu(id->command_set_2);
+	id->cfsse          = __le16_to_cpu(id->cfsse);
+	id->cfs_enable_1   = __le16_to_cpu(id->cfs_enable_1);
+	id->cfs_enable_2   = __le16_to_cpu(id->cfs_enable_2);
+	id->csf_default    = __le16_to_cpu(id->csf_default);
 	id->dma_ultra      = __le16_to_cpu(id->dma_ultra);
 	id->word89         = __le16_to_cpu(id->word89);
 	id->word90         = __le16_to_cpu(id->word90);
-	id->word91         = __le16_to_cpu(id->word91);
+	id->CurAPMvalues   = __le16_to_cpu(id->CurAPMvalues);
 	id->word92         = __le16_to_cpu(id->word92);
-	id->word93         = __le16_to_cpu(id->word93);
+	id->hw_config      = __le16_to_cpu(id->hw_config);
 	id->word94         = __le16_to_cpu(id->word94);
 	id->word95         = __le16_to_cpu(id->word95);
 	id->word96         = __le16_to_cpu(id->word96);
@@ -769,7 +769,6 @@
 	id->word125        = __le16_to_cpu(id->word125);
 	id->word126        = __le16_to_cpu(id->word126);
 	id->word127        = __le16_to_cpu(id->word127);
-	id->security       = __le16_to_cpu(id->security);
 	for (i=0; i<127; i++)
 	        id->reserved[i] = __le16_to_cpu(id->reserved[i]);
 }
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.3.39/linux/arch/ppc/kernel/smp.c	Mon Dec 20 18:48:21 1999
+++ linux/arch/ppc/kernel/smp.c	Thu Jan 13 18:03:57 2000
@@ -446,6 +446,8 @@
 	 */
 	if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) )
 		do_openpic_setup_cpu();
+	if ( _machine == _MACH_gemini )
+		gemini_init_l2();
 	while(!smp_commenced)
 		barrier();
 	__sti();
diff -u --recursive --new-file v2.3.39/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.3.39/linux/arch/ppc/xmon/xmon.c	Tue Dec  7 09:32:42 1999
+++ linux/arch/ppc/xmon/xmon.c	Thu Jan 13 18:03:57 2000
@@ -469,7 +469,7 @@
 	unsigned sp;
 	unsigned stack[2];
 	struct pt_regs regs;
-	extern char ret_from_int, ret_from_syscall_1, ret_from_syscall_2;
+	extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2;
 	extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
 	extern char ret_from_except;
 
@@ -483,7 +483,7 @@
 		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 			break;
 		printf("%x ", stack[1]);
-		if (stack[1] == (unsigned) &ret_from_int
+		if (stack[1] == (unsigned) &ret_from_intercept
 		    || stack[1] == (unsigned) &ret_from_except
 		    || stack[1] == (unsigned) &ret_from_syscall_1
 		    || stack[1] == (unsigned) &ret_from_syscall_2
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/ap1000/apmmu.c linux/arch/sparc/ap1000/apmmu.c
--- v2.3.39/linux/arch/sparc/ap1000/apmmu.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/sparc/ap1000/apmmu.c	Thu Jan 13 12:03:00 2000
@@ -908,7 +908,6 @@
 				(phys>>12),
 				APMMU_CACHE|APMMU_PRIV|APMMU_VALID);
 	init_mm.mmap->vm_start = PAGE_OFFSET;
-	stack_top = PAGE_OFFSET - PAGE_SIZE;
 }
 
 extern unsigned long free_area_init(unsigned long, unsigned long);
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.3.39/linux/arch/sparc/config.in	Wed Dec 29 13:13:13 1999
+++ linux/arch/sparc/config.in	Sat Jan 15 22:08:28 2000
@@ -1,8 +1,10 @@
-# $Id: config.in,v 1.79 1999/12/23 01:46:00 davem Exp $
+# $Id: config.in,v 1.80 2000/01/14 07:12:30 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
 mainmenu_name "Linux/SPARC Kernel Configuration"
+
+define_bool CONFIG_UID16 y
 
 mainmenu_option next_comment
 comment 'Code maturity level options'
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.3.39/linux/arch/sparc/defconfig	Wed Dec 29 13:13:13 1999
+++ linux/arch/sparc/defconfig	Sat Jan 15 22:08:28 2000
@@ -1,6 +1,7 @@
 #
 # Automatically generated make config: don't edit
 #
+CONFIG_UID16=y
 
 #
 # Code maturity level options
@@ -8,28 +9,25 @@
 CONFIG_EXPERIMENTAL=y
 
 #
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODVERSIONS=y
-CONFIG_KMOD=y
-
-#
 # General setup
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-# CONFIG_AP1000 is not set
 # CONFIG_SMP is not set
+# CONFIG_AP1000 is not set
 # CONFIG_SUN4 is not set
 # CONFIG_PCI is not set
-# CONFIG_PCI_NAMES is not set
 
 #
 # Console drivers
 #
 CONFIG_PROM_CONSOLE=y
 CONFIG_FB=y
+
+#
+# Frame-buffer support
+#
+CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FB_SBUS=y
 CONFIG_FB_CGSIX=y
@@ -67,6 +65,7 @@
 # CONFIG_SUN_VIDEOPIX is not set
 CONFIG_SUN_AURORA=m
 # CONFIG_TADPOLE_TS102_UCTRL is not set
+# CONFIG_SUN_JSFLASH is not set
 
 #
 # Linux/SPARC audio subsystem (EXPERIMENTAL)
@@ -82,7 +81,6 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
@@ -91,9 +89,17 @@
 # CONFIG_PRINTER is not set
 
 #
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODVERSIONS=y
+CONFIG_KMOD=y
+
+#
 # Floppy, IDE, and other block devices
 #
 CONFIG_BLK_DEV_FD=y
+# CONFIG_BLK_DEV_IDE is not set
 CONFIG_BLK_DEV_MD=y
 CONFIG_MD_LINEAR=m
 CONFIG_MD_STRIPED=m
@@ -239,14 +245,15 @@
 # CONFIG_ADFS_FS is not set
 CONFIG_AFFS_FS=m
 # CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 # CONFIG_UMSDOS_FS is not set
 CONFIG_VFAT_FS=m
 CONFIG_EFS_FS=m
+# CONFIG_CRAMFS is not set
 CONFIG_ISO9660_FS=m
 # CONFIG_JOLIET is not set
-# CONFIG_UDF_FS is not set
 CONFIG_MINIX_FS=m
 # CONFIG_NTFS_FS is not set
 CONFIG_HPFS_FS=m
@@ -256,6 +263,8 @@
 CONFIG_ROMFS_FS=m
 CONFIG_EXT2_FS=y
 CONFIG_SYSV_FS=m
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
 CONFIG_UFS_FS=m
 CONFIG_UFS_FS_WRITE=y
 
@@ -265,7 +274,7 @@
 CONFIG_CODA_FS=m
 CONFIG_NFS_FS=y
 CONFIG_NFSD=m
-# CONFIG_NFSD_SUN is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 CONFIG_SMB_FS=m
@@ -275,7 +284,9 @@
 # CONFIG_NCPFS_STRONG is not set
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
 # CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -284,9 +295,6 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-CONFIG_BSD_DISKLABEL=y
-CONFIG_SOLARIS_X86_PARTITION=y
-# CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
 CONFIG_SUN_PARTITION=y
 CONFIG_NLS=y
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.3.39/linux/arch/sparc/kernel/process.c	Tue Jan  4 13:57:16 2000
+++ linux/arch/sparc/kernel/process.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.142 1999/12/27 06:08:31 anton Exp $
+/*  $Id: process.c,v 1.143 2000/01/09 09:13:28 anton Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -502,6 +502,9 @@
 	p->thread.kpsr = current->thread.fork_kpsr;
 #endif
 	p->thread.kwim = current->thread.fork_kwim;
+
+	/* This is used for sun4c only */
+	atomic_set(&p->thread.refcount, 1);
 
 	if(regs->psr & PSR_PS) {
 		extern struct pt_regs fake_swapper_regs;
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.3.39/linux/arch/sparc/kernel/sparc_ksyms.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.85 2000/01/08 16:38:18 anton Exp $
+/* $Id: sparc_ksyms.c,v 1.86 2000/01/09 10:46:49 anton Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -124,10 +124,6 @@
 EXPORT_SYMBOL_NOVERS(___up_write);
 
 EXPORT_SYMBOL(sparc_valid_addr_bitmap);
-
-#ifndef CONFIG_SUN4
-EXPORT_SYMBOL(stack_top);
-#endif
 
 /* Atomic operations. */
 EXPORT_SYMBOL_PRIVATE(_atomic_add);
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/kernel/sunos_asm.S linux/arch/sparc/kernel/sunos_asm.S
--- v2.3.39/linux/arch/sparc/kernel/sunos_asm.S	Fri Dec 13 01:37:31 1996
+++ linux/arch/sparc/kernel/sunos_asm.S	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: sunos_asm.S,v 1.14 1996/12/04 18:25:48 jj Exp $
+/* $Id: sunos_asm.S,v 1.15 2000/01/11 17:33:21 jj Exp $
  * sunos_asm.S: SunOS system calls which must have a low-level
  *              entry point to operate correctly.
  *
@@ -33,10 +33,10 @@
 	/* SunOS getuid() returns uid in %o0 and euid in %o1 */
 	.globl	C_LABEL(sunos_getuid)
 C_LABEL(sunos_getuid):
-	call	C_LABEL(sys_geteuid)
+	call	C_LABEL(sys_geteuid16)
 	 nop
 
-	call	C_LABEL(sys_getuid)
+	call	C_LABEL(sys_getuid16)
 	 st	%o0, [%sp + REGWIN_SZ + PT_I1]
 
 	b	C_LABEL(ret_sys_call)
@@ -45,10 +45,10 @@
 	/* SunOS getgid() returns gid in %o0 and egid in %o1 */
 	.globl	C_LABEL(sunos_getgid)
 C_LABEL(sunos_getgid):
-	call	C_LABEL(sys_getegid)
+	call	C_LABEL(sys_getegid16)
 	 nop
 
-	call	C_LABEL(sys_getgid)
+	call	C_LABEL(sys_getgid16)
 	 st	%o0, [%sp + REGWIN_SZ + PT_I1]
 
 	b	C_LABEL(ret_sys_call)
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/kernel/systbls.S linux/arch/sparc/kernel/systbls.S
--- v2.3.39/linux/arch/sparc/kernel/systbls.S	Wed Dec 29 13:13:13 1999
+++ linux/arch/sparc/kernel/systbls.S	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.88 1999/12/21 14:09:06 jj Exp $
+/* $Id: systbls.S,v 1.90 2000/01/11 17:33:20 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -20,30 +20,30 @@
 sys_call_table:
 /*0*/	.long sys_nis_syscall, sys_exit, sys_fork, sys_read, sys_write
 /*5*/	.long sys_open, sys_close, sys_wait4, sys_creat, sys_link
-/*10*/  .long sys_unlink, sunos_execv, sys_chdir, sys_chown, sys_mknod
-/*15*/	.long sys_chmod, sys_lchown, sparc_brk, sys_nis_syscall, sys_lseek
-/*20*/	.long sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
+/*10*/  .long sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys_mknod
+/*15*/	.long sys_chmod, sys_lchown16, sparc_brk, sys_nis_syscall, sys_lseek
+/*20*/	.long sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16
 /*25*/	.long sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_pause
-/*30*/	.long sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
-/*35*/	.long sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile
-/*40*/	.long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
-/*45*/	.long sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
-/*50*/	.long sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys_ioctl
+/*30*/	.long sys_utime, sys_lchown, sys_fchown, sys_access, sys_nice
+/*35*/	.long sys_chown, sys_sync, sys_kill, sys_newstat, sys_sendfile
+/*40*/	.long sys_newlstat, sys_dup, sys_pipe, sys_times, sys_getuid
+/*45*/	.long sys_umount, sys_setgid16, sys_getgid16, sys_signal, sys_geteuid16
+/*50*/	.long sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys_ioctl
 /*55*/	.long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve
 /*60*/	.long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
-/*65*/	.long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_nis_syscall
-/*70*/	.long sys_nis_syscall, sys_mmap, sys_nis_syscall, sys_munmap, sys_mprotect
-/*75*/	.long sys_nis_syscall, sys_vhangup, sys_truncate64, sys_nis_syscall, sys_getgroups
-/*80*/	.long sys_setgroups, sys_getpgrp, sys_nis_syscall, sys_setitimer, sys_ftruncate64
-/*85*/	.long sys_swapon, sys_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
-/*90*/	.long sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
+/*65*/	.long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_geteuid
+/*70*/	.long sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect
+/*75*/	.long sys_setregid, sys_vhangup, sys_truncate64, sys_getgroups, sys_getgroups16
+/*80*/	.long sys_setgroups16, sys_getpgrp, sys_setgroups, sys_setitimer, sys_ftruncate64
+/*85*/	.long sys_swapon, sys_getitimer, sys_setuid, sys_sethostname, sys_setgid
+/*90*/	.long sys_dup2, sys_setfsuid, sys_fcntl, sys_select, sys_setfsgid
 /*95*/	.long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*100*/	.long sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending
-/*105*/	.long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
-/*110*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*105*/	.long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_setresuid, sys_getresuid
+/*110*/	.long sys_setresgid, sys_getresgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*115*/	.long sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd
-/*120*/	.long sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
-/*125*/	.long sys_nis_syscall, sys_setreuid, sys_setregid, sys_rename, sys_truncate
+/*120*/	.long sys_readv, sys_writev, sys_settimeofday, sys_fchown16, sys_fchmod
+/*125*/	.long sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
 /*130*/	.long sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
 /*135*/	.long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64
 /*140*/	.long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
@@ -63,7 +63,7 @@
 /*210*/	.long sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys_sysinfo
 /*215*/	.long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/	.long sys_sigprocmask, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
-/*225*/	.long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
+/*225*/	.long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16
 /*230*/	.long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
 					  /* "We are the Knights of the Forest of Ni!!" */
 /*235*/	.long sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
@@ -83,7 +83,7 @@
 	.long sys_close, sunos_wait4, sys_creat
 	.long sys_link, sys_unlink, sunos_execv
 	.long sys_chdir, sunos_nosys, sys_mknod
-	.long sys_chmod, sys_lchown, sunos_brk
+	.long sys_chmod, sys_lchown16, sunos_brk
 	.long sunos_nosys, sys_lseek, sunos_getpid
 	.long sunos_nosys, sunos_nosys, sunos_nosys
 	.long sunos_getuid, sunos_nosys, sys_ptrace
@@ -104,8 +104,8 @@
 	.long sunos_nosys, sunos_sbrk, sunos_sstk
 	.long sunos_mmap, sunos_vadvise, sys_munmap
 	.long sys_mprotect, sunos_madvise, sys_vhangup
-	.long sunos_nosys, sunos_mincore, sys_getgroups
-	.long sys_setgroups, sys_getpgrp, sunos_setpgrp
+	.long sunos_nosys, sunos_mincore, sys_getgroups16
+	.long sys_setgroups16, sys_getpgrp, sunos_setpgrp
 	.long sys_setitimer, sunos_nosys, sys_swapon
 	.long sys_getitimer, sys_gethostname, sys_sethostname
 	.long sunos_getdtablesize, sys_dup2, sunos_nop
@@ -119,9 +119,9 @@
 	.long sys_sigstack, sys_recvmsg, sys_sendmsg
 	.long sunos_nosys, sys_gettimeofday, sys_getrusage
 	.long sunos_getsockopt, sunos_nosys, sunos_readv
-	.long sunos_writev, sys_settimeofday, sys_fchown
-	.long sys_fchmod, sys_recvfrom, sys_setreuid
-	.long sys_setregid, sys_rename, sys_truncate
+	.long sunos_writev, sys_settimeofday, sys_fchown16
+	.long sys_fchmod, sys_recvfrom, sys_setreuid16
+	.long sys_setregid16, sys_rename, sys_truncate
 	.long sys_ftruncate, sys_flock, sunos_nosys
 	.long sys_sendto, sys_shutdown, sys_socketpair
 	.long sys_mkdir, sys_rmdir, sys_utimes
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.3.39/linux/arch/sparc/mm/init.c	Tue Jan  4 13:57:16 2000
+++ linux/arch/sparc/mm/init.c	Sat Jan 15 22:08:28 2000
@@ -1,9 +1,10 @@
-/*  $Id: init.c,v 1.72 1999/12/27 06:30:06 anton Exp $
+/*  $Id: init.c,v 1.73 2000/01/15 00:51:26 anton Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *  Copyright (C) 1995 Eddie C. Dost (ecd@skynet.be)
  *  Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *  Copyright (C) 2000 Anton Blanchard (anton@progsoc.uts.edu.au)
  */
 
 #include <linux/config.h>
@@ -70,8 +71,7 @@
 pte_t __bad_page(void)
 {
 	memset((void *) &empty_bad_page, 0, PAGE_SIZE);
-	return pte_mkdirty(mk_pte_phys((((unsigned long) &empty_bad_page) 
-					- PAGE_OFFSET + phys_base),
+	return pte_mkdirty(mk_pte_phys((unsigned long)__pa(&empty_bad_page) + phys_base,
 				       PAGE_SHARED));
 }
 
@@ -115,7 +115,7 @@
 		add_to_free_ctxlist(ctx_list_pool + ctx);
 }
 
-#undef DEBUG_BOOTMEM
+#define DEBUG_BOOTMEM
 
 extern unsigned long cmdline_memory_size;
 
@@ -125,6 +125,10 @@
 	unsigned long end_of_phys_memory = 0UL;
 	int i;
 
+	/* Limit maximum memory until we implement highmem for sparc */
+	if (cmdline_memory_size > 0x9000000)
+		cmdline_memory_size = 0x9000000;
+
 	/* XXX It is a bit ambiguous here, whether we should
 	 * XXX treat the user specified mem=xxx as total wanted
 	 * XXX physical memory, or as a limit to the upper
@@ -161,7 +165,7 @@
 	/* Start with page aligned address of last symbol in kernel
 	 * image.  
 	 */
-	start_pfn  = PAGE_ALIGN((unsigned long) &_end) - PAGE_OFFSET;
+	start_pfn  = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &_end));
 
 	/* Adjust up to the physical address where the kernel begins. */
 	start_pfn += phys_base;
@@ -281,8 +285,8 @@
 		unsigned long start, end;
 
 		start = sp_banks[i].base_addr;
-		end = start +
-			sp_banks[i].num_bytes;
+		end = start + sp_banks[i].num_bytes;
+
 		while (start < end) {
 			set_bit (start >> 20,
 				sparc_valid_addr_bitmap);
@@ -379,19 +383,17 @@
 	}
 	memset(sparc_valid_addr_bitmap, 0, i << 2);
 
-	addr = KERNBASE;
-	last = PAGE_ALIGN((unsigned long)&_end);
 	/* fix this */
-	while(addr < last) {
 #ifdef CONFIG_BLK_DEV_INITRD
+	addr = __va(phys_base);
+	last = PAGE_ALIGN((unsigned long)&_end) + phys_base;
+	while(addr < last) {
 		if (initrd_below_start_ok && addr >= initrd_start && addr < initrd_end)
 			mem_map[MAP_NR(addr)].flags &= ~(1<<PG_reserved);
 		else
-#endif	
-			mem_map[MAP_NR(addr)].flags |= (1<<PG_reserved);
-		set_bit(MAP_NR(addr) >> 8, sparc_valid_addr_bitmap);
 		addr += PAGE_SIZE;
 	}
+#endif	
 
 	taint_real_pages();
 
@@ -444,9 +446,7 @@
 		unsigned long page;
 		struct page *p;
 
-		page = (addr +
-			((unsigned long) __va(phys_base)) -
-			PAGE_OFFSET);
+		page = addr + phys_base;
 		p = mem_map + MAP_NR(page);
 
 		ClearPageReserved(p);
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c
--- v2.3.39/linux/arch/sparc/mm/io-unit.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/sparc/mm/io-unit.c	Sat Jan 15 22:08:28 2000
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.19 2000/01/08 17:01:18 anton Exp $
+/* $Id: io-unit.c,v 1.20 2000/01/15 00:51:27 anton Exp $
  * io-unit.c:  IO-UNIT specific routines for memory management.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
@@ -190,7 +190,7 @@
 			pmdp = pmd_offset(pgdp, addr);
 			ptep = pte_offset(pmdp, addr);
 
-			set_pte(ptep, pte_val(mk_pte(page, dvma_prot)));
+			set_pte(ptep, pte_val(mk_pte(mem_map + MAP_NR(page), dvma_prot)));
 			
 			i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
 
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c
--- v2.3.39/linux/arch/sparc/mm/iommu.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/sparc/mm/iommu.c	Sat Jan 15 22:08:28 2000
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.17 2000/01/08 17:01:18 anton Exp $
+/* $Id: iommu.c,v 1.18 2000/01/15 00:51:27 anton Exp $
  * iommu.c:  IOMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -241,13 +241,13 @@
 			else if (viking_flush)
 				viking_flush_page(page);
 			else
-				flush_page_to_ram(page);
+				__flush_page_to_ram(page);
 
 			pgdp = pgd_offset(&init_mm, addr);
 			pmdp = pmd_offset(pgdp, addr);
 			ptep = pte_offset(pmdp, addr);
 
-			set_pte(ptep, pte_val(mk_pte(page, dvma_prot)));
+			set_pte(ptep, mk_pte(mem_map + MAP_NR(page), dvma_prot));
 			if (ipte_cache != 0) {
 				iopte_val(*iopte++) = MKIOPTE(__pa(page));
 			} else {
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/mm/loadmmu.c linux/arch/sparc/mm/loadmmu.c
--- v2.3.39/linux/arch/sparc/mm/loadmmu.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/sparc/mm/loadmmu.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: loadmmu.c,v 1.52 2000/01/08 16:38:20 anton Exp $
+/* $Id: loadmmu.c,v 1.53 2000/01/09 10:46:50 anton Exp $
  * loadmmu.c:  This code loads up all the mm function pointers once the
  *             machine type has been determined.  It also sets the static
  *             mmu values such as PAGE_NONE, etc.
@@ -18,8 +18,6 @@
 #include <asm/a.out.h>
 #include <asm/mmu_context.h>
 #include <asm/oplib.h>
-
-unsigned long stack_top = 0xf0000000 - PAGE_SIZE;
 
 struct ctx_list *ctx_list_pool;
 struct ctx_list ctx_free;
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.3.39/linux/arch/sparc/mm/srmmu.c	Wed Dec 29 13:13:13 1999
+++ linux/arch/sparc/mm/srmmu.c	Sat Jan 15 22:08:28 2000
@@ -1,10 +1,11 @@
-/* $Id: srmmu.c,v 1.199 1999/12/23 02:00:51 davem Exp $
+/* $Id: srmmu.c,v 1.203 2000/01/15 00:51:28 anton Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
  * Copyright (C) 1995 Pete Zaitcev
  * Copyright (C) 1996 Eddie C. Dost    (ecd@skynet.be)
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1999 Anton Blanchard (anton@progsoc.uts.edu.au)
  */
 
 #include <linux/config.h>
@@ -16,8 +17,10 @@
 #include <linux/init.h>
 #include <linux/blk.h>
 #include <linux/spinlock.h>
+#include <linux/bootmem.h>
 
 #include <asm/page.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/kdebug.h>
@@ -44,9 +47,6 @@
 
 #include <asm/btfixup.h>
 
-/* #define DEBUG_MAP_KERNEL */
-/* #define PAGESKIP_DEBUG */
-
 enum mbus_module srmmu_modtype;
 unsigned int hwbug_bitmask;
 int vac_cache_size;
@@ -55,6 +55,8 @@
 
 extern struct resource sparc_iomap;
 
+extern unsigned long last_valid_pfn;
+
 #ifdef __SMP__
 #define FLUSH_BEGIN(mm)
 #define FLUSH_END
@@ -63,9 +65,6 @@
 #define FLUSH_END	}
 #endif
 
-static int phys_mem_contig;
-BTFIXUPDEF_SETHI(page_contig_offset)
-
 BTFIXUPDEF_CALL(void, ctxd_set, ctxd_t *, pgd_t *)
 BTFIXUPDEF_CALL(void, pmd_set, pmd_t *, pte_t *)
 
@@ -96,95 +95,9 @@
 ctxd_t *srmmu_ctx_table_phys;
 ctxd_t *srmmu_context_table;
 
-/* Don't change this without changing access to this
- * in arch/sparc/mm/viking.S
- */
-static struct srmmu_trans {
-	unsigned long vbase;
-	unsigned long pbase;
-	unsigned long size;
-} srmmu_map[SPARC_PHYS_BANKS];
-
-#define SRMMU_HASHSZ	256
-
-/* Not static, viking.S uses it. */
-unsigned long srmmu_v2p_hash[SRMMU_HASHSZ];
-static unsigned long srmmu_p2v_hash[SRMMU_HASHSZ];
-
-#define srmmu_ahashfn(addr)	((addr) >> 24)
-
 int viking_mxcc_present = 0;
 static spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED;
 
-/* Physical memory can be _very_ non-contiguous on the sun4m, especially
- * the SS10/20 class machines and with the latest openprom revisions.
- * So we have to do a quick lookup.
- * We use the same for SS1000/SC2000 as a fall back, when phys memory is
- * non-contiguous.
- */
-static inline unsigned long srmmu_v2p(unsigned long vaddr)
-{
-	unsigned long off = srmmu_v2p_hash[srmmu_ahashfn(vaddr)];
-	
-	return (vaddr + off);
-}
-
-static inline unsigned long srmmu_p2v(unsigned long paddr)
-{
-	unsigned long off = srmmu_p2v_hash[srmmu_ahashfn(paddr)];
-	
-	if (off != 0xffffffffUL)
-		return (paddr - off);
-	else
-		return 0xffffffffUL;
-}
-
-/* Physical memory on most SS1000/SC2000 can be contiguous, so we handle that case
- * as a special case to make things faster.
- */
-/* FIXME: gcc is stupid here and generates very very bad code in this
- * heavily used routine. So we help it a bit. */
-static inline unsigned long srmmu_c_v2p(unsigned long vaddr)
-{
-#if KERNBASE != 0xf0000000
-	if (vaddr >= KERNBASE) return vaddr - KERNBASE;
-	return vaddr - BTFIXUP_SETHI(page_contig_offset);
-#else
-	register unsigned long kernbase;
-	
-	__asm__ ("sethi %%hi(0xf0000000), %0" : "=r"(kernbase));
-	return vaddr - ((vaddr >= kernbase) ? kernbase : BTFIXUP_SETHI(page_contig_offset));
-#endif
-}
-
-static inline unsigned long srmmu_c_p2v(unsigned long paddr)
-{
-#if KERNBASE != 0xf0000000
-	if (paddr < (0xfd000000 - KERNBASE)) return paddr + KERNBASE;
-	return (paddr + BTFIXUP_SETHI(page_contig_offset));
-#else
-	register unsigned long kernbase;
-	register unsigned long limit;
-	
-	__asm__ ("sethi %%hi(0x0d000000), %0" : "=r"(limit));
-	__asm__ ("sethi %%hi(0xf0000000), %0" : "=r"(kernbase));
-
-	return paddr + ((paddr < limit) ? kernbase : BTFIXUP_SETHI(page_contig_offset));
-#endif
-}
-
-/* On boxes where there is no lots_of_ram, KERNBASE is mapped to PA<0> and highest
-   PA is below 0x0d000000, we can optimize even more :) */
-static inline unsigned long srmmu_s_v2p(unsigned long vaddr)
-{
-	return vaddr - PAGE_OFFSET;
-}
-
-static inline unsigned long srmmu_s_p2v(unsigned long paddr)
-{
-	return paddr + PAGE_OFFSET;
-}
-
 /* In general all page table modifications should use the V8 atomic
  * swap instruction.  This insures the mmu and the cpu are in sync
  * with respect to ref/mod bits in the page tables.
@@ -198,91 +111,6 @@
 /* Functions really use this, not srmmu_swap directly. */
 #define srmmu_set_entry(ptr, newentry) srmmu_swap((unsigned long *) (ptr), (newentry))
 
-#ifdef PAGESKIP_DEBUG
-#define PGSKIP_DEBUG(from,to) prom_printf("PG_skip %ld->%ld\n", (long)(from), (long)(to)); printk("PG_skip %ld->%ld\n", (long)(from), (long)(to))
-#else
-#define PGSKIP_DEBUG(from,to) do { } while (0)
-#endif
-
-void __init srmmu_frob_mem_map(unsigned long start_mem)
-{
-	unsigned long bank_start, bank_end = 0;
-	unsigned long addr;
-	int i;
-
-	/* First, mark all pages as invalid. */
-	for(addr = PAGE_OFFSET; MAP_NR(addr) < max_mapnr; addr += PAGE_SIZE)
-		mem_map[MAP_NR(addr)].flags |= (1<<PG_reserved);
-		
-	/* Next, pg[0-3] is sun4c cruft, so we can free it... */
-	mem_map[MAP_NR(pg0)].flags &= ~(1<<PG_reserved);
-	mem_map[MAP_NR(pg1)].flags &= ~(1<<PG_reserved);
-	mem_map[MAP_NR(pg2)].flags &= ~(1<<PG_reserved);
-	mem_map[MAP_NR(pg3)].flags &= ~(1<<PG_reserved);
-	
-	start_mem = PAGE_ALIGN(start_mem);
-	for(i = 0; srmmu_map[i].size; i++) {
-		bank_start = srmmu_map[i].vbase;
-		
-		/* Making a one or two pages PG_skip holes
-		 * is not necessary.  We add one more because
-		 * we must set the PG_skip flag on the first
-		 * two mem_map[] entries for the hole.  Go and
-		 * see the mm/filemap.c:shrink_mmap() loop for
-		 * details. -DaveM
-		 */
-		if (i && bank_start - bank_end > 3 * PAGE_SIZE) {
-			mem_map[MAP_NR(bank_end)].flags |= (1<<PG_skip);
-			mem_map[MAP_NR(bank_end)].next_hash = mem_map + MAP_NR(bank_start);
-			mem_map[MAP_NR(bank_end)+1UL].flags |= (1<<PG_skip);
-			mem_map[MAP_NR(bank_end)+1UL].next_hash = mem_map + MAP_NR(bank_start);
-			PGSKIP_DEBUG(MAP_NR(bank_end), MAP_NR(bank_start));
-			if (bank_end > KERNBASE && bank_start < KERNBASE) {
-				mem_map[0].flags |= (1<<PG_skip);
-				mem_map[0].next_hash = mem_map + MAP_NR(bank_start);
-				mem_map[1].flags |= (1<<PG_skip);
-				mem_map[1].next_hash = mem_map + MAP_NR(bank_start);
-				PGSKIP_DEBUG(0, MAP_NR(bank_start));
-			}
-		}
-		
-		bank_end = bank_start + srmmu_map[i].size;
-		while(bank_start < bank_end) {
-			set_bit(MAP_NR(bank_start) >> 8, sparc_valid_addr_bitmap);
-			if((bank_start >= KERNBASE) &&
-			   (bank_start < start_mem)) {
-				bank_start += PAGE_SIZE;
-				continue;
-			}
-			mem_map[MAP_NR(bank_start)].flags &= ~(1<<PG_reserved);
-			bank_start += PAGE_SIZE;
-		}
-		
-		if (bank_end == 0xfd000000)
-			bank_end = PAGE_OFFSET;
-	}
-	
-	if (bank_end < KERNBASE) {
-		mem_map[MAP_NR(bank_end)].flags |= (1<<PG_skip);
-		mem_map[MAP_NR(bank_end)].next_hash = mem_map + MAP_NR(KERNBASE);
-		mem_map[MAP_NR(bank_end)+1UL].flags |= (1<<PG_skip);
-		mem_map[MAP_NR(bank_end)+1UL].next_hash = mem_map + MAP_NR(KERNBASE);
-		PGSKIP_DEBUG(MAP_NR(bank_end), MAP_NR(KERNBASE));
-	} else if (MAP_NR(bank_end) < max_mapnr) {
-		mem_map[MAP_NR(bank_end)].flags |= (1<<PG_skip);
-		mem_map[MAP_NR(bank_end)+1UL].flags |= (1<<PG_skip);
-		if (mem_map[0].flags & (1 << PG_skip)) {
-			mem_map[MAP_NR(bank_end)].next_hash = mem_map[0].next_hash;
-			mem_map[MAP_NR(bank_end)+1UL].next_hash = mem_map[0].next_hash;
-			PGSKIP_DEBUG(MAP_NR(bank_end), mem_map[0].next_hash - mem_map);
-		} else {
-			mem_map[MAP_NR(bank_end)].next_hash = mem_map;
-			mem_map[MAP_NR(bank_end)+1UL].next_hash = mem_map;
-			PGSKIP_DEBUG(MAP_NR(bank_end), 0);
-		}
-	}
-}
-
 /* The very generic SRMMU page table operations. */
 static inline int srmmu_device_memory(unsigned long x)
 {
@@ -290,31 +118,13 @@
 }
 
 static unsigned long srmmu_pgd_page(pgd_t pgd)
-{ return srmmu_device_memory(pgd_val(pgd))?~0:srmmu_p2v((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); }
+{ return srmmu_device_memory(pgd_val(pgd))?~0:(unsigned long)__va((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); }
 
 static unsigned long srmmu_pmd_page(pmd_t pmd)
-{ return srmmu_device_memory(pmd_val(pmd))?~0:srmmu_p2v((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); }
-
-static unsigned long srmmu_pte_page(pte_t pte)
-{ return srmmu_device_memory(pte_val(pte))?~0:srmmu_p2v((pte_val(pte) & SRMMU_PTE_PMASK) << 4); }
-
-static unsigned long srmmu_c_pgd_page(pgd_t pgd)
-{ return srmmu_device_memory(pgd_val(pgd))?~0:srmmu_c_p2v((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); }
-
-static unsigned long srmmu_c_pmd_page(pmd_t pmd)
-{ return srmmu_device_memory(pmd_val(pmd))?~0:srmmu_c_p2v((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); }
-
-static unsigned long srmmu_c_pte_page(pte_t pte)
-{ return srmmu_device_memory(pte_val(pte))?~0:srmmu_c_p2v((pte_val(pte) & SRMMU_PTE_PMASK) << 4); }
+{ return srmmu_device_memory(pmd_val(pmd))?~0:(unsigned long)__va((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); }
 
-static unsigned long srmmu_s_pgd_page(pgd_t pgd)
-{ return srmmu_device_memory(pgd_val(pgd))?~0:srmmu_s_p2v((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); }
-
-static unsigned long srmmu_s_pmd_page(pmd_t pmd)
-{ return srmmu_device_memory(pmd_val(pmd))?~0:srmmu_s_p2v((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); }
-
-static unsigned long srmmu_s_pte_page(pte_t pte)
-{ return srmmu_device_memory(pte_val(pte))?~0:srmmu_s_p2v((pte_val(pte) & SRMMU_PTE_PMASK) << 4); }
+static unsigned long srmmu_pte_pagenr(pte_t pte)
+{ return srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT); }
 
 static inline int srmmu_pte_none(pte_t pte)
 { return !(pte_val(pte) & 0xFFFFFFF); }
@@ -359,14 +169,8 @@
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
-static pte_t srmmu_mk_pte(unsigned long page, pgprot_t pgprot)
-{ return __pte(((srmmu_v2p(page)) >> 4) | pgprot_val(pgprot)); }
-
-static pte_t srmmu_c_mk_pte(unsigned long page, pgprot_t pgprot)
-{ return __pte(((srmmu_c_v2p(page)) >> 4) | pgprot_val(pgprot)); }
-
-static pte_t srmmu_s_mk_pte(unsigned long page, pgprot_t pgprot)
-{ return __pte(((srmmu_s_v2p(page)) >> 4) | pgprot_val(pgprot)); }
+static pte_t srmmu_mk_pte(struct page *page, pgprot_t pgprot)
+{ return __pte((((page - mem_map) << PAGE_SHIFT) >> 4) | pgprot_val(pgprot)); }
 
 static pte_t srmmu_mk_pte_phys(unsigned long page, pgprot_t pgprot)
 { return __pte(((page) >> 4) | pgprot_val(pgprot)); }
@@ -378,47 +182,17 @@
 
 static void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
 { 
-	set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pgdp) >> 4)));
+	set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__pa((unsigned long) pgdp) >> 4)));
 }
 
 static void srmmu_pgd_set(pgd_t * pgdp, pmd_t * pmdp)
 {
-	set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pmdp) >> 4)));
+	set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (__pa((unsigned long) pmdp) >> 4)));
 }
 
 static void srmmu_pmd_set(pmd_t * pmdp, pte_t * ptep)
 {
-	set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (srmmu_v2p((unsigned long) ptep) >> 4)));
-}
-
-static void srmmu_c_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
-{ 
-	set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (srmmu_c_v2p((unsigned long) pgdp) >> 4)));
-}
-
-static void srmmu_c_pgd_set(pgd_t * pgdp, pmd_t * pmdp)
-{
-	set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (srmmu_c_v2p((unsigned long) pmdp) >> 4)));
-}
-
-static void srmmu_c_pmd_set(pmd_t * pmdp, pte_t * ptep)
-{
-	set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (srmmu_c_v2p((unsigned long) ptep) >> 4)));
-}
-
-static void srmmu_s_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
-{ 
-	set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (srmmu_s_v2p((unsigned long) pgdp) >> 4)));
-}
-
-static void srmmu_s_pgd_set(pgd_t * pgdp, pmd_t * pmdp)
-{
-	set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (srmmu_s_v2p((unsigned long) pmdp) >> 4)));
-}
-
-static void srmmu_s_pmd_set(pmd_t * pmdp, pte_t * ptep)
-{
-	set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (srmmu_s_v2p((unsigned long) ptep) >> 4)));
+	set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (__pa((unsigned long) ptep) >> 4)));
 }
 
 static inline pte_t srmmu_pte_modify(pte_t pte, pgprot_t newprot)
@@ -444,26 +218,6 @@
 	return (pte_t *) srmmu_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1));
 }
 
-static inline pmd_t *srmmu_c_pmd_offset(pgd_t * dir, unsigned long address)
-{
-	return (pmd_t *) srmmu_c_pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1));
-}
-
-static inline pte_t *srmmu_c_pte_offset(pmd_t * dir, unsigned long address)
-{
-	return (pte_t *) srmmu_c_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1));
-}
-
-static inline pmd_t *srmmu_s_pmd_offset(pgd_t * dir, unsigned long address)
-{
-	return (pmd_t *) srmmu_s_pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1));
-}
-
-static inline pte_t *srmmu_s_pte_offset(pmd_t * dir, unsigned long address)
-{
-	return (pte_t *) srmmu_s_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1));
-}
-
 static inline pte_t *srmmu_get_pte_fast(void)
 {
 	struct page *ret;
@@ -841,7 +595,7 @@
 		tmp |= SRMMU_PRIV_RDONLY;
 	else
 		tmp |= SRMMU_PRIV;
-	flush_page_to_ram(virt_addr);
+	__flush_page_to_ram(virt_addr);
 	set_pte(ptep, __pte(tmp));
 	flush_tlb_all();
 }
@@ -857,7 +611,7 @@
 	ptep = pte_offset(pmdp, virt_addr);
 
 	/* No need to flush uncacheable page. */
-	set_pte(ptep, mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
+	pte_clear(ptep);
 	flush_tlb_all();
 }
 
@@ -879,6 +633,11 @@
 	free_pages((unsigned long)tsk, 1);
 }
 
+static void srmmu_get_task_struct(struct task_struct *tsk)
+{
+	atomic_inc(&mem_map[MAP_NR(tsk)].count);
+}
+
 /* tsunami.S */
 extern void tsunami_flush_cache_all(void);
 extern void tsunami_flush_cache_mm(struct mm_struct *mm);
@@ -1235,8 +994,6 @@
 extern void viking_flush_page(unsigned long page);
 extern void viking_mxcc_flush_page(unsigned long page);
 extern void viking_flush_chunk(unsigned long chunk);
-extern void viking_c_flush_chunk(unsigned long chunk);
-extern void viking_s_flush_chunk(unsigned long chunk);
 extern void viking_mxcc_flush_chunk(unsigned long chunk);
 extern void viking_flush_tlb_all(void);
 extern void viking_flush_tlb_mm(struct mm_struct *mm);
@@ -1276,7 +1033,7 @@
 
 static void hypersparc_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
 {
-	srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) pgdp) >> 4))));
+	srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) pgdp) >> 4))));
 	hypersparc_flush_page_to_ram((unsigned long)ctxp);
 	hyper_flush_whole_icache();
 }
@@ -1291,57 +1048,23 @@
 		alloc_context(old_mm, mm);
 		spin_unlock(&srmmu_context_spinlock);
 		ctxp = &srmmu_context_table[mm->context];
-		srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) mm->pgd) >> 4))));
+		srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) mm->pgd) >> 4))));
 		hypersparc_flush_page_to_ram((unsigned long)ctxp);
 	}
 	hyper_flush_whole_icache();
 	srmmu_set_context(mm->context);
 }
 
-static unsigned long mempool;
-
 /* NOTE: All of this startup code assumes the low 16mb (approx.) of
  *       kernel mappings are done with one single contiguous chunk of
  *       ram.  On small ram machines (classics mainly) we only get
  *       around 8mb mapped for us.
  */
 
-static unsigned long kbpage;
-
-/* Some dirty hacks to abstract away the painful boot up init. */
-static inline unsigned long srmmu_early_paddr(unsigned long vaddr)
-{
-	return ((vaddr - KERNBASE) + kbpage);
-}
-
-static inline void srmmu_early_pgd_set(pgd_t *pgdp, pmd_t *pmdp)
-{
-	set_pte((pte_t *)pgdp, __pte((SRMMU_ET_PTD | (srmmu_early_paddr((unsigned long) pmdp) >> 4))));
-}
-
-static inline void srmmu_early_pmd_set(pmd_t *pmdp, pte_t *ptep)
-{
-	set_pte((pte_t *)pmdp, __pte((SRMMU_ET_PTD | (srmmu_early_paddr((unsigned long) ptep) >> 4))));
-}
-
-static inline unsigned long srmmu_early_pgd_page(pgd_t pgd)
-{
-	return (((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4) - kbpage) + KERNBASE;
-}
-
-static inline unsigned long srmmu_early_pmd_page(pmd_t pmd)
-{
-	return (((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4) - kbpage) + KERNBASE;
-}
-
-static inline pmd_t *srmmu_early_pmd_offset(pgd_t *dir, unsigned long address)
-{
-	return (pmd_t *) srmmu_early_pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1));
-}
-
-static inline pte_t *srmmu_early_pte_offset(pmd_t *dir, unsigned long address)
+void __init early_pgtable_allocfail(char *type)
 {
-	return (pte_t *) srmmu_early_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1));
+	prom_printf("inherit_prom_mappings: Cannot alloc kernel %s.\n", type);
+	prom_halt();
 }
 
 static inline void srmmu_allocate_ptable_skeleton(unsigned long start, unsigned long end)
@@ -1353,13 +1076,20 @@
 	while(start < end) {
 		pgdp = srmmu_pgd_offset(&init_mm, start);
 		if(srmmu_pgd_none(*pgdp)) {
-			pmdp = sparc_init_alloc(&mempool, SRMMU_PMD_TABLE_SIZE);
-			srmmu_early_pgd_set(pgdp, pmdp);
+			pmdp = __alloc_bootmem(SRMMU_PMD_TABLE_SIZE,
+					SRMMU_PMD_TABLE_SIZE, 0UL);
+			if (pmdp == NULL)
+				early_pgtable_allocfail("pmd");
+			memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE);
+			srmmu_pgd_set(pgdp, pmdp);
 		}
-		pmdp = srmmu_early_pmd_offset(pgdp, start);
+		pmdp = srmmu_pmd_offset(pgdp, start);
 		if(srmmu_pmd_none(*pmdp)) {
-			ptep = sparc_init_alloc(&mempool, SRMMU_PTE_TABLE_SIZE);
-			srmmu_early_pmd_set(pmdp, ptep);
+			ptep = __alloc_bootmem(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE, 0UL);
+			if (ptep == NULL)
+				early_pgtable_allocfail("pte");
+			memset(ptep, 0, SRMMU_PTE_TABLE_SIZE);
+			srmmu_pmd_set(pmdp, ptep);
 		}
 		start = (start + SRMMU_PMD_SIZE) & SRMMU_PMD_MASK;
 	}
@@ -1408,94 +1138,34 @@
 			continue;
 		}
 		if(srmmu_pgd_none(*pgdp)) {
-			pmdp = sparc_init_alloc(&mempool, SRMMU_PMD_TABLE_SIZE);
-			srmmu_early_pgd_set(pgdp, pmdp);
+			pmdp = __alloc_bootmem(SRMMU_PMD_TABLE_SIZE,
+					SRMMU_PMD_TABLE_SIZE, 0UL);
+			if (pmdp == NULL)
+				early_pgtable_allocfail("pmd");
+			memset(pmdp, 0, SRMMU_PMD_TABLE_SIZE);
+			srmmu_pgd_set(pgdp, pmdp);
 		}
-		pmdp = srmmu_early_pmd_offset(pgdp, start);
+		pmdp = srmmu_pmd_offset(pgdp, start);
 		if(what == 1) {
 			*pmdp = __pmd(prompte);
 			start += SRMMU_PMD_SIZE;
 			continue;
 		}
 		if(srmmu_pmd_none(*pmdp)) {
-			ptep = sparc_init_alloc(&mempool, SRMMU_PTE_TABLE_SIZE);
-			srmmu_early_pmd_set(pmdp, ptep);
+			ptep = __alloc_bootmem(SRMMU_PTE_TABLE_SIZE, SRMMU_PTE_TABLE_SIZE, 0UL);
+			if (ptep == NULL)
+				early_pgtable_allocfail("pte");
+			memset(ptep, 0, SRMMU_PTE_TABLE_SIZE);
+			srmmu_pmd_set(pmdp, ptep);
 		}
-		ptep = srmmu_early_pte_offset(pmdp, start);
+		ptep = srmmu_pte_offset(pmdp, start);
 		*ptep = __pte(prompte);
 		start += PAGE_SIZE;
 	}
 }
 
-#ifdef DEBUG_MAP_KERNEL
-#define MKTRACE(foo) prom_printf foo
-#else
-#define MKTRACE(foo)
-#endif
-
-static int lots_of_ram __initdata = 0;
-static int srmmu_low_pa __initdata = 0;
 static unsigned long end_of_phys_memory __initdata = 0;
 
-void __init srmmu_end_memory(unsigned long memory_size, unsigned long *end_mem_p)
-{
-	unsigned int sum = 0;
-	unsigned long last = 0xff000000;
-	long first, cur;
-	unsigned long pa;
-	unsigned long total = 0;
-	int i;
-
-	pa = srmmu_hwprobe(KERNBASE + PAGE_SIZE);
-	pa = (pa & SRMMU_PTE_PMASK) << 4;
-	if (!sp_banks[0].base_addr && pa == PAGE_SIZE) {
-		for(i = 0; sp_banks[i].num_bytes != 0; i++) {
-			if (sp_banks[i].base_addr + sp_banks[i].num_bytes > 0x0d000000)
-				break;
-		}
-		if (!sp_banks[i].num_bytes) {
-			srmmu_low_pa = 1;
-			end_of_phys_memory = SRMMU_PGDIR_ALIGN(sp_banks[i-1].base_addr + sp_banks[i-1].num_bytes);
-			*end_mem_p = KERNBASE + end_of_phys_memory;
-			if (sp_banks[0].num_bytes >= (6 * 1024 * 1024) || end_of_phys_memory <= 0x06000000) {
-				/* Make sure there will be enough memory for the whole mem_map (even if sparse) */
-				return;
-			}
-		}
-	}
-	for(i = 0; sp_banks[i].num_bytes != 0; i++) {
-		pa = sp_banks[i].base_addr;
-		first = (pa & (~SRMMU_PGDIR_MASK));
-		cur = (sp_banks[i].num_bytes + first - SRMMU_PGDIR_SIZE);
-		if (cur < 0) cur = 0;
-		if (!first || last != (pa & SRMMU_PGDIR_MASK))
-			total += SRMMU_PGDIR_SIZE;
-		sum += sp_banks[i].num_bytes;
-		if (memory_size) {
-			if (sum > memory_size) {
-				sp_banks[i].num_bytes -=
-					(sum - memory_size);
-				cur = (sp_banks[i].num_bytes + first - SRMMU_PGDIR_SIZE);
-				if (cur < 0) cur = 0;
-				total += SRMMU_PGDIR_ALIGN(cur);
-				sum = memory_size;
-				sp_banks[++i].base_addr = 0xdeadbeef;
-				sp_banks[i].num_bytes = 0;
-				break;
-			}
-		}
-		total += SRMMU_PGDIR_ALIGN(cur);
-		last = (sp_banks[i].base_addr + sp_banks[i].num_bytes - 1) & SRMMU_PGDIR_MASK;
-	}
-	if (total <= 0x0d000000)
-		*end_mem_p = KERNBASE + total;
-	else {
-		*end_mem_p = 0xfd000000;
-		lots_of_ram = 1;
-	}
-	end_of_phys_memory = total;
-}
-
 #define KERNEL_PTE(page_shifted) ((page_shifted)|SRMMU_CACHE|SRMMU_PRIV|SRMMU_VALID)
 
 /* Create a third-level SRMMU 16MB page mapping. */
@@ -1504,44 +1174,10 @@
 	pgd_t *pgdp = srmmu_pgd_offset(&init_mm, vaddr);
 	unsigned long big_pte;
 
-	MKTRACE(("dlm[v<%08lx>-->p<%08lx>]", vaddr, phys_base));
 	big_pte = KERNEL_PTE(phys_base >> 4);
 	*pgdp = __pgd(big_pte);
 }
 
-/* Look in the sp_bank for the given physical page, return the
- * index number the entry was found in, or -1 for not found.
- */
-static inline int find_in_spbanks(unsigned long phys_page)
-{
-	int entry;
-
-	for(entry = 0; sp_banks[entry].num_bytes; entry++) {
-		unsigned long start = sp_banks[entry].base_addr;
-		unsigned long end = start + sp_banks[entry].num_bytes;
-
-		if((start <= phys_page) && (phys_page < end))
-			return entry;
-	}
-	return -1;
-}
-
-/* Find an spbank entry not mapped as of yet, TAKEN_VECTOR is an
- * array of char's, each member indicating if that spbank is mapped
- * yet or not.
- */
-static int __init find_free_spbank(char *taken_vector)
-{
-	int entry;
-
-	for(entry = 0; sp_banks[entry].num_bytes; entry++)
-		if(!taken_vector[entry])
-			break;
-	return entry;
-}
-
-static unsigned long map_spbank_last_pa __initdata = 0xff000000;
-
 /* Map sp_bank entry SP_ENTRY, starting at virtual address VBASE.
  */
 static unsigned long __init map_spbank(unsigned long vbase, int sp_entry)
@@ -1549,20 +1185,11 @@
 	unsigned long pstart = (sp_banks[sp_entry].base_addr & SRMMU_PGDIR_MASK);
 	unsigned long vstart = (vbase & SRMMU_PGDIR_MASK);
 	unsigned long vend = SRMMU_PGDIR_ALIGN(vbase + sp_banks[sp_entry].num_bytes);
-	static int srmmu_bank = 0;
 
-	MKTRACE(("map_spbank %d[v<%08lx>p<%08lx>s<%08lx>]", sp_entry, vbase, sp_banks[sp_entry].base_addr, sp_banks[sp_entry].num_bytes));
-	MKTRACE(("map_spbank2 %d[p%08lx v%08lx-%08lx]", sp_entry, pstart, vstart, vend));
 	while(vstart < vend) {
 		do_large_mapping(vstart, pstart);
 		vstart += SRMMU_PGDIR_SIZE; pstart += SRMMU_PGDIR_SIZE;
 	}
-	srmmu_map[srmmu_bank].vbase = vbase;
-	srmmu_map[srmmu_bank].pbase = sp_banks[sp_entry].base_addr;
-	srmmu_map[srmmu_bank].size = sp_banks[sp_entry].num_bytes;
-	if (srmmu_map[srmmu_bank].size)
-		srmmu_bank++;
-	map_spbank_last_pa = pstart - SRMMU_PGDIR_SIZE;
 	return vstart;
 }
 
@@ -1573,251 +1200,35 @@
 	prom_halt();
 }
 
-/* Assumptions: The bank given to the kernel from the prom/bootloader
- * is part of a full bank which is at least 4MB in size and begins at
- * 0xf0000000 (ie. KERNBASE).
- */
 static inline void map_kernel(void)
 {
-	unsigned long raw_pte, physpage;
-	unsigned long vaddr, low_base;
-	char etaken[SPARC_PHYS_BANKS];
-	int entry;
-
-	/* Step 1: Clear out sp_banks taken map. */
-	MKTRACE(("map_kernel: clearing etaken vector... "));
-	for(entry = 0; entry < SPARC_PHYS_BANKS; entry++)
-		etaken[entry] = 0;
-
-	low_base = KERNBASE;
-
-	/* Step 2: Fill in KERNBASE base pgd.  Lots of sanity checking here. */
-	raw_pte = srmmu_hwprobe(KERNBASE + PAGE_SIZE);
-	if((raw_pte & SRMMU_ET_MASK) != SRMMU_ET_PTE)
-		memprobe_error("Wheee, kernel not mapped at all by boot loader.\n");
-	physpage = (raw_pte & SRMMU_PTE_PMASK) << 4;
-	physpage -= PAGE_SIZE;
-	if(physpage & ~(SRMMU_PGDIR_MASK))
-		memprobe_error("Wheee, kernel not mapped on 16MB physical boundry.\n");
-	entry = find_in_spbanks(physpage);
-	if(entry == -1 || (sp_banks[entry].base_addr != physpage))
-		memprobe_error("Kernel mapped in non-existant memory.\n");
-	MKTRACE(("map_kernel: map_spbank(vbase=%08x, entry<%d>)[%08lx,%08lx]\n", KERNBASE, entry, sp_banks[entry].base_addr, sp_banks[entry].num_bytes));
-	if (sp_banks[entry].num_bytes > 0x0d000000) {
-		unsigned long orig_base = sp_banks[entry].base_addr;
-		unsigned long orig_len = sp_banks[entry].num_bytes;
-		unsigned long can_map = 0x0d000000;
-		
-		/* Map a partial bank in this case, adjust the base
-		 * and the length, but don't mark it used.
-		 */
-		sp_banks[entry].num_bytes = can_map;
-		MKTRACE(("wheee really big mapping [%08lx,%08lx]", orig_base, can_map));
-		vaddr = map_spbank(KERNBASE, entry);
-		MKTRACE(("vaddr now %08lx ", vaddr));
-		sp_banks[entry].base_addr = orig_base + can_map;
-		sp_banks[entry].num_bytes = orig_len - can_map;
-		MKTRACE(("adjust[%08lx,%08lx]\n", (orig_base + can_map), (orig_len - can_map)));
-		MKTRACE(("map_kernel: skipping first loop\n"));
-		goto loop_skip;
-	}
-	vaddr = map_spbank(KERNBASE, entry);
-	etaken[entry] = 1;
-
-	/* Step 3: Map what we can above KERNBASE. */
-	MKTRACE(("map_kernel: vaddr=%08lx, entering first loop\n", vaddr));
-	for(;;) {
-		unsigned long bank_size;
-
-		MKTRACE(("map_kernel: ffsp()"));
-		entry = find_free_spbank(&etaken[0]);
-		bank_size = sp_banks[entry].num_bytes;
-		MKTRACE(("<%d> base=%08lx bs=%08lx ", entry, sp_banks[entry].base_addr, bank_size));
-		if(!bank_size)
-			break;
-		if (srmmu_low_pa)
-			vaddr = KERNBASE + sp_banks[entry].base_addr;
-		else if (sp_banks[entry].base_addr & (~SRMMU_PGDIR_MASK)) {
-			if (map_spbank_last_pa == (sp_banks[entry].base_addr & SRMMU_PGDIR_MASK))
-				vaddr -= SRMMU_PGDIR_SIZE;
-			vaddr += (sp_banks[entry].base_addr & (~SRMMU_PGDIR_MASK));
-		}
-		if ((vaddr + bank_size - KERNBASE) > 0x0d000000) {
-			unsigned long orig_base = sp_banks[entry].base_addr;
-			unsigned long orig_len = sp_banks[entry].num_bytes;
-			unsigned long can_map = (0xfd000000 - vaddr);
-
-			/* Map a partial bank in this case, adjust the base
-			 * and the length, but don't mark it used.
-			 */
-			sp_banks[entry].num_bytes = can_map;
-			MKTRACE(("wheee really big mapping [%08lx,%08lx]", orig_base, can_map));
-			vaddr = map_spbank(vaddr, entry);
-			MKTRACE(("vaddr now %08lx ", vaddr));
-			sp_banks[entry].base_addr = orig_base + can_map;
-			sp_banks[entry].num_bytes = orig_len - can_map;
-			MKTRACE(("adjust[%08lx,%08lx]\n", (orig_base + can_map), (orig_len - can_map)));
-			break;
-		}
-
-		/* Ok, we can map this one, do it. */
-		MKTRACE(("map_spbank(%08lx,entry<%d>) ", vaddr, entry));
-		vaddr = map_spbank(vaddr, entry);
-		etaken[entry] = 1;
-		MKTRACE(("vaddr now %08lx\n", vaddr));
-	}
-	MKTRACE(("\n"));
-	/* If not lots_of_ram, assume we did indeed map it all above. */
-loop_skip:
-	if(!lots_of_ram)
-		goto check_and_return;
-	
-	/* Step 4: Map the rest (if any) right below KERNBASE. */
-	MKTRACE(("map_kernel: doing low mappings... "));
-	low_base = (KERNBASE - end_of_phys_memory + 0x0d000000);
-	MKTRACE(("end_of_phys_memory=%08lx low_base=%08lx\n", end_of_phys_memory, low_base));
-
-	/* Ok, now map 'em. */
-	MKTRACE(("map_kernel: Allocate pt skeleton (%08lx, %08x)\n",low_base,KERNBASE));
-	srmmu_allocate_ptable_skeleton(low_base, KERNBASE);
-	vaddr = low_base;
-	map_spbank_last_pa = 0xff000000;
-	MKTRACE(("map_kernel: vaddr=%08lx Entering second loop for low maps.\n", vaddr));
-	for(;;) {
-		unsigned long bank_size;
-
-		entry = find_free_spbank(&etaken[0]);
-		bank_size = sp_banks[entry].num_bytes;
-		MKTRACE(("map_kernel: e<%d> base=%08lx bs=%08lx ", entry, sp_banks[entry].base_addr, bank_size));
-		if(!bank_size)
-			break;
-		if (sp_banks[entry].base_addr & (~SRMMU_PGDIR_MASK)) {
-			if (map_spbank_last_pa == (sp_banks[entry].base_addr & SRMMU_PGDIR_MASK))
-				vaddr -= SRMMU_PGDIR_SIZE;
-			vaddr += (sp_banks[entry].base_addr & (~SRMMU_PGDIR_MASK));
-		}
-		if((vaddr + bank_size) > KERNBASE)
-			memprobe_error("Wheee, kernel low mapping overflow.\n");
-		MKTRACE(("map_spbank(%08lx, %d) ", vaddr, entry));
-		vaddr = map_spbank(vaddr, entry);
-		etaken[entry] = 1;
-		MKTRACE(("Now, vaddr=%08lx end_of_phys_memory=%08lx\n", vaddr, end_of_phys_memory));
-	}
-	MKTRACE(("\n"));
-
-check_and_return:
-	/* Step 5: Sanity check, make sure we did it all. */
-	MKTRACE(("check_and_return: "));
-	for(entry = 0; sp_banks[entry].num_bytes; entry++) {
-		MKTRACE(("e[%d]=%d ", entry, etaken[entry]));
-		if(!etaken[entry]) {
-			MKTRACE(("oops\n"));
-			memprobe_error("Some bank did not get mapped.\n");
-		}
-	}
-	MKTRACE(("success\n"));
-	init_mm.mmap->vm_start = page_offset = low_base;
-	stack_top = page_offset - PAGE_SIZE;
-	BTFIXUPSET_SETHI(page_offset, low_base);
-	BTFIXUPSET_SETHI(stack_top, page_offset - PAGE_SIZE);
-	BTFIXUPSET_SIMM13(user_ptrs_per_pgd, page_offset / SRMMU_PGDIR_SIZE);
-	
-#if 1
-	for(entry = 0; srmmu_map[entry].size; entry++) {
-		printk("[%d]: v[%08lx,%08lx](%lx) p[%08lx]\n", entry,
-		       srmmu_map[entry].vbase,
-		       srmmu_map[entry].vbase + srmmu_map[entry].size,
-		       srmmu_map[entry].size,
-		       srmmu_map[entry].pbase);
-	}
-#endif
+	int i;
 
-	/* Now setup the p2v/v2p hash tables. */
-	for(entry = 0; entry < SRMMU_HASHSZ; entry++)
-		srmmu_v2p_hash[entry] = ((0xff - entry) << 24);
-	for(entry = 0; entry < SRMMU_HASHSZ; entry++)
-		srmmu_p2v_hash[entry] = 0xffffffffUL;
-	for(entry = 0; srmmu_map[entry].size; entry++) {
-		unsigned long addr;
-
-		for(addr = srmmu_map[entry].vbase;
-		    addr < (srmmu_map[entry].vbase + srmmu_map[entry].size);
-		    addr += (1 << 24))
-			srmmu_v2p_hash[srmmu_ahashfn(addr)] =
-				srmmu_map[entry].pbase - srmmu_map[entry].vbase;
-		for(addr = srmmu_map[entry].pbase;
-		    addr < (srmmu_map[entry].pbase + srmmu_map[entry].size);
-		    addr += (1 << 24))
-			srmmu_p2v_hash[srmmu_ahashfn(addr)] = 
-				srmmu_map[entry].pbase - srmmu_map[entry].vbase;
-	}
-
-	BTFIXUPSET_SETHI(page_contig_offset, page_offset - (0xfd000000 - KERNBASE));
-	if (srmmu_low_pa)
-		phys_mem_contig = 0;
-	else {
-		phys_mem_contig = 1;
-		for(entry = 0; srmmu_map[entry].size; entry++)
-			if (srmmu_map[entry].pbase != srmmu_c_v2p (srmmu_map[entry].vbase)) {
-				phys_mem_contig = 0;
-				break;
-			}
-	}
-	if (phys_mem_contig) {
-		printk ("SRMMU: Physical memory is contiguous, bypassing VA<->PA hashes.\n");
-		BTFIXUPSET_CALL(pte_page, srmmu_c_pte_page, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pmd_page, srmmu_c_pmd_page, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pgd_page, srmmu_c_pgd_page, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(mk_pte, srmmu_c_mk_pte, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pte_offset, srmmu_c_pte_offset, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pmd_offset, srmmu_c_pmd_offset, BTFIXUPCALL_NORM);
-		if (BTFIXUPVAL_CALL(ctxd_set) == (unsigned long)srmmu_ctxd_set)
-			BTFIXUPSET_CALL(ctxd_set, srmmu_c_ctxd_set, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pgd_set, srmmu_c_pgd_set, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pmd_set, srmmu_c_pmd_set, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(mmu_v2p, srmmu_c_v2p, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(mmu_p2v, srmmu_c_p2v, BTFIXUPCALL_NORM);
-		if (BTFIXUPVAL_CALL(flush_chunk) == (unsigned long)viking_flush_chunk)
-			BTFIXUPSET_CALL(flush_chunk, viking_c_flush_chunk, BTFIXUPCALL_NORM);
-	} else if (srmmu_low_pa) {
-		printk ("SRMMU: Compact physical memory. Using strightforward VA<->PA translations.\n");
-		BTFIXUPSET_CALL(pte_page, srmmu_s_pte_page, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pmd_page, srmmu_s_pmd_page, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pgd_page, srmmu_s_pgd_page, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(mk_pte, srmmu_s_mk_pte, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pte_offset, srmmu_s_pte_offset, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pmd_offset, srmmu_s_pmd_offset, BTFIXUPCALL_NORM);
-		if (BTFIXUPVAL_CALL(ctxd_set) == (unsigned long)srmmu_ctxd_set)
-			BTFIXUPSET_CALL(ctxd_set, srmmu_s_ctxd_set, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pgd_set, srmmu_s_pgd_set, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(pmd_set, srmmu_s_pmd_set, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(mmu_v2p, srmmu_s_v2p, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(mmu_p2v, srmmu_s_p2v, BTFIXUPCALL_NORM);
-		if (BTFIXUPVAL_CALL(flush_chunk) == (unsigned long)viking_flush_chunk)
-			BTFIXUPSET_CALL(flush_chunk, viking_s_flush_chunk, BTFIXUPCALL_NORM);
+	for (i = 0; sp_banks[i].num_bytes != 0; i++) {
+		map_spbank(__va(sp_banks[i].base_addr), i);
 	}
-	btfixup();
 
-	return; /* SUCCESS! */
+	init_mm.mmap->vm_start = PAGE_OFFSET;
+	BTFIXUPSET_SIMM13(user_ptrs_per_pgd, PAGE_OFFSET / SRMMU_PGDIR_SIZE);
 }
 
 /* Paging initialization on the Sparc Reference MMU. */
-extern unsigned long free_area_init(unsigned long, unsigned long);
-extern unsigned long sparc_context_init(unsigned long, int);
+extern void sparc_context_init(int);
 
-extern int physmem_mapped_contig;
 extern int linux_num_cpus;
 
 void (*poke_srmmu)(void) __initdata = NULL;
 
-unsigned long __init srmmu_paging_init(unsigned long start_mem, unsigned long end_mem)
+extern unsigned long bootmem_init(void);
+extern void sun_serial_setup(void);
+
+void __init srmmu_paging_init(void)
 {
-	unsigned long ptables_start;
 	int i, cpunode;
 	char node_str[128];
+	unsigned long end_pfn;
 
 	sparc_iomap.start = 0xfd000000;    /* 16MB of IOSPACE on all sun4m's. */
-	physmem_mapped_contig = 0;         /* for init.c:taint_real_pages()   */
 
 	if (sparc_cpu_model == sun4d)
 		num_contexts = 65536; /* We know it is Viking */
@@ -1840,32 +1251,42 @@
 		prom_halt();
 	}
 		
-	ptables_start = mempool = PAGE_ALIGN(start_mem);
 	memset(swapper_pg_dir, 0, PAGE_SIZE);
-	kbpage = srmmu_hwprobe(KERNBASE + PAGE_SIZE);
-	kbpage = (kbpage & SRMMU_PTE_PMASK) << 4;
-	kbpage -= PAGE_SIZE;
 
-	srmmu_allocate_ptable_skeleton(KERNBASE, end_mem);
+	last_valid_pfn = end_pfn = bootmem_init();
+
+	srmmu_allocate_ptable_skeleton(KERNBASE, __va(end_of_phys_memory));
 #if CONFIG_SUN_IO
 	srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END);
 	srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END);
 #endif
 
-	mempool = PAGE_ALIGN(mempool);
+	/* This does not logically belong here, but we need to
+	 * call it at the moment we are able to use the bootmem
+	 * allocator.
+	 */
+	sun_serial_setup();
+
         srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE));
 	map_kernel();
-	srmmu_context_table = sparc_init_alloc(&mempool, num_contexts*sizeof(ctxd_t));
-	srmmu_ctx_table_phys = (ctxd_t *) srmmu_v2p((unsigned long) srmmu_context_table);
+
+#define BOOTMEM_BROKEN
+#ifdef BOOTMEM_BROKEN
+	srmmu_context_table = __alloc_bootmem(num_contexts*sizeof(ctxd_t)*2, SMP_CACHE_BYTES, 0UL);
+	(unsigned long)srmmu_context_table += num_contexts*sizeof(ctxd_t);
+	(unsigned long)srmmu_context_table &= ~(num_contexts*sizeof(ctxd_t)-1);
+#else
+	srmmu_context_table = __alloc_bootmem(num_contexts*sizeof(ctxd_t), num_contexts*sizeof(ctxd_t), 0UL);
+#endif
+
+	srmmu_ctx_table_phys = (ctxd_t *) __pa((unsigned long) srmmu_context_table);
 	for(i = 0; i < num_contexts; i++)
 		ctxd_set(&srmmu_context_table[i], swapper_pg_dir);
 
-	start_mem = PAGE_ALIGN(mempool);
-
 	flush_cache_all();
 	if(BTFIXUPVAL_CALL(flush_page_for_dma) == (unsigned long)viking_flush_page) {
-		unsigned long start = ptables_start;
-		unsigned long end = start_mem;
+		unsigned long start = (unsigned long)srmmu_context_table;
+		unsigned long end = PAGE_ALIGN((unsigned long)srmmu_context_table + num_contexts*sizeof(ctxd_t));
 
 		while(start < end) {
 			viking_flush_page(start);
@@ -1876,22 +1297,27 @@
 	flush_tlb_all();
 	poke_srmmu();
 
-	start_mem = sparc_context_init(start_mem, num_contexts);
-	start_mem = free_area_init(start_mem, end_mem);
+	sparc_context_init(num_contexts);
+
+	{
+		unsigned int zones_size[MAX_NR_ZONES] = { 0, 0, 0};
+
+		zones_size[ZONE_DMA] = end_pfn;
+		free_area_init(zones_size);
+	}
 	
 #ifdef CONFIG_BLK_DEV_INITRD
 	/* If initial ramdisk was specified with physical address,
 	   translate it here, as the p2v translation in srmmu
 	   is not straightforward. */
 	if (initrd_start && initrd_start < KERNBASE) {
-		initrd_start = srmmu_p2v(initrd_start);
-		initrd_end = srmmu_p2v(initrd_end);
+		initrd_start = __va(initrd_start);
+		initrd_end = __va(initrd_end);
 		if (initrd_end <= initrd_start)
 			initrd_start = 0;
 	}
 #endif
 
-	return PAGE_ALIGN(start_mem);
 }
 
 static int srmmu_mmu_info(char *buf)
@@ -2012,7 +1438,7 @@
 		flush_cache_mm(mm);
 
 		ctxp = &srmmu_context_table[mm->context];
-		srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (srmmu_v2p((unsigned long) swapper_pg_dir) >> 4))));
+		srmmu_set_entry((pte_t *)ctxp, __pte((SRMMU_ET_PTD | (__pa((unsigned long) swapper_pg_dir) >> 4))));
 		hypersparc_flush_page_to_ram((unsigned long)ctxp);
 
 		flush_tlb_mm(mm);
@@ -2127,7 +1553,7 @@
 	BTFIXUPSET_CALL(flush_tlb_range, hypersparc_flush_tlb_range, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_page, hypersparc_flush_tlb_page, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(__flush_page_to_ram, hypersparc_flush_page_to_ram, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_sig_insns, hypersparc_flush_sig_insns, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP);
 
@@ -2201,7 +1627,7 @@
 
 	BTFIXUPSET_CALL(flush_chunk, cypress_flush_chunk, BTFIXUPCALL_NORM); /* local flush _only_ */
 
-	BTFIXUPSET_CALL(flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(__flush_page_to_ram, cypress_flush_page_to_ram, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_sig_insns, cypress_flush_sig_insns, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(flush_page_for_dma, cypress_flush_page_for_dma, BTFIXUPCALL_NOP);
 
@@ -2315,7 +1741,7 @@
 	BTFIXUPSET_CALL(flush_tlb_page, swift_flush_tlb_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_range, swift_flush_tlb_range, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(__flush_page_to_ram, swift_flush_page_to_ram, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_sig_insns, swift_flush_sig_insns, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_page_for_dma, swift_flush_page_for_dma, BTFIXUPCALL_NORM);
 
@@ -2475,7 +1901,7 @@
 	BTFIXUPSET_CALL(flush_tlb_page, turbosparc_flush_tlb_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_range, turbosparc_flush_tlb_range, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(__flush_page_to_ram, turbosparc_flush_page_to_ram, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_chunk, turbosparc_flush_chunk, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(flush_sig_insns, turbosparc_flush_sig_insns, BTFIXUPCALL_NOP);
@@ -2517,7 +1943,7 @@
 	BTFIXUPSET_CALL(flush_tlb_page, tsunami_flush_tlb_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_range, tsunami_flush_tlb_range, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(flush_page_to_ram, tsunami_flush_page_to_ram, BTFIXUPCALL_NOP);
+	BTFIXUPSET_CALL(__flush_page_to_ram, tsunami_flush_page_to_ram, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(flush_sig_insns, tsunami_flush_sig_insns, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_page_for_dma, tsunami_flush_page_for_dma, BTFIXUPCALL_NORM);
 
@@ -2574,7 +2000,7 @@
 	BTFIXUPCOPY_CALL(flush_cache_mm, local_flush_cache_mm);
 	BTFIXUPCOPY_CALL(flush_cache_range, local_flush_cache_range);
 	BTFIXUPCOPY_CALL(flush_cache_page, local_flush_cache_page);
-	BTFIXUPCOPY_CALL(flush_page_to_ram, local_flush_page_to_ram);
+	BTFIXUPCOPY_CALL(__flush_page_to_ram, local_flush_page_to_ram);
 	BTFIXUPCOPY_CALL(flush_sig_insns, local_flush_sig_insns);
 	BTFIXUPCOPY_CALL(flush_page_for_dma, local_flush_page_for_dma);
 	btfixup();
@@ -2637,7 +2063,7 @@
 		BTFIXUPSET_CALL(flush_tlb_range, viking_flush_tlb_range, BTFIXUPCALL_NORM);
 	}
 
-	BTFIXUPSET_CALL(flush_page_to_ram, viking_flush_page_to_ram, BTFIXUPCALL_NOP);
+	BTFIXUPSET_CALL(__flush_page_to_ram, viking_flush_page_to_ram, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(flush_sig_insns, viking_flush_sig_insns, BTFIXUPCALL_NOP);
 
 	poke_srmmu = poke_viking;
@@ -2883,7 +2309,7 @@
 	BTFIXUPSET_CALL(set_pte, srmmu_set_pte_cacheable, BTFIXUPCALL_SWAPO0O1);
 	BTFIXUPSET_CALL(switch_mm, srmmu_switch_mm, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(pte_page, srmmu_pte_page, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(pte_pagenr, srmmu_pte_pagenr, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pmd_page, srmmu_pmd_page, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(pgd_page, srmmu_pgd_page, BTFIXUPCALL_NORM);
 
@@ -2934,12 +2360,11 @@
 	BTFIXUPSET_CALL(destroy_context, srmmu_destroy_context, BTFIXUPCALL_NORM);
 	
 	BTFIXUPSET_CALL(mmu_info, srmmu_mmu_info, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(mmu_v2p, srmmu_v2p, BTFIXUPCALL_NORM);
-	BTFIXUPSET_CALL(mmu_p2v, srmmu_p2v, BTFIXUPCALL_NORM);
 
 	/* Task struct and kernel stack allocating/freeing. */
 	BTFIXUPSET_CALL(alloc_task_struct, srmmu_alloc_task_struct, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(free_task_struct, srmmu_free_task_struct, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(get_task_struct, srmmu_get_task_struct, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(quick_kernel_fault, srmmu_quick_kernel_fault, BTFIXUPCALL_NORM);
 
@@ -2966,7 +2391,7 @@
 	BTFIXUPCOPY_CALL(local_flush_tlb_mm, flush_tlb_mm);
 	BTFIXUPCOPY_CALL(local_flush_tlb_range, flush_tlb_range);
 	BTFIXUPCOPY_CALL(local_flush_tlb_page, flush_tlb_page);
-	BTFIXUPCOPY_CALL(local_flush_page_to_ram, flush_page_to_ram);
+	BTFIXUPCOPY_CALL(local_flush_page_to_ram, __flush_page_to_ram);
 	BTFIXUPCOPY_CALL(local_flush_sig_insns, flush_sig_insns);
 	BTFIXUPCOPY_CALL(local_flush_page_for_dma, flush_page_for_dma);
 
@@ -2980,7 +2405,7 @@
 		BTFIXUPSET_CALL(flush_tlb_range, smp_flush_tlb_range, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_page, smp_flush_tlb_page, BTFIXUPCALL_NORM);
 	}
-	BTFIXUPSET_CALL(flush_page_to_ram, smp_flush_page_to_ram, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(__flush_page_to_ram, smp_flush_page_to_ram, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_sig_insns, smp_flush_sig_insns, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_page_for_dma, smp_flush_page_for_dma, BTFIXUPCALL_NORM);
 #endif
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.3.39/linux/arch/sparc/mm/sun4c.c	Tue Jan 11 22:31:38 2000
+++ linux/arch/sparc/mm/sun4c.c	Sat Jan 15 22:08:28 2000
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.183 2000/01/08 16:38:20 anton Exp $
+/* $Id: sun4c.c,v 1.185 2000/01/15 00:51:32 anton Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -1148,21 +1148,23 @@
 	unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr));
 	int entry = BUCKET_NUM(tsaddr);
 
-	/* We are deleting a mapping, so the flush here is mandatory. */
-	sun4c_flush_page_hw(tsaddr);
+	if (atomic_dec_and_test(&(tsk)->thread.refcount)) {
+		/* We are deleting a mapping, so the flush here is mandatory. */
+		sun4c_flush_page_hw(tsaddr);
 #ifndef CONFIG_SUN4	
-	sun4c_flush_page_hw(tsaddr + PAGE_SIZE);
+		sun4c_flush_page_hw(tsaddr + PAGE_SIZE);
 #endif
-	sun4c_put_pte(tsaddr, 0);
+		sun4c_put_pte(tsaddr, 0);
 #ifndef CONFIG_SUN4	
-	sun4c_put_pte(tsaddr + PAGE_SIZE, 0);
+		sun4c_put_pte(tsaddr + PAGE_SIZE, 0);
 #endif
-	sun4c_bucket[entry] = BUCKET_EMPTY;
-	if (entry < sun4c_lowbucket_avail)
-		sun4c_lowbucket_avail = entry;
+		sun4c_bucket[entry] = BUCKET_EMPTY;
+		if (entry < sun4c_lowbucket_avail)
+			sun4c_lowbucket_avail = entry;
 
-	free_pages(pages, TASK_STRUCT_ORDER);
-	garbage_collect(entry);
+		free_pages(pages, TASK_STRUCT_ORDER);
+		garbage_collect(entry);
+	}
 }
 
 static void sun4c_free_task_struct_sw(struct task_struct *tsk)
@@ -1171,21 +1173,28 @@
 	unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr));
 	int entry = BUCKET_NUM(tsaddr);
 
-	/* We are deleting a mapping, so the flush here is mandatory. */
-	sun4c_flush_page_sw(tsaddr);
+	if (atomic_dec_and_test(&(tsk)->thread.refcount)) {
+		/* We are deleting a mapping, so the flush here is mandatory. */
+		sun4c_flush_page_sw(tsaddr);
 #ifndef CONFIG_SUN4	
-	sun4c_flush_page_sw(tsaddr + PAGE_SIZE);
+		sun4c_flush_page_sw(tsaddr + PAGE_SIZE);
 #endif
-	sun4c_put_pte(tsaddr, 0);
+		sun4c_put_pte(tsaddr, 0);
 #ifndef CONFIG_SUN4	
-	sun4c_put_pte(tsaddr + PAGE_SIZE, 0);
+		sun4c_put_pte(tsaddr + PAGE_SIZE, 0);
 #endif
-	sun4c_bucket[entry] = BUCKET_EMPTY;
-	if (entry < sun4c_lowbucket_avail)
-		sun4c_lowbucket_avail = entry;
+		sun4c_bucket[entry] = BUCKET_EMPTY;
+		if (entry < sun4c_lowbucket_avail)
+			sun4c_lowbucket_avail = entry;
 
-	free_pages(pages, TASK_STRUCT_ORDER);
-	garbage_collect(entry);
+		free_pages(pages, TASK_STRUCT_ORDER);
+		garbage_collect(entry);
+	}
+}
+
+static void sun4c_get_task_struct(struct task_struct *tsk)
+{
+		atomic_inc(&(tsk)->thread.refcount);
 }
 
 static void __init sun4c_init_buckets(void)
@@ -1554,13 +1563,12 @@
 	}
 }
 
-static void sun4c_flush_page_to_ram_hw(struct page *page)
+static void sun4c_flush_page_to_ram_hw(unsigned long page)
 {
 	unsigned long flags;
-	unsigned long addr = page_address(page);
 
 	save_and_cli(flags);
-	sun4c_flush_page_hw(addr);
+	sun4c_flush_page_hw(page);
 	restore_flags(flags);
 }
 
@@ -1677,13 +1685,12 @@
 	}
 }
 
-static void sun4c_flush_page_to_ram_sw(struct page *page)
+static void sun4c_flush_page_to_ram_sw(unsigned long page)
 {
 	unsigned long flags;
-	unsigned long addr = page_address(page);
 
 	save_and_cli(flags);
-	sun4c_flush_page_sw(addr);
+	sun4c_flush_page_sw(page);
 	restore_flags(flags);
 }
 
@@ -2629,7 +2636,7 @@
 		BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page_hw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(flush_page_to_ram, sun4c_flush_page_to_ram_hw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range_hw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page_hw, BTFIXUPCALL_NORM);
@@ -2640,7 +2647,7 @@
 		BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page_sw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(flush_page_to_ram, sun4c_flush_page_to_ram_sw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range_sw, BTFIXUPCALL_NORM);
 		BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page_sw, BTFIXUPCALL_NORM);
@@ -2719,6 +2726,7 @@
 
 	/* Task struct and kernel stack allocating/freeing. */
 	BTFIXUPSET_CALL(alloc_task_struct, sun4c_alloc_task_struct, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(get_task_struct, sun4c_get_task_struct, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(quick_kernel_fault, sun4c_quick_kernel_fault, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM);
diff -u --recursive --new-file v2.3.39/linux/arch/sparc/mm/viking.S linux/arch/sparc/mm/viking.S
--- v2.3.39/linux/arch/sparc/mm/viking.S	Tue Aug 31 17:29:13 1999
+++ linux/arch/sparc/mm/viking.S	Sat Jan 15 22:08:28 2000
@@ -1,4 +1,4 @@
-/* $Id: viking.S,v 1.14 1999/08/14 03:51:50 anton Exp $
+/* $Id: viking.S,v 1.15 2000/01/15 00:51:36 anton Exp $
  * viking.S: High speed Viking cache/mmu operations
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -35,37 +35,14 @@
 	.globl	viking_flush_tlb_all, viking_flush_tlb_mm
 	.globl	viking_flush_tlb_range, viking_flush_tlb_page
 
-	.globl	viking_c_flush_chunk, viking_s_flush_chunk
-
-viking_s_flush_chunk:
-	sethi	%hi(KERNBASE), %g2
-	ba	2f
-	 sub	%o0, %g2, %g3
-
-viking_c_flush_chunk:
-	sethi	%hi(KERNBASE), %g2
-	cmp	%o0, %g2
-	bgeu	2f
-	 sub	%o0, %g2, %g3
-	sethi	BTFIXUP_SETHI(page_contig_offset), %g2
-	ba	2f
-	 sub	%o0, %g2, %g3
-
-viking_flush_page:
 viking_flush_chunk:
-	sethi	%hi(C_LABEL(srmmu_v2p_hash)), %g2
-	srl	%o0, 24, %o1
-	or	%g2, %lo(C_LABEL(srmmu_v2p_hash)), %g2
-	sll	%o1, 2, %o1
-	ld	[%g2 + %o1], %g3
-	and	%o0, PAGE_MASK, %o0
-	cmp	%g3, -1
-	be	9f
-	 add	%o0, %g3, %g3
-2:	srl	%g3, 12, %g1		! ppage >> 12
+viking_flush_page:
+	sethi	%hi(PAGE_OFFSET), %g2
+	sub	%o0, %g2, %g3
+	srl	%g3, 12, %g1		! ppage >> 12
 
 	clr	%o1			! set counter, 0 - 127
-	sethi	%hi(KERNBASE + PAGE_SIZE - 0x80000000), %o3
+	sethi	%hi(PAGE_OFFSET + PAGE_SIZE - 0x80000000), %o3
 	sethi	%hi(0x80000000), %o4
 	sethi	%hi(VIKING_PTAG_VALID), %o5
 	sethi	%hi(2*PAGE_SIZE), %o0
@@ -85,7 +62,7 @@
 
 	andcc	%g2, %o5, %g0		! ptag VALID?
 	be	7f
-	 add	%g4, %o3, %g2		! (KERNBASE + PAGE_SIZE) | (set << 5)
+	 add	%g4, %o3, %g2		! (PAGE_OFFSET + PAGE_SIZE) | (set << 5)
 	ld	[%g2], %g3
 	ld	[%g2 + %g7], %g3
 	add	%g2, %o0, %g2
@@ -113,16 +90,9 @@
 	 nop
 
 viking_mxcc_flush_page:
-	sethi	%hi(C_LABEL(srmmu_v2p_hash)), %g2
-	srl	%o0, 24, %o1
-	or	%g2, %lo(C_LABEL(srmmu_v2p_hash)), %g2
-	sll	%o1, 2, %o1
-	ld	[%g2 + %o1], %g3
-	and	%o0, PAGE_MASK, %o0
-	cmp	%g3, -1
-	be	9f
-	 add	%o0, %g3, %g3
-2:	sub	%g3, -PAGE_SIZE, %g3		! ppage + PAGE_SIZE
+	sethi	%hi(PAGE_OFFSET), %g2
+	sub	%o0, %g2, %g3
+	sub	%g3, -PAGE_SIZE, %g3		! ppage + PAGE_SIZE
 	sethi	%hi(MXCC_SRCSTREAM), %o3	! assume %hi(MXCC_SRCSTREAM) == %hi(MXCC_DESTSTREAM)
 	mov	0x10, %g2			! set cacheable bit
 	or	%o3, %lo(MXCC_SRCSTREAM), %o2
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.3.39/linux/arch/sparc64/config.in	Wed Dec 29 13:13:13 1999
+++ linux/arch/sparc64/config.in	Fri Jan 14 00:50:53 2000
@@ -110,7 +110,7 @@
       define_bool CONFIG_IDEDMA_AUTO y
       define_bool CONFIG_IDEDMA_NEW_DRIVE_LISTINGS y
       define_bool CONFIG_BLK_DEV_NS87415 y
-      define_bool CONFIG_BLK_DEV_CMD646 y
+      define_bool CONFIG_BLK_DEV_CMD64X y
    fi
 fi
 
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.3.39/linux/arch/sparc64/defconfig	Tue Jan  4 13:57:16 2000
+++ linux/arch/sparc64/defconfig	Fri Jan 14 00:50:53 2000
@@ -139,7 +139,7 @@
 CONFIG_IDEDMA_AUTO=y
 CONFIG_IDEDMA_NEW_DRIVE_LISTINGS=y
 CONFIG_BLK_DEV_NS87415=y
-CONFIG_BLK_DEV_CMD646=y
+CONFIG_BLK_DEV_CMD64X=y
 
 #
 # Networking options
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/binfmt_elf32.c linux/arch/sparc64/kernel/binfmt_elf32.c
--- v2.3.39/linux/arch/sparc64/kernel/binfmt_elf32.c	Mon Aug  2 22:07:16 1999
+++ linux/arch/sparc64/kernel/binfmt_elf32.c	Sat Jan 15 22:08:28 2000
@@ -129,6 +129,13 @@
 	char	pr_psargs[ELF_PRARGSZ];	/* initial part of arg list */
 };
 
+#include <linux/highuid.h>
+
+#undef NEW_TO_OLD_UID
+#undef NEW_TO_OLD_GID
+#define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
+#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
+
 #define elf_addr_t	u32
 #define elf_caddr_t	u32
 #undef start_thread
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- v2.3.39/linux/arch/sparc64/kernel/entry.S	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/entry.S	Sat Jan 15 22:08:28 2000
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.110 1999/11/19 05:52:50 davem Exp $
+/* $Id: entry.S,v 1.112 2000/01/14 07:12:31 davem Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -768,9 +768,9 @@
 	/* SunOS getuid() returns uid in %o0 and euid in %o1 */
 	.globl	sunos_getuid
 sunos_getuid:
-	call	sys_geteuid
+	call	sys32_geteuid16
 	 nop
-	call	sys_getuid
+	call	sys32_getuid16
 	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
 	b,pt	%xcc, ret_sys_call
 	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
@@ -778,9 +778,9 @@
 	/* SunOS getgid() returns gid in %o0 and egid in %o1 */
 	.globl	sunos_getgid
 sunos_getgid:
-	call	sys_getegid
+	call	sys32_getegid16
 	 nop
-	call	sys_getgid
+	call	sys32_getgid16
 	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
 	b,pt	%xcc, ret_sys_call
 	 stx	%o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.3.39/linux/arch/sparc64/kernel/ioctl32.c	Tue Jan  4 13:57:16 2000
+++ linux/arch/sparc64/kernel/ioctl32.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.72 2000/01/04 15:43:45 davem Exp $
+/* $Id: ioctl32.c,v 1.73 2000/01/11 01:06:47 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997  Jakub Jelinek  (jj@sunsite.mff.cuni.cz)
@@ -594,6 +594,8 @@
 			err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
 			err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
 			err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
+			if (err)
+				err = -EFAULT;
 			break;
 		}
 	}
@@ -667,7 +669,7 @@
 		err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4);
 		err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start));
 	}
-	return err;
+	return err ? -EFAULT : 0;
 }
 
 struct  fbcmap32 {
@@ -715,7 +717,7 @@
 		ret |= copy_to_user ((char *)A(g), green, f.count);
 		ret |= copy_to_user ((char *)A(b), blue, f.count);
 	}
-	return ret;
+	return ret ? -EFAULT : 0;
 }
 
 struct fbcursor32 {
@@ -826,8 +828,10 @@
 		err |= __get_user(green, &((struct fb_cmap32 *)arg)->green);
 		err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue);
 		err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp);
-		if (err)
+		if (err) {
+			err = -EFAULT;
 			goto out;
+		}
 		err = -ENOMEM;
 		cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
 		if (!cmap.red)
@@ -851,8 +855,10 @@
 		err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16));
 		err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16));
 		if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16));
-		if (err)
+		if (err) {
+			err = -EFAULT;
 			goto out;
+		}
 		break;
 	default:
 		do {
@@ -896,6 +902,9 @@
 	case FBIOPUTCMAP:
 		break;
 	}
+	if (err)
+		err = -EFAULT;
+
 out:	if (cmap.red) kfree(cmap.red);
 	if (cmap.green) kfree(cmap.green);
 	if (cmap.blue) kfree(cmap.blue);
@@ -1064,8 +1073,10 @@
 			err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
 			err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
 			err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
-			if (err)
+			if (err) {
+				err = -EFAULT;
 				goto out;
+			}
 			break;
 		}
 		case FDSETDRVPRM32:
@@ -1097,8 +1108,10 @@
 			err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect));
 			err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
 			err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
-			if (err)
+			if (err) {
+				err = -EFAULT;
 				goto out;
+			}
 			break;
 		}
 		case FDGETDRVSTAT32:
@@ -1221,6 +1234,9 @@
 		default:
 			break;
 	}
+	if (err)
+		err = -EFAULT;
+
 out:	if (karg) kfree(karg);
 	return err;
 }
@@ -1396,8 +1412,7 @@
 		return err;
 	switch (cmd) {
 	case MTIOCPOS32:
-		if (__put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno))
-			return -EFAULT;
+		err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno);
 		break;
 	case MTIOCGET32:
 		err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type);
@@ -1422,7 +1437,7 @@
 	case MTIOCSETCONFIG32:
 		break;
 	}
-	return err;
+	return err ? -EFAULT: 0;
 }
 
 struct cdrom_read32 {
@@ -1438,11 +1453,21 @@
 	__kernel_caddr_t32	buf;
 };
 
+struct cdrom_generic_command32 {
+	unsigned char		cmd[CDROM_PACKET_SIZE];
+	__kernel_caddr_t32	buffer;
+	unsigned int		buflen;
+	int			stat;
+	__kernel_caddr_t32	sense;
+	__kernel_caddr_t32	reserved[3];
+};
+
 static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
 	struct cdrom_read cdread;
 	struct cdrom_read_audio cdreadaudio;
+	struct cdrom_generic_command cgc;
 	__kernel_caddr_t32 addr;
 	char *data = 0;
 	void *karg;
@@ -1477,6 +1502,17 @@
 			return -ENOMEM;
 		cdreadaudio.buf = data;
 		break;
+	case CDROM_SEND_PACKET:
+		karg = &cgc;
+		err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd));
+		err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
+		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
+		if (err)
+			return -EFAULT;
+		if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL)
+			return -ENOMEM;
+		cgc.buffer = data;
+		break;
 	default:
 		do {
 			static int count = 0;
@@ -1502,11 +1538,15 @@
 	case CDROMREADAUDIO:
 		err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352);
 		break;
+	case CDROM_SEND_PACKET:
+		err = copy_to_user((char *)A(addr), data, cgc.buflen);
+		break;
 	default:
 		break;
 	}
-out:	if (data) kfree(data);
-	return err;
+out:	if (data)
+		kfree(data);
+	return err ? -EFAULT : 0;
 }
 
 struct loop_info32 {
@@ -1558,7 +1598,7 @@
 		}
 		break;
 	}
-	return err;
+	return err ? -EFAULT : 0;
 }
 
 extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
@@ -1835,6 +1875,7 @@
 	case CDROMREADCOOKED:
 	case CDROMREADAUDIO:
 	case CDROMREADALL:
+	case CDROM_SEND_PACKET:
 		error = cdrom_ioctl_trans(fd, cmd, arg);
 		goto out;
 		
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- v2.3.39/linux/arch/sparc64/kernel/pci.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/sparc64/kernel/pci.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.13 2000/01/06 23:51:49 davem Exp $
+/* $Id: pci.c,v 1.14 2000/01/13 00:05:43 davem Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -226,6 +226,11 @@
 int pci_assign_resource(struct pci_dev *dev, int i)
 {
 	return -ENOSYS; /* :-)... actually implement this soon */
+}
+
+int pcibios_enable_device(struct pci_dev *pdev)
+{
+	return 0;
 }
 
 char * __init pcibios_setup(char *str)
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.3.39/linux/arch/sparc64/kernel/pci_psycho.c	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/pci_psycho.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.7 1999/12/17 12:31:57 jj Exp $
+/* $Id: pci_psycho.c,v 1.9 2000/01/11 23:38:32 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1278,6 +1278,11 @@
 	p->iommu.page_table = (iopte_t *)tsbbase;
 	p->iommu.page_table_sz_bits = 17;
 	p->iommu.page_table_map_base = 0xc0000000;
+#ifndef NEW_PCI_DMA_MAP
+	memset((char *)tsbbase, 0, PAGE_SIZE << 5);
+#else
+	memset((char *)tsbbase, 0, PAGE_SIZE << 7);
+#endif
 
 #ifndef NEW_PCI_DMA_MAP
 	iopte = (iopte_t *)tsbbase;
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.3.39/linux/arch/sparc64/kernel/pci_sabre.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/sparc64/kernel/pci_sabre.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.8 2000/01/06 23:51:49 davem Exp $
+/* $Id: pci_sabre.c,v 1.10 2000/01/11 23:38:35 davem Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1148,6 +1148,7 @@
 	}
 	p->iommu.page_table = (iopte_t *)tsbbase;
 	p->iommu.page_table_map_base = dvma_offset;
+	memset((char *)tsbbase, 0, PAGE_SIZE << order);
 
 #ifndef NEW_PCI_DMA_MAP
 	iopte = (iopte_t *)tsbbase;
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/signal32.c linux/arch/sparc64/kernel/signal32.c
--- v2.3.39/linux/arch/sparc64/kernel/signal32.c	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/signal32.c	Sat Jan 15 22:08:28 2000
@@ -1,4 +1,4 @@
-/*  $Id: signal32.c,v 1.56 1999/12/20 01:16:16 davem Exp $
+/*  $Id: signal32.c,v 1.58 2000/01/14 09:40:08 jj Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/sys32.S linux/arch/sparc64/kernel/sys32.S
--- v2.3.39/linux/arch/sparc64/kernel/sys32.S	Wed Dec 29 13:13:14 1999
+++ linux/arch/sparc64/kernel/sys32.S	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: sys32.S,v 1.9 1999/12/21 14:09:18 jj Exp $
+/* $Id: sys32.S,v 1.11 2000/01/11 17:33:29 jj Exp $
  * sys32.S: I-cache tricks for 32-bit compatability layer simple
  *          conversions.
  *
@@ -20,7 +20,7 @@
 
 	.align		32
 	.globl		sys32_lseek
-	.globl		sys32_chmod, sys32_chown, sys32_lchown, sys32_mknod
+	.globl		sys32_chmod, sys32_mknod
 sys32_lseek:
 	sra		%o1, 0, %o1
 	sethi		%hi(sys_lseek), %g1
@@ -32,20 +32,6 @@
 	orcc		%g2, %lo(0xffff), %g2
 	jmpl		%g1 + %lo(sys_chmod), %g0
 	 and		%o1, %g2, %o1
-sys32_chown:
-	sethi		%hi(0xffff), %g2
-	sethi		%hi(sys_chown), %g1
-	orcc		%g2, %lo(0xffff), %g2
-	and		%o1, %g2, %o1
-	jmpl		%g1 + %lo(sys_chown), %g0
-	 and		%o2, %g2, %o2
-sys32_lchown:
-	sethi		%hi(0xffff), %g2
-	sethi		%hi(sys_lchown), %g1
-	orcc		%g2, %lo(0xffff), %g2
-	and		%o1, %g2, %o1
-	jmpl		%g1 + %lo(sys_lchown), %g0
-	 and		%o2, %g2, %o2
 sys32_mknod:
 	sethi		%hi(0xffff), %g2
 	sethi		%hi(sys_mknod), %g1
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- v2.3.39/linux/arch/sparc64/kernel/sys_sparc.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/sparc64/kernel/sys_sparc.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.32 2000/01/05 01:00:40 davem Exp $
+/* $Id: sys_sparc.c,v 1.33 2000/01/11 17:33:25 jj Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -22,6 +22,7 @@
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/malloc.h>
+#include <linux/ipc.h>
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
@@ -98,7 +99,7 @@
 			err = -EFAULT;
 			if(get_user(fourth.__pad, (void **)ptr))
 				goto out;
-			err = sys_semctl (first, second, (int)third, fourth);
+			err = sys_semctl (first, second | IPC_64, (int)third, fourth);
 			goto out;
 			}
 		default:
@@ -118,7 +119,7 @@
 			err = sys_msgget ((key_t) first, second);
 			goto out;
 		case MSGCTL:
-			err = sys_msgctl (first, second, (struct msqid_ds *) ptr);
+			err = sys_msgctl (first, second | IPC_64, (struct msqid_ds *) ptr);
 			goto out;
 		default:
 			err = -EINVAL;
@@ -136,7 +137,7 @@
 			err = sys_shmget (first, second, (int)third);
 			goto out;
 		case SHMCTL:
-			err = sys_shmctl (first, second, (struct shmid_ds *) ptr);
+			err = sys_shmctl (first, second | IPC_64, (struct shmid_ds *) ptr);
 			goto out;
 		default:
 			err = -EINVAL;
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.3.39/linux/arch/sparc64/kernel/sys_sparc32.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Sat Jan 15 22:08:29 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.127 2000/01/04 23:54:41 davem Exp $
+/* $Id: sys_sparc32.c,v 1.130 2000/01/14 09:40:07 jj Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -43,6 +43,7 @@
 #include <linux/stat.h>
 #include <linux/filter.h>
 #include <linux/highmem.h>
+#include <linux/highuid.h>
 
 #include <asm/types.h>
 #include <asm/ipc.h>
@@ -76,6 +77,181 @@
 	__ret;				\
 })
 
+extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
+extern asmlinkage long sys_setregid(gid_t, gid_t);
+extern asmlinkage long sys_setgid(gid_t);
+extern asmlinkage long sys_setreuid(uid_t, uid_t);
+extern asmlinkage long sys_setuid(uid_t);
+extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
+extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
+extern asmlinkage long sys_setfsuid(uid_t);
+extern asmlinkage long sys_setfsgid(gid_t);
+ 
+/* For this source file, we want overflow handling. */
+
+#undef high2lowuid
+#undef high2lowgid
+#undef low2highuid
+#undef low2highgid
+#undef SET_UID16
+#undef SET_GID16
+#undef NEW_TO_OLD_UID
+#undef NEW_TO_OLD_GID
+#undef SET_OLDSTAT_UID
+#undef SET_OLDSTAT_GID
+#undef SET_STAT_UID
+#undef SET_STAT_GID
+
+#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
+#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
+#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
+#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
+#define SET_UID16(var, uid)	var = high2lowuid(uid)
+#define SET_GID16(var, gid)	var = high2lowgid(gid)
+#define NEW_TO_OLD_UID(uid)	high2lowuid(uid)
+#define NEW_TO_OLD_GID(gid)	high2lowgid(gid)
+#define SET_OLDSTAT_UID(stat, uid)	(stat).st_uid = high2lowuid(uid)
+#define SET_OLDSTAT_GID(stat, gid)	(stat).st_gid = high2lowgid(gid)
+#define SET_STAT_UID(stat, uid)		(stat).st_uid = high2lowuid(uid)
+#define SET_STAT_GID(stat, gid)		(stat).st_gid = high2lowgid(gid)
+
+asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
+{
+	return sys_chown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
+{
+	return sys_lchown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
+{
+	return sys_fchown(fd, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
+{
+	return sys_setregid(low2highgid(rgid), low2highgid(egid));
+}
+
+asmlinkage long sys32_setgid16(u16 gid)
+{
+	return sys_setgid((gid_t)gid);
+}
+
+asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
+{
+	return sys_setreuid(low2highuid(ruid), low2highuid(euid));
+}
+
+asmlinkage long sys32_setuid16(u16 uid)
+{
+	return sys_setuid((uid_t)uid);
+}
+
+asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
+{
+	return sys_setresuid(low2highuid(ruid), low2highuid(euid),
+		low2highuid(suid));
+}
+
+asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
+{
+	int retval;
+
+	if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
+	    !(retval = put_user(high2lowuid(current->euid), euid)))
+		retval = put_user(high2lowuid(current->suid), suid);
+
+	return retval;
+}
+
+asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
+{
+	return sys_setresgid(low2highgid(rgid), low2highgid(egid),
+		low2highgid(sgid));
+}
+
+asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
+{
+	int retval;
+
+	if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
+	    !(retval = put_user(high2lowgid(current->egid), egid)))
+		retval = put_user(high2lowgid(current->sgid), sgid);
+
+	return retval;
+}
+
+asmlinkage long sys32_setfsuid16(u16 uid)
+{
+	return sys_setfsuid((uid_t)uid);
+}
+
+asmlinkage long sys32_setfsgid16(u16 gid)
+{
+	return sys_setfsgid((gid_t)gid);
+}
+
+asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
+{
+	u16 groups[NGROUPS];
+	int i,j;
+
+	if (gidsetsize < 0)
+		return -EINVAL;
+	i = current->ngroups;
+	if (gidsetsize) {
+		if (i > gidsetsize)
+			return -EINVAL;
+		for(j=0;j<i;j++)
+			groups[j] = current->groups[j];
+		if (copy_to_user(grouplist, groups, sizeof(u16)*i))
+			return -EFAULT;
+	}
+	return i;
+}
+
+asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
+{
+	u16 groups[NGROUPS];
+	int i;
+
+	if (!capable(CAP_SETGID))
+		return -EPERM;
+	if ((unsigned) gidsetsize > NGROUPS)
+		return -EINVAL;
+	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
+		return -EFAULT;
+	for (i = 0 ; i < gidsetsize ; i++)
+		current->groups[i] = (gid_t)groups[i];
+	current->ngroups = gidsetsize;
+	return 0;
+}
+
+asmlinkage long sys32_getuid16(void)
+{
+	return high2lowuid(current->uid);
+}
+
+asmlinkage long sys32_geteuid16(void)
+{
+	return high2lowuid(current->euid);
+}
+
+asmlinkage long sys32_getgid16(void)
+{
+	return high2lowgid(current->gid);
+}
+
+asmlinkage long sys32_getegid16(void)
+{
+	return high2lowgid(current->egid);
+}
+
 /* In order to reduce some races, while at the same time doing additional
  * checking and hopefully speeding things up, we copy filenames to the
  * kernel data space before using them..
@@ -191,6 +367,17 @@
         unsigned short  sem_nsems;              /* no. of semaphores in array */
 };
 
+struct semid64_ds32 {
+	struct ipc64_perm sem_perm;		  /* this structure is the same on sparc32 and sparc64 */
+	unsigned int	  __pad1;
+	__kernel_time_t32 sem_otime;
+	unsigned int	  __pad2;
+	__kernel_time_t32 sem_ctime;
+	u32 sem_nsems;
+	u32 __unused1;
+	u32 __unused2;
+};
+
 struct msqid_ds32
 {
         struct ipc_perm32 msg_perm;
@@ -208,16 +395,51 @@
         __kernel_ipc_pid_t32 msg_lrpid;
 };
 
+struct msqid64_ds32 {
+	struct ipc64_perm msg_perm;
+	unsigned int   __pad1;
+	__kernel_time_t32 msg_stime;
+	unsigned int   __pad2;
+	__kernel_time_t32 msg_rtime;
+	unsigned int   __pad3;
+	__kernel_time_t32 msg_ctime;
+	unsigned int  msg_cbytes;
+	unsigned int  msg_qnum;
+	unsigned int  msg_qbytes;
+	__kernel_pid_t32 msg_lspid;
+	__kernel_pid_t32 msg_lrpid;
+	unsigned int  __unused1;
+	unsigned int  __unused2;
+};
+
+
 struct shmid_ds32 {
-        struct ipc_perm32       shm_perm;
-        int                     shm_segsz;
-        __kernel_time_t32       shm_atime;
-        __kernel_time_t32       shm_dtime;
-        __kernel_time_t32       shm_ctime;
-        __kernel_ipc_pid_t32    shm_cpid; 
-        __kernel_ipc_pid_t32    shm_lpid; 
-        unsigned short          shm_nattch;
+	struct ipc_perm32       shm_perm;
+	int                     shm_segsz;
+	__kernel_time_t32       shm_atime;
+	__kernel_time_t32       shm_dtime;
+	__kernel_time_t32       shm_ctime;
+	__kernel_ipc_pid_t32    shm_cpid; 
+	__kernel_ipc_pid_t32    shm_lpid; 
+	unsigned short          shm_nattch;
+};
+
+struct shmid64_ds32 {
+	struct ipc64_perm	shm_perm;
+	unsigned int		__pad1;
+	__kernel_time_t32	shm_atime;
+	unsigned int		__pad2;
+	__kernel_time_t32	shm_dtime;
+	unsigned int		__pad3;
+	__kernel_time_t32	shm_ctime;
+	__kernel_size_t32	shm_segsz;
+	__kernel_pid_t32	shm_cpid;
+	__kernel_pid_t32	shm_lpid;
+	unsigned int		shm_nattch;
+	unsigned int		__unused1;
+	unsigned int		__unused2;
 };
+
                                                         
 /*
  * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
@@ -245,6 +467,34 @@
 	     IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
 	     IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
 		err = sys_semctl (first, second, third, fourth);
+	} else if (third & IPC_64) {
+		struct semid64_ds s;
+		struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
+		mm_segment_t old_fs;
+		int need_back_translation;
+
+		if (third == (IPC_SET|IPC_64)) {
+			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
+			err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
+			err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
+			if (err)
+				goto out;
+			fourth.__pad = &s;
+		}
+		need_back_translation =
+			(IPCOP_MASK (third) &
+			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
+		if (need_back_translation)
+			fourth.__pad = &s;
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_semctl (first, second, third, fourth);
+		set_fs (old_fs);
+		if (need_back_translation) {
+			int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t));
+			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
+			if (err2) err = -EFAULT;
+		}
 	} else {
 		struct semid_ds s;
 		struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
@@ -270,10 +520,10 @@
 		set_fs (old_fs);
 		if (need_back_translation) {
 			int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
-			err2 |= __put_user (s.sem_perm.uid, &usp->sem_perm.uid);
-			err2 |= __put_user (s.sem_perm.gid, &usp->sem_perm.gid);
-			err2 |= __put_user (s.sem_perm.cuid, &usp->sem_perm.cuid);
-			err2 |= __put_user (s.sem_perm.cgid, &usp->sem_perm.cgid);
+			err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
+			err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
+			err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
+			err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
 			err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
 			err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
 			err2 |= __put_user (s.sem_otime, &usp->sem_otime);
@@ -357,6 +607,34 @@
 	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
 	     IPCOP_MASK (IPC_RMID))) {
 		err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
+	} else if (second & IPC_64) {
+		struct msqid64_ds m;
+		struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == (IPC_SET|IPC_64)) {
+			err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
+			err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
+			err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
+			err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_msgctl (first, second, (struct msqid_ds *)&m);
+		set_fs (old_fs);
+		if (IPCOP_MASK (second) &
+		    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = copy_to_user(&up->msg_perm, &m.msg_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
+			err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
+			err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
+			err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
+			err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
+			err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
+			if (err2)
+				err = -EFAULT;
+		}
 	} else {
 		struct msqid_ds m;
 		struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
@@ -377,10 +655,10 @@
 		if (IPCOP_MASK (second) &
 		    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
 			int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
-			err2 |= __put_user (m.msg_perm.uid, &up->msg_perm.uid);
-			err2 |= __put_user (m.msg_perm.gid, &up->msg_perm.gid);
-			err2 |= __put_user (m.msg_perm.cuid, &up->msg_perm.cuid);
-			err2 |= __put_user (m.msg_perm.cgid, &up->msg_perm.cgid);
+			err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
+			err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
+			err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
+			err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
 			err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
 			err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
 			err2 |= __put_user (m.msg_stime, &up->msg_stime);
@@ -423,12 +701,45 @@
 	if (IPCOP_MASK (second) &
 	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
 	     IPCOP_MASK (IPC_RMID))) {
+		if (second == (IPC_INFO|IPC_64))
+			second = IPC_INFO; /* So that we don't have to translate it */
 		err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
+	} else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
+		struct shmid64_ds s;
+		struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == (IPC_SET|IPC_64)) {
+			err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
+			err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
+			err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_shmctl (first, second, (struct shmid_ds *)&s);
+		set_fs (old_fs);
+		if (err < 0)
+			goto out;
+
+		/* Mask it even in this case so it becomes a CSE. */
+		if (IPCOP_MASK (second) &
+		    (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = copy_to_user (&up->shm_perm, &s.shm_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
+			err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
+			err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
+			err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
+			err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
+			if (err2)
+				err = -EFAULT;
+		}
 	} else {
 		struct shmid_ds s;
 		struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
 		mm_segment_t old_fs;
 
+		second &= ~IPC_64;
 		if (second == IPC_SET) {
 			err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
 			err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
@@ -462,10 +773,10 @@
 		} else if (IPCOP_MASK (second) &
 			   (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
 			int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
-			err2 |= __put_user (s.shm_perm.uid, &up->shm_perm.uid);
-			err2 |= __put_user (s.shm_perm.gid, &up->shm_perm.gid);
-			err2 |= __put_user (s.shm_perm.cuid, &up->shm_perm.cuid);
-			err2 |= __put_user (s.shm_perm.cgid, &up->shm_perm.cgid);
+			err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
+			err2 |= __put_user (high2lowuid(s.shm_perm.gid), &up->shm_perm.gid);
+			err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
+			err2 |= __put_user (high2lowuid(s.shm_perm.cgid), &up->shm_perm.cgid);
 			err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
 			err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
 			err2 |= __put_user (s.shm_atime, &up->shm_atime);
@@ -1244,8 +1555,8 @@
 	err |= put_user(ino, &statbuf->st_ino);
 	err |= put_user(mode, &statbuf->st_mode);
 	err |= put_user(nlink, &statbuf->st_nlink);
-	err |= put_user(uid, &statbuf->st_uid);
-	err |= put_user(gid, &statbuf->st_gid);
+	err |= put_user(high2lowuid(uid), &statbuf->st_uid);
+	err |= put_user(high2lowgid(gid), &statbuf->st_gid);
 	err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
 	err |= put_user(size, &statbuf->st_size);
 	err |= put_user(atime, &statbuf->st_atime);
@@ -1392,11 +1703,11 @@
 
 	n->dir_mode = n32->dir_mode;
 	n->file_mode = n32->file_mode;
-	n->gid = n32->gid;
-	n->uid = n32->uid;
+	n->gid = low2highgid(n32->gid);
+	n->uid = low2highuid(n32->uid);
 	memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
 	n->wdog_pid = n32->wdog_pid;
-	n->mounted_uid = n32->mounted_uid;
+	n->mounted_uid = low2highuid(n32->mounted_uid);
 	return raw_data;
 }
 
@@ -1415,9 +1726,9 @@
 	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
 
 	s->version = s32->version;
-	s->mounted_uid = s32->mounted_uid;
-	s->uid = s32->uid;
-	s->gid = s32->gid;
+	s->mounted_uid = low2highuid(s32->mounted_uid);
+	s->uid = low2highuid(s32->uid);
+	s->gid = low2highgid(s32->gid);
 	s->file_mode = s32->file_mode;
 	s->dir_mode = s32->dir_mode;
 	return raw_data;
@@ -1853,91 +2164,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_setreuid(uid_t ruid, uid_t euid);
-
-asmlinkage int sys32_setreuid(__kernel_uid_t32 ruid, __kernel_uid_t32 euid)
-{
-	uid_t sruid, seuid;
-
-	sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
-	seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
-	return sys_setreuid(sruid, seuid);
-}
-
-extern asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
-
-asmlinkage int sys32_setresuid(__kernel_uid_t32 ruid,
-			       __kernel_uid_t32 euid,
-			       __kernel_uid_t32 suid)
-{
-	uid_t sruid, seuid, ssuid;
-
-	sruid = (ruid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)ruid);
-	seuid = (euid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)euid);
-	ssuid = (suid == (__kernel_uid_t32)-1) ? ((uid_t)-1) : ((uid_t)suid);
-	return sys_setresuid(sruid, seuid, ssuid);
-}
-
-extern asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid);
-
-asmlinkage int sys32_getresuid(__kernel_uid_t32 *ruid, __kernel_uid_t32 *euid, __kernel_uid_t32 *suid)
-{
-	uid_t a, b, c;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-		
-	set_fs (KERNEL_DS);
-	ret = sys_getresuid(&a, &b, &c);
-	set_fs (old_fs);
-	if (put_user (a, ruid) || put_user (b, euid) || put_user (c, suid))
-		return -EFAULT;
-	return ret;
-}
-
-extern asmlinkage int sys_setregid(gid_t rgid, gid_t egid);
-
-asmlinkage int sys32_setregid(__kernel_gid_t32 rgid, __kernel_gid_t32 egid)
-{
-	gid_t srgid, segid;
-
-	srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
-	segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
-	return sys_setregid(srgid, segid);
-}
-
-extern asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
-
-asmlinkage int sys32_setresgid(__kernel_gid_t32 rgid,
-			       __kernel_gid_t32 egid,
-			       __kernel_gid_t32 sgid)
-{
-	gid_t srgid, segid, ssgid;
-
-	srgid = (rgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)rgid);
-	segid = (egid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)egid);
-	ssgid = (sgid == (__kernel_gid_t32)-1) ? ((gid_t)-1) : ((gid_t)sgid);
-	return sys_setresgid(srgid, segid, ssgid);
-}
-
-extern asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);
-
-asmlinkage int sys32_getresgid(__kernel_gid_t32 *rgid, __kernel_gid_t32 *egid, __kernel_gid_t32 *sgid)
-{
-	gid_t a, b, c;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-		
-	set_fs (KERNEL_DS);
-	ret = sys_getresgid(&a, &b, &c);
-	set_fs (old_fs);
-	if (!ret) {
-		ret = put_user (a, rgid);
-		ret |= put_user (b, egid);
-		ret |= put_user (c, sgid);
-	}
-	return ret;
-}
-
 struct tms32 {
 	__kernel_clock_t32 tms_utime;
 	__kernel_clock_t32 tms_stime;
@@ -1968,43 +2194,6 @@
 	return ret;
 }
 
-extern asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist);
-
-asmlinkage int sys32_getgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
-{
-	gid_t gl[NGROUPS];
-	int ret, i;
-	mm_segment_t old_fs = get_fs ();
-	
-	set_fs (KERNEL_DS);
-	ret = sys_getgroups(gidsetsize, gl);
-	set_fs (old_fs);
-	if (gidsetsize && ret > 0 && ret <= NGROUPS)
-		for (i = 0; i < ret; i++, grouplist++)
-			if (__put_user (gl[i], grouplist))
-				return -EFAULT;
-	return ret;
-}
-
-extern asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist);
-
-asmlinkage int sys32_setgroups(int gidsetsize, __kernel_gid_t32 *grouplist)
-{
-	gid_t gl[NGROUPS];
-	int ret, i;
-	mm_segment_t old_fs = get_fs ();
-	
-	if ((unsigned) gidsetsize > NGROUPS)
-		return -EINVAL;
-	for (i = 0; i < gidsetsize; i++, grouplist++)
-		if (__get_user (gl[i], grouplist))
-			return -EFAULT;
-        set_fs (KERNEL_DS);
-	ret = sys_setgroups(gidsetsize, gl);
-	set_fs (old_fs);
-	return ret;
-}
-
 #define RLIM_INFINITY32	0x7fffffff
 #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
 
@@ -3554,6 +3743,8 @@
 		      &arg32->ca32_export.ex32_anon_uid);
 	err |= __get_user(karg->ca_export.ex_anon_gid,
 		      &arg32->ca32_export.ex32_anon_gid);
+	karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
+	karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
 	return err;
 }
 
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.3.39/linux/arch/sparc64/kernel/systbls.S	Fri Jan  7 19:13:21 2000
+++ linux/arch/sparc64/kernel/systbls.S	Sat Jan 15 22:08:29 2000
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.62 2000/01/04 23:54:43 davem Exp $
+/* $Id: systbls.S,v 1.65 2000/01/14 07:12:34 davem Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -21,30 +21,30 @@
 sys_call_table32:
 /*0*/	.word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write
 /*5*/	.word sparc32_open, sys_close, sys32_wait4, sys_creat, sys_link
-/*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys32_chown, sys32_mknod
-/*15*/	.word sys32_chmod, sys32_lchown, sparc_brk, sys_perfctr, sys32_lseek
-/*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
+/*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys32_chown16, sys32_mknod
+/*15*/	.word sys32_chmod, sys32_lchown16, sparc_brk, sys_perfctr, sys32_lseek
+/*20*/	.word sys_getpid, sys_capget, sys_capset, sys32_setuid16, sys32_getuid16
 /*25*/	.word sys_time, sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause
-/*30*/	.word sys32_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
-	.word sys_nis_syscall, sys_sync, sys_kill, sys32_newstat, sys32_sendfile
-/*40*/	.word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_nis_syscall
-	.word sys_umount, sys_setgid, sys_getgid, sys_signal, sys_geteuid
-/*50*/	.word sys_getegid, sys_acct, sys_nis_syscall, sys_nis_syscall, sys32_ioctl
+/*30*/	.word sys32_utime, sys_lchown, sys_fchown, sys_access, sys_nice
+	.word sys_chown, sys_sync, sys_kill, sys32_newstat, sys32_sendfile
+/*40*/	.word sys32_newlstat, sys_dup, sys_pipe, sys32_times, sys_getuid
+	.word sys_umount, sys32_setgid16, sys32_getgid16, sys_signal, sys32_geteuid16
+/*50*/	.word sys32_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys32_ioctl
 	.word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve
 /*60*/	.word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize
-	.word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_nis_syscall
-/*70*/	.word sys_nis_syscall, sys32_mmap, sys_nis_syscall, sys_munmap, sys_mprotect
-	.word sys_nis_syscall, sys_vhangup, sys32_truncate64, sys_nis_syscall, sys32_getgroups
-/*80*/	.word sys32_setgroups, sys_getpgrp, sys_nis_syscall, sys32_setitimer, sys32_ftruncate64
-	.word sys_swapon, sys32_getitimer, sys_nis_syscall, sys_sethostname, sys_nis_syscall
-/*90*/	.word sys_dup2, sys_nis_syscall, sys32_fcntl, sys32_select, sys_nis_syscall
+	.word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_geteuid
+/*70*/	.word sys_getegid, sys32_mmap, sys_setreuid, sys_munmap, sys_mprotect
+	.word sys_setregid, sys_vhangup, sys32_truncate64, sys_getgroups, sys32_getgroups16
+/*80*/	.word sys32_setgroups16, sys_getpgrp, sys_setgroups, sys32_setitimer, sys32_ftruncate64
+	.word sys_swapon, sys32_getitimer, sys_setuid, sys_sethostname, sys_setgid
+/*90*/	.word sys_dup2, sys_setfsuid, sys32_fcntl, sys32_select, sys_setfsgid
 	.word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
-	.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
-/*110*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+	.word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
+/*110*/	.word sys_setresgid, sys_getresgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
-/*120*/	.word sys32_readv, sys32_writev, sys32_settimeofday, sys_fchown, sys_fchmod
-	.word sys_nis_syscall, sys32_setreuid, sys32_setregid, sys_rename, sys_truncate
+/*120*/	.word sys32_readv, sys32_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
+	.word sys_nis_syscall, sys32_setreuid16, sys32_setregid16, sys_rename, sys_truncate
 /*130*/	.word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
 	.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64
 /*140*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
@@ -64,7 +64,7 @@
 /*210*/	.word sys_nis_syscall, sys_nis_syscall, sys_waitpid, sys_swapoff, sys32_sysinfo
 	.word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
 /*220*/	.word sys32_sigprocmask, sys32_create_module, sys32_delete_module, sys32_get_kernel_syms, sys_getpgid
-	.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
+	.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
 /*230*/	.word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
 	.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
@@ -99,8 +99,8 @@
 /*90*/	.word sys_dup2, sys_nis_syscall, sys_fcntl, sys_select, sys_nis_syscall
 	.word sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept
 /*100*/	.word sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending
-	.word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_nis_syscall, sys_nis_syscall
-/*110*/	.word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_recvmsg, sys_sendmsg
+	.word sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_setresuid, sys_getresuid
+/*110*/	.word sys_setresgid, sys_getresgid, sys_nis_syscall, sys_recvmsg, sys_sendmsg
 	.word sys_nis_syscall, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd
 /*120*/	.word sys_readv, sys_writev, sys_settimeofday, sys_fchown, sys_fchmod
 	.word sys_recvfrom, sys_setreuid, sys_setregid, sys_rename, sys_truncate
@@ -143,7 +143,7 @@
 	.word sys_close, sunos_wait4, sys_creat
 	.word sys_link, sys_unlink, sunos_execv
 	.word sys_chdir, sunos_nosys, sys32_mknod
-	.word sys32_chmod, sys32_lchown, sunos_brk
+	.word sys32_chmod, sys32_lchown16, sunos_brk
 	.word sunos_nosys, sys32_lseek, sunos_getpid
 	.word sunos_nosys, sunos_nosys, sunos_nosys
 	.word sunos_getuid, sunos_nosys, sys_ptrace
@@ -164,8 +164,8 @@
 	.word sunos_nosys, sunos_sbrk, sunos_sstk
 	.word sunos_mmap, sunos_vadvise, sys_munmap
 	.word sys_mprotect, sunos_madvise, sys_vhangup
-	.word sunos_nosys, sunos_mincore, sys32_getgroups
-	.word sys32_setgroups, sys_getpgrp, sunos_setpgrp
+	.word sunos_nosys, sunos_mincore, sys32_getgroups16
+	.word sys32_setgroups16, sys_getpgrp, sunos_setpgrp
 	.word sys32_setitimer, sunos_nosys, sys_swapon
 	.word sys32_getitimer, sys_gethostname, sys_sethostname
 	.word sunos_getdtablesize, sys_dup2, sunos_nop
@@ -179,9 +179,9 @@
 	.word sys32_sigstack, sys32_recvmsg, sys32_sendmsg
 	.word sunos_nosys, sys32_gettimeofday, sys32_getrusage
 	.word sunos_getsockopt, sunos_nosys, sunos_readv
-	.word sunos_writev, sys32_settimeofday, sys_fchown
-	.word sys_fchmod, sys32_recvfrom, sys32_setreuid
-	.word sys_setregid, sys_rename, sys_truncate
+	.word sunos_writev, sys32_settimeofday, sys32_fchown16
+	.word sys_fchmod, sys32_recvfrom, sys32_setreuid16
+	.word sys32_setregid16, sys_rename, sys_truncate
 	.word sys_ftruncate, sys_flock, sunos_nosys
 	.word sys32_sendto, sys_shutdown, sys_socketpair
 	.word sys_mkdir, sys_rmdir, sys32_utimes
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/solaris/entry64.S linux/arch/sparc64/solaris/entry64.S
--- v2.3.39/linux/arch/sparc64/solaris/entry64.S	Tue Apr 14 17:44:21 1998
+++ linux/arch/sparc64/solaris/entry64.S	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: entry64.S,v 1.5 1998/03/26 08:46:15 jj Exp $
+/* $Id: entry64.S,v 1.6 2000/01/12 02:59:26 davem Exp $
  * entry64.S:  Solaris syscall emulation entry point.
  *
  * Copyright (C) 1996,1997,1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz)
@@ -183,15 +183,15 @@
 
 	.globl	solaris_getuid
 solaris_getuid:
-	lduh		[%g6 + AOFF_task_euid], %o1
-	lduh		[%g6 + AOFF_task_uid], %o0
+	lduw		[%g6 + AOFF_task_euid], %o1
+	lduw		[%g6 + AOFF_task_uid], %o0
 	b,pt		%xcc, ret_from_solaris
 	 stx		%o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
 
 	.globl	solaris_getgid
 solaris_getgid:
-	lduh		[%g6 + AOFF_task_egid], %o1
-	lduh		[%g6 + AOFF_task_gid], %o0
+	lduw		[%g6 + AOFF_task_egid], %o1
+	lduw		[%g6 + AOFF_task_gid], %o0
 	b,pt		%xcc, ret_from_solaris
 	 stx		%o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
 
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c
--- v2.3.39/linux/arch/sparc64/solaris/fs.c	Fri Jan  7 19:13:21 2000
+++ linux/arch/sparc64/solaris/fs.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: fs.c,v 1.15 2000/01/04 23:54:47 davem Exp $
+/* $Id: fs.c,v 1.16 2000/01/12 02:59:27 davem Exp $
  * fs.c: fs related syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -706,71 +706,6 @@
 		return NR_OPEN;
 	}
 	return -EINVAL;
-}
-
-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
-{
-	struct inode * inode;
-	struct iattr newattrs;
-	int error;
-
-	error = -ENOENT;
-	if (!(inode = dentry->d_inode)) {
-		printk("chown_common: NULL inode\n");
-		goto out;
-	}
-	error = -EROFS;
-	if (IS_RDONLY(inode))
-		goto out;
-	error = -EPERM;
-	if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
-		goto out;
-	if (user == (uid_t) -1)
-		user = inode->i_uid;
-	if (group == (gid_t) -1)
-		group = inode->i_gid;
-	newattrs.ia_mode = inode->i_mode;
-	newattrs.ia_uid = user;
-	newattrs.ia_gid = group;
-	newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
-	/*
-	 * If the owner has been changed, remove the setuid bit
-	 */
-	if (inode->i_mode & S_ISUID) {
-		newattrs.ia_mode &= ~S_ISUID;
-		newattrs.ia_valid |= ATTR_MODE;
-	}
-	/*
-	 * If the group has been changed, remove the setgid bit
-	 *
-	 * Don't remove the setgid bit if no group execute bit.
-	 * This is a file marked for mandatory locking.
-	 */
-	if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
-		newattrs.ia_mode &= ~S_ISGID;
-		newattrs.ia_valid |= ATTR_MODE;
-	}
-	error = DQUOT_TRANSFER(dentry, &newattrs);
-out:
-	return error;
-}
-
-/* Linux chown works like Solaris lchown. Solaris chown does follow symlink */
-asmlinkage int solaris_chown(u32 filename, s32 user, s32 group)
-{
-	struct dentry * dentry;
-	int error;
-
-	lock_kernel();
-	dentry = namei((const char *)A(filename));
-
-	error = PTR_ERR(dentry);
-	if (!IS_ERR(dentry)) {
-		error = chown_common(dentry, user, group);
-		dput(dentry);
-	}
-	unlock_kernel();
-	return error;
 }
 
 /* At least at the time I'm writing this, Linux doesn't have ACLs, so we
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c
--- v2.3.39/linux/arch/sparc64/solaris/misc.c	Wed Dec 29 13:13:15 1999
+++ linux/arch/sparc64/solaris/misc.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.19 1999/12/15 17:51:25 jj Exp $
+/* $Id: misc.c,v 1.20 2000/01/12 02:59:26 davem Exp $
  * misc.c: Miscelaneous syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -399,18 +399,6 @@
 	case SOLARIS_CONFIG_TIMER_MAX:		return -EINVAL;
 	default: return -EINVAL;
 	}
-}
-
-asmlinkage int solaris_setreuid(s32 ruid, s32 euid)
-{
-	int (*sys_setreuid)(uid_t, uid_t) = (int (*)(uid_t, uid_t))SYS(setreuid);
-	return sys_setreuid(ruid, euid);
-}
-
-asmlinkage int solaris_setregid(s32 rgid, s32 egid)
-{
-	int (*sys_setregid)(gid_t, gid_t) = (int (*)(gid_t, gid_t))SYS(setregid);
-	return sys_setregid(rgid, egid);
 }
 
 asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
diff -u --recursive --new-file v2.3.39/linux/arch/sparc64/solaris/systbl.S linux/arch/sparc64/solaris/systbl.S
--- v2.3.39/linux/arch/sparc64/solaris/systbl.S	Wed Mar 10 16:53:37 1999
+++ linux/arch/sparc64/solaris/systbl.S	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: systbl.S,v 1.8 1999/02/11 18:34:02 davem Exp $
+/* $Id: systbl.S,v 1.10 2000/01/12 02:59:26 davem Exp $
  * systbl.S: System call entry point table for Solaris compatibility.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -40,7 +40,7 @@
 	.word CHAIN(time)		/* time			13	*/
 	.word solaris_mknod		/* mknod	sox	14	*/
 	.word CHAIN(chmod)		/* chmod	so	15	*/ 
-	.word solaris_chown		/* chown	sdd	16	*/
+	.word CHAIN(chown)		/* chown	sdd	16	*/
 	.word solaris_brk		/* brk/break	x	17	*/
 	.word solaris_stat		/* stat		sp	18	*/
 	.word CHAIN(lseek)		/* seek/lseek	ddd	19	*/
@@ -230,8 +230,8 @@
 	.word CHAIN(nanosleep)		/* nanosleep	dd	199	*/
 	.word solaris_facl		/* facl		dddp	200	*/
 	.word solaris_unimplemented	/* 			201	*/
-	.word solaris_setreuid		/* setreuid	dd	202	*/
-	.word solaris_setregid		/* setregid	dd	203	*/
+	.word CHAIN(setreuid)		/* setreuid	dd	202	*/
+	.word CHAIN(setregid)		/* setregid	dd	203	*/
 	.word solaris_unimplemented	/* 			204	*/
 	.word solaris_unimplemented	/* 			205	*/
 	.word solaris_unimplemented	/* 			206	*/
diff -u --recursive --new-file v2.3.39/linux/drivers/Makefile linux/drivers/Makefile
--- v2.3.39/linux/drivers/Makefile	Tue Jan  4 13:57:16 2000
+++ linux/drivers/Makefile	Thu Jan 13 16:49:22 2000
@@ -9,7 +9,7 @@
 
 SUB_DIRS     := block char net parport sound misc
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp i2o \
+ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp i2o ieee1394 \
 				macintosh video dio zorro fc4 usb \
 				nubus tc ap1000 atm pcmcia i2c telephony
 
@@ -97,6 +97,15 @@
 else
   ifeq ($(CONFIG_SCSI),m)
   MOD_SUB_DIRS += scsi
+  endif
+endif
+
+ifeq ($(CONFIG_IEEE1394),y)
+SUB_DIRS += ieee1394
+MOD_SUB_DIRS += ieee1394
+else
+  ifeq ($(CONFIG_IEEE1394),m)
+  MOD_SUB_DIRS += ieee1394
   endif
 endif
 
diff -u --recursive --new-file v2.3.39/linux/drivers/acorn/block/mfmhd.c linux/drivers/acorn/block/mfmhd.c
--- v2.3.39/linux/drivers/acorn/block/mfmhd.c	Tue Jan 11 22:31:38 2000
+++ linux/drivers/acorn/block/mfmhd.c	Tue Jan 18 18:54:20 2000
@@ -115,6 +115,7 @@
 
 #define MAJOR_NR	MFM_ACORN_MAJOR
 #include <linux/blk.h>
+#include <linux/blkpg.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -975,7 +976,7 @@
 	DBG("mfm_request: Dropping out bottom\n");
 }
 
-static void do_mfm_request(void)
+static void do_mfm_request(request_queue_t *q)
 {
 	DBG("do_mfm_request: about to mfm_request\n");
 	mfm_request();
@@ -1017,8 +1018,7 @@
 
 
 /*
- * Tell the user about the drive if we decided it exists.  Also,
- * set the size of the drive.
+ * Tell the user about the drive if we decided it exists.
  */
 static void mfm_geometry (int drive)
 {
@@ -1027,8 +1027,6 @@
 			mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 4096,
 			mfm_info[drive].cylinders, mfm_info[drive].heads, mfm_info[drive].sectors,
 			mfm_info[drive].lowcurrent, mfm_info[drive].precomp);
-	mfm[drive << 6].start_sect = 0;
-	mfm[drive << 6].nr_sects = mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2;
 }
 
 #ifdef CONFIG_BLK_DEV_MFM_AUTODETECT
@@ -1210,24 +1208,6 @@
 			return -EFAULT;
 		return 0;
 
-	case BLKFLSBUF:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EACCES;
-		fsync_dev(dev);
-		invalidate_buffers(dev);
-		return 0;
-
-	case BLKRASET:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EACCES;
-		if (arg > 0xff)
-			return -EINVAL;
-		read_ahead[major] = arg;
-		return 0;
-
-	case BLKRAGET:
-		return put_user(read_ahead[major], (long *)arg);
-
 	case BLKGETSIZE:
 		return put_user (mfm[minor].nr_sects, (long *)arg);
 
@@ -1248,7 +1228,13 @@
 			return -EACCES;
 		return mfm_reread_partitions(dev);
 
-	RO_IOCTLS(dev, arg);
+	case BLKFLSBUF:
+	case BLKROSET:
+	case BLKROGET:
+	case BLKRASET:
+	case BLKRAGET:
+	case BLKPG:
+		return blk_ioctl(dev, cmd, arg);
 
 	default:
 		return -EINVAL;
@@ -1294,6 +1280,7 @@
  * Set the CHS from the ADFS boot block if it is present.  This is not ideal
  * since if there are any non-ADFS partitions on the disk, this won't work!
  * Hence, I want to get rid of this...
+ * 	Please, do. It does seriously sucking things.
  */
 void xd_set_geometry(kdev_t dev, unsigned char secsptrack, unsigned char heads,
 		     unsigned long discsize, unsigned int secsize)
@@ -1319,18 +1306,16 @@
 		if (raw_cmd.dev == drive)
 			mfm_specify ();
 		mfm_geometry (drive);
+		mfm[drive << 6].start_sect = 0;
+		mfm[drive << 6].nr_sects = mfm_info[drive].cylinders * mfm_info[drive].heads * mfm_info[drive].sectors / 2;
 	}
 }
 
-static void mfm_geninit (struct gendisk *gdev);
-
 static struct gendisk mfm_gendisk = {
 	MAJOR_NR,		/* Major number */
 	"mfm",			/* Major name */
 	6,			/* Bits to shift to get real from partition */
 	1 << 6,			/* Number of partitions per real */
-	MFM_MAXDRIVES,		/* maximum number of real */
-	mfm_geninit,		/* init function */
 	mfm,			/* hd struct */
 	mfm_sizes,		/* block sizes */
 	0,			/* number */
@@ -1338,17 +1323,30 @@
 	NULL			/* next */
 };
 
-static void mfm_geninit (struct gendisk *gdev)
+static struct block_device_operations mfm_fops =
+{
+	open:		mfm_open,
+	release:	mfm_release,
+	ioctl:		mfm_ioctl,
+};
+
+static void mfm_geninit (void)
 {
 	int i;
 
-	mfm_drives = mfm_initdrives();
+	for (i = 0; i < (MFM_MAXDRIVES << 6); i++) {
+		/* Can't increase this - if you do all hell breaks loose */
+		mfm_blocksizes[i] = 1024;
+		mfm_sectsizes[i] = 512;
+	}
+	blksize_size[MAJOR_NR] = mfm_blocksizes;
+	hardsect_size[MAJOR_NR] = mfm_sectsizes;
 
-	printk("mfm: detected %d hard drive%s\n", mfm_drives, mfm_drives == 1 ? "" : "s");
-	gdev->nr_real = mfm_drives;
+	mfm_drives = mfm_initdrives();
 
-	for (i = 0; i < mfm_drives; i++)
-		mfm_geometry (i);
+	printk("mfm: detected %d hard drive%s\n", mfm_drives,
+				mfm_drives == 1 ? "" : "s");
+	mfm_gendisk.nr_real = mfm_drives;
 
 	if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))
 		printk("mfm: unable to get IRQ%d\n", mfm_irq);
@@ -1356,22 +1354,15 @@
 	if (mfm_irqenable)
 		outw(0x80, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
 
-	for (i = 0; i < (MFM_MAXDRIVES << 6); i++) {
-		mfm_blocksizes[i] = 1024;	/* Can't increase this - if you do all hell breaks loose */
-		mfm_sectsizes[i] = 512;
+	for (i = 0; i < mfm_drives; i++) {
+		mfm_geometry (i);
+		register_disk(&mfm_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6,
+				&mfm_fops,
+				mfm_info[i].cylinders * mfm_info[i].heads *
+				mfm_info[i].sectors / 2);
 	}
-	blksize_size[MAJOR_NR] = mfm_blocksizes;
-	hardsect_size[MAJOR_NR] = mfm_sectsizes;
 }
 
-static struct block_device_operations mfm_fops =
-{
-	open:		mfm_open,
-	release:	mfm_release,
-	ioctl:		mfm_ioctl,
-};
-
-
 static struct expansion_card *ecs;
 
 /*
@@ -1421,11 +1412,6 @@
 {
 	unsigned char irqmask;
 
-	if (register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) {
-		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
-		return -1;
-	}
-
 	if (mfm_probecontroller(ONBOARD_MFM_ADDRESS)) {
 		mfm_addr	= ONBOARD_MFM_ADDRESS;
 		mfm_IRQPollLoc	= IOC_IRQSTATB;
@@ -1448,6 +1434,12 @@
 		ecard_claim(ecs);
 	}
 
+	if (register_blkdev(MAJOR_NR, "mfm", &mfm_fops)) {
+		printk("mfm_init: unable to get major number %d\n", MAJOR_NR);
+		ecard_release(ecs);
+		return -1;
+	}
+
 	printk("mfm: found at address %08X, interrupt %d\n", mfm_addr, mfm_irq);
 	request_region (mfm_addr, 10, "mfm");
 
@@ -1456,7 +1448,7 @@
 	hdc63463_irqpolladdress	= ioaddr(mfm_IRQPollLoc);
 	hdc63463_irqpollmask	= irqmask;
 
-	blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
+	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
 	read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB?) read ahread */
 
 #ifndef MODULE
@@ -1467,6 +1459,7 @@
 	Busy = 0;
 	lastspecifieddrive = -1;
 
+	mfm_geninit();
 	return 0;
 }
 
@@ -1505,10 +1498,10 @@
 		mfm_gendisk.part[minor].nr_sects = 0;
 	}
 
-	mfm_gendisk.part[start].nr_sects = mfm_info[target].heads *
-	    mfm_info[target].cylinders * mfm_info[target].sectors / 2;
+	/* Divide by 2, since sectors are 2 times smaller than usual ;-) */
 
-	resetup_one_dev(&mfm_gendisk, target);
+	grok_partitions(&mfm_gendisk, target, 1<<6, mfm_info[target].heads *
+		    mfm_info[target].cylinders * mfm_info[target].sectors / 2);
 
 	mfm_info[target].busy = 0;
 	wake_up (&mfm_wait_open);
@@ -1518,11 +1511,7 @@
 #ifdef MODULE
 int init_module(void)
 {
-	int ret;
-	ret = mfm_init();
-	if (!ret)
-		mfm_geninit(&mfm_gendisk);
-	return ret;
+	return mfm_init();
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.39/linux/drivers/acorn/scsi/Config.in linux/drivers/acorn/scsi/Config.in
--- v2.3.39/linux/drivers/acorn/scsi/Config.in	Mon Oct 11 15:38:14 1999
+++ linux/drivers/acorn/scsi/Config.in	Thu Jan 13 13:30:31 2000
@@ -6,12 +6,12 @@
    bool '  Support SCSI 2 Tagged queueing' CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE
    bool '  Support SCSI 2 Synchronous Transfers' CONFIG_SCSI_ACORNSCSI_SYNC
 fi
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   dep_tristate 'ARXE SCSI support (EXPERIMENTAL)' CONFIG_SCSI_ARXESCSI $CONFIG_SCSI
-   dep_tristate 'CumanaSCSI II support (EXPERIMENTAL)' CONFIG_SCSI_CUMANA_2 $CONFIG_SCSI
-   dep_tristate 'EESOX support (EXPERIMENTAL)' CONFIG_SCSI_EESOXSCSI $CONFIG_SCSI
-   dep_tristate 'PowerTec support (EXPERIMENTAL)' CONFIG_SCSI_POWERTECSCSI $CONFIG_SCSI
+dep_tristate 'ARXE SCSI support' CONFIG_SCSI_ARXESCSI $CONFIG_SCSI
+dep_tristate 'CumanaSCSI II support' CONFIG_SCSI_CUMANA_2 $CONFIG_SCSI
+dep_tristate 'EESOX support' CONFIG_SCSI_EESOXSCSI $CONFIG_SCSI
+dep_tristate 'PowerTec support' CONFIG_SCSI_POWERTECSCSI $CONFIG_SCSI
 
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    comment 'The following drivers are not fully supported'
 
    dep_tristate 'CumanaSCSI I support' CONFIG_SCSI_CUMANA_1 $CONFIG_SCSI
diff -u --recursive --new-file v2.3.39/linux/drivers/ap1000/ap.c linux/drivers/ap1000/ap.c
--- v2.3.39/linux/drivers/ap1000/ap.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/ap1000/ap.c	Tue Jan 18 18:54:20 2000
@@ -274,6 +274,8 @@
   blksize_size[MAJOR_NR] = ap_blocksizes;
 
   read_ahead[MAJOR_NR] = 32; /* 16k read ahead */
+  for (i=0;i<NUM_APDEVS;i++)
+	register_disk(NILL, MKDEV(MAJOR_NR,i), 1, &ap_fops, 0);
 
   return(0);
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/ap1000/ddv.c linux/drivers/ap1000/ddv.c
--- v2.3.39/linux/drivers/ap1000/ddv.c	Tue Jan 11 22:31:38 2000
+++ linux/drivers/ap1000/ddv.c	Tue Jan 18 18:54:20 2000
@@ -76,7 +76,7 @@
 extern int ddv_restart_cpu(void);
 extern int ddv_mlist_available(void);
 static int ddv_revalidate(kdev_t dev, struct gendisk *gdev);
-static void ddv_geninit(struct gendisk *ignored);
+static void ddv_geninit(void);
 static void ddv_release(struct inode * inode, struct file * filp);
 static void ddv_request1(void);
 
@@ -109,12 +109,6 @@
 	DEVICE_NAME,		/* Major name */
 	PARTN_BITS,		/* Bits to shift to get real from partition */
 	1 << PARTN_BITS,	/* Number of partitions per real */
-	1,	        /* maximum number of real */
-#ifdef MODULE
-	NULL,		/* called from init_module */
-#else
-        ddv_geninit,     /* init function */
-#endif
 	partition_tables,/* hd struct */
 	ddv_blk_length,	/* block sizes */
 	1,		/* number */
@@ -122,7 +116,6 @@
 	NULL		/* next */
 };
 
-
 struct ddv_geometry {
 	unsigned char heads;
 	unsigned char sectors;
@@ -695,6 +688,7 @@
 	wake_up(&busy_wait);	
 }
 
+extern struct block_device_operations ddv_fops;
 
 static void ddv_load_opiu(void)
 {
@@ -738,11 +732,10 @@
 	ddv_geometry.cylinders = ddv_sect_length[0] / 
 		(ddv_geometry.heads*ddv_geometry.sectors);
 
-	ddv_gendisk.part[0].start_sect = 0;
-	ddv_gendisk.part[0].nr_sects = ddv_sect_length[0];
-
-	resetup_one_dev(&ddv_gendisk, 0);
+	register_disk(&ddv_gendisk, MKDEV(MAJOR_NR,0), 1<<PARTN_BITS,
+			&ddv_fops, ddv_sect_length[0]);
 	
+	/* FIXME. The crap below is, well, crap. Pseudo-RAID and unsafe one */
 	for (i=0;i<PARDISK_BASE;i++) {
 		ddv_sect_length[i] = ddv_gendisk.part[i].nr_sects;
 		ddv_blk_length[i] = ddv_gendisk.part[i].nr_sects >> 1;
@@ -794,8 +787,7 @@
 	ddv_sect_length[start] = DiskInfo->blocks;
 	ddv_blk_length[start] = DiskInfo->blocks >> 1;
 
-	gdev->part[start].nr_sects = ddv_sect_length[start];
-	resetup_one_dev(gdev, target);
+	grok_partitions(gdev, target, 1<<PARTN_BITS, ddv_sect_length[start]);
 
 	printk("sect_length[%d]=%d blk_length[%d]=%d\n",
 	       start,ddv_sect_length[start],
@@ -936,11 +928,13 @@
 
 	kernel_thread(ddv_daemon, NULL, 0);
 
+	ddv_geninit();
+
 	return(0);
 }
 
 
-static void ddv_geninit(struct gendisk *ignored)
+static void ddv_geninit(void)
 {
 	int i;
 	static int done = 0;
@@ -981,10 +975,8 @@
 int init_module(void)
 {
 	int error = ddv_init();
-	if (!error) {
-		ddv_geninit(&(struct gendisk) { 0,0,0,0,0,0,0,0,0,0,0 });
+	if (!error)
 		printk(KERN_INFO "DDV: Loaded as module.\n");
-	}
 	return error;
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.3.39/linux/drivers/block/Config.in	Fri Jan  7 19:13:21 2000
+++ linux/drivers/block/Config.in	Mon Jan 17 15:24:03 2000
@@ -37,6 +37,9 @@
       if [ "$CONFIG_BLK_DEV_CMD640" = "y" ]; then
 	 bool '    CMD640 enhanced support' CONFIG_BLK_DEV_CMD640_ENHANCED
       fi
+      if [ "$CONFIG_ISAPNP" = "y" ]; then
+	 bool '  ISA-PNP EIDE support' CONFIG_BLK_DEV_ISAPNP
+      fi
       if [ "$CONFIG_PCI" = "y" ]; then
 	 bool '  RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000
 	 bool '  Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI
@@ -53,22 +56,29 @@
 	    fi
 	    bool '    Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD
 	    bool '    AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210
-	       if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_AEC6210" = "y" ]; then
-		  bool '      AEC6210 Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_AEC6210_TUNING
-	       fi
+	    if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_AEC6210" = "y" ]; then
+	       bool '      AEC6210 Tuning support (EXPERIMENTAL)' CONFIG_BLK_DEV_AEC6210_TUNING
+	    fi
+	    bool '    CMD64X chipset support' CONFIG_BLK_DEV_CMD64X
+	    if [ "$CONFIG_BLK_DEV_CMD64X" = "y" -a "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y"  ]; then
+	       bool '      CMD64X chipset RAID support (EXPERIMENTAL) (WIP)' CONFIG_BLK_DEV_CMD64X_RAID
+	    fi
 	    if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
-	       bool '    ALI M15x3 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_ALI15X3
-	       bool '    CMD646 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CMD646
 	       bool '    CY82C693 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_CY82C693
 	    fi
 	    if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then
+	       bool '    ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3
+	       if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
+		  bool '    AMD Viper support (EXPERIMENTAL)' CONFIG_BLK_DEV_AMD7409
+	       fi
   	       bool '    HPT34X chipset support' CONFIG_BLK_DEV_HPT34X
 	       if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT34X" = "y" ]; then
 		  bool '      HPT34X DMA support (EXPERIMENTAL)' CONFIG_BLK_DEV_HPT34X_DMA
 	       fi
 	       bool '    HPT366 chipset support' CONFIG_BLK_DEV_HPT366
 	       if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" -a "$CONFIG_BLK_DEV_HPT366" = "y" ]; then
-		  bool '      HPT366 Fast Interrupt support (EXPERIMENTAL)' HPT366_FAST_IRQ_PREDICTION
+		  bool '      HPT366 Fast Interrupt support (EXPERIMENTAL) (WIP)' HPT366_FAST_IRQ_PREDICTION
+		  bool '      HPT366 mode three unsupported (EXPERIMENTAL) (WIP)' HPT366_MODE3
 	       fi
 	       if [ "$CONFIG_X86" = "y" ]; then
 		  bool '    Intel PIIXn chipsets support' CONFIG_BLK_DEV_PIIX
@@ -225,7 +235,9 @@
 if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
      "$CONFIG_BLK_DEV_AEC6210" = "y" -o \
      "$CONFIG_BLK_DEV_ALI15X3" = "y" -o \
+     "$CONFIG_BLK_DEV_AMD7409" = "y" -o \
      "$CONFIG_BLK_DEV_CMD640" = "y" -o \
+     "$CONFIG_BLK_DEV_CMD64X" = "y" -o \
      "$CONFIG_BLK_DEV_CY82C693" = "y" -o \
      "$CONFIG_BLK_DEV_HPT34X" = "y" -o \
      "$CONFIG_BLK_DEV_HPT366" = "y" -o \
diff -u --recursive --new-file v2.3.39/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.3.39/linux/drivers/block/DAC960.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/DAC960.c	Tue Jan 18 18:54:20 2000
@@ -1066,8 +1066,6 @@
   Controller->GenericDiskInfo.major_name = "rd";
   Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits;
   Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions;
-  Controller->GenericDiskInfo.max_nr = DAC960_MaxLogicalDrives;
-  Controller->GenericDiskInfo.init = DAC960_InitializeGenericDiskInfo;
   Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount;
   Controller->GenericDiskInfo.real_devices = Controller;
   Controller->GenericDiskInfo.next = NULL;
@@ -1166,6 +1164,7 @@
       Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction;
       add_timer(&Controller->MonitoringTimer);
       Controller->ControllerInitialized = true;
+      DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
     }
   else DAC960_FinalizeController(Controller);
 }
@@ -2439,7 +2438,6 @@
       Controller->LogicalDriveInitialState[LogicalDriveNumber] =
 	DAC960_LogicalDrive_Online;
       DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
-      resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
     }
   if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0)
     return -ENXIO;
@@ -2573,7 +2571,13 @@
 	  */
 	  set_blocksize(Device, BLOCK_SIZE);
 	}
-      resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
+      /*
+       * Leonard, I'll tie you, draw around you a pentagram
+       * and read this file. Aloud. 
+       */
+      grok_partitions(
+	&Controller->GenericDiskInfo, LogicalDriveNumber, DAC960_MaxPartitions,
+	Controller->LogicalDriveInformation[Controller->LogicalDriveInformationIndex][LogicalDriveNumber].LogicalDriveSize);
       return 0;
     }
   return -EINVAL;
@@ -2895,8 +2899,10 @@
   for (LogicalDriveNumber = 0;
        LogicalDriveNumber < Controller->LogicalDriveCount;
        LogicalDriveNumber++)
-    GenericDiskInfo->part[DAC960_MinorNumber(LogicalDriveNumber, 0)].nr_sects =
-      LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize;
+	register_disk(GenericDiskInfo, MKDEV(GenericDiskInfo->major,
+				       LogicalDriveNumber*DAC960_MaxPartitions),
+		DAC960_MaxPartitions, &DAC960_FileOperations,
+		LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize);
 }
 
 
@@ -3518,10 +3524,6 @@
       DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
       if (Controller == NULL) continue;
       DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo);
-      for (LogicalDriveNumber = 0;
-	   LogicalDriveNumber < Controller->LogicalDriveCount;
-	   LogicalDriveNumber++)
-	resetup_one_dev(&Controller->GenericDiskInfo, LogicalDriveNumber);
     }
   return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.3.39/linux/drivers/block/Makefile	Thu Nov 18 20:25:37 1999
+++ linux/drivers/block/Makefile	Fri Jan 14 00:50:53 2000
@@ -114,6 +114,10 @@
 IDE_OBJS += alim15x3.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_AMD7409),y)
+IDE_OBJS += amd7409.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_BUDDHA),y)
 IDE_OBJS += buddha.o
 endif
@@ -122,8 +126,8 @@
 IDE_OBJS += cmd640.o
 endif
 
-ifeq ($(CONFIG_BLK_DEV_CMD646),y)
-IDE_OBJS += cmd646.o
+ifeq ($(CONFIG_BLK_DEV_CMD64X),y)
+IDE_OBJS += cmd64x.o
 endif
 
 ifeq ($(CONFIG_BLK_DEV_CY82C693),y)
diff -u --recursive --new-file v2.3.39/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.3.39/linux/drivers/block/acsi.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/acsi.c	Tue Jan 18 18:54:21 2000
@@ -369,7 +369,7 @@
 static void acsi_prevent_removal( int target, int flag );
 static int acsi_change_blk_size( int target, int lun);
 static int acsi_mode_sense( int target, int lun, SENSE_DATA *sd );
-static void acsi_geninit( struct gendisk *gd );
+static void acsi_geninit(void);
 static int revalidate_acsidisk( int dev, int maxusage );
 static int acsi_revalidate (dev_t);
 
@@ -1386,21 +1386,15 @@
 
 
 static struct gendisk acsi_gendisk = {
-	MAJOR_NR,			/* Major number */	
-	"ad",				/* Major name */
-	4,					/* Bits to shift to get real from partition */
-	1 << 4,				/* Number of partitions per real */
-	MAX_DEV,			/* maximum number of real */
-#ifdef MODULE
-	NULL,				/* called from init_module() */
-#else
-	acsi_geninit,		/* init function */
-#endif
-	acsi_part,			/* hd struct */
-	acsi_sizes,			/* block sizes */
-	0,					/* number */
+	MAJOR_NR,		/* Major number */	
+	"ad",			/* Major name */
+	4,			/* Bits to shift to get real from partition */
+	1 << 4,			/* Number of partitions per real */
+	acsi_part,		/* hd struct */
+	acsi_sizes,		/* block sizes */
+	0,			/* number */
 	(void *)acsi_info,	/* internal */
-	NULL				/* next */
+	NULL			/* next */
 };
 	
 #define MAX_SCSI_DEVICE_CODE 10
@@ -1659,7 +1653,15 @@
 int SLM_devices[8];
 #endif
 
-static void acsi_geninit( struct gendisk *gd )
+static struct block_device_operations acsi_fops = {
+	open:			acsi_open,
+	release:		acsi_release,
+	ioctl:			acsi_ioctl,
+	check_media_change:	acsi_media_change,
+	revalidate:		acsi_revalidate,
+};
+
+static void acsi_geninit(void)
 {
 	int i, target, lun;
 	struct acsi_info_struct *aip;
@@ -1741,14 +1743,15 @@
 			NDevices, n_slm );
 #endif
 					 
-	for( i = 0; i < NDevices; ++i ) {
-		acsi_part[i<<4].start_sect = 0;
-		acsi_part[i<<4].nr_sects = acsi_info[i].size;
-	}
-	acsi_gendisk.nr_real = NDevices;
 	for( i = 0; i < (MAX_DEV << 4); i++ )
 		acsi_blocksizes[i] = 1024;
 	blksize_size[MAJOR_NR] = acsi_blocksizes;
+	for( i = 0; i < NDevices; ++i )
+		register_disk(&acsi_gendisk, MKDEV(MAJOR_NR,i<<4),
+				(acsi_info[i].type==HARDDISK)?1<<4:1,
+				&acsi_fops,
+				acsi_info[i].size);
+	acsi_gendisk.nr_real = NDevices;
 }
 
 #ifdef CONFIG_ATARI_SLM_MODULE
@@ -1766,18 +1769,11 @@
 }
 #endif /* CONFIG_ATARI_SLM_MODULE */
 
-static struct block_device_operations acsi_fops = {
-	open:			acsi_open,
-	release:		acsi_release,
-	ioctl:			acsi_ioctl,
-	check_media_change:	acsi_media_change,
-	revalidate:		acsi_revalidate,
-};
-
 
 int acsi_init( void )
 
 {
+	int err = 0;
 	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
 		return 0;
 
@@ -1801,10 +1797,11 @@
 	gendisk_head = &acsi_gendisk;
 
 #ifdef CONFIG_ATARI_SLM
-	return( slm_init() );
-#else
-	return 0;
+	err = slm_init();
 #endif
+	if (!err)
+		acsi_geninit();
+	return err;
 }
 
 
@@ -1816,7 +1813,6 @@
 	if ((err = acsi_init()))
 		return( err );
 	printk( KERN_INFO "ACSI driver loaded as module.\n");
-	acsi_geninit( &(struct gendisk){ 0,0,0,0,0,0,0,0,0,0,0 } );
 	return( 0 );
 }
 
@@ -1914,9 +1910,7 @@
 	ENABLE_IRQ();
 	stdma_release();
 	
-	gdev->part[start].nr_sects = aip->size;
-	if (aip->type == HARDDISK && aip->size > 0)
-		resetup_one_dev(gdev, device);
+	grok_partitions(gdev, device, (aip->type==HARDDISK)?1<<4:1, aip->size);
 
 	DEVICE_BUSY = 0;
 	wake_up(&busy_wait);
diff -u --recursive --new-file v2.3.39/linux/drivers/block/aec6210.c linux/drivers/block/aec6210.c
--- v2.3.39/linux/drivers/block/aec6210.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/aec6210.c	Fri Jan 14 00:50:53 2000
@@ -287,8 +287,6 @@
 
 	if (hwif->dma_base) {
 		hwif->dmaproc = &aec6210_dmaproc;
-		hwif->drives[0].autotune = 0;
-		hwif->drives[1].autotune = 0;
 	} else {
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/alim15x3.c linux/drivers/block/alim15x3.c
--- v2.3.39/linux/drivers/block/alim15x3.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/block/alim15x3.c	Mon Jan 17 15:23:11 2000
@@ -1,10 +1,10 @@
 /*
- * linux/drivers/block/alim15x3.c	Version 0.07	Dec. 13, 1999
+ * linux/drivers/block/alim15x3.c	Version 0.08	Jan. 14, 2000
  *
- *  Copyright (C) 1998-99 Michel Aubry, Maintainer
- *  Copyright (C) 1998-99 Andrzej Krzysztofowicz, Maintainer
+ *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
+ *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
  *
- *  Copyright (C) 1998-99 Andre Hedrick (andre@suse.com)
+ *  Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com)
  *  May be copied or modified under the terms of the GNU General Public License
  *
  *  (U)DMA capable version of ali 1533/1543(C), 1535(D)
@@ -274,8 +274,8 @@
 		if (r_clc >= 16)
 			r_clc = 0;
 	}
-	save_flags(flags);
-	cli();
+	__save_flags(flags);
+	__cli();
 	
 	/* 
 	 * PIO mode => ATA FIFO on, ATAPI FIFO off
@@ -297,7 +297,7 @@
 	
 	pci_write_config_byte(dev, port, s_clc);
 	pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc);
-	restore_flags(flags);
+	__restore_flags(flags);
 
 	/*
 	 * setup   active  rec
@@ -311,280 +311,170 @@
 
 }
 
-static __inline__ unsigned char dma2_bits_to_command(unsigned char bits)
+static int ali15x3_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	if (bits & 0x04)
-		return XFER_MW_DMA_2;
-	if (bits & 0x02)
-		return XFER_MW_DMA_1;
-	return XFER_MW_DMA_0;
-}
-
-static __inline__ unsigned char udma2_bits_to_command(unsigned char bits)
-{
-	if (bits & 0x10)
-		return XFER_UDMA_4;
-	if (bits & 0x08)
-		return XFER_UDMA_3;
-	if (bits & 0x04)
-		return XFER_UDMA_2;
-	if (bits & 0x02)
-		return XFER_UDMA_1;
-	return XFER_UDMA_0;
-}
-
-static __inline__ int wait_for_ready(ide_drive_t *drive)
-{
-	int timeout = 20000;	/* (old value: 100) */
-	byte stat;
+	ide_hwif_t *hwif = HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	byte unit		= (drive->select.b.unit & 0x01);
+	byte tmpbyte		= 0x00;
+	int m5229_udma		= hwif->channel? 0x57 : 0x56;
+	int err			= 0;
 
-	while (--timeout) {
-		stat = GET_STAT();
+	if (speed < XFER_UDMA_0) {
+		byte ultra_enable	= (unit) ? 0x7f : 0xf7;
 		/*
-		 * printk("STAT(%2x) ", stat);
+		 * clear "ultra enable" bit
 		 */
-		if (!(stat & BUSY_STAT)) {
-			if ((stat & READY_STAT) || (stat & ERR_STAT)) {
-				break;
-			}
-		}
-		/*
-		 * (old value: 100)
-		 */
-		udelay(150);
+		pci_read_config_byte(dev, m5229_udma, &tmpbyte);
+		tmpbyte &= ultra_enable;
+		pci_write_config_byte(dev, m5229_udma, tmpbyte);
 	}
-	if ((stat & ERR_STAT) || timeout <= 0)
-		return 1;
-	return 0;
-}
-
-static void ali15x3_do_setfeature(ide_drive_t *drive, byte command)
-{
-	unsigned long flags;
-	byte old_select;
-
-	save_flags(flags);
-	cli();
-		
-	/* save old selected device */
-	old_select = IN_BYTE(IDE_SELECT_REG);
-	/* "SELECT " */
-	OUT_BYTE(drive->select.all, IDE_SELECT_REG);
-	/* "SETXFER " */
-	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
-	/* "CMND " */
-	OUT_BYTE(command, IDE_NSECTOR_REG);
-
-	if(wait_for_ready(drive))	/* "wait " */
-		goto out;
-
-	/* "SETFEATURE " */
-	OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
-	/* "wait " */
-	(void) wait_for_ready(drive);
 
-out:
-	/*
-	 * restore to old "selected device"
-	 */
-	OUT_BYTE(old_select, IDE_SELECT_REG);
-	restore_flags(flags);
-}
+	err = ide_config_drive_speed(drive, speed);
 
-static void ali15x3_dma2_enable(ide_drive_t *drive, unsigned long dma_base)
-{
-	byte unit = (drive->select.b.unit & 0x01);
-	byte bits = (drive->id->dma_mword | drive->id->dma_1word) & 0x07;
-	byte ultra = (unit) ? 0x7f : 0xf7;
-	byte tmpbyte;
-	ide_hwif_t *hwif = HWIF(drive);
-	unsigned long flags;
-	int m5229_udma_setting_index = hwif->channel? 0x57 : 0x56;		
-	
-	ali15x3_do_setfeature(drive, dma2_bits_to_command(bits));
+	if (speed >= XFER_SW_DMA_0) {
+		unsigned long dma_base = hwif->dma_base;
 
-	/*
-	 * clear "ultra enable" bit
-	 */
-	pci_read_config_byte(hwif->pci_dev, m5229_udma_setting_index, &tmpbyte);
-#if 0
-	if (unit) {
-		tmpbyte &= 0x7f;
-	} else {
-		tmpbyte &= 0xf7;
+		outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
 	}
-#else
-	tmpbyte &= ultra;
-#endif
-	save_flags(flags);
-	cli();
-	pci_write_config_byte(hwif->pci_dev, m5229_udma_setting_index, tmpbyte);
-	restore_flags(flags);
-	drive->id->dma_ultra = 0x00;
-
-	/*
-	 * Enable DMA
-	 */
-	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
-	printk("ALI15X3: MultiWord DMA enabled\n");
-}
-
-static void ali15x3_udma_enable(ide_drive_t *drive, unsigned long dma_base)
-{	
-	byte unit = (drive->select.b.unit & 0x01);
-	byte bits = drive->id->dma_ultra & 0x1f;	
-	byte tmpbyte;
-	ide_hwif_t *hwif = HWIF(drive);
-	unsigned long flags;
-	unsigned char udma_mode = 0;
-	int m5229_udma_setting_index = hwif->channel? 0x57 : 0x56;
 
-	if (bits & 0x18) {
-		/*
-		 * 00011000, disk: ultra66
-		 */
-		if (m5229_revision < 0xc2) {
-			/*
-			 * controller: ultra33
-			 */
-			bits = 0x04;
-			/*
-			 * 00000100, use ultra33, mode 2
-			 */
-			drive->id->dma_ultra &= ~0xFF00;
-			drive->id->dma_ultra |= 0x0004;			
-		} else {
-			/*
-			 * controller: ultra66
-			 *
-			 * Try to detect word93 bit13 and
-			 * 80-pin cable (from host view)
-			 */
-			if (!((drive->id->word93 & 0x2000) &&
-			    cable_80_pin[hwif->channel])) {	
-				bits = 0x04;
-				/*
-				 * 00000100, use ultra33, mode 2
-				 */
-				drive->id->dma_ultra &= ~0xFF00;
-				drive->id->dma_ultra |= 0x0004;
-			}
+	if (speed >= XFER_UDMA_0) {
+		pci_read_config_byte(dev, m5229_udma, &tmpbyte);
+		tmpbyte &= (0x0f << ((1-unit) << 2));
+		/*
+		 * enable ultra dma and set timing
+		 */
+		tmpbyte |= ((0x08 | (4-speed)) << (unit << 2));
+		pci_write_config_byte(dev, m5229_udma, tmpbyte);
+		if (speed >= XFER_UDMA_3) {
+			pci_read_config_byte(dev, 0x4b, &tmpbyte);
+			tmpbyte |= 1;
+			pci_write_config_byte(dev, 0x4b, tmpbyte);
 		}
 	}
 
-	/*
-	 * set feature regardless
-	 */
-	ali15x3_do_setfeature(drive, udma_mode = udma2_bits_to_command(bits));
-	udma_mode &= 0x0f;	/* get UDMA mode */
+	return (err);
+}
+
+static int config_chipset_for_dma (ide_drive_t *drive, byte ultra33)
+{
+	struct hd_driveid *id	= drive->id;
+	ide_hwif_t *hwif	= HWIF(drive);
+	byte speed		= 0x00;
+	byte ultra66		= ((hwif->udma_four) && (id->hw_config & 0x2000)) ? 1 : 0;
+	int  rval;
+
+	if ((id->dma_ultra & 0x0010) && (ultra66) && (ultra33)) {
+		speed = XFER_UDMA_4;
+	} else if ((id->dma_ultra & 0x0008) && (ultra66) && (ultra33)) {
+		speed = XFER_UDMA_3;
+	} else if ((id->dma_ultra & 0x0004) && (ultra33)) {
+		speed = XFER_UDMA_2;
+	} else if ((id->dma_ultra & 0x0002) && (ultra33)) {
+		speed = XFER_UDMA_1;
+	} else if ((id->dma_ultra & 0x0001) && (ultra33)) {
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		speed = XFER_SW_DMA_0;
+	} else {
+		return ((int) ide_dma_off_quietly);
+	}
 
-	/*
-	 * Enable DMA and UltraDMA
-	 */
-	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
-	/*
-	 * m5229 ultra
-	 */
-	pci_read_config_byte(hwif->pci_dev, m5229_udma_setting_index, &tmpbyte);
-	/*
-	 * clear bit0~3 or bit 4~7
-	 */
-	tmpbyte &= (0x0f << ((1-unit) << 2));
-	/*
-	 * enable ultra dma and set timing
-	 */
-	tmpbyte |= ((0x08 | (4-udma_mode)) << (unit << 2));
-	/*
-	 * set to m5229
-	 */
-	save_flags(flags);
-	cli();		
-	pci_write_config_byte(hwif->pci_dev, m5229_udma_setting_index, tmpbyte);
-	restore_flags(flags);
+	(void) ali15x3_tune_chipset(drive, speed);
 
-	if (udma_mode >= 3) {
-		/*
-		 * ultra 66
-		 */
-		pci_read_config_byte(hwif->pci_dev, 0x4b, &tmpbyte);
-		tmpbyte |= 1;			
-		save_flags(flags);
-		cli();
-		pci_write_config_byte(hwif->pci_dev, 0x4b, tmpbyte);		
-		restore_flags(flags);
-	}
+	rval = (int)(	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+			((id->dma_mword >> 8) & 7) ? ide_dma_on :
+			((id->dma_1word >> 8) & 7) ? ide_dma_on :
+						     ide_dma_off_quietly);
 
-	printk("ALI15X3: Ultra DMA enabled\n");
+	return rval;
 }
 
-static int ali15x3_dma_onoff(ide_drive_t *drive, int enable)
+static void config_chipset_for_pio (ide_drive_t *drive)
 {
-	if (enable) {
-		ide_hwif_t *hwif = HWIF(drive);
-		unsigned long dma_base = hwif->dma_base;
-		struct hd_driveid *id = drive->id;
-				
-		if ((id->field_valid & 0x0004) && 
-		    (id->dma_ultra & 0x001f)) {
-			/*
-			 * 1543C_E, in ultra mode, WDC "harddisk"
-			 * will cause "CRC" errors (even if no CRC problem),
-			 * so we try to use "DMA" here
-			 */
-			if (m5229_revision <= 0x20) {
-				/*
-				 * Normal MultiWord DMA modes.
-				 */
-				ali15x3_dma2_enable(drive, dma_base);
-			} else if ((m5229_revision < 0xC2) && 
-				   ((drive->media!=ide_disk) ||
-				    (chip_is_1543c_e &&
-				     strstr(id->model, "WDC ")))) {
-				/*
-				 * Normal MultiWord DMA modes.
-				 */
-				ali15x3_dma2_enable(drive, dma_base);
-			} else {
-				/*
-				 * m5229_revision >= 0xC2 for UltraDMA modes.
-				 */
-				ali15x3_udma_enable(drive, dma_base);
-			}
-		} else {
-			/*
-			 * Normal MultiWord DMA modes.
-			 */
-			ali15x3_dma2_enable(drive, dma_base);
-		}
-	}
+	ali15x3_tune_drive(drive, 5);
+}
 
-	drive->using_dma = enable;	/* on, off */
-	return 0;
+
+static byte ali15x3_can_ultra (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+
+	if (m5229_revision <= 0x20) {
+		return 0;
+	} else if ((m5229_revision < 0xC2) &&
+		   ((drive->media!=ide_disk) ||
+		    (chip_is_1543c_e &&
+		     strstr(id->model, "WDC ")))) {
+		return 0;
+	} else {
+		return 1;
+	}
 }
 
 static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
 {
-	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
+	struct hd_driveid *id		= drive->id;
+	ide_hwif_t *hwif		= HWIF(drive);
+	ide_dma_action_t dma_func	= ide_dma_on;
+	byte can_ultra_dma		= ali15x3_can_ultra(drive);
 
 	if ((m5229_revision<=0x20) && (drive->media!=ide_disk))
 		return hwif->dmaproc(ide_dma_off_quietly, drive);
-	/*
-	 * Even if the drive is not _currently_ in a DMA
-	 * mode, we succeed, and we'll enable it manually
-	 * below in alim15x3_dma_onoff
-	 */
-	if ((id != NULL) && (id->capability & 1) && hwif->autodma) {
-		if (id->field_valid & 0x0004) {
-			if (id->dma_ultra & 0x001F)
-				return hwif->dmaproc(ide_dma_on, drive);
-		}
-		if (id->field_valid & 0x0002) {
-			if ((id->dma_mword & 0x0007) || (id->dma_1word & 0x0007))
-				return hwif->dmaproc(ide_dma_on, drive);
+
+	if ((id != NULL) && ((id->capability & 1) != 0) && hwif->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			dma_func = ide_dma_off;
+			goto fast_ata_pio;
+		}
+		dma_func = ide_dma_off_quietly;
+		if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) {
+			if (id->dma_ultra & 0x001F) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive, can_ultra_dma);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0007) ||
+			    (id->dma_1word & 0x0007)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive, can_ultra_dma);
+				if (dma_func != ide_dma_on)
+					goto no_dma_set;
+			}
+		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+			if (id->eide_dma_time > 150) {
+				goto no_dma_set;
+			}
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive, can_ultra_dma);
+			if (dma_func != ide_dma_on)
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
 		}
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+		dma_func = ide_dma_off_quietly;
+no_dma_set:
+		config_chipset_for_pio(drive);
 	}
-	return hwif->dmaproc(ide_dma_off_quietly, drive);
+	return hwif->dmaproc(dma_func, drive);
 }
 
 static int ali15x3_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
@@ -592,10 +482,6 @@
 	switch(func) {
 		case ide_dma_check:
 			return ali15x3_config_drive_for_dma(drive);
-		case ide_dma_on:
-		case ide_dma_off:
-		case ide_dma_off_quietly:
-			return ali15x3_dma_onoff(drive, (func == ide_dma_on));
 		case ide_dma_write:
 			if ((m5229_revision < 0xC2) && (drive->media != ide_disk))
 				return 1;	/* try PIO instead of DMA */
@@ -610,8 +496,6 @@
 unsigned int __init pci_init_ali15x3 (struct pci_dev *dev, const char *name)
 {
 	unsigned long fixdma_base = dev->resource[4].start;
-	byte tmpbyte;
-	unsigned long flags;
 
 	pci_read_config_byte(dev, PCI_REVISION_ID, &m5229_revision);
 
@@ -630,14 +514,22 @@
 		if (inb(fixdma_base+2) & 0x80)
 			printk("%s: simplex device: DMA will fail!!\n", name);
 	}
+	return 0;
+}
 
-	/*
-	 * FIXME !!! This detection needs to be in "ata66_ali15x3()"
-	 * below as a standard detection return.
-	 */
+unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif)
+{
+	struct pci_dev *dev	= hwif->pci_dev;
+	byte ata66mask		= hwif->channel ? 0x02 : 0x01;
+	unsigned int ata66	= 0;
+
+	unsigned long flags;
+	byte tmpbyte;
+
+	__save_flags(flags);
+	__cli();
 
 	if (m5229_revision >= 0xC2) {
-		unsigned long flags;
 		/*
 		 * 1543C-B?, 1535, 1535D, 1553
 		 * Note 1: not all "motherboard" support this detection
@@ -645,8 +537,6 @@
 		 *         but in this case, we will not set the device to
 		 *         ultra 66, the detection result is not important
 		 */
-		save_flags(flags);
-		cli();
 
 		/*
 		 * enable "Cable Detection", m5229, 0x4b, bit3
@@ -669,7 +559,6 @@
 			 */
 			pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
 		}
-		restore_flags(flags);
 		/*
 		 * Ultra66 cable detection (from Host View)
 		 * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
@@ -679,30 +568,23 @@
 		 * 0x4a, bit0 is 0 => primary channel
 		 * has 80-pin (from host view)
 		 */
-		if (!(tmpbyte & 0x01))
-			cable_80_pin[0] = 1;
+		if (!(tmpbyte & 0x01)) cable_80_pin[0] = 1;
 		/*
 		 * 0x4a, bit1 is 0 => secondary channel
 		 * has 80-pin (from host view)
 		 */
-		if (!(tmpbyte & 0x02))
-			cable_80_pin[1] = 1;
+		if (!(tmpbyte & 0x02)) cable_80_pin[1] = 1;
 	} else {
-		unsigned long flags;
 		/*
 		 * revision 0x20 (1543-E, 1543-F)
 		 * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E)
 		 * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7
 		 */
 		pci_read_config_byte(dev, 0x4b, &tmpbyte);
-		save_flags(flags);
-		cli();
 		/*
 		 * clear bit 7
 		 */
 		pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
-		restore_flags(flags);
-
 		/*
 		 * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
 		 */
@@ -710,131 +592,17 @@
 		chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
 	}
 
-	if (m5229_revision == 0x20) {
-		/*
-		 * check M1533 revision (offset 0x08)
-		 */
-		pci_read_config_byte(isa_dev, 0x08, &tmpbyte);
-		if (tmpbyte == 0x0A) {
-			unsigned long flags;
-			pci_read_config_byte(dev, 0x4e, &tmpbyte);
-			save_flags(flags);
-			cli();
-			/*
-			 * set bit 6
-			 */
-			pci_write_config_byte(dev, 0x4e, tmpbyte | 0x40);
-			restore_flags(flags);
-
-			/*
-			 * this special version is similar to revision 0xC2
-			 * but does not support UDMA66
-			 * (cable_80_pin[0] = 0; cable_80_pin[1] = 0;)
-			 */
-			m5229_revision = 0xC2;
-		}
-	}
-	
 	/*
 	 * CD_ROM DMA on (m5229, 0x53, bit0)
-	 * 	Enable this bit even if we want to use PIO
+	 *      Enable this bit even if we want to use PIO
 	 * PIO FIFO off (m5229, 0x53, bit1)
-	 * 	The hardware will use 0x54h and 0x55h to control PIO FIFO
+	 *      The hardware will use 0x54h and 0x55h to control PIO FIFO
 	 */
 	pci_read_config_byte(dev, 0x53, &tmpbyte);
 	tmpbyte = (tmpbyte & (~0x02)) | 0x01;
-	save_flags(flags);
-	cli();
-	pci_write_config_byte(dev, 0x53, tmpbyte);
-	restore_flags(flags);	 
-
-	return 0;
-}
-
-unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif)
-{
-#if 0
-	/*
-	 * FIXME !!! This detection needs to be in "ata66_ali15x3()"
-	 * below as a standard detection return.
-	 */
-
-	if (m5229_revision >= 0xC2) {
-		unsigned long flags;
-		/*
-		 * 1543C-B?, 1535, 1535D, 1553
-		 * Note 1: not all "motherboard" support this detection
-		 * Note 2: if no udma 66 device, the detection may "error".
-		 *         but in this case, we will not set the device to
-		 *         ultra 66, the detection result is not important
-		 */
-		save_flags(flags);
-		cli();
-
-		/*
-		 * enable "Cable Detection", m5229, 0x4b, bit3
-		 */
-		pci_read_config_byte(dev, 0x4b, &tmpbyte);
-		pci_write_config_byte(dev, 0x4b, tmpbyte | 0x08);
-
-		/*
-		 * set south-bridge's enable bit, m1533, 0x79
-		 */
-		pci_read_config_byte(isa_dev, 0x79, &tmpbyte);
-		if (m5229_revision == 0xC2) {
-			/*
-			 * 1543C-B0 (m1533, 0x79, bit 2)
-			 */
-			pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x04);
-		} else if (m5229_revision == 0xC3) {
-			/*
-			 * 1553/1535 (m1533, 0x79, bit 1)
-			 */
-			pci_write_config_byte(isa_dev, 0x79, tmpbyte | 0x02);
-		}
-		restore_flags(flags);
-		/*
-		 * Ultra66 cable detection (from Host View)
-		 * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
-		 */
-		pci_read_config_byte(dev, 0x4a, &tmpbyte);
-		/*
-		 * 0x4a, bit0 is 0 => primary channel
-		 * has 80-pin (from host view)
-		 */
-		if (!(tmpbyte & 0x01))
-			cable_80_pin[0] = 1;
-		/*
-		 * 0x4a, bit1 is 0 => secondary channel
-		 * has 80-pin (from host view)
-		 */
-		if (!(tmpbyte & 0x02))
-			cable_80_pin[1] = 1;
-	} else {
-		unsigned long flags;
-		/*
-		 * revision 0x20 (1543-E, 1543-F)
-		 * revision 0xC0, 0xC1 (1543C-C, 1543C-D, 1543C-E)
-		 * clear CD-ROM DMA write bit, m5229, 0x4b, bit 7
-		 */
-		pci_read_config_byte(dev, 0x4b, &tmpbyte);
-		save_flags(flags);
-		cli();
-		/*
-		 * clear bit 7
-		 */
-		pci_write_config_byte(dev, 0x4b, tmpbyte & 0x7F);
-		restore_flags(flags);
 
-		/*
-		 * check m1533, 0x5e, bit 1~4 == 1001 => & 00011110 = 00010010
-		 */
-		pci_read_config_byte(isa_dev, 0x5e, &tmpbyte);
-		chip_is_1543c_e = ((tmpbyte & 0x1e) == 0x12) ? 1: 0;
-	}
+	pci_write_config_byte(dev, 0x53, tmpbyte);
 
-	byte ata66mask		= hwif->channel ? 0x02 : 0x01;
-	unsigned int ata66	= 0;
 	/*
 	 * Ultra66 cable detection (from Host View)
 	 * m5229, 0x4a, bit0: primary, bit1: secondary 80 pin
@@ -845,12 +613,11 @@
 	 * 0x4a, bit1 is 0 => secondary channel
 	 * has 80-pin (from host view)
 	 */
-	pci_read_config_byte(hwif->pci_dev, 0x4a, &tmpbyte);
+	pci_read_config_byte(dev, 0x4a, &tmpbyte);
 	ata66 = (!(tmpbyte & ata66mask)) ? 0 : 1;
+	__restore_flags(flags);
+
 	return(ata66);
-#else
-	return 0;
-#endif
 }
 
 void __init ide_init_ali15x3 (ide_hwif_t *hwif)
@@ -871,8 +638,7 @@
 		ideic = ideic & 0x03;
 
 		/* get IRQ for IDE Controller */
-		if ((hwif->channel && ideic == 0x03) ||
-		    (!hwif->channel && !ideic)) {
+		if ((hwif->channel && ideic == 0x03) || (!hwif->channel && !ideic)) {
 			/*
 			 * get SIRQ1 routing table
 			 */
@@ -905,9 +671,11 @@
 	}
 	
 #if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS)
-	ali_proc = 1;
-	bmide_dev = hwif->pci_dev;
-	ali_display_info = &ali_get_info;
+	if (!ali_proc) {
+		ali_proc = 1;
+		bmide_dev = hwif->pci_dev;
+		ali_display_info = &ali_get_info;
+	}
 #endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */
 
 	return;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/amd7409.c linux/drivers/block/amd7409.c
--- v2.3.39/linux/drivers/block/amd7409.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/amd7409.c	Fri Jan 14 00:50:53 2000
@@ -0,0 +1,290 @@
+/*
+ * linux/drivers/block/amd7409.c	Version 0.01	Jan. 10, 2000
+ *
+ * Copyright (C) 2000			Andre Hedrick <andre@suse.com>
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+/*
+ * Here is where all the hard work goes to program the chipset.
+ *
+ */
+static int amd7409_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	int err			= 0;
+	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) +
+				   (drive->select.b.unit & 0x01));
+	byte drive_pci		= 0x00;
+	byte drive_pci2		= 0x00;
+	byte drive_timing	= 0x00;
+	byte pio_timing		= 0x00;
+
+        switch (drive_number) {
+		case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break;
+		case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break;
+		case 2: drive_pci = 0x51; drive_pci2 = 0x49; break;
+		case 3: drive_pci = 0x50; drive_pci2 = 0x48; break;
+		default:
+                        return ((int) ide_dma_off_quietly);
+        }
+
+	pci_read_config_byte(dev, drive_pci, &drive_timing);
+	pci_read_config_byte(dev, drive_pci2, &pio_timing);
+
+	printk("%s: UDMA 0x%02x PIO 0x%02x ",
+		drive->name, drive_timing, pio_timing);
+
+	switch(speed) {
+		case XFER_UDMA_4:
+			drive_timing &= ~0xC7;
+			drive_timing |= 0x45;
+			pci_write_config_byte(dev, drive_pci, drive_timing);
+			break;
+		case XFER_UDMA_3:
+			drive_timing &= ~0xC7;
+			drive_timing |= 0x44;
+			pci_write_config_byte(dev, drive_pci, drive_timing);
+			break;
+		case XFER_UDMA_2:
+			drive_timing &= ~0xC7;
+			drive_timing |= 0x40;
+			pci_write_config_byte(dev, drive_pci, drive_timing);
+			break;
+		case XFER_UDMA_1:
+			drive_timing &= ~0xC7;
+			drive_timing |= 0x41;
+			pci_write_config_byte(dev, drive_pci, drive_timing);
+			break;
+		case XFER_UDMA_0:
+			drive_timing &= ~0xC7;
+			drive_timing |= 0x42;
+			pci_write_config_byte(dev, drive_pci, drive_timing);
+			break;
+		case XFER_MW_DMA_2:break;
+		case XFER_MW_DMA_1:break;
+		case XFER_MW_DMA_0:break;
+		case XFER_SW_DMA_2:break;
+		case XFER_SW_DMA_1:break;
+		case XFER_SW_DMA_0:break;
+		case XFER_PIO_4:break;
+		case XFER_PIO_3:break;
+		case XFER_PIO_2:break;
+		case XFER_PIO_1:break;
+		case XFER_PIO_0:break;
+		default: break;
+        }
+
+	printk(":: UDMA 0x%02x PIO 0x%02x\n", drive_timing, pio_timing);
+
+	err = ide_config_drive_speed(drive, speed);
+	return (err);
+}
+
+/*
+ * This allows the configuration of ide_pci chipset registers
+ * for cards that learn about the drive's UDMA, DMA, PIO capabilities
+ * after the drive is reported by the OS.
+ */
+static int config_chipset_for_dma (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+	byte speed		= 0x00;
+	int  rval;
+
+	if ((id->dma_ultra & 0x0010) && (HWIF(drive)->udma_four)) {
+		speed = XFER_UDMA_4;
+	} else if ((id->dma_ultra & 0x0008) && (HWIF(drive)->udma_four)) {
+		speed = XFER_UDMA_3;
+	} else if (id->dma_ultra & 0x0004) {
+		speed = XFER_UDMA_2;
+	} else if (id->dma_ultra & 0x0002) {
+		speed = XFER_UDMA_1;
+	} else if (id->dma_ultra & 0x0001) {
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		speed = XFER_SW_DMA_0;
+        } else {
+		return ((int) ide_dma_off_quietly);
+	}
+
+	(void) amd7409_tune_chipset(drive, speed);
+
+	rval = (int)(	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+			((id->dma_mword >> 8) & 7) ? ide_dma_on :
+			((id->dma_1word >> 8) & 7) ? ide_dma_on :
+						     ide_dma_off_quietly);
+
+	return rval;
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive)
+{
+	unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
+	unsigned short xfer_pio	= drive->id->eide_pio_modes;
+	byte			timing, speed, pio;
+
+	pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+	if (xfer_pio> 4)
+		xfer_pio = 0;
+
+	if (drive->id->eide_pio_iordy > 0) {
+		for (xfer_pio = 5;
+			xfer_pio>0 &&
+			drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
+			xfer_pio--);
+	} else {
+		xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
+			   (drive->id->eide_pio_modes & 2) ? 0x04 :
+			   (drive->id->eide_pio_modes & 1) ? 0x03 :
+			   (drive->id->tPIO & 2) ? 0x02 :
+			   (drive->id->tPIO & 1) ? 0x01 : xfer_pio;
+	}
+
+	timing = (xfer_pio >= pio) ? xfer_pio : pio;
+
+	switch(timing) {
+		case 4: speed = XFER_PIO_4;break;
+		case 3: speed = XFER_PIO_3;break;
+		case 2: speed = XFER_PIO_2;break;
+		case 1: speed = XFER_PIO_1;break;
+		default:
+			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
+			break;
+	}
+	(void) amd7409_tune_chipset(drive, speed);
+}
+
+static void amd7409_tune_drive (ide_drive_t *drive, byte pio)
+{
+	byte speed;
+	switch(pio) {
+		case 4:		speed = XFER_PIO_4;break;
+		case 3:		speed = XFER_PIO_3;break;
+		case 2:		speed = XFER_PIO_2;break;
+		case 1:		speed = XFER_PIO_1;break;
+		default:	speed = XFER_PIO_0;break;
+	}
+	(void) amd7409_tune_chipset(drive, speed);
+}
+
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+	ide_dma_action_t dma_func = ide_dma_on;
+
+	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			dma_func = ide_dma_off;
+			goto fast_ata_pio;
+		}
+		dma_func = ide_dma_off_quietly;
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & 0x001F) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0007) ||
+			    (id->dma_1word & 0x0007)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive);
+				if (dma_func != ide_dma_on)
+					goto no_dma_set;
+			}
+		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+			if (id->eide_dma_time > 150) {
+				goto no_dma_set;
+			}
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive);
+			if (dma_func != ide_dma_on)
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+		dma_func = ide_dma_off_quietly;
+no_dma_set:
+
+		config_chipset_for_pio(drive);
+	}
+	return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * amd7409_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+
+int amd7409_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			return config_drive_xfer_rate(drive);
+		default:
+			break;
+	}
+	return ide_dmaproc(func, drive);	/* use standard DMA stuff */
+}
+
+unsigned int __init ata66_amd7409 (ide_hwif_t *hwif)
+{
+#if 0
+	byte ata66 = 0;
+
+	pci_read_config_byte(hwif->pci_dev, 0x48, &ata66);
+	return ((ata66 & 0x02) ? 0 : 1);
+#else
+	return 0;
+#endif
+}
+
+void __init ide_init_amd7409 (ide_hwif_t *hwif)
+{
+	hwif->tuneproc = &amd7409_tune_drive;
+	if (hwif->dma_base) {
+		hwif->dmaproc = &amd7409_dmaproc;
+	} else {
+		hwif->autodma = 0;
+		hwif->drives[0].autotune = 1;
+		hwif->drives[1].autotune = 1;
+	}
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/block/cmd646.c linux/drivers/block/cmd646.c
--- v2.3.39/linux/drivers/block/cmd646.c	Mon Aug  2 22:07:16 1999
+++ linux/drivers/block/cmd646.c	Wed Dec 31 16:00:00 1969
@@ -1,289 +0,0 @@
-/* $Id: cmd646.c,v 1.15 1999/07/23 01:48:37 davem Exp $
- * cmd646.c: Enable interrupts at initialization time on Ultra/PCI machines.
- *           Note, this driver is not used at all on other systems because
- *           there the "BIOS" has done all of the following already.
- *           Due to massive hardware bugs, UltraDMA is only supported
- *           on the 646U2 and not on the 646U.
- *
- * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
- * Copyright (C) 1998       David S. Miller (davem@dm.cobaltmicro.com)
- */
-
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/hdreg.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-
-static int cmd646_config_drive_for_dma(ide_drive_t *drive)
-{
-	struct hd_driveid *id = drive->id;
-	ide_hwif_t *hwif = HWIF(drive);
-
-	/* Even if the drive is not _currently_ in a DMA
-	 * mode, we succeed, and we'll enable it manually
-	 * below in cmd646_dma_onoff.
-	 *
-	 * This is done for disks only, CDROMs and other
-	 * IDE devices are just too quirky.
-	 */
-	if((id != NULL) &&
-	   ((id->capability & 1) != 0) &&
-	   hwif->autodma &&
-	   (drive->media == ide_disk)) {
-		if(id->field_valid & 0x0004) {
-			if(id->dma_ultra & 0x0007)
-				return hwif->dmaproc(ide_dma_on, drive);
-		}
-		if(id->field_valid & 0x0002)
-			if((id->dma_mword & 0x0004) || (id->dma_1word & 0x0004))
-				return hwif->dmaproc(ide_dma_on, drive);
-	}
-	return hwif->dmaproc(ide_dma_off_quietly, drive);
-}
-
-/* This is fun.  -DaveM */
-#define IDE_SETXFER		SETFEATURES_XFER
-#define IDE_SETFEATURE		WIN_SETFEATURES
-#define IDE_DMA2_ENABLE		XFER_MW_DMA_2
-#define IDE_DMA1_ENABLE		XFER_MW_DMA_1
-#define IDE_DMA0_ENABLE		XFER_MW_DMA_0
-#define IDE_UDMA2_ENABLE	XFER_UDMA_2
-#define IDE_UDMA1_ENABLE	XFER_UDMA_1
-#define IDE_UDMA0_ENABLE	XFER_UDMA_0
-
-static __inline__ unsigned char dma2_bits_to_command(unsigned char bits)
-{
-	if(bits & 0x04)
-		return IDE_DMA2_ENABLE;
-	if(bits & 0x02)
-		return IDE_DMA1_ENABLE;
-	return IDE_DMA0_ENABLE;
-}
-
-static __inline__ unsigned char udma2_bits_to_command(unsigned char bits)
-{
-	if(bits & 0x04)
-		return IDE_UDMA2_ENABLE;
-	if(bits & 0x02)
-		return IDE_UDMA1_ENABLE;
-	return IDE_UDMA0_ENABLE;
-}
-
-static __inline__ int wait_for_ready(ide_drive_t *drive)
-{
-	int timeout = 100;
-	byte stat;
-
-	while(--timeout) {
-		stat = GET_STAT();
-
-		printk("STAT(%2x) ", stat);
-		if(!(stat & BUSY_STAT)) {
-			if((stat & READY_STAT) || (stat & ERR_STAT))
-				break;
-		}
-		udelay(100);
-	}
-	if((stat & ERR_STAT) || timeout <= 0)
-		return 1;
-	return 0;
-}
-
-static void cmd646_do_setfeature(ide_drive_t *drive, byte command)
-{
-#if 0
-	(void) ide_config_drive_speed(drive, command);
-#else
-	unsigned long flags;
-	byte old_select;
-
-	save_flags(flags);
-	cli();
-	printk("SELECT ");
-	old_select = IN_BYTE(IDE_SELECT_REG);
-	OUT_BYTE(drive->select.all, IDE_SELECT_REG);
-	printk("SETXFER ");
-	OUT_BYTE(IDE_SETXFER, IDE_FEATURE_REG);
-	printk("CMND ");
-	OUT_BYTE(command, IDE_NSECTOR_REG);
-	printk("wait ");
-	if(wait_for_ready(drive))
-		goto out;
-	printk("SETFEATURE ");
-	OUT_BYTE(IDE_SETFEATURE, IDE_COMMAND_REG);
-	printk("wait ");
-	(void) wait_for_ready(drive);
-out:
-	OUT_BYTE(old_select, IDE_SELECT_REG);
-	restore_flags(flags);
-#endif
-}
-
-static void cmd646_dma2_enable(ide_drive_t *drive, unsigned long dma_base)
-{
-	byte unit = (drive->select.b.unit & 0x01);
-	byte bits = (drive->id->dma_mword | drive->id->dma_1word) & 0x07;
-
-	printk("CMD646: MDMA enable [");
-	if((((drive->id->dma_mword & 0x0007) << 8) !=
-	    (drive->id->dma_mword & 0x0700)))
-		cmd646_do_setfeature(drive, dma2_bits_to_command(bits));
-	printk("DMA_CAP ");
-	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
-	printk("DONE]\n");
-}
-
-static void cmd646_udma_enable(ide_drive_t *drive, unsigned long dma_base)
-{
-	byte unit = (drive->select.b.unit & 0x01);
-	byte udma_ctrl, bits = drive->id->dma_ultra & 0x07;
-	byte udma_timing_bits;
-
-	printk("CMD646: UDMA enable [");
-	if(((drive->id->dma_ultra & 0x0007) << 8) !=
-	   (drive->id->dma_ultra & 0x0700))
-		cmd646_do_setfeature(drive, udma2_bits_to_command(bits));
-
-	/* Enable DMA and UltraDMA */
-	printk("DMA_CAP ");
-	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
-
-	udma_ctrl = inb(dma_base + 3);
-
-	/* Put this channel into UDMA mode. */
-	printk("UDMA_CTRL ");
-	udma_ctrl |= (1 << unit);
-
-	/* Set UDMA2 usable timings. */
-	if(bits & 0x04)
-		udma_timing_bits = 0x10;
-	else if(bits & 0x02)
-		udma_timing_bits = 0x20;
-	else
-		udma_timing_bits = 0x30;
-	udma_ctrl &= ~(0x30 << (unit * 2));
-	udma_ctrl |=  (udma_timing_bits << (unit * 2));
-
-	outb(udma_ctrl, dma_base+3);
-	printk("DONE]\n");
-}
-
-static int cmd646_dma_onoff(ide_drive_t *drive, int enable)
-{
-	if(enable) {
-		ide_hwif_t *hwif = HWIF(drive);
-		unsigned long dma_base = hwif->dma_base;
-		struct hd_driveid *id = drive->id;
-		unsigned int class_rev;
-
-		/* UltraDMA only supported on PCI646U and PCI646U2,
-		 * which correspond to revisions 0x03 and 0x05 respectively.
-		 * Actually, although the CMD tech support people won't
-		 * tell me the details, the 0x03 revision cannot support
-		 * UDMA correctly without hardware modifications, and even
-		 * then it only works with Quantum disks due to some
-		 * hold time assumptions in the 646U part which are fixed
-		 * in the 646U2.
-		 * So we only do UltraDMA on revision 0x05 chipsets.
-		 */
-		pci_read_config_dword(hwif->pci_dev,
-				      PCI_CLASS_REVISION,
-				      &class_rev);
-		class_rev &= 0xff;
-		if((class_rev == 0x05) &&
-		   (id->field_valid & 0x0004) &&
-		   (id->dma_ultra & 0x07)) {
-			/* UltraDMA modes. */
-			cmd646_udma_enable(drive, dma_base);
-		} else {
-			/* Normal MultiWord DMA modes. */
-			cmd646_dma2_enable(drive, dma_base);
-		}
-	}
-	drive->using_dma = enable;
-	return 0;
-}
-
-static int cmd646_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
-	if(func == ide_dma_check)
-		return cmd646_config_drive_for_dma(drive);
-	else if(func == ide_dma_on || func == ide_dma_off || func == ide_dma_off_quietly)
-		return cmd646_dma_onoff(drive, (func == ide_dma_on));
-
-	/* Other cases are done by generic IDE-DMA code. */
-	return ide_dmaproc(func, drive);
-}
-
-/*
- * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
- * event order for DMA transfers.
- */
-static int cmd646_1_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
-	ide_hwif_t *hwif = HWIF(drive);
-	unsigned long dma_base = hwif->dma_base;
-	byte dma_stat;
-
-	if (func == ide_dma_end) {
-		drive->waiting_for_dma = 0;
-		dma_stat = inb(dma_base+2);		/* get DMA status */
-		outb(inb(dma_base)&~1, dma_base);	/* stop DMA */
-		outb(dma_stat|6, dma_base+2);	/* clear the INTR & ERROR bits */
-		return (dma_stat & 7) != 4;	/* verify good DMA status */
-	}
-
-	/* Other cases are done by generic IDE-DMA code. */
-	return cmd646_dmaproc(func, drive);
-}
-
-void __init ide_init_cmd646 (ide_hwif_t *hwif)
-{
-	struct pci_dev *dev = hwif->pci_dev;
-	unsigned char mrdmode;
-	unsigned int class_rev;
-
-	pci_read_config_dword(hwif->pci_dev, PCI_CLASS_REVISION, &class_rev);
-	class_rev &= 0xff;
-
-	hwif->chipset = ide_cmd646;
-
-	/* Set a good latency timer and cache line size value. */
-	(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-#ifdef __sparc_v9__
-	(void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10);
-#endif
-
-	/* Setup interrupts. */
-	(void) pci_read_config_byte(dev, 0x71, &mrdmode);
-	mrdmode &= ~(0x30);
-	(void) pci_write_config_byte(dev, 0x71, mrdmode);
-
-	/* Use MEMORY READ LINE for reads.
-	 * NOTE: Although not mentioned in the PCI0646U specs,
-	 *       these bits are write only and won't be read
-	 *       back as set or not.  The PCI0646U2 specs clarify
-	 *       this point.
-	 */
-	(void) pci_write_config_byte(dev, 0x71, mrdmode | 0x02);
-
-	/* Set reasonable active/recovery/address-setup values. */
-	(void) pci_write_config_byte(dev, 0x53, 0x40);
-	(void) pci_write_config_byte(dev, 0x54, 0x3f);
-	(void) pci_write_config_byte(dev, 0x55, 0x40);
-	(void) pci_write_config_byte(dev, 0x56, 0x3f);
-	(void) pci_write_config_byte(dev, 0x57, 0x5c);
-	(void) pci_write_config_byte(dev, 0x58, 0x3f);
-	(void) pci_write_config_byte(dev, 0x5b, 0x3f);
-
-	if (hwif->dma_base) {
-		if (class_rev == 0x01) {
-			hwif->dmaproc = &cmd646_1_dmaproc;
-		} else {
-			hwif->dmaproc = &cmd646_dmaproc;
-		}
-	}
-}
diff -u --recursive --new-file v2.3.39/linux/drivers/block/cmd64x.c linux/drivers/block/cmd64x.c
--- v2.3.39/linux/drivers/block/cmd64x.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/cmd64x.c	Fri Jan 14 00:50:53 2000
@@ -0,0 +1,340 @@
+/* $Id: cmd64x.c,v 1.20 1999/12/30 03:48:37
+ *
+ * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
+ *           Note, this driver is not used at all on other systems because
+ *           there the "BIOS" has done all of the following already.
+ *           Due to massive hardware bugs, UltraDMA is only supported
+ *           on the 646U2 and not on the 646U.
+ *
+ * Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
+ * Copyright (C) 1998       David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1999       Andre Hedrick (andre@suse.com)
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+
+#define CMD_DEBUG 0
+
+#if CMD_DEBUG
+#define cmdprintk(x...)	printk(##x)
+#else
+#define cmdprintk(x...)
+#endif
+
+static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
+{
+	struct hd_driveid *id	= drive->id;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	unsigned long dma_base	= hwif->dma_base;
+
+ 	byte unit		= (drive->select.b.unit & 0x01);
+	byte speed		= 0x00;
+	byte udma_timing_bits	= 0x00;
+	byte udma_33		= ((rev >= 0x05) || (ultra_66)) ? 1 : 0;
+	byte udma_66		= ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+	/* int drive_number	= ((hwif->channel ? 2 : 0) + unit); */
+	int rval;
+
+	switch(dev->device) {
+		case PCI_DEVICE_ID_CMD_643:
+		case PCI_DEVICE_ID_CMD_646:
+		case PCI_DEVICE_ID_CMD_648:
+		default:
+			break;
+	}
+
+	if (drive->media != ide_disk) {
+		cmdprintk("CMD64X: drive->media != ide_disk at double check, inital check failed!!\n");
+		return ((int) ide_dma_off);
+	}
+
+	/* UltraDMA only supported on PCI646U and PCI646U2,
+	 * which correspond to revisions 0x03, 0x05 and 0x07 respectively.
+	 * Actually, although the CMD tech support people won't
+	 * tell me the details, the 0x03 revision cannot support
+	 * UDMA correctly without hardware modifications, and even
+	 * then it only works with Quantum disks due to some
+	 * hold time assumptions in the 646U part which are fixed
+	 * in the 646U2.
+	 * So we only do UltraDMA on revision 0x05 and 0x07 chipsets.
+	 */
+
+	if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) {
+		speed = XFER_UDMA_4;
+		udma_timing_bits = 0x10;	/* 2 clock */
+	} else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) {
+		speed = XFER_UDMA_3;
+		udma_timing_bits = 0x20;	/* 3 clock */
+	} else if ((id->dma_ultra & 0x0004) && (udma_33)) {
+		speed = XFER_UDMA_2;
+		udma_timing_bits = 0x10;	/* 2 clock */
+	} else if ((id->dma_ultra & 0x0002) && (udma_33)) {
+		speed = XFER_UDMA_1;
+		udma_timing_bits = 0x20;	/* 3 clock */
+	} else if ((id->dma_ultra & 0x0001) && (udma_33)) {
+		speed = XFER_UDMA_0;
+		udma_timing_bits = 0x30;	/* 4 clock */
+	} else if (id->dma_mword & 0x0004) {
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_mword & 0x0001) {
+		speed = XFER_MW_DMA_0;
+	} else if (id->dma_1word & 0x0004) {
+		speed = XFER_SW_DMA_2;
+	} else if (id->dma_1word & 0x0002) {
+		speed = XFER_SW_DMA_1;
+	} else if (id->dma_1word & 0x0001) {
+		speed = XFER_SW_DMA_0;
+	} else {
+		return ((int) ide_dma_off_quietly);
+	}
+
+	(void) ide_config_drive_speed(drive, speed);
+	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+
+	if (speed >= XFER_UDMA_0) {
+		byte udma_ctrl = inb(dma_base + 3);
+		/* Put this channel into UDMA mode. */
+		udma_ctrl |= (1 << unit);
+		udma_ctrl &= ~(0x04 << unit);
+		if (udma_66)
+			udma_ctrl |= (0x04 << unit);
+		udma_ctrl &= ~(0x30 << (unit * 2));
+		udma_ctrl |=  (udma_timing_bits << (unit * 2));
+		outb(udma_ctrl, dma_base+3);
+	}
+
+	rval = (int)(	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+			((id->dma_mword >> 8) & 7) ? ide_dma_on :
+			((id->dma_1word >> 8) & 7) ? ide_dma_on :
+						     ide_dma_off_quietly);
+
+	return rval;
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive, unsigned int rev)
+{
+	/*  FIXME!! figure out some PIOing junk.... */
+}
+
+static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	unsigned int class_rev	= 0;
+	byte can_ultra_33	= 0;
+	byte can_ultra_66	= 0;
+	ide_dma_action_t dma_func = ide_dma_on;
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;	
+
+	switch(dev->device) {
+		case PCI_DEVICE_ID_CMD_643:
+			can_ultra_33 = 1;
+			can_ultra_66 = 0;
+			break;
+		case PCI_DEVICE_ID_CMD_646:
+			can_ultra_33 = (class_rev >= 0x05) ? 1 : 0;
+			can_ultra_66 = 0;
+			break;
+		case PCI_DEVICE_ID_CMD_648:
+			can_ultra_33 = 1;
+			can_ultra_66 = 1;
+			break;
+		default:
+			return hwif->dmaproc(ide_dma_off, drive);
+	}
+
+	if ((id != NULL) && ((id->capability & 1) != 0) &&
+	    hwif->autodma && (drive->media == ide_disk)) {
+		/* Consult the list of known "bad" drives */
+		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+			dma_func = ide_dma_off;
+			goto fast_ata_pio;
+		}
+		dma_func = ide_dma_off_quietly;
+		if ((id->field_valid & 4) && (can_ultra_33)) {
+			if (id->dma_ultra & 0x001F) {
+				/* Force if Capable UltraDMA */
+				dma_func = config_chipset_for_dma(drive, class_rev, can_ultra_66);
+				if ((id->field_valid & 2) &&
+				    (dma_func != ide_dma_on))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+try_dma_modes:
+			if ((id->dma_mword & 0x0007) ||
+			    (id->dma_1word & 0x0007)) {
+				/* Force if Capable regular DMA modes */
+				dma_func = config_chipset_for_dma(drive, class_rev, 0);
+				if (dma_func != ide_dma_on)
+					goto no_dma_set;
+			}
+		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+			if (id->eide_dma_time > 150) {
+				goto no_dma_set;
+			}
+			/* Consult the list of known "good" drives */
+			dma_func = config_chipset_for_dma(drive, class_rev, 0);
+			if (dma_func != ide_dma_on)
+				goto no_dma_set;
+		} else {
+			goto fast_ata_pio;
+		}
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+		dma_func = ide_dma_off_quietly;
+no_dma_set:
+		config_chipset_for_pio(drive, class_rev);
+	}
+	return hwif->dmaproc(dma_func, drive);
+}
+
+static int cmd64x_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	switch (func) {
+		case ide_dma_check:
+			return cmd64x_config_drive_for_dma(drive);
+		default:
+			break;
+	}
+	/* Other cases are done by generic IDE-DMA code. */
+	return ide_dmaproc(func, drive);
+}
+
+/*
+ * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old
+ * event order for DMA transfers.
+ */
+static int cmd646_1_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	unsigned long dma_base = hwif->dma_base;
+	byte dma_stat;
+
+	if (func == ide_dma_end) {
+		drive->waiting_for_dma = 0;
+		dma_stat = inb(dma_base+2);		/* get DMA status */
+		outb(inb(dma_base)&~1, dma_base);	/* stop DMA */
+		outb(dma_stat|6, dma_base+2);		/* clear the INTR & ERROR bits */
+		return (dma_stat & 7) != 4;		/* verify good DMA status */
+	}
+
+	/* Other cases are done by generic IDE-DMA code. */
+	return cmd64x_dmaproc(func, drive);
+}
+
+unsigned int __init pci_init_cmd64x (struct pci_dev *dev, const char *name)
+{
+	unsigned char mrdmode;
+	unsigned int class_rev;
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+
+	switch(dev->device) {
+		case PCI_DEVICE_ID_CMD_643:
+			break;
+		case PCI_DEVICE_ID_CMD_646:
+			printk("%s: chipset revision 0x%02X, ", name, class_rev);
+			switch(class_rev) {
+				case 0x07:
+				case 0x05:
+					printk("UltraDMA Capable");
+					break;
+				case 0x03:
+					printk("MultiWord DMA Force Limited");
+					break;
+				case 0x01:
+				default:
+					printk("MultiWord DMA Limited, IRQ workaround enabled");
+					break;
+				}
+			printk("\n");
+                        break;
+		case PCI_DEVICE_ID_CMD_648:
+			break;
+		default:
+			break;
+	}
+
+	/* Set a good latency timer and cache line size value. */
+	(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+#ifdef __sparc_v9__
+	(void) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x10);
+#endif
+
+	/* Setup interrupts. */
+	(void) pci_read_config_byte(dev, 0x71, &mrdmode);
+	mrdmode &= ~(0x30);
+	(void) pci_write_config_byte(dev, 0x71, mrdmode);
+
+	/* Use MEMORY READ LINE for reads.
+	 * NOTE: Although not mentioned in the PCI0646U specs,
+	 *       these bits are write only and won't be read
+	 *       back as set or not.  The PCI0646U2 specs clarify
+	 *       this point.
+	 */
+	(void) pci_write_config_byte(dev, 0x71, mrdmode | 0x02);
+
+	/* Set reasonable active/recovery/address-setup values. */
+	(void) pci_write_config_byte(dev, 0x53, 0x40);
+	(void) pci_write_config_byte(dev, 0x54, 0x3f);
+	(void) pci_write_config_byte(dev, 0x55, 0x40);
+	(void) pci_write_config_byte(dev, 0x56, 0x3f);
+	(void) pci_write_config_byte(dev, 0x57, 0x5c);
+	(void) pci_write_config_byte(dev, 0x58, 0x3f);
+	(void) pci_write_config_byte(dev, 0x5b, 0x3f);
+	return 0;
+}
+
+unsigned int __init ata66_cmd64x (ide_hwif_t *hwif)
+{
+	byte ata66 = 0;
+	byte mask = (hwif->channel) ? 0x02 : 0x01;
+
+	pci_read_config_byte(hwif->pci_dev, 0x79, &ata66);
+	return (ata66 & mask) ? 1 : 0;
+}
+
+void __init ide_init_cmd64x (ide_hwif_t *hwif)
+{
+	struct pci_dev *dev	= hwif->pci_dev;
+	unsigned int class_rev;
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+
+	if (!hwif->dma_base)
+		return;
+
+	switch(dev->device) {
+		case PCI_DEVICE_ID_CMD_643:
+			hwif->dmaproc = &cmd64x_dmaproc;
+			break;
+		case PCI_DEVICE_ID_CMD_646:
+			hwif->chipset = ide_cmd646;
+			if (class_rev == 0x01) {
+				hwif->dmaproc = &cmd646_1_dmaproc;
+			} else {
+				hwif->dmaproc = &cmd64x_dmaproc;
+			}
+			break;
+		case PCI_DEVICE_ID_CMD_648:
+			hwif->dmaproc = &cmd64x_dmaproc;
+			break;
+		default:
+			break;
+	}
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.3.39/linux/drivers/block/cpqarray.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/cpqarray.c	Tue Jan 18 18:54:21 2000
@@ -171,9 +171,8 @@
 			     int length, int *eof, void *data) {}
 #endif
 
-static void ida_geninit(struct gendisk *g)
+static void ida_geninit(int ctlr)
 {
-	int ctlr = g-ida_gendisk;
 	int i,j;
 	drv_info_t *drv;
 
@@ -317,13 +316,6 @@
 	cpqarray_init();
 	if (nr_ctlr == 0)
 		return -EIO;
-
-	for(i=0; i<nr_ctlr; i++) {
-		ida_geninit(&ida_gendisk[i]); 
-		for(j=0; j<NWD; j++)	
-			if (ida_sizes[(i<<CTLR_SHIFT) + (j<<NWD_SHIFT)])
-				resetup_one_dev(&ida_gendisk[i], j);
-	}
 	return 0;
 }
 
@@ -375,7 +367,7 @@
 		do_ida_request4, do_ida_request5,
 		do_ida_request6, do_ida_request7,
 	};
-	int i;
+	int i,j;
 
 	/* detect controllers */
 	cpqarray_pci_detect();
@@ -460,22 +452,21 @@
 		hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);
 
 		ida_procinit(i);
-		ida_gendisk[i].major = MAJOR_NR + i;
-		ida_gendisk[i].major_name = "ida";
-		ida_gendisk[i].minor_shift = NWD_SHIFT;
-		ida_gendisk[i].max_p = 16;
-		ida_gendisk[i].max_nr = 16;
-		ida_gendisk[i].init = ida_geninit;
-		ida_gendisk[i].part = ida + (i*256);
-		ida_gendisk[i].sizes = ida_sizes + (i*256);
-		/* ida_gendisk[i].nr_real is handled by getgeometry */
 	
 		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i), request_fns[i]);
 		blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 0);
 
 		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;
+		ida_gendisk[i].major = MAJOR_NR + i;
+		ida_gendisk[i].major_name = "ida";
+		ida_gendisk[i].minor_shift = NWD_SHIFT;
+		ida_gendisk[i].max_p = 16;
+		ida_gendisk[i].part = ida + (i*256);
+		ida_gendisk[i].sizes = ida_sizes + (i*256);
+		/* ida_gendisk[i].nr_real is handled by getgeometry */
 
 		/* Get on the disk list */
 		ida_gendisk[i].next = gendisk_head;
@@ -487,6 +478,10 @@
 		hba[i]->timer.function = ida_timer;
 		add_timer(&hba[i]->timer);
 
+		ida_geninit(i);
+		for(j=0; j<NWD; j++)	
+			register_disk(&ida_gendisk[i], MKDEV(MAJOR_NR+i,j<<4),
+					16, &ida_fops, hba[i]->drv[j].nr_blks);
 	}
 	/* done ! */
 	return;
@@ -1494,7 +1489,7 @@
 	getgeometry(ctlr);
 	hba[ctlr]->access.set_intr_mask(hba[ctlr], FIFO_NOT_EMPTY);
 
-	ida_geninit(&ida_gendisk[ctlr]);
+	ida_geninit(ctlr);
 	for(i=0; i<NWD; i++)
 		if (ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)])
 			revalidate_logvol(dev+(i<<NWD_SHIFT), 2);
@@ -1545,8 +1540,8 @@
 		blksize_size[MAJOR_NR+ctlr][minor] = 1024;
 	}
 
-	gdev->part[start].nr_sects =  hba[ctlr]->drv[target].nr_blks;
-	resetup_one_dev(gdev, target);
+	/* 16 minors per disk... */
+	grok_partitions(gdev, target, 16, hba[ctlr]->drv[target].nr_blks);
 	hba[ctlr]->drv[target].usage_count--;
 	return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/block/cy82c693.c linux/drivers/block/cy82c693.c
--- v2.3.39/linux/drivers/block/cy82c693.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/cy82c693.c	Fri Jan 14 00:50:53 2000
@@ -434,8 +434,6 @@
 	hwif->tuneproc = &cy82c693_tune_drive;
 	if (hwif->dma_base) {
 		hwif->dmaproc = &cy82c693_dmaproc;
-		hwif->drives[0].autotune = 0;
-		hwif->drives[1].autotune = 0;
 	} else {
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.3.39/linux/drivers/block/floppy.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/floppy.c	Tue Jan 18 18:54:21 2000
@@ -4164,6 +4164,16 @@
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		unregister_blkdev(MAJOR_NR,"fd");		
 	}
+	
+	for (drive = 0; drive < N_DRIVE; drive++) {
+		if (!(allowed_drive_mask & (1 << drive)))
+			continue;
+		if (fdc_state[FDC(drive)].version == FDC_NONE)
+			continue;
+		for (i = 0; i<NUMBER(floppy_type); i++)
+			register_disk(NULL, MKDEV(MAJOR_NR,TOMINOR(drive)+i*4),
+					1, &floppy_fops, 0);
+	}
 	return have_no_fdc;
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/block/genhd.c linux/drivers/block/genhd.c
--- v2.3.39/linux/drivers/block/genhd.c	Fri Oct 22 13:21:47 1999
+++ linux/drivers/block/genhd.c	Thu Jan 13 16:49:22 2000
@@ -28,6 +28,7 @@
 extern int atmdev_init(void);
 extern int i2o_init(void);
 extern int cpqarray_init(void);
+extern void ieee1394_init(void);
 
 void __init device_init(void)
 {
@@ -53,6 +54,9 @@
 #endif
 #ifdef CONFIG_SCSI
 	scsi_dev_init();
+#endif
+#ifdef CONFIG_IEEE1394
+        ieee1394_init();
 #endif
 #ifdef CONFIG_BLK_CPQ_DA
 	cpqarray_init();
diff -u --recursive --new-file v2.3.39/linux/drivers/block/hd.c linux/drivers/block/hd.c
--- v2.3.39/linux/drivers/block/hd.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/hd.c	Tue Jan 18 18:54:21 2000
@@ -662,15 +662,11 @@
 	return 0;
 }
 
-static void hd_geninit(struct gendisk *);
-
 static struct gendisk hd_gendisk = {
 	MAJOR_NR,	/* Major number */	
 	"hd",		/* Major name */
 	6,		/* Bits to shift to get real from partition */
 	1 << 6,		/* Number of partitions per real */
-	MAX_HD,		/* maximum number of real */
-	hd_geninit,	/* init function */
 	hd,		/* hd struct */
 	hd_sizes,	/* block sizes */
 	0,		/* number */
@@ -690,6 +686,12 @@
 	sti();
 }
 
+static struct block_device_operations hd_fops = {
+	open:		hd_open,
+	release:	hd_release,
+	ioctl:		hd_ioctl,
+};
+
 /*
  * This is the hard disk IRQ description. The SA_INTERRUPT in sa_flags
  * means we run the IRQ-handler with interrupts disabled:  this is bad for
@@ -699,10 +701,17 @@
  * We enable interrupts in some of the routines after making sure it's
  * safe.
  */
-static void hd_geninit(struct gendisk *ignored)
+static void hd_geninit(void)
 {
 	int drive;
 
+	for(drive=0; drive < (MAX_HD << 6); drive++) {
+		hd_blocksizes[drive] = 1024;
+		hd_hardsectsizes[drive] = 512;
+	}
+	blksize_size[MAJOR_NR] = hd_blocksizes;
+	hardsect_size[MAJOR_NR] = hd_hardsectsizes;
+
 #ifdef __i386__
 	if (!NR_HD) {
 		extern struct drive_info drive_info;
@@ -765,37 +774,30 @@
 #endif
 
 	for (drive=0 ; drive < NR_HD ; drive++) {
-		hd[drive<<6].nr_sects = hd_info[drive].head *
-			hd_info[drive].sect * hd_info[drive].cyl;
 		printk ("hd%c: %ldMB, CHS=%d/%d/%d\n", drive+'a',
 			hd[drive<<6].nr_sects / 2048, hd_info[drive].cyl,
 			hd_info[drive].head, hd_info[drive].sect);
 	}
-	if (NR_HD) {
-		if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
-			printk("hd: unable to get IRQ%d for the hard disk driver\n",HD_IRQ);
-			NR_HD = 0;
-		} else {
-			request_region(HD_DATA, 8, "hd");
-			request_region(HD_CMD, 1, "hd(cmd)");
-		}
+	if (!NR_HD)
+		return;
+
+	if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
+		printk("hd: unable to get IRQ%d for the hard disk driver\n",
+			HD_IRQ);
+		NR_HD = 0;
+		return;
 	}
+	request_region(HD_DATA, 8, "hd");
+	request_region(HD_CMD, 1, "hd(cmd)");
+
 	hd_gendisk.nr_real = NR_HD;
 
-	for(drive=0; drive < (MAX_HD << 6); drive++) {
-		hd_blocksizes[drive] = 1024;
-		hd_hardsectsizes[drive] = 512;
-	}
-	blksize_size[MAJOR_NR] = hd_blocksizes;
-	hardsect_size[MAJOR_NR] = hd_hardsectsizes;
+	for(drive=0; drive < NR_HD; drive++)
+		register_disk(&hd_gendisk, MKDEV(MAJOR_NR,drive<<6), 1<<6,
+			&hd_fops, hd_info[drive].head * hd_info[drive].sect *
+			hd_info[drive].cyl);
 }
 
-static struct block_device_operations hd_fops = {
-	open:		hd_open,
-	release:	hd_release,
-	ioctl:		hd_ioctl,
-};
-
 int __init hd_init(void)
 {
 	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
@@ -807,6 +809,7 @@
 	hd_gendisk.next = gendisk_head;
 	gendisk_head = &hd_gendisk;
 	timer_table[HD_TIMER].fn = hd_times_out;
+	hd_geninit();
 	return 0;
 }
 
@@ -867,8 +870,7 @@
 	MAYBE_REINIT;
 #endif
 
-	gdev->part[start].nr_sects = CAPACITY;
-	resetup_one_dev(gdev, target);
+	grok_partitions(gdev, target, 1<<6, CAPACITY);
 
 	DEVICE_BUSY = 0;
 	wake_up(&busy_wait);
diff -u --recursive --new-file v2.3.39/linux/drivers/block/hpt34x.c linux/drivers/block/hpt34x.c
--- v2.3.39/linux/drivers/block/hpt34x.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/hpt34x.c	Fri Jan 14 00:50:53 2000
@@ -377,8 +377,6 @@
 #endif
 #endif /* CONFIG_BLK_DEV_HPT34X_DMA */
 		hwif->dmaproc = &hpt34x_dmaproc;
-		hwif->drives[0].autotune = 0;
-		hwif->drives[1].autotune = 0;
 	} else {
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/hpt366.c linux/drivers/block/hpt366.c
--- v2.3.39/linux/drivers/block/hpt366.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/hpt366.c	Fri Jan 14 00:50:53 2000
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/hpt366.c		Version 0.14	Dec. 13, 1999
+ * linux/drivers/block/hpt366.c		Version 0.15	Dec. 22, 1999
  *
  * Copyright (C) 1999			Andre Hedrick <andre@suse.com>
  * May be copied or modified under the terms of the GNU General Public License
@@ -30,6 +30,7 @@
 #include "ide_modes.h"
 
 const char *bad_ata66_4[] = {
+	"QUANTUM FIREBALLP KA9.1",
 	"WDC AC310200R",
 	NULL
 };
@@ -121,6 +122,7 @@
 
 extern char *ide_xfer_verbose (byte xfer_rate);
 byte hpt363_shared_irq = 0;
+byte hpt363_shared_pin = 0;
 
 static int check_in_drive_lists (ide_drive_t *drive, const char **list)
 {
@@ -421,34 +423,31 @@
 
 int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
 {
-#if 0
-	byte reg50h = 0, reg52h = 0;
-#endif
 	switch (func) {
 		case ide_dma_check:
 			return config_drive_xfer_rate(drive);
-#if 0
-		case ide_dma_lostirq:
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
-			printk("%s: (ide_dma_lostirq) reg52h=0x%02x\n", drive->name, reg52h);
-			break;
 		case ide_dma_timeout:
-			(void) ide_dmaproc(ide_dma_off_quietly, drive);
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
-			printk("%s: (ide_dma_timeout) reg52h=0x%02x\n", drive->name, reg52h);
-			if (reg52h & 0x04) {
+			/* ide_do_reset(drive); */
+
+			if (0) {
+				byte reg50h = 0, reg52h = 0;
+				(void) ide_dmaproc(ide_dma_off_quietly, drive);
+				pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
+				pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
+				printk("%s: (ide_dma_timeout) reg52h=0x%02x\n", drive->name, reg52h);
+				if (reg52h & 0x04) {
+					pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
+					pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0xff);
+					pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h);
+				}
 				pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
-				pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0xff);
-				pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h);
+				pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
+				printk("%s: (ide_dma_timeout) reg50h=0x%02x reg52h=0x%02x :: again\n", drive->name, reg50h, reg52h);
+				(void) ide_dmaproc(ide_dma_on, drive);
+				if (reg52h & 0x04)
+					(void) ide_dmaproc(ide_dma_off, drive);
 			}
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
-			pci_read_config_byte(HWIF(drive)->pci_dev, 0x52, &reg52h);
-			printk("%s: (ide_dma_timeout) reg50h=0x%02x reg52h=0x%02x :: again\n", drive->name, reg50h, reg52h);
-			(void) ide_dmaproc(ide_dma_on, drive);
-			if (reg52h & 0x04)
-				(void) ide_dmaproc(ide_dma_off, drive);
-			return 1;
-#endif
+			break;
 		default:
 			break;
 	}
@@ -502,15 +501,15 @@
 		hwif->mate->mate = hwif;
 		hwif->serialized = hwif->mate->serialized = 1;
 	}
+
+	if ((PCI_FUNC(hwif->pci_dev->devfn) & 1) && (hpt363_shared_pin)) {
+
+	}
 #endif
 
 	hwif->tuneproc = &hpt366_tune_drive;
 	if (hwif->dma_base) {
 		hwif->dmaproc = &hpt366_dmaproc;
-#if 0
-		hwif->drives[0].autotune = 0;
-		hwif->drives[1].autotune = 0;
-#endif
 	} else {
 		hwif->autodma = 0;
 		hwif->drives[0].autotune = 1;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.3.39/linux/drivers/block/ide-cd.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/ide-cd.c	Sun Jan 16 20:41:39 2000
@@ -2005,9 +2005,60 @@
 	return cdrom_lockdoor (drive, lock);
 }
 
+#undef __ACER50__
+
+#ifdef __ACER50__
+/*
+ * the buffer struct used by ide_cdrom_get_capabilities()
+ */
+struct get_capabilities_buf {
+	char pad[8];
+	struct atapi_capabilities_page cap;	/* this is 4 bytes short of ATAPI standard */
+	char extra_cap[4];			/* Acer 50X needs the regulation size buffer */
+};
+
+static
+int ide_cdrom_get_capabilities (struct cdrom_device_info *cdi, struct get_capabilities_buf *buf)
+{
+	int stat, attempts = 3, buflen = sizeof(*buf);
+	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	struct cdrom_generic_command cgc;
+
+	/*
+	 * Most drives don't care about the buffer size;
+	 * they return as much info as there's room for.
+	 * But some older drives (?) had trouble with the
+	 * standard size, preferring 4 bytes less.
+	 * And the modern Acer 50X rejects anything smaller
+	 * than the standard size.
+	 */
+	if (!(drive->id && !strcmp(drive->id->model,"ATAPI CD ROM DRIVE 50X MAX")))
+		buflen -= sizeof(buf->extra_cap);	/* for all drives except Acer 50X */
+
+	do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
+		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
+		if (stat == 0) {
+			/*
+			 * The ACER/AOpen 24X cdrom has the speed
+			 * fields byte-swapped from the standard.
+			 */
+			if (!(drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4))) {
+				buf->cap.curspeed = ntohs(buf->cap.curspeed);
+				buf->cap.maxspeed = ntohs(buf->cap.maxspeed);
+			}
+			CDROM_STATE_FLAGS (drive)->current_speed = (((unsigned int)buf->cap.curspeed) + (176/2)) / 176;
+			CDROM_CONFIG_FLAGS(drive)->max_speed     = (((unsigned int)buf->cap.maxspeed) + (176/2)) / 176;
+			return 0;
+		}
+	} while (--attempts);
+	return stat;
+}
+#endif /* __ACER50__ */
+
 static
 int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
 {
+#ifndef __ACER50__
         int stat, attempts = 3;
 	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
 	struct cdrom_generic_command cgc;
@@ -2015,11 +2066,19 @@
 		char pad[8];
 		struct atapi_capabilities_page cap;
 	} buf;
+#else
+	int stat;
+	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+	struct cdrom_generic_command cgc;
+	struct get_capabilities_buf buf;
+#endif /* __ACER50__ */
 
 	if ((stat = cdrom_select_speed (drive, speed)) < 0)
 		return stat;
 
 	init_cdrom_command(&cgc, &buf, sizeof(buf));
+
+#ifndef __ACER50__
 	/* Now with that done, update the speed fields */
         do {    /* we seem to get stat=0x01,err=0x00 the first time (??) */
                 if (attempts-- <= 0)
@@ -2039,6 +2098,11 @@
                 CDROM_CONFIG_FLAGS (drive)->max_speed = 
 			(ntohs(buf.cap.maxspeed) + (176/2)) / 176;
         }
+#else
+	if (ide_cdrom_get_capabilities(cdi,&buf))
+		return 0;
+#endif /* __ACER50__ */
+
         cdi->speed = CDROM_STATE_FLAGS (drive)->current_speed;
         return 0;
 }
@@ -2216,12 +2280,18 @@
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *cdi = &info->devinfo;
+#ifndef __ACER50__
 	int stat, nslots = 1, attempts = 3;
 	struct cdrom_generic_command cgc;
 	struct {
 		char pad[8];
 		struct atapi_capabilities_page cap;
 	} buf;
+#else
+	int nslots = 1;
+	struct cdrom_generic_command cgc;
+	struct get_capabilities_buf buf;
+#endif /* __ACER50__ */
 
 	if (CDROM_CONFIG_FLAGS (drive)->nec260) {
 		CDROM_CONFIG_FLAGS (drive)->no_eject = 0;                       
@@ -2238,12 +2308,17 @@
 	 */
 	cdi->handle = (ide_drive_t *) drive;
 	cdi->ops = &ide_cdrom_dops;
+#ifndef __ACER50__
 	/* we seem to get stat=0x01,err=0x00 the first time (??) */
 	do {
 		if (attempts-- <= 0)
 			return 0;
 		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
 	} while (stat);
+#else
+	if (ide_cdrom_get_capabilities(cdi,&buf))
+		return 0;
+#endif /* __ACER50__ */
 
 	if (buf.cap.lock == 0)
 		CDROM_CONFIG_FLAGS (drive)->no_doorlock = 1;
@@ -2282,6 +2357,7 @@
 		}
 	}
 
+#ifndef __ACER50__
 	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
 	if (drive->id && !drive->id->model[0] && !strncmp(drive->id->fw_rev, "241N", 4)) {
 		CDROM_STATE_FLAGS (drive)->current_speed  = 
@@ -2294,6 +2370,7 @@
 		CDROM_CONFIG_FLAGS (drive)->max_speed = 
 			(ntohs(buf.cap.maxspeed) + (176/2)) / 176;
 	}
+#endif /* __ACER50__ */
 
 	/* don't print speed if the drive reported 0.
 	 */
@@ -2321,7 +2398,7 @@
 
 	if (drive->using_dma) {
 		if ((drive->id->field_valid & 4) &&
-		    (drive->id->word93 & 0x2000) &&
+		    (drive->id->hw_config & 0x2000) &&
 		    (HWIF(drive)->udma_four) &&
 		    (drive->id->dma_ultra & (drive->id->dma_ultra >> 11) & 3)) {
 			printk(", UDMA(66)");	/* UDMA BIOS-enabled! */
@@ -2598,7 +2675,7 @@
 }
 #endif /* MODULE */
  
-int __init ide_cdrom_init (void)
+int ide_cdrom_init (void)
 {
 	ide_drive_t *drive;
 	struct cdrom_info *info;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
--- v2.3.39/linux/drivers/block/ide-disk.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/ide-disk.c	Fri Jan 14 00:50:53 2000
@@ -139,10 +139,20 @@
 	int i;
 	unsigned int msect, nsect;
 	struct request *rq;
-
+#if 0
 	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
 		return ide_error(drive, "read_intr", stat);
 	}
+#else	/* new way for dealing with premature shared PCI interrupts */
+	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
+		if (stat & (ERR_STAT|DRQ_STAT)) {
+			return ide_error(drive, "read_intr", stat);
+		}
+		/* no data yet, so wait for another interrupt */
+		ide_set_handler(drive, &read_intr, WAIT_CMD, NULL);
+		return ide_started;
+	}
+#endif
 	msect = drive->mult_count;
 	
 read_next:
@@ -163,7 +173,7 @@
 	rq->buffer += nsect<<9;
 	rq->errors = 0;
 	i = (rq->nr_sectors -= nsect);
-	if ((rq->current_nr_sectors -= nsect) <= 0)
+	if (((long)(rq->current_nr_sectors -= nsect)) <= 0)
 		ide_end_request(1, HWGROUP(drive));
 	if (i > 0) {
 		if (msect)
@@ -198,7 +208,7 @@
 			rq->errors = 0;
 			i = --rq->nr_sectors;
 			--rq->current_nr_sectors;
-			if (rq->current_nr_sectors <= 0)
+			if (((long)rq->current_nr_sectors) <= 0)
 				ide_end_request(1, hwgroup);
 			if (i > 0) {
 				idedisk_output_data (drive, rq->buffer, SECTOR_WORDS);
@@ -207,8 +217,8 @@
 			}
                         return ide_stopped;
 		}
-                printk("%s: write_intr error2: nr_sectors=%ld, stat=0x%02x\n", drive->name, rq->nr_sectors, stat);
-        }
+		return ide_stopped;	/* the original code did this here (?) */
+	}
 	return ide_error(drive, "write_intr", stat);
 }
 
@@ -221,12 +231,22 @@
 int ide_multwrite (ide_drive_t *drive, unsigned int mcount)
 {
  	ide_hwgroup_t	*hwgroup= HWGROUP(drive);
+
+	/*
+	 *	This may look a bit odd, but remember wrq is a copy of the
+	 *	request not the original. The pointers are real however so the
+	 *	bh's are not copies. Remember that or bad stuff will happen
+	 *
+	 *	At the point we are called the drive has asked us for the
+	 *	data, and its our job to feed it, walking across bh boundaries
+	 *	if need be.
+	 */
+
  	struct request	*rq = &hwgroup->wrq;
 
   	do {
  		unsigned long flags;
   		unsigned int nsect = rq->current_nr_sectors;
-
 		if (nsect > mcount)
 			nsect = mcount;
 		mcount -= nsect;
@@ -241,9 +261,11 @@
 #ifdef CONFIG_BLK_DEV_PDC4030
 		rq->sector += nsect;
 #endif
-		if ((rq->nr_sectors -= nsect) <= 0) {
+		if (((long)(rq->nr_sectors -= nsect)) <= 0) {
+#ifdef DEBUG
 			printk("%s: multwrite: count=%d, current=%ld\n",
 				drive->name, nsect, rq->nr_sectors);
+#endif
 			spin_unlock_irqrestore(&io_request_lock, flags);
 			break;
 		}
@@ -253,11 +275,14 @@
 				rq->buffer             = rq->bh->b_data;
 			} else {
 				spin_unlock_irqrestore(&io_request_lock, flags);
-				printk("%s: buffer list corrupted\n", drive->name);
+				printk("%s: buffer list corrupted (%ld, %ld, %d)\n",
+					drive->name, rq->current_nr_sectors,
+					rq->nr_sectors, nsect);
 				ide_end_request(0, hwgroup);
 				return 1;
 			}
 		} else {
+			/* Fix the pointer.. we ate data */
 			rq->buffer += nsect << 9;
 		}
                 spin_unlock_irqrestore(&io_request_lock, flags);
@@ -277,6 +302,10 @@
 
 	if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
 		if (stat & DRQ_STAT) {
+			/*
+			 *	The drive wants data. Remember rq is the copy
+			 *	of the request
+			 */
 			if (rq->nr_sectors) {
 				if (ide_multwrite(drive, drive->mult_count))
 					return ide_stopped;
@@ -284,6 +313,10 @@
 				return ide_started;
 			}
 		} else {
+			/*
+			 *	If the copy has all the blocks completed then
+			 *	we can end the original request.
+			 */
 			if (!rq->nr_sectors) {	/* all done? */
 				rq = hwgroup->rq;
 				for (i = rq->nr_sectors; i > 0;){
@@ -293,6 +326,7 @@
 				return ide_stopped;
 			}
 		}
+		return ide_stopped;	/* the original code did this here (?) */
 	}
 	return ide_error(drive, "multwrite_intr", stat);
 }
@@ -302,13 +336,9 @@
  */
 static ide_startstop_t set_multmode_intr (ide_drive_t *drive)
 {
-	byte stat = GET_STAT();
+	byte stat;
 
-#if 0
-	if (OK_STAT(stat,READY_STAT,BAD_STAT) || drive->mult_req == 0) {
-#else
-	if (OK_STAT(stat,READY_STAT,BAD_STAT)) {
-#endif
+	if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT)) {
 		drive->mult_count = drive->mult_req;
 	} else {
 		drive->mult_req = drive->mult_count = 0;
@@ -323,11 +353,16 @@
  */
 static ide_startstop_t set_geometry_intr (ide_drive_t *drive)
 {
-	byte stat = GET_STAT();
+	byte stat;
 
-	if (!OK_STAT(stat,READY_STAT,BAD_STAT))
+	if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT))
+		return ide_stopped;
+
+	if (stat & (ERR_STAT|DRQ_STAT))
 		return ide_error(drive, "set_geometry_intr", stat);
-	return ide_stopped;
+
+	ide_set_handler(drive, &set_geometry_intr, WAIT_CMD, NULL);
+	return ide_started;	
 }
 
 /*
@@ -419,6 +454,8 @@
 			 * of data to be written.  If we hit an error (corrupted buffer list)
 			 * in ide_multwrite(), then we need to remove the handler/timer
 			 * before returning.  Fortunately, this NEVER happens (right?).
+			 *
+			 * Except when you get an error it seems...
 			 */
 			hwgroup->wrq = *rq; /* scratchpad */
 			ide_set_handler (drive, &multwrite_intr, WAIT_CMD, NULL);
@@ -772,7 +809,7 @@
 			drive->bios_cyl, drive->bios_head, drive->bios_sect);
 
 	if (drive->using_dma) {
-		if ((id->field_valid & 4) && (id->word93 & 0x2000) &&
+		if ((id->field_valid & 4) && (id->hw_config & 0x2000) &&
 		    (HWIF(drive)->udma_four) &&
 		    (id->dma_ultra & (id->dma_ultra >> 11) & 3)) {
 			printk(", UDMA(66)");	/* UDMA BIOS-enabled! */
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
--- v2.3.39/linux/drivers/block/ide-dma.c	Thu Nov 18 20:25:37 1999
+++ linux/drivers/block/ide-dma.c	Fri Jan 14 00:50:53 2000
@@ -358,7 +358,7 @@
 			return hwif->dmaproc(ide_dma_off, drive);
 
 		/* Enable DMA on any drive that has UltraDMA (mode 3/4) enabled */
-		if ((id->field_valid & 4) && (hwif->udma_four) && (id->word93 & 0x2000))
+		if ((id->field_valid & 4) && (hwif->udma_four) && (id->hw_config & 0x2000))
 			if ((id->dma_ultra & (id->dma_ultra >> 11) & 3))
 				return hwif->dmaproc(ide_dma_on, drive);
 		/* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-features.c linux/drivers/block/ide-features.c
--- v2.3.39/linux/drivers/block/ide-features.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/ide-features.c	Fri Jan 14 00:50:53 2000
@@ -188,7 +188,7 @@
 			printk("%s: Speed warnings UDMA 3/4 is not functional.\n", HWIF(drive)->name);
 			return 1;
 		}
-		if ((drive->id->word93 & 0x2000) == 0) {
+		if ((drive->id->hw_config & 0x2000) == 0) {
 			printk("%s: Speed warnings UDMA 3/4 is not functional.\n", drive->name);
 			return 1;
 		}
@@ -213,6 +213,22 @@
 	return 0;
 }
 
+#if 0
+ide_startstop_t set_drive_speed_intr (ide_drive_t *drive)
+{
+	byte stat;
+
+	if (!OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT))
+/*
+ *	if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,BAD_STAT))
+ *	if (stat != DRIVE_READY)
+ */
+		(void) ide_dump_status(drive, "set_drive_speed_status", stat);
+
+	return ide_stopped;
+}
+#endif
+
 int ide_config_drive_speed (ide_drive_t *drive, byte speed)
 {
 	unsigned long flags;
@@ -243,6 +259,10 @@
 #endif
 
 	__restore_flags(flags);	/* local CPU only */
+
+#if 0
+	ide_set_handler(drive, &set_drive_speed_intr, WAIT_CMD, NULL);
+#endif
 
 	stat = GET_STAT();
 	if (stat != DRIVE_READY)
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-geometry.c linux/drivers/block/ide-geometry.c
--- v2.3.39/linux/drivers/block/ide-geometry.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/block/ide-geometry.c	Fri Jan 14 00:50:53 2000
@@ -60,6 +60,7 @@
 	/* Extract drive geometry from CMOS+BIOS if not already setup */
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		ide_drive_t *drive = &hwif->drives[unit];
+#if 0
 		if ((cmos_disks & (0xf0 >> (unit*4))) &&
 		    !drive->present && !drive->nobios) {
 			drive->cyl   = drive->bios_cyl  = *(unsigned short *)BIOS;
@@ -67,6 +68,22 @@
 			drive->sect  = drive->bios_sect = *(BIOS+14);
 			drive->ctl   = *(BIOS+8);
 		}
+#else
+		if ((cmos_disks & (0xf0 >> (unit*4)))
+		   && !drive->present && !drive->nobios) {
+			unsigned short cyl = *(unsigned short *)BIOS;
+			unsigned char head = *(BIOS+2);
+			unsigned char sect = *(BIOS+14);
+			if (cyl > 0 && head > 0 && sect > 0 && sect < 64) {
+				drive->cyl   = drive->bios_cyl  = cyl;
+				drive->head  = drive->bios_head = head;
+				drive->sect  = drive->bios_sect = sect;
+				drive->ctl   = *(BIOS+8);
+			} else {
+				printk("hd%d: C/H/S=%d/%d/%d from BIOS ignored\n", unit, cyl, head, sect);
+			}
+		}
+#endif
 		BIOS += 16;
 	}
 #endif
@@ -78,7 +95,7 @@
  * Otherwise: find out how OnTrack Disk Manager would translate the disk.
  */
 static void
-ontrack(ide_drive_t *drive, int heads, int *c, int *h, int *s) {
+ontrack(ide_drive_t *drive, int heads, unsigned int *c, int *h, int *s) {
 	static const byte dm_head_vals[] = {4, 8, 16, 32, 64, 128, 255, 0};
 	const byte *headp = dm_head_vals;
 	unsigned long total, tracks;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
--- v2.3.39/linux/drivers/block/ide-pci.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/block/ide-pci.c	Fri Jan 14 00:50:53 2000
@@ -41,6 +41,7 @@
 #define DEVID_CMD640	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_640})
 #define DEVID_CMD643	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_643})
 #define DEVID_CMD646	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_646})
+#define DEVID_CMD648	((ide_pci_devid_t){PCI_VENDOR_ID_CMD,     PCI_DEVICE_ID_CMD_648})
 #define DEVID_SIS5513	((ide_pci_devid_t){PCI_VENDOR_ID_SI,      PCI_DEVICE_ID_SI_5513})
 #define DEVID_OPTI621	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C621})
 #define DEVID_OPTI621V	((ide_pci_devid_t){PCI_VENDOR_ID_OPTI,    PCI_DEVICE_ID_OPTI_82C558})
@@ -60,7 +61,7 @@
 #define DEVID_CY82C693	((ide_pci_devid_t){PCI_VENDOR_ID_CONTAQ,  PCI_DEVICE_ID_CONTAQ_82C693})
 #define DEVID_HINT	((ide_pci_devid_t){0x3388,                0x8013})
 #define DEVID_CX5530	((ide_pci_devid_t){PCI_VENDOR_ID_CYRIX,   PCI_DEVICE_ID_CYRIX_5530_IDE})
-#define DEVID_AMD7409	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     0x7409})
+#define DEVID_AMD7409	((ide_pci_devid_t){PCI_VENDOR_ID_AMD,     PCI_DEVICE_ID_AMD_VIPER_7409})
 
 #define	IDE_IGNORE	((void *)-1)
 
@@ -93,14 +94,31 @@
 #define DMA_ALI15X3	NULL
 #endif
 
-#ifdef CONFIG_BLK_DEV_CMD646
-extern void ide_init_cmd646(ide_hwif_t *);
-#define INIT_CMD646	&ide_init_cmd646
+#ifdef CONFIG_BLK_DEV_AMD7409
+extern unsigned int ata66_amd7409(ide_hwif_t *);
+extern void ide_init_amd7409(ide_hwif_t *);
+#define ATA66_AMD7409	&ata66_amd7409
+#define INIT_AMD7409	&ide_init_amd7409
+#else
+#define ATA66_AMD7409	NULL
+#define INIT_AMD7409	NULL
+#endif
+
+#ifdef CONFIG_BLK_DEV_CMD64X
+extern unsigned int pci_init_cmd64x(struct pci_dev *, const char *);
+extern unsigned int ata66_cmd64x(ide_hwif_t *);
+extern void ide_init_cmd64x(ide_hwif_t *);
+extern void ide_dmacapable_cmd64x(ide_hwif_t *, unsigned long);
+#define PCI_CMD64X	&pci_init_cmd64x
+#define ATA66_CMD64X	&ata66_cmd64x
+#define INIT_CMD64X	&ide_init_cmd64x
 #else
+#define PCI_CMD64X	NULL
+#define ATA66_CMD64X	NULL
 #ifdef __sparc_v9__
-#define INIT_CMD646	IDE_IGNORE
+#define INIT_CMD64X	IDE_IGNORE
 #else
-#define INIT_CMD646	NULL
+#define INIT_CMD64X	NULL
 #endif
 #endif
 
@@ -128,6 +146,7 @@
 
 #ifdef CONFIG_BLK_DEV_HPT366
 extern byte hpt363_shared_irq;
+extern byte hpt363_shared_pin;
 extern unsigned int pci_init_hpt366(struct pci_dev *, const char *);
 extern unsigned int ata66_hpt366(ide_hwif_t *);
 extern void ide_init_hpt366(ide_hwif_t *);
@@ -138,6 +157,7 @@
 #define DMA_HPT366	&ide_dmacapable_hpt366
 #else
 static byte hpt363_shared_irq = 0;
+static byte hpt363_shared_pin = 0;
 #define PCI_HPT366	NULL
 #define ATA66_HPT366	NULL
 #define INIT_HPT366	NULL
@@ -271,8 +291,9 @@
 	{DEVID_CMD640,	"CMD640",	NULL,		NULL,		IDE_IGNORE,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
 	{DEVID_NS87410,	"NS87410",	NULL,		NULL,		NULL,		NULL,		{{0x43,0x08,0x08}, {0x47,0x08,0x08}}, 	ON_BOARD,	0 },
 	{DEVID_SIS5513,	"SIS5513",	PCI_SIS5513,	ATA66_SIS5513,	INIT_SIS5513,	NULL,		{{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, 	ON_BOARD,	0 },
-	{DEVID_CMD643,	"CMD643",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
-	{DEVID_CMD646,	"CMD646",	NULL,		NULL,		INIT_CMD646,	NULL,		{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_CMD643,	"CMD643",	PCI_CMD64X,	NULL,		INIT_CMD64X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_CMD646,	"CMD646",	PCI_CMD64X,	NULL,		INIT_CMD64X,	NULL,		{{0x00,0x00,0x00}, {0x51,0x80,0x80}}, 	ON_BOARD,	0 },
+	{DEVID_CMD648,	"CMD648",	PCI_CMD64X,	ATA66_CMD64X,	INIT_CMD64X,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_HT6565,	"HT6565",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 },
 	{DEVID_OPTI621,	"OPTI621",	NULL,		NULL,		INIT_OPTI621,	NULL,		{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
 	{DEVID_OPTI621X,"OPTI621X",	NULL,		NULL,		INIT_OPTI621,	NULL,		{{0x45,0x80,0x00}, {0x40,0x08,0x00}}, 	ON_BOARD,	0 },
@@ -289,7 +310,7 @@
 	{DEVID_CY82C693,"CY82C693",	PCI_CY82C693,	NULL,		INIT_CY82C693,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_HINT,	"HINT_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
 	{DEVID_CX5530,	"CX5530",	NULL,		NULL,		INIT_CX5530,	NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
-	{DEVID_AMD7409,	"AMD7409",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
+	{DEVID_AMD7409,	"AMD7409",	NULL,		ATA66_AMD7409,	INIT_AMD7409,	NULL,		{{0x40,0x01,0x01}, {0x40,0x02,0x02}},	ON_BOARD,	0 },
 	{IDE_PCI_DEVID_NULL, "PCI_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}}, 	ON_BOARD,	0 }};
 
 /*
@@ -496,6 +517,8 @@
 		printk("%s: bad irq (%d): will probe later\n", d->name, pciirq);
 		pciirq = 0;
 	} else {
+		if (d->init_chipset)
+			(void) d->init_chipset(dev, d->name);
 #ifdef __sparc__
 		printk("%s: 100%% native mode on irq %s\n",
 		       d->name, __irq_itoa(pciirq));
@@ -642,8 +665,9 @@
 		    (PCI_FUNC(findev->devfn) & 1)) {
 			dev2 = findev;
 			pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin2);
-			hpt363_shared_irq = (pin1 != pin2) ? 1 : 0;
-			if (hpt363_shared_irq) {
+			hpt363_shared_pin = (pin1 != pin2) ? 1 : 0;
+			hpt363_shared_irq = (dev->irq == dev2->irq) ? 1 : 0;
+			if (hpt363_shared_pin && hpt363_shared_irq) {
 				d->bootable = ON_BOARD;
 				printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2);
 			}
@@ -656,6 +680,15 @@
 		return;
 	d2 = d;
 	printk("%s: IDE controller on PCI bus %02x dev %02x\n", d2->name, dev2->bus->number, dev2->devfn);
+	if (hpt363_shared_pin && !hpt363_shared_irq) {
+		printk("%s: IDE controller run unsupported mode three!!!\n", d2->name);
+#ifndef HPT366_MODE3
+		printk("%s: IDE controller report to <andre@suse.com>\n", d->name);
+		return;
+#else /* HPT366_MODE3 */
+		printk("%s: OVERRIDE IDE controller not advisable this mode!!!\n", d2->name);
+#endif /* HPT366_MODE3 */
+	}
 	ide_setup_pci_device(dev2, d2);
 }
 
@@ -663,7 +696,7 @@
  * ide_scan_pcibus() gets invoked at boot time from ide.c.
  * It finds all PCI IDE controllers and calls ide_setup_pci_device for them.
  */
-void __init ide_scan_pcibus (void)
+void __init ide_forward_scan_pcibus (void)
 {
 	struct pci_dev		*dev;
 	ide_pci_devid_t		devid;
@@ -692,4 +725,41 @@
 			ide_setup_pci_device(dev, d);
 		}
 	}
+}
+
+void __init ide_reverse_scan_pcibus (void)
+{
+	struct pci_dev		*dev;
+	ide_pci_devid_t		devid;
+	ide_pci_device_t	*d;
+
+	pci_for_each_dev_reverse(dev) {
+		devid.vid = dev->vendor;
+		devid.did = dev->device;
+		for (d = ide_pci_chipsets; d->devid.vid && !IDE_PCI_DEVID_EQ(d->devid, devid); ++d);
+		if (d->init_hwif == IDE_IGNORE)
+			printk("%s: ignored by ide_scan_pci_device() (uses own driver)\n", d->name);
+		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_OPTI621V) && !(PCI_FUNC(dev->devfn) & 1))
+			continue;	/* OPTI Viper-M uses same devid for functions 0 and 1 */
+		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE)))
+			continue;	/* CY82C693 is more than only a IDE controller */
+		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1))
+			continue;	/* UM8886A/BF pair */
+		else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366))
+			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);
+			else
+				printk("%s: IDE controller on PCI bus %02x dev %02x\n", d->name, dev->bus->number, dev->devfn);
+			ide_setup_pci_device(dev, d);
+		}
+	}
+}
+
+void __init ide_scan_pcibus (int scan_direction)
+{
+	if (!scan_direction) ide_forward_scan_pcibus();
+		else ide_reverse_scan_pcibus();
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- v2.3.39/linux/drivers/block/ide-probe.c	Wed Dec 29 13:13:15 1999
+++ linux/drivers/block/ide-probe.c	Sun Jan 16 19:34:28 2000
@@ -687,9 +687,7 @@
 	gd->major_name	= IDE_MAJOR_NAME;	/* treated special in genhd.c */
 	gd->minor_shift	= PARTN_BITS;		/* num bits for partitions */
 	gd->max_p	= 1<<PARTN_BITS;	/* 1 + max partitions / drive */
-	gd->max_nr	= units;		/* max num real drives */
 	gd->nr_real	= units;		/* current num real drives */
-	gd->init	= &ide_geninit;		/* initialization function */
 	gd->real_devices= hwif;			/* ptr to internal data */
 	gd->next	= NULL;			/* linked list of major devs */
 
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
--- v2.3.39/linux/drivers/block/ide-tape.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/block/ide-tape.c	Fri Jan 14 00:50:53 2000
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/ide-tape.c	Version 1.16e		Oct   3, 1999
+ * linux/drivers/block/ide-tape.c	Version 1.16f		Dec  15, 1999
  *
  * Copyright (C) 1995 - 1999 Gadi Oxman <gadio@netvision.net.il>
  *
@@ -224,6 +224,57 @@
  *                        case the tape block size is larger than PAGE_SIZE.
  *                       Decrease the default disconnection time to tn.
  * Ver 1.16e Oct  3 99   Minor fixes.
+ * Ver 1.16e1 Oct 13 99  Patches by Arnold Niessen,
+ *                          niessen@iae.nl / arnold.niessen@philips.com
+ *                   GO-1)  Undefined code in idetape_read_position
+ *				according to Gadi's email
+ *                   AJN-1) Minor fix asc == 11 should be asc == 0x11
+ *                               in idetape_issue_packet_command (did effect
+ *                               debugging output only)
+ *                   AJN-2) Added more debugging output, and
+ *                              added ide-tape: where missing. I would also
+ *				like to add tape->name where possible
+ *                   AJN-3) Added different debug_level's 
+ *                              via /proc/ide/hdc/settings
+ * 				"debug_level" determines amount of debugging output;
+ * 				can be changed using /proc/ide/hdx/settings
+ * 				0 : almost no debugging output
+ * 				1 : 0+output errors only
+ * 				2 : 1+output all sensekey/asc
+ * 				3 : 2+follow all chrdev related procedures
+ * 				4 : 3+follow all procedures
+ * 				5 : 4+include pc_stack rq_stack info
+ * 				6 : 5+USE_COUNT updates
+ *                   AJN-4) Fixed timeout for retension in idetape_queue_pc_tail
+ *				from 5 to 10 minutes
+ *                   AJN-5) Changed maximum number of blocks to skip when
+ *                              reading tapes with multiple consecutive write
+ *                              errors from 100 to 1000 in idetape_get_logical_blk
+ *                   Proposed changes to code:
+ *                   1) output "logical_blk_num" via /proc
+ *                   2) output "current_operation" via /proc
+ *                   3) Either solve or document the fact that `mt rewind' is
+ *                      required after reading from /dev/nhtx to be
+ *			able to rmmod the idetape module;
+ *			Also, sometimes an application finishes but the
+ *			device remains `busy' for some time. Same cause ?
+ *                   Proposed changes to release-notes:
+ *		     4) write a simple `quickstart' section in the
+ *                      release notes; I volunteer if you don't want to
+ * 		     5) include a pointer to video4linux in the doc
+ *                      to stimulate video applications
+ *                   6) release notes lines 331 and 362: explain what happens
+ *			if the application data rate is higher than 1100 KB/s; 
+ *			similar approach to lower-than-500 kB/s ?
+ *		     7) 6.6 Comparison; wouldn't it be better to allow different 
+ *			strategies for read and write ?
+ *			Wouldn't it be better to control the tape buffer
+ *			contents instead of the bandwidth ?
+ *		     8) line 536: replace will by would (if I understand
+ *			this section correctly, a hypothetical and unwanted situation
+ *			 is being described)
+ * Ver 1.16f Dec 15 99   Change place of the secondary OnStream header frames.
+ *
  *
  * Here are some words from the first releases of hd.c, which are quoted
  * in ide.c and apply here as well:
@@ -361,7 +412,7 @@
 /*
  *	OnStream support
  */
-#define ONSTREAM_DEBUG		(0)
+#define ONSTREAM_DEBUG		(1)
 #define OS_CONFIG_PARTITION	(0xff)
 #define OS_DATA_PARTITION	(0)
 #define OS_PARTITION_VERSION	(1)
@@ -502,7 +553,7 @@
  *	is verified to be stable enough. This will make it much more
  *	esthetic.
  */
-#define IDETAPE_DEBUG_LOG		0
+#define IDETAPE_DEBUG_LOG		1
 #define IDETAPE_DEBUG_BUGS		1
 
 /*
@@ -755,7 +806,7 @@
 	 *	NULL if we do not need to retry any packet command. This is
 	 *	required since an additional packet command is needed before the
 	 *	retry, to get detailed information on what went wrong.
-      	 */
+	 */
 	idetape_pc_t *pc;			/* Current packet command */
 	idetape_pc_t *failed_pc; 		/* Last failed packet command */
 	idetape_pc_t pc_stack[IDETAPE_PC_STACK];/* Packet command stack */
@@ -941,6 +992,19 @@
 	int controlled_previous_pipeline_head, uncontrolled_previous_pipeline_head;
 	unsigned long controlled_previous_head_time, uncontrolled_previous_head_time;
 	int restart_speed_control_req;
+
+        /*
+         * Debug_level determines amount of debugging output;
+         * can be changed using /proc/ide/hdx/settings
+         * 0 : almost no debugging output
+         * 1 : 0+output errors only
+         * 2 : 1+output all sensekey/asc
+         * 3 : 2+follow all chrdev related procedures
+         * 4 : 3+follow all procedures
+         * 5 : 4+include pc_stack rq_stack info
+         * 6 : 5+USE_COUNT updates
+         */
+         int debug_level; 
 } idetape_tape_t;
 
 /*
@@ -1386,7 +1450,8 @@
 	idetape_tape_t *tape = drive->driver_data;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "ide-tape: pc_stack_index=%d\n",tape->pc_stack_index);
+	if (tape->debug_level >= 5)
+		printk (KERN_INFO "ide-tape: pc_stack_index=%d\n",tape->pc_stack_index);
 #endif /* IDETAPE_DEBUG_LOG */
 	if (tape->pc_stack_index==IDETAPE_PC_STACK)
 		tape->pc_stack_index=0;
@@ -1411,7 +1476,8 @@
 	idetape_tape_t *tape = drive->driver_data;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "ide-tape: rq_stack_index=%d\n",tape->rq_stack_index);
+	if (tape->debug_level >= 5)
+		printk (KERN_INFO "ide-tape: rq_stack_index=%d\n",tape->rq_stack_index);
 #endif /* IDETAPE_DEBUG_LOG */
 	if (tape->rq_stack_index==IDETAPE_PC_STACK)
 		tape->rq_stack_index=0;
@@ -1450,7 +1516,8 @@
 	 *	Without debugging, we only log an error if we decided to
 	 *	give up retrying.
 	 */
-	printk (KERN_INFO "ide-tape: pc = %x, sense key = %x, asc = %x, ascq = %x\n",pc->c[0],result->sense_key,result->asc,result->ascq);
+	if (tape->debug_level >= 1)
+		printk (KERN_INFO "ide-tape: pc = %x, sense key = %x, asc = %x, ascq = %x\n",pc->c[0],result->sense_key,result->asc,result->ascq);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (tape->onstream && result->sense_key == 2 && result->asc == 0x53 && result->ascq == 2) {
@@ -1494,7 +1561,8 @@
 	idetape_stage_t *stage = tape->next_stage;
 
 #if IDETAPE_DEBUG_LOG
-	printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
+	if (tape->debug_level >= 4)
+		printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
 #endif
 	while (stage) {
 		if (stage->rq.cmd == IDETAPE_WRITE_RQ)
@@ -1515,7 +1583,8 @@
 	struct request *rq = &stage->rq;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_active_next_stage\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_active_next_stage\n");
 #endif /* IDETAPE_DEBUG_LOG */
 #if IDETAPE_DEBUG_BUGS
 	if (stage == NULL) {
@@ -1544,7 +1613,8 @@
 	int increase = (tape->max_pipeline - tape->min_pipeline) / 10;
 	
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_increase_max_pipeline_stages\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
 	tape->max_stages += increase;
@@ -1592,7 +1662,8 @@
 	idetape_stage_t *stage;
 	
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_remove_stage_head\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n");
 #endif /* IDETAPE_DEBUG_LOG */
 #if IDETAPE_DEBUG_BUGS
 	if (tape->first_stage == NULL) {
@@ -1638,7 +1709,8 @@
 #endif
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_end_request\n");
+        if (tape->debug_level >= 4)
+	printk (KERN_INFO "ide-tape: Reached idetape_end_request\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
 	switch (uptodate) {
@@ -1657,17 +1729,20 @@
 		tape->nr_pending_stages--;
 		if (rq->cmd == IDETAPE_WRITE_RQ) {
 #if ONSTREAM_DEBUG
-			if (tape->onstream) {
-				stage = tape->first_stage;
-				aux = stage->aux;
-				p = stage->bh->b_data;
-				if (ntohl(aux->logical_blk_num) < 11300 && ntohl(aux->logical_blk_num) > 11100)
-					printk(KERN_INFO "finished writing logical blk %lu (data %x %x %x %x)\n", ntohl(aux->logical_blk_num), *p++, *p++, *p++, *p++);
+			if (tape->debug_level >= 2) {
+				if (tape->onstream) {
+					stage = tape->first_stage;
+					aux = stage->aux;
+					p = stage->bh->b_data;
+					if (ntohl(aux->logical_blk_num) < 11300 && ntohl(aux->logical_blk_num) > 11100)
+						printk(KERN_INFO "ide-tape: finished writing logical blk %lu (data %x %x %x %x)\n", ntohl(aux->logical_blk_num), *p++, *p++, *p++, *p++);
+				}
 			}
 #endif
 			if (tape->onstream && !tape->raw) {
 				if (tape->first_frame_position == 0xba4) {
 #if ONSTREAM_DEBUG
+				if (tape->debug_level >= 2)
 					printk("ide-tape: %s: skipping over config parition..\n", tape->name);
 #endif
 					tape->onstream_write_error = 2;
@@ -1723,13 +1798,14 @@
 	idetape_tape_t *tape = drive->driver_data;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n");
 #endif /* IDETAPE_DEBUG_LOG */
 	if (!tape->pc->error) {
 		idetape_analyze_error (drive,(idetape_request_sense_result_t *) tape->pc->buffer);
 		idetape_end_request (1,HWGROUP (drive));
 	} else {
-		printk (KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n");
+		printk (KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n");
 		idetape_end_request (0,HWGROUP (drive));
 	}
 	return ide_stopped;
@@ -1802,7 +1878,8 @@
 	idetape_tape_t *tape = drive->driver_data;
 
 #if IDETAPE_DEBUG_LOG
-	printk(KERN_INFO "idetape_postpone_request\n");
+	if (tape->debug_level >= 4)
+		printk(KERN_INFO "ide-tape: idetape_postpone_request\n");
 #endif
 	tape->postponed_rq = HWGROUP(drive)->rq;
 	ide_stall_queue(drive, tape->dsc_polling_frequency);
@@ -1831,7 +1908,8 @@
 #endif
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "ide-tape: Reached idetape_pc_intr interrupt handler\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_pc_intr interrupt handler\n");
 #endif /* IDETAPE_DEBUG_LOG */	
 
 	status.all = GET_STAT();					/* Clear the interrupt */
@@ -1856,7 +1934,8 @@
 			idetape_update_buffers (pc);
 		}
 #if IDETAPE_DEBUG_LOG
-		printk (KERN_INFO "ide-tape: DMA finished\n");
+		if (tape->debug_level >= 4)
+			printk (KERN_INFO "ide-tape: DMA finished\n");
 #endif /* IDETAPE_DEBUG_LOG */
 	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
@@ -1865,7 +1944,8 @@
 		cmd_time = (jiffies - tape->cmd_start_time) * 1000 / HZ;
 		tape->max_cmd_time = IDE_MAX(cmd_time, tape->max_cmd_time);
 #if IDETAPE_DEBUG_LOG
-		printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
+		if (tape->debug_level >= 2)
+			printk (KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
 #endif /* IDETAPE_DEBUG_LOG */
 		clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);
 
@@ -1881,14 +1961,16 @@
 			status.b.check = 0;
 		if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) {	/* Error detected */
 #if IDETAPE_DEBUG_LOG
-			printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name);
+			if (tape->debug_level >= 1)
+				printk (KERN_INFO "ide-tape: %s: I/O error, ",tape->name);
 #endif /* IDETAPE_DEBUG_LOG */
 			if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
 				printk (KERN_ERR "ide-tape: I/O error in request sense command\n");
 				return ide_do_reset (drive);
 			}
 #if IDETAPE_DEBUG_LOG
-			printk(KERN_INFO "[cmd %x]: check condition\n", pc->c[0]);
+			if (tape->debug_level >= 1)
+				printk(KERN_INFO "ide-tape: [cmd %x]: check condition\n", pc->c[0]);
 #endif
 			return idetape_retry_pc (drive);				/* Retry operation */
 		}
@@ -1922,7 +2004,7 @@
 	}
 	if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) {	/* Hopefully, we will never get here */
 		printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read");
-		printk (KERN_ERR "but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write");
+		printk (KERN_ERR "ide-tape: but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write");
 		return ide_do_reset (drive);
 	}
 	if (!test_bit (PC_WRITING, &pc->flags)) {			/* Reading - Check that we have enough space */
@@ -1935,7 +2017,8 @@
 				return ide_started;
 			}
 #if IDETAPE_DEBUG_LOG
-			printk (KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n");
+			if (tape->debug_level >= 2)
+				printk (KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n");
 #endif /* IDETAPE_DEBUG_LOG */
 		}
 	}
@@ -1953,7 +2036,8 @@
 	pc->actually_transferred+=bcount.all;					/* Update the current position */
 	pc->current_position+=bcount.all;
 #if IDETAPE_DEBUG_LOG
-	printk(KERN_INFO "[cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
+	if (tape->debug_level >= 2)
+		printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
 #endif
 	ide_set_handler (drive,&idetape_pc_intr,IDETAPE_WAIT_CMD,NULL);		/* And set the interrupt handler again */
 	return ide_started;
@@ -2061,7 +2145,7 @@
 			if (!(pc->c[0] == 0 && tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8))) {
 				printk (KERN_ERR "ide-tape: %s: I/O error, pc = %2x, key = %2x, asc = %2x, ascq = %2x\n",
 					tape->name, pc->c[0], tape->sense_key, tape->asc, tape->ascq);
-				if (tape->onstream && pc->c[0] == 8 && tape->sense_key == 3 && tape->asc == 11)
+				if (tape->onstream && pc->c[0] == 8 && tape->sense_key == 3 && tape->asc == 0x11)  /* AJN-1: 11 should be 0x11 */
 					printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name);
 			}
 			pc->error = IDETAPE_ERROR_GENERAL;		/* Giving up */
@@ -2070,7 +2154,8 @@
 		return pc->callback(drive);
 	}
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Retry number - %d\n",pc->retries);
+	if (tape->debug_level >= 2)
+		printk (KERN_INFO "ide-tape: Retry number - %d\n",pc->retries);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	pc->retries++;
@@ -2117,7 +2202,8 @@
 	idetape_tape_t *tape = drive->driver_data;
 	
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "ide-tape: Reached idetape_pc_callback\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_pc_callback\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
 	idetape_end_request (tape->pc->error ? 0:1, HWGROUP(drive));
@@ -2163,7 +2249,8 @@
 	IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
 #endif
 #if IDETAPE_DEBUG_LOG
-	printk(KERN_INFO "buffer fill callback, %d/%d\n", tape->cur_frames, tape->max_frames);
+	if (tape->debug_level >= 1)
+		printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", tape->cur_frames, tape->max_frames);
 #endif
 	idetape_end_request (tape->pc->error ? 0:1, HWGROUP(drive));
 	return ide_stopped;
@@ -2277,7 +2364,8 @@
 	}
 
 #if IDETAPE_DEBUG_LOG	
-	printk (KERN_INFO "ide-tape: Reached idetape_rw_callback\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_rw_callback\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
 	tape->first_frame_position += blocks;
@@ -2384,8 +2472,10 @@
 	idetape_status_reg_t status;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
-	printk (KERN_INFO "sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
+	if (tape->debug_level >= 5)
+		printk (KERN_INFO "ide-tape: rq_status: %d, rq_dev: %u, cmd: %d, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->cmd,rq->errors);
+	if (tape->debug_level >= 2)
+		printk (KERN_INFO "ide-tape: sector: %ld, nr_sectors: %ld, current_nr_sectors: %ld\n",rq->sector,rq->nr_sectors,rq->current_nr_sectors);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (!IDETAPE_RQ_CMD (rq->cmd)) {
@@ -2456,15 +2546,17 @@
 	   ((rq->cmd == IDETAPE_WRITE_RQ && (tape->cur_frames == tape->max_frames || (tape->speed_control && tape->cur_frames > 5 && (tape->insert_speed > tape->max_insert_speed || (0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */))))) ||
 	    (rq->cmd == IDETAPE_READ_RQ && (tape->cur_frames == 0 || (tape->speed_control && (tape->cur_frames < tape->max_frames - 5) && tape->insert_speed > tape->max_insert_speed)) && rq->nr_sectors))) {
 #if IDETAPE_DEBUG_LOG
-		printk(KERN_INFO "postponing request, cmd %d, cur %d, max %d\n",
-			rq->cmd, tape->cur_frames, tape->max_frames);
+		if (tape->debug_level >= 4)
+			printk(KERN_INFO "ide-tape: postponing request, cmd %d, cur %d, max %d\n",
+				rq->cmd, tape->cur_frames, tape->max_frames);
 #endif
 		if (tape->postpone_cnt++ < 500) {
 			status.b.dsc = 0;
 			tape->req_buffer_fill = 1;
 		}
 #if ONSTREAM_DEBUG
-		else printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n", tape->name, tape->postpone_cnt);
+		else if (tape->debug_level >= 4) 
+			printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n", tape->name, tape->postpone_cnt);
 #endif
 	}
 	if (!test_and_clear_bit (IDETAPE_IGNORE_DSC, &tape->flags) && !status.b.dsc) {
@@ -2530,7 +2622,8 @@
 			return ide_stopped;
 		case IDETAPE_ABORTED_READ_RQ:
 #if IDETAPE_DEBUG_LOG
-			printk(KERN_INFO "ide-tape: %s: detected aborted read rq\n", tape->name);
+			if (tape->debug_level >= 2)
+				printk(KERN_INFO "ide-tape: %s: detected aborted read rq\n", tape->name);
 #endif
 			rq->cmd = IDETAPE_READ_RQ;
 			idetape_end_request (IDETAPE_ERROR_EOD, HWGROUP(drive));
@@ -2643,7 +2736,8 @@
 	idetape_stage_t *cache_stage = tape->cache_stage;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_kmalloc_stage\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_kmalloc_stage\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (tape->nr_stages >= tape->max_stages)
@@ -2737,7 +2831,8 @@
 	unsigned long flags;
 	
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_add_stage_tail\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_add_stage_tail\n");
 #endif /* IDETAPE_DEBUG_LOG */
 	spin_lock_irqsave(&tape->spinlock, flags);
 	stage->next=NULL;
@@ -2851,14 +2946,17 @@
 	idetape_read_position_result_t *result;
 	
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_read_position_callback\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (!tape->pc->error) {
 		result = (idetape_read_position_result_t *) tape->pc->buffer;
 #if IDETAPE_DEBUG_LOG
-		printk (KERN_INFO "BOP - %s\n",result->bop ? "Yes":"No");
-		printk (KERN_INFO "EOP - %s\n",result->eop ? "Yes":"No");
+		if (tape->debug_level >= 2)
+			printk (KERN_INFO "ide-tape: BOP - %s\n",result->bop ? "Yes":"No");
+		if (tape->debug_level >= 2)
+			printk (KERN_INFO "ide-tape: EOP - %s\n",result->eop ? "Yes":"No");
 #endif /* IDETAPE_DEBUG_LOG */
 		if (result->bpu) {
 			printk (KERN_INFO "ide-tape: Block location is unknown to the tape\n");
@@ -2866,7 +2964,8 @@
 			idetape_end_request (0,HWGROUP (drive));
 		} else {
 #if IDETAPE_DEBUG_LOG
-			printk (KERN_INFO "Block Location - %lu\n", ntohl (result->first_block));
+			if (tape->debug_level >= 2)
+				printk (KERN_INFO "ide-tape: Block Location - %lu\n", ntohl (result->first_block));
 #endif /* IDETAPE_DEBUG_LOG */
 			tape->partition = result->partition;
 			tape->first_frame_position = ntohl (result->first_block);
@@ -2952,7 +3051,7 @@
 	pc->callback = &idetape_pc_callback;
 }
 
-static int idetape_wait_ready(ide_drive_t *drive, unsigned long long timeout)
+static int idetape_wait_ready (ide_drive_t *drive, unsigned long long timeout)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_pc_t pc;
@@ -2975,7 +3074,7 @@
 		if (!(tape->sense_key == 2 && tape->asc == 4 && (tape->ascq == 1 || tape->ascq == 8)))
 			break;
 		current->state = TASK_INTERRUPTIBLE;
-		schedule_timeout(HZ / 10);
+  		schedule_timeout(HZ / 10);
 	}
 	return -EIO;
 }
@@ -2988,7 +3087,8 @@
 	rc = __idetape_queue_pc_tail(drive, pc);
 	if (rc)	return rc;
 	if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags))
-		rc = idetape_wait_ready(drive, 60 * 5 * HZ);
+		rc = idetape_wait_ready(drive, 60 * 10 * HZ);   /* AJN-4: Changed from 5 to 10 minutes;
+                          because retension takes approx. 8:20 with Onstream 30GB tape */
 	return rc;
 }
 
@@ -3012,17 +3112,20 @@
 	pc->callback = &idetape_read_position_callback;
 }
 
-static int idetape_read_position(ide_drive_t *drive)
+static int idetape_read_position (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_pc_t pc;
 	int position;
 
+#ifdef NO_LONGER_REQUIRED
 	idetape_flush_tape_buffers(drive);
+#endif
 	idetape_create_read_position_cmd(&pc);
 	if (idetape_queue_pc_tail (drive,&pc))
 		return -1;
 	position = tape->first_frame_position;
+#ifdef NO_LONGER_REQUIRED
 	if (tape->onstream) {
 		if ((position != tape->last_frame_position - tape->blocks_in_buffer) &&
 		    (position != tape->last_frame_position + tape->blocks_in_buffer)) {
@@ -3033,6 +3136,7 @@
 			}
 		}
 	}
+#endif
 	return position;
 }
 
@@ -3054,7 +3158,7 @@
 	pc->callback = &idetape_pc_callback;
 }
 
-static void idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc, int prevent)
+static void idetape_create_prevent_cmd (ide_drive_t *drive, idetape_pc_t *pc, int prevent)
 {
 	idetape_init_pc(pc);
 	pc->c[0] = IDETAPE_PREVENT_CMD;
@@ -3130,7 +3234,8 @@
 	if (restore_position) {
 		position = idetape_read_position(drive);
 #if ONSTREAM_DEBUG
-		printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", position, cnt);
+		if (tape->debug_level >= 2)
+			printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", position, cnt);
 #endif
 		seek = position > cnt ? position - cnt : 0;
 		if (idetape_position_tape(drive, seek, 0, 0)) {
@@ -3140,7 +3245,7 @@
 	}
 }
 
-static void idetape_update_stats(ide_drive_t *drive)
+static void idetape_update_stats (ide_drive_t *drive)
 {
 	idetape_pc_t pc;
 
@@ -3159,7 +3264,8 @@
 	struct request rq;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "idetape_queue_rw_tail: cmd=%d\n",cmd);
+	if (tape->debug_level >= 2)
+		printk (KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd);
 #endif /* IDETAPE_DEBUG_LOG */
 #if IDETAPE_DEBUG_BUGS
 	if (idetape_pipeline_active (tape)) {
@@ -3192,7 +3298,7 @@
  * of the write error recovery mechanism for old OnStream
  * firmware revisions.
  */
-static void idetape_onstream_read_back_buffer(ide_drive_t *drive)
+static void idetape_onstream_read_back_buffer (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	int frames, i, logical_blk_num;
@@ -3214,7 +3320,8 @@
 		p = stage->bh->b_data;
 		idetape_queue_rw_tail(drive, IDETAPE_READ_BUFFER_RQ, tape->capabilities.ctl, stage->bh);
 #if ONSTREAM_DEBUG
-		printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++);
+		if (tape->debug_level >= 2)
+			printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++);
 #endif
 		rq = &stage->rq;
 		ide_init_drive_cmd (rq);
@@ -3237,14 +3344,15 @@
 	}
 	idetape_update_stats(drive);
 #if ONSTREAM_DEBUG
-	printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", tape->name, tape->cur_frames);
+	if (tape->debug_level >= 2)
+		printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", tape->name, tape->cur_frames);
 #endif
 }
 
 /*
  * Error recovery algorithm for the OnStream tape.
  */
-static void idetape_onstream_write_error_recovery(ide_drive_t *drive)
+static void idetape_onstream_write_error_recovery (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	unsigned int block;
@@ -3263,11 +3371,13 @@
 		}
 		idetape_read_position(drive);
 #if ONSTREAM_DEBUG
-		printk(KERN_ERR "ide-tape: %s: positioning complete, cur_frames %d, pos %d, tape pos %d\n", tape->name, tape->cur_frames, tape->first_frame_position, tape->last_frame_position);
+		if (tape->debug_level >= 1)
+			printk(KERN_ERR "ide-tape: %s: positioning complete, cur_frames %d, pos %d, tape pos %d\n", tape->name, tape->cur_frames, tape->first_frame_position, tape->last_frame_position);
 #endif
 	} else if (tape->onstream_write_error == 2) {
 #if ONSTREAM_DEBUG
-		printk(KERN_INFO "ide-tape: %s: skipping over config partition\n", tape->name);
+		if (tape->debug_level >= 1)
+			printk(KERN_INFO "ide-tape: %s: skipping over config partition\n", tape->name);
 #endif
 		idetape_flush_tape_buffers(drive);
 		block = idetape_read_position(drive);
@@ -3297,7 +3407,7 @@
 	}
 }
 
-static void idetape_create_inquiry_cmd(idetape_pc_t *pc)
+static void idetape_create_inquiry_cmd (idetape_pc_t *pc)
 {
 	idetape_init_pc(pc);
 	pc->c[0] = IDETAPE_INQUIRY_CMD;
@@ -3350,7 +3460,7 @@
 /*
  * Verify that we have the correct tape frame
  */
-static int idetape_verify_stage(ide_drive_t *drive, idetape_stage_t *stage, int logical_blk_num, int quiet)
+static int idetape_verify_stage (ide_drive_t *drive, idetape_stage_t *stage, int logical_blk_num, int quiet)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	os_aux_t *aux = stage->aux;
@@ -3404,7 +3514,7 @@
 		return 0;
 	}
 	if (ntohs(par->wrt_pass_cntr) != tape->wrt_pass_cntr) {
-		printk(KERN_INFO "ide-tape: %s: skipping frame, wrt_pass_cntr %d (expected %d)\n", tape->name, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr);
+		printk(KERN_INFO "ide-tape: %s: skipping frame, wrt_pass_cntr %d (expected %d)(logical_blk_num %lu)\n", tape->name, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num));
 		return 0;
 	}
 	if (aux->frame_seq_num != aux->logical_blk_num) {
@@ -3423,7 +3533,7 @@
 	return 1;
 }
 
-static void idetape_wait_first_stage(ide_drive_t *drive)
+static void idetape_wait_first_stage (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	unsigned long flags;
@@ -3455,7 +3565,8 @@
 	struct request *rq;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_add_chrdev_write_request\n");
+	if (tape->debug_level >= 3)
+		printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
      	/*
@@ -3577,7 +3688,7 @@
 			bh = tape->bh;
 			while (i) {
 				if (bh == NULL) {
-					printk(KERN_INFO "bug, bh NULL\n");
+					printk(KERN_INFO "ide-tape: bug, bh NULL\n");
 					break;
 				}
 				min = IDE_MIN(i, bh->b_size - atomic_read(&bh->b_count));
@@ -3614,7 +3725,7 @@
 #endif /* IDETAPE_DEBUG_BUGS */
 }
 
-static void idetape_restart_speed_control(ide_drive_t *drive)
+static void idetape_restart_speed_control (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 
@@ -3629,7 +3740,7 @@
 	tape->controlled_previous_head_time = tape->uncontrolled_previous_head_time = jiffies;
 }
 
-static int idetape_initiate_read(ide_drive_t *drive, int max_stages)
+static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_stage_t *new_stage;
@@ -3698,7 +3809,7 @@
 	return 0;
 }
 
-static int idetape_get_logical_blk(ide_drive_t *drive, int logical_blk_num, int max_stages, int quiet)
+static int idetape_get_logical_blk (ide_drive_t *drive, int logical_blk_num, int max_stages, int quiet)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	unsigned long flags;
@@ -3708,7 +3819,7 @@
 	 * Search and wait for the next logical tape block
 	 */
 	while (1) {
-		if (cnt++ > 100) {
+		if (cnt++ > 1000) {   /* AJN: was 100 */
 			printk(KERN_INFO "ide-tape: %s: couldn't find logical block %d, aborting\n", tape->name, logical_blk_num);
 			return 0;
 		}
@@ -3716,7 +3827,8 @@
 		if (tape->first_stage == NULL) {
 			if (tape->onstream) {
 #if ONSTREAM_DEBUG
-				printk(KERN_INFO "ide-tape: %s: first_stage == NULL, pipeline error %d\n", tape->name, test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags));
+				if (tape->debug_level >= 1)
+					printk(KERN_INFO "ide-tape: %s: first_stage == NULL, pipeline error %d\n", tape->name, test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags));
 #endif
 				clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
 				position = idetape_read_position(drive);
@@ -3761,7 +3873,8 @@
 	int bytes_read;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_add_chrdev_read_request, %d blocks\n", blocks);
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_add_chrdev_read_request, %d blocks\n", blocks);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	/*
@@ -3784,7 +3897,8 @@
 
 	if (tape->onstream && !tape->raw && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) {
 #if ONSTREAM_DEBUG
-		printk(KERN_INFO "ide-tape: %s: EOD reached\n", tape->name);
+		if (tape->debug_level >= 2)
+			printk(KERN_INFO "ide-tape: %s: EOD reached\n", tape->name);
 #endif
 		return 0;
 	}
@@ -3796,7 +3910,8 @@
 		idetape_switch_buffers (tape, tape->first_stage);
 		if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) {
 #if ONSTREAM_DEBUG
-			printk(KERN_INFO "error detected, bytes_read %d\n", bytes_read);
+			if (tape->debug_level >= 1)
+				printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read);
 #endif
 		}
 		clear_bit (IDETAPE_FILEMARK, &tape->flags);
@@ -3871,7 +3986,8 @@
 	idetape_pc_t pc;
 	idetape_tape_t *tape = drive->driver_data;
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_rewind_tape\n");
+	if (tape->debug_level >= 2)
+		printk (KERN_INFO "ide-tape: Reached idetape_rewind_tape\n");
 #endif /* IDETAPE_DEBUG_LOG */	
 	
 	idetape_create_rewind_cmd (drive, &pc);
@@ -3899,7 +4015,8 @@
 	idetape_config_t config;
 
 #if IDETAPE_DEBUG_LOG	
-	printk (KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n");
+	if (tape->debug_level >= 4)
+		printk (KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n");
 #endif /* IDETAPE_DEBUG_LOG */
 	switch (cmd) {
 		case 0x0340:
@@ -3928,12 +4045,18 @@
 static int idetape_blkdev_open (struct inode *inode, struct file *filp, ide_drive_t *drive)
 {
 	MOD_INC_USE_COUNT;
+#if ONSTREAM_DEBUG
+        printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_blkdev_open\n");
+#endif
 	return 0;
 }
 
 static void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_drive_t *drive)
 {
 	MOD_DEC_USE_COUNT;
+#if ONSTREAM_DEBUG
+        printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_blkdev_release\n");
+#endif
 }
 
 /*
@@ -3974,7 +4097,8 @@
 		if (last_mark_addr == -1)
 			return -EIO;
 #if ONSTREAM_DEBUG
-		printk(KERN_INFO "ide-tape: positioning to last mark at %d\n", last_mark_addr);
+		if (tape->debug_level >= 2)
+			printk(KERN_INFO "ide-tape: positioning to last mark at %d\n", last_mark_addr);
 #endif
 		idetape_position_tape(drive, last_mark_addr, 0, 0);
 		cnt++;
@@ -4001,7 +4125,7 @@
  *
  * Just scans for the filemark sequentially.
  */
-static int idetape_onstream_space_over_filemarks_forward_slow(ide_drive_t *drive,short mt_op,int mt_count)
+static int idetape_onstream_space_over_filemarks_forward_slow (ide_drive_t *drive,short mt_op,int mt_count)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	int cnt = 0;
@@ -4020,7 +4144,8 @@
 			cnt++;
 		if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) {
 #if ONSTREAM_DEBUG
-			printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name);
+			if (tape->debug_level >= 2)
+				printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name);
 #endif
 			return -EIO;
 		}
@@ -4043,7 +4168,7 @@
 /*
  * Fast linux specific version of OnStream FSF
  */
-static int idetape_onstream_space_over_filemarks_forward_fast(ide_drive_t *drive,short mt_op,int mt_count)
+static int idetape_onstream_space_over_filemarks_forward_fast (ide_drive_t *drive,short mt_op,int mt_count)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	int cnt = 0, next_mark_addr;
@@ -4062,7 +4187,8 @@
 			break;
 		if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) {
 #if ONSTREAM_DEBUG
-			printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name);
+			if (tape->debug_level >= 2)
+				printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name);
 #endif
 			return -EIO;
 		}
@@ -4092,10 +4218,11 @@
 		if (!next_mark_addr || next_mark_addr > tape->eod_frame_addr) {
 			printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name);
 			return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count - cnt);
-		}
 #if ONSTREAM_DEBUG
-		else printk(KERN_INFO "ide-tape: positioning to next mark at %d\n", next_mark_addr);
+		} else if (tape->debug_level >= 2) {
+		     printk(KERN_INFO "ide-tape: positioning to next mark at %d\n", next_mark_addr);
 #endif
+		}
 		idetape_position_tape(drive, next_mark_addr, 0, 0);
 		cnt++;
 		if (!idetape_get_logical_blk(drive, -1, 10, 0)) {
@@ -4218,6 +4345,7 @@
  *	The tape is optimized to maximize throughput when it is transferring
  *	an integral number of the "continuous transfer limit", which is
  *	a parameter of the specific tape (26 KB on my particular tape).
+ *      (32 kB for Onstream)
  *
  *	As of version 1.3 of the driver, the character device provides an
  *	abstract continuous view of the media - any mix of block sizes (even 1
@@ -4226,6 +4354,7 @@
  *	so that an unmatch between the user's block size to the recommended
  *	size will only result in a (slightly) increased driver overhead, but
  *	will no longer hit performance.
+ *      This is not applicable to Onstream.
  */
 static ssize_t idetape_chrdev_read (struct file *file, char *buf,
 				    size_t count, loff_t *ppos)
@@ -4244,7 +4373,8 @@
 		return -EINVAL;
 	}
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_chrdev_read, count %d\n", count);
+	if (tape->debug_level >= 3)
+		printk (KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %d\n", count);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (tape->chrdev_direction != idetape_direction_read) {
@@ -4280,7 +4410,8 @@
 finish:
 	if (!actually_read && test_bit (IDETAPE_FILEMARK, &tape->flags)) {
 #if IDETAPE_DEBUG_LOG
-		printk(KERN_INFO "ide-tape: %s: spacing over filemark\n", tape->name);
+		if (tape->debug_level >= 2)
+			printk(KERN_INFO "ide-tape: %s: spacing over filemark\n", tape->name);
 #endif
 		idetape_space_over_filemarks (drive, MTFSF, 1);
 		return 0;
@@ -4293,7 +4424,7 @@
 	return actually_read;
 }
 
-static void idetape_update_last_marker(ide_drive_t *drive, int last_mark_addr, int next_mark_addr)
+static void idetape_update_last_marker (ide_drive_t *drive, int last_mark_addr, int next_mark_addr)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_stage_t *stage;
@@ -4310,8 +4441,10 @@
 	idetape_flush_tape_buffers(drive);
 	position = idetape_read_position(drive);
 #if ONSTREAM_DEBUG
-	printk(KERN_INFO "current position (2) %d, lblk %d\n", position, tape->logical_blk_num);
-	printk(KERN_INFO "current position (2) tape block %d\n", tape->last_frame_position);
+	if (tape->debug_level >= 2)
+		printk(KERN_INFO "ide-tape: current position (2) %d, lblk %d\n", position, tape->logical_blk_num);
+	if (tape->debug_level >= 2)
+		printk(KERN_INFO "ide-tape: current position (2) tape block %d\n", tape->last_frame_position);
 #endif
 	idetape_position_tape(drive, last_mark_addr, 0, 0);
 	if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bh)) {
@@ -4328,7 +4461,8 @@
 		return;
 	}
 #if ONSTREAM_DEBUG
-	printk(KERN_INFO "writing back marker\n");
+	if (tape->debug_level >= 2)
+		printk(KERN_INFO "ide-tape: writing back marker\n");
 #endif
 	aux->next_mark_addr = htonl(next_mark_addr);
 	idetape_position_tape(drive, last_mark_addr, 0, 0);
@@ -4344,7 +4478,7 @@
 	return;
 }
 
-static void __idetape_write_header(ide_drive_t *drive, int block, int cnt)
+static void __idetape_write_header (ide_drive_t *drive, int block, int cnt)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_stage_t *stage;
@@ -4358,7 +4492,7 @@
 	idetape_position_tape(drive, block, 0, 0);
 	memset(&header, 0, sizeof(header));
 	strcpy(header.ident_str, "ADR_SEQ");
-	header.major_rev = header.minor_rev = 1;
+	header.major_rev = header.minor_rev = 2;
 	header.par_num = 1;
 	header.partition.partition_num = OS_DATA_PARTITION;
 	header.partition.par_desc_ver = OS_PARTITION_VERSION;
@@ -4378,21 +4512,23 @@
 	idetape_flush_tape_buffers (drive);
 }
 
-static void idetape_write_header(ide_drive_t *drive, int locate_eod)
+static void idetape_write_header (ide_drive_t *drive, int locate_eod)
 {
 	idetape_tape_t *tape = drive->driver_data;
 
 #if ONSTREAM_DEBUG
-	printk(KERN_INFO "ide-tape: %s: writing tape header\n", tape->name);
+	if (tape->debug_level >= 2)
+		printk(KERN_INFO "ide-tape: %s: writing tape header\n", tape->name);
 #endif
 	if (!tape->onstream || tape->raw)
 		return;
 	tape->update_frame_cntr++;
 	__idetape_write_header(drive, 5, 5);
-	__idetape_write_header(drive, 0xbb2, 6);
+	__idetape_write_header(drive, 0xbae, 5);
 	if (locate_eod) {
 #if ONSTREAM_DEBUG
-		printk(KERN_INFO "ide-tape: %s: locating back to eod frame addr %d\n", tape->name, tape->eod_frame_addr);
+		if (tape->debug_level >= 2)
+			printk(KERN_INFO "ide-tape: %s: locating back to eod frame addr %d\n", tape->name, tape->eod_frame_addr);
 #endif
 		idetape_position_tape(drive, tape->eod_frame_addr, 0, 0);
 	}
@@ -4416,7 +4552,8 @@
 		return -EINVAL;
 	}
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_chrdev_write, count %d\n", count);
+	if (tape->debug_level >= 3)
+		printk (KERN_INFO "ide-tape: Reached idetape_chrdev_write, count %d\n", count);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (tape->chrdev_direction != idetape_direction_write) {	/* Initialize write operation */
@@ -4439,8 +4576,10 @@
 				tape->logical_blk_num = 0;
 				tape->wrt_pass_cntr++;
 #if ONSTREAM_DEBUG
-				printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to 20\n", tape->name);
-				printk(KERN_INFO "ide-tape: %s: allocating new write pass counter %d\n", tape->name, tape->wrt_pass_cntr);
+				if (tape->debug_level >= 2)
+					printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to 20\n", tape->name);
+				if (tape->debug_level >= 2)
+					printk(KERN_INFO "ide-tape: %s: allocating new write pass counter %d\n", tape->name, tape->wrt_pass_cntr);
 #endif
 				tape->filemark_cnt = 0;
 				tape->eod_frame_addr = 20;
@@ -4448,13 +4587,15 @@
 				idetape_write_header(drive, 1);
 			}
 #if ONSTREAM_DEBUG
-			printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr);
+			if (tape->debug_level >= 2)
+				printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr);
 #endif
 			position = idetape_read_position(drive);
 			if (position != tape->eod_frame_addr)
 				idetape_position_tape(drive, tape->eod_frame_addr, 0, 0);
 #if ONSTREAM_DEBUG
-			printk(KERN_INFO "ide-tape: %s: first_frame_position %d\n", tape->name, tape->first_frame_position);
+			if (tape->debug_level >= 2)
+				printk(KERN_INFO "ide-tape: %s: first_frame_position %d\n", tape->name, tape->first_frame_position);
 #endif
 		}
 
@@ -4471,7 +4612,8 @@
 			return retval;
 		}
 #if ONSTREAM_DEBUG
-		printk("ide-tape: first_frame_position %d\n", tape->first_frame_position);
+		if (tape->debug_level >= 2)
+			printk("ide-tape: first_frame_position %d\n", tape->first_frame_position);
 #endif
 	}
 	if (count==0)
@@ -4512,7 +4654,7 @@
 	return (actually_written);
 }
 
-static int idetape_write_filemark(ide_drive_t *drive)
+static int idetape_write_filemark (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	int last_mark_addr;
@@ -4543,7 +4685,7 @@
 	return 0;
 }
 
-static void idetape_write_eod(ide_drive_t *drive)
+static void idetape_write_eod (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 
@@ -4560,7 +4702,7 @@
 	return;
 }
 
-int idetape_seek_logical_blk(ide_drive_t *drive, int logical_blk_num)
+int idetape_seek_logical_blk (ide_drive_t *drive, int logical_blk_num)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	int estimated_address = logical_blk_num + 20;
@@ -4666,7 +4808,8 @@
 	int i,retval;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",mt_op,mt_count);
+	if (tape->debug_level >= 1)
+		printk (KERN_INFO "ide-tape: Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",mt_op,mt_count);
 #endif /* IDETAPE_DEBUG_LOG */
 	/*
 	 *	Commands which need our pipelined read-ahead stages.
@@ -4716,7 +4859,8 @@
 		case MTEOM:
 			if (tape->onstream) {
 #if ONSTREAM_DEBUG
-				printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr);
+				if (tape->debug_level >= 2)
+					printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr);
 #endif
 				idetape_position_tape(drive, tape->eod_frame_addr, 0, 0);
 				if (!idetape_get_logical_blk(drive, -1, 10, 0))
@@ -4833,7 +4977,8 @@
 	int block_offset = 0, position = tape->first_frame_position;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_chrdev_ioctl, cmd=%u\n",cmd);
+	if (tape->debug_level >= 3)
+		printk (KERN_INFO "ide-tape: Reached idetape_chrdev_ioctl, cmd=%u\n",cmd);
 #endif /* IDETAPE_DEBUG_LOG */
 
 	tape->restart_speed_control_req = 1;
@@ -4890,7 +5035,7 @@
 	}
 }
 
-static int __idetape_analyze_headers(ide_drive_t *drive, int block)
+static int __idetape_analyze_headers (ide_drive_t *drive, int block)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	idetape_stage_t *stage;
@@ -4910,7 +5055,8 @@
 	if (stage == NULL)
 		return 0;
 #if ONSTREAM_DEBUG
-	printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name);
+	if (tape->debug_level >= 2)
+		printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name);
 #endif
 	idetape_position_tape(drive, block, 0, 0);
 	if (!idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, 1, stage->bh)) {
@@ -4925,8 +5071,8 @@
 		__idetape_kfree_stage (stage);
 		return 0;
 	}
-	if (header->major_rev != 1 || header->minor_rev != 1)
-		printk(KERN_INFO "ide-tape: warning: revision %d.%d detected (1.1 supported)\n", header->major_rev, header->minor_rev);
+	if (header->major_rev != 1 || (header->minor_rev != 1 && header->minor_rev != 2))
+		printk(KERN_INFO "ide-tape: warning: revision %d.%d detected (1.1/1.2 supported)\n", header->major_rev, header->minor_rev);
 	if (header->par_num != 1)
 		printk(KERN_INFO "ide-tape: warning: %d partitions defined, only one supported\n", header->par_num);
 	tape->wrt_pass_cntr = ntohs(header->partition.wrt_pass_cntr);
@@ -4946,13 +5092,14 @@
 		tape->linux_media = 0;
 	}
 #if ONSTREAM_DEBUG
-	printk(KERN_INFO "ide-tape: %s: detected write pass counter %d, eod frame addr %d\n", tape->name, tape->wrt_pass_cntr, tape->eod_frame_addr);
+	if (tape->debug_level >= 2)
+		printk(KERN_INFO "ide-tape: %s: detected write pass counter %d, eod frame addr %d\n", tape->name, tape->wrt_pass_cntr, tape->eod_frame_addr);
 #endif
 	__idetape_kfree_stage (stage);
 	return 1;
 }
 
-static int idetape_analyze_headers(ide_drive_t *drive)
+static int idetape_analyze_headers (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	int position, block;
@@ -4966,7 +5113,7 @@
 	for (block = 5; block < 10; block++)
 		if (__idetape_analyze_headers(drive, block))
 			goto ok;
-	for (block = 0xbb2; block < 0xbb8; block++)
+	for (block = 0xbae; block < 0xbb3; block++)
 		if (__idetape_analyze_headers(drive, block))
 			goto ok;
 	printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", tape->name);
@@ -4990,7 +5137,7 @@
 	unsigned int minor=MINOR (inode->i_rdev);
 			
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_chrdev_open\n");
+	printk (KERN_INFO "ide-tape: Reached idetape_chrdev_open\n");
 #endif /* IDETAPE_DEBUG_LOG */
 	
 	if ((drive = get_drive_ptr (inode->i_rdev)) == NULL)
@@ -5000,6 +5147,10 @@
 	if (test_and_set_bit (IDETAPE_BUSY, &tape->flags))
 		return -EBUSY;
 	MOD_INC_USE_COUNT;
+#if ONSTREAM_DEBUG
+	if (tape->debug_level >= 6)
+		printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_chrdev_open-1\n");
+#endif
 	if (!tape->onstream) {
 		idetape_read_position(drive);
 		if (!test_bit (IDETAPE_ADDRESS_VALID, &tape->flags))
@@ -5016,15 +5167,27 @@
 	if (idetape_wait_ready(drive, 60 * HZ)) {
 		clear_bit(IDETAPE_BUSY, &tape->flags);
 		MOD_DEC_USE_COUNT;
+#if ONSTREAM_DEBUG
+	if (tape->debug_level >= 6)
+		printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_open-1\n");
+#endif
 		printk(KERN_ERR "ide-tape: %s: drive not ready\n", tape->name);
 		return -EBUSY;
 	}
 	idetape_read_position(drive);
 	MOD_DEC_USE_COUNT;
+#if ONSTREAM_DEBUG
+	if (tape->debug_level >= 6)
+		printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_open-2\n");
+#endif
 	clear_bit (IDETAPE_PIPELINE_ERROR, &tape->flags);
 
 	if (tape->chrdev_direction == idetape_direction_none) {
 		MOD_INC_USE_COUNT;
+#if ONSTREAM_DEBUG
+		if (tape->debug_level >= 6)
+			printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_chrdev_open-2\n");
+#endif
 		idetape_create_prevent_cmd(drive, &pc, 1);
 		if (!idetape_queue_pc_tail (drive,&pc)) {
 			if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
@@ -5049,7 +5212,8 @@
 	unsigned int minor=MINOR (inode->i_rdev);
 			
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Reached idetape_chrdev_release\n");
+	if (tape->debug_level >= 3)
+		printk (KERN_INFO "ide-tape: Reached idetape_chrdev_release\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
 	if (tape->chrdev_direction == idetape_direction_write) {
@@ -5085,6 +5249,10 @@
 				tape->door_locked = DOOR_UNLOCKED;
 		}
 		MOD_DEC_USE_COUNT;
+#if ONSTREAM_DEBUG
+		if (tape->debug_level >= 6)
+			printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_chrdev_release\n");
+#endif
 	}
 	clear_bit (IDETAPE_BUSY, &tape->flags);
 	return 0;
@@ -5112,14 +5280,14 @@
 	*((unsigned short *) &gcw) = id->config;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Dumping ATAPI Identify Device tape parameters\n");
-	printk (KERN_INFO "Protocol Type: ");
+	printk (KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n");
+	printk (KERN_INFO "ide-tape: Protocol Type: ");
 	switch (gcw.protocol) {
 		case 0: case 1: printk (KERN_INFO "ATA\n");break;
 		case 2:	printk (KERN_INFO "ATAPI\n");break;
 		case 3: printk (KERN_INFO "Reserved (Unknown to ide-tape)\n");break;
 	}
-	printk (KERN_INFO "Device Type: %x - ",gcw.device_type);	
+	printk (KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type);	
 	switch (gcw.device_type) {
 		case 0: printk (KERN_INFO "Direct-access Device\n");break;
 		case 1: printk (KERN_INFO "Streaming Tape Device\n");break;
@@ -5130,32 +5298,32 @@
 		case 0x1f: printk (KERN_INFO "Unknown or no Device type\n");break;
 		default: printk (KERN_INFO "Reserved\n");
 	}
-	printk (KERN_INFO "Removable: %s",gcw.removable ? "Yes\n":"No\n");	
-	printk (KERN_INFO "Command Packet DRQ Type: ");
+	printk (KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n");	
+	printk (KERN_INFO "ide-tape: Command Packet DRQ Type: ");
 	switch (gcw.drq_type) {
 		case 0: printk (KERN_INFO "Microprocessor DRQ\n");break;
 		case 1: printk (KERN_INFO "Interrupt DRQ\n");break;
 		case 2: printk (KERN_INFO "Accelerated DRQ\n");break;
 		case 3: printk (KERN_INFO "Reserved\n");break;
 	}
-	printk (KERN_INFO "Command Packet Size: ");
+	printk (KERN_INFO "ide-tape: Command Packet Size: ");
 	switch (gcw.packet_size) {
 		case 0: printk (KERN_INFO "12 bytes\n");break;
 		case 1: printk (KERN_INFO "16 bytes\n");break;
 		default: printk (KERN_INFO "Reserved\n");break;
 	}
-	printk (KERN_INFO "Model: %.40s\n",id->model);
-	printk (KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev);
-	printk (KERN_INFO "Serial Number: %.20s\n",id->serial_no);
-	printk (KERN_INFO "Write buffer size: %d bytes\n",id->buf_size*512);
-	printk (KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
-	printk (KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
-	printk (KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
-	printk (KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
-	printk (KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
-	printk (KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO);
-	printk (KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA);
-	printk (KERN_INFO "Single Word DMA supported modes: ");
+	printk (KERN_INFO "ide-tape: Model: %.40s\n",id->model);
+	printk (KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev);
+	printk (KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no);
+	printk (KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512);
+	printk (KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
+	printk (KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
+	printk (KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
+	printk (KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
+	printk (KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
+	printk (KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO);
+	printk (KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA);
+	printk (KERN_INFO "ide-tape: Single Word DMA supported modes: ");
 	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
 		if (id->dma_1word & mask)
 			printk (KERN_INFO "%d ",i);
@@ -5163,7 +5331,7 @@
 			printk (KERN_INFO "(active) ");
 	}
 	printk (KERN_INFO "\n");
-	printk (KERN_INFO "Multi Word DMA supported modes: ");
+	printk (KERN_INFO "ide-tape: Multi Word DMA supported modes: ");
 	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
 		if (id->dma_mword & mask)
 			printk (KERN_INFO "%d ",i);
@@ -5172,33 +5340,33 @@
 	}
 	printk (KERN_INFO "\n");
 	if (id->field_valid & 0x0002) {
-		printk (KERN_INFO "Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None");
-		printk (KERN_INFO "Minimum Multi-word DMA cycle per word: ");
+		printk (KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",id->eide_pio_modes & 1 ? "Mode 3":"None");
+		printk (KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: ");
 		if (id->eide_dma_min == 0)
 			printk (KERN_INFO "Not supported\n");
 		else
 			printk (KERN_INFO "%d ns\n",id->eide_dma_min);
 
-		printk (KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: ");
+		printk (KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: ");
 		if (id->eide_dma_time == 0)
 			printk (KERN_INFO "Not supported\n");
 		else
 			printk (KERN_INFO "%d ns\n",id->eide_dma_time);
 
-		printk (KERN_INFO "Minimum PIO cycle without IORDY: ");
+		printk (KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: ");
 		if (id->eide_pio == 0)
 			printk (KERN_INFO "Not supported\n");
 		else
 			printk (KERN_INFO "%d ns\n",id->eide_pio);
 
-		printk (KERN_INFO "Minimum PIO cycle with IORDY: ");
+		printk (KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: ");
 		if (id->eide_pio_iordy == 0)
 			printk (KERN_INFO "Not supported\n");
 		else
 			printk (KERN_INFO "%d ns\n",id->eide_pio_iordy);
 		
 	} else
-		printk (KERN_INFO "According to the device, fields 64-70 are not valid.\n");
+		printk (KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n");
 #endif /* IDETAPE_DEBUG_LOG */
 
 	/* Check that we can support this device */
@@ -5221,7 +5389,7 @@
 /*
  * Notify vendor ID to the OnStream tape drive
  */
-static void idetape_onstream_set_vendor(ide_drive_t *drive, char *vendor)
+static void idetape_onstream_set_vendor (ide_drive_t *drive, char *vendor)
 {
 	idetape_pc_t pc;
 	idetape_mode_parameter_header_t *header;
@@ -5248,7 +5416,7 @@
  * Various unused OnStream commands
  */
 #if ONSTREAM_DEBUG
-static void idetape_onstream_set_retries(ide_drive_t *drive, int retries)
+static void idetape_onstream_set_retries (ide_drive_t *drive, int retries)
 {
 	idetape_pc_t pc;
 
@@ -5269,7 +5437,7 @@
 /*
  * Configure 32.5KB block size.
  */
-static void idetape_onstream_configure_block_size(ide_drive_t *drive)
+static void idetape_onstream_configure_block_size (ide_drive_t *drive)
 {
 	idetape_pc_t pc;
 	idetape_mode_parameter_header_t *header;
@@ -5285,10 +5453,10 @@
 	bs = (idetape_block_size_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
 
 #if IDETAPE_DEBUG_LOG
-	printk(KERN_INFO "32KB play back: %s\n", bs->play32 ? "Yes" : "No");
-	printk(KERN_INFO "32.5KB play back: %s\n", bs->play32_5 ? "Yes" : "No");
-	printk(KERN_INFO "32KB record: %s\n", bs->record32 ? "Yes" : "No");
-	printk(KERN_INFO "32.5KB record: %s\n", bs->record32_5 ? "Yes" : "No");
+	printk(KERN_INFO "ide-tape: 32KB play back: %s\n", bs->play32 ? "Yes" : "No");
+	printk(KERN_INFO "ide-tape: 32.5KB play back: %s\n", bs->play32_5 ? "Yes" : "No");
+	printk(KERN_INFO "ide-tape: 32KB record: %s\n", bs->record32 ? "Yes" : "No");
+	printk(KERN_INFO "ide-tape: 32.5KB record: %s\n", bs->record32_5 ? "Yes" : "No");
 #endif
 
 	/*
@@ -5315,7 +5483,7 @@
 /*
  * Use INQUIRY to get the firmware revision
  */
-static void idetape_get_inquiry_results(ide_drive_t *drive)
+static void idetape_get_inquiry_results (ide_drive_t *drive)
 {
 	char *r;
 	idetape_tape_t *tape = drive->driver_data;
@@ -5345,13 +5513,13 @@
 /*
  * Configure the OnStream ATAPI tape drive for default operation
  */
-static void idetape_configure_onstream(ide_drive_t *drive)
+static void idetape_configure_onstream (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 
 	if (tape->firmware_revision_num < 105) {
-		printk("ide-tape: %s: Old OnStream firmware revision detected (%s)\n", tape->name, tape->firmware_revision);
-		printk("ide-tape: %s: An upgrade to version 1.05 or above is recommended\n", tape->name);
+		printk(KERN_INFO "ide-tape: %s: Old OnStream firmware revision detected (%s)\n", tape->name, tape->firmware_revision);
+		printk(KERN_INFO "ide-tape: %s: An upgrade to version 1.05 or above is recommended\n", tape->name);
 	}
 
 	/*
@@ -5410,37 +5578,37 @@
 		tape->tape_block_size = 32768;
 
 #if IDETAPE_DEBUG_LOG
-	printk (KERN_INFO "Dumping the results of the MODE SENSE packet command\n");
-	printk (KERN_INFO "Mode Parameter Header:\n");
-	printk (KERN_INFO "Mode Data Length - %d\n",header->mode_data_length);
-	printk (KERN_INFO "Medium Type - %d\n",header->medium_type);
-	printk (KERN_INFO "Device Specific Parameter - %d\n",header->dsp);
-	printk (KERN_INFO "Block Descriptor Length - %d\n",header->bdl);
+	printk (KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n");
+	printk (KERN_INFO "ide-tape: Mode Parameter Header:\n");
+	printk (KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length);
+	printk (KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type);
+	printk (KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp);
+	printk (KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl);
 	
-	printk (KERN_INFO "Capabilities and Mechanical Status Page:\n");
-	printk (KERN_INFO "Page code - %d\n",capabilities->page_code);
-	printk (KERN_INFO "Page length - %d\n",capabilities->page_length);
-	printk (KERN_INFO "Read only - %s\n",capabilities->ro ? "Yes":"No");
-	printk (KERN_INFO "Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No");
-	printk (KERN_INFO "Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No");
-	printk (KERN_INFO "Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No");
-	printk (KERN_INFO "Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No");
-	printk (KERN_INFO "The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No");
-	printk (KERN_INFO "The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No");
-	printk (KERN_INFO "Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No");
-	printk (KERN_INFO "Supports error correction - %s\n",capabilities->ecc ? "Yes":"No");
-	printk (KERN_INFO "Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No");
-	printk (KERN_INFO "Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No");
-	printk (KERN_INFO "Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No");
-	printk (KERN_INFO "Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No");
-	printk (KERN_INFO "Maximum supported speed in KBps - %d\n",capabilities->max_speed);
-	printk (KERN_INFO "Continuous transfer limits in blocks - %d\n",capabilities->ctl);
-	printk (KERN_INFO "Current speed in KBps - %d\n",capabilities->speed);	
-	printk (KERN_INFO "Buffer size - %d\n",capabilities->buffer_size*512);
+	printk (KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n");
+	printk (KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code);
+	printk (KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length);
+	printk (KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No");
+	printk (KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed);
+	printk (KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl);
+	printk (KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed);	
+	printk (KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512);
 #endif /* IDETAPE_DEBUG_LOG */
 }
 
-static void idetape_add_settings(ide_drive_t *drive)
+static void idetape_add_settings (ide_drive_t *drive)
 {
 	idetape_tape_t *tape = drive->driver_data;
 
@@ -5465,6 +5633,7 @@
 		ide_add_setting(drive,	"max_frames",	SETTING_READ,	-1,	-1,		TYPE_SHORT,	0,			0xffff,			1,				1,				&tape->max_frames,		NULL);
 		ide_add_setting(drive,	"insert_speed",	SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->insert_speed,		NULL);
 		ide_add_setting(drive,	"speed_control",SETTING_RW,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->speed_control,		NULL);
+		ide_add_setting(drive,	"debug_level",SETTING_RW,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->debug_level,		NULL);
 		ide_add_setting(drive,	"tape_still_time",SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->tape_still_time,		NULL);
 		ide_add_setting(drive,	"max_insert_speed",SETTING_RW,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->max_insert_speed,	NULL);
 		ide_add_setting(drive,	"insert_size",	SETTING_READ,	-1,	-1,		TYPE_INT,	0,			0xffff,			1,				1,				&tape->insert_size,		NULL);
@@ -5686,6 +5855,9 @@
 	int minor, failed = 0, supported = 0;
 
 	MOD_INC_USE_COUNT;
+#if ONSTREAM_DEBUG
+        printk(KERN_INFO "ide-tape: MOD_INC_USE_COUNT in idetape_init\n");
+#endif
 	if (!idetape_chrdev_present)
 		for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++ )
 			idetape_chrdevs[minor].drive = NULL;
@@ -5693,11 +5865,18 @@
 	if ((drive = ide_scan_devices (ide_tape, idetape_driver.name, NULL, failed++)) == NULL) {
 		ide_register_module (&idetape_module);
 		MOD_DEC_USE_COUNT;
+#if ONSTREAM_DEBUG
+		if (tape->debug_level >= 6)
+			printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n");
+#endif
 		return 0;
 	}
 	if (!idetape_chrdev_present && register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) {
 		printk (KERN_ERR "ide-tape: Failed to register character device interface\n");
 		MOD_DEC_USE_COUNT;
+#if ONSTREAM_DEBUG
+		printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n");
+#endif
 		return -EBUSY;
 	}
 	do {
@@ -5734,6 +5913,9 @@
 		idetape_chrdev_present = 1;
 	ide_register_module (&idetape_module);
 	MOD_DEC_USE_COUNT;
+#if ONSTREAM_DEBUG
+	printk(KERN_INFO "ide-tape: MOD_DEC_USE_COUNT in idetape_init\n");
+#endif
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.39/linux/drivers/block/ide.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/ide.c	Tue Jan 18 18:54:21 2000
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c		Version 6.21	November 9, 1999
+ *  linux/drivers/block/ide.c		Version 6.30	Dec 28, 1999
  *
  *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
  */
@@ -108,6 +108,7 @@
  *			  Specifically Promise's PDC20262 chipset.
  * Version 6.21		Fixing/Fixed SMP spinlock issue with insight from an old
  *			  hat that clarified original low level driver design.
+ * Version 6.30		Added SMP support; fixed multmode issues.  -ml
  *
  *  Some additional driver compile-time options are in ./include/linux/ide.h
  *
@@ -116,8 +117,8 @@
  *
  */
 
-#define	REVISION	"Revision: 6.21"
-#define	VERSION		"Id: ide.c 6.21 1999/11/10"
+#define	REVISION	"Revision: 6.30"
+#define	VERSION		"Id: ide.c 6.30 1999/12/28"
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
@@ -169,6 +170,10 @@
 static int	system_bus_speed; /* holds what we think is VESA/PCI bus speed */
 static int	initializing;     /* set while initializing built-in drivers */
 
+#ifdef CONFIG_BLK_DEV_IDEPCI
+static int ide_scan_direction = 0;	/* HELLO, comment me!! */
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+
 #if defined(__mc68000__) || defined(CONFIG_APUS)
 /*
  * ide_lock is used by the Atari code to obtain access to the IDE interrupt,
@@ -542,22 +547,28 @@
 	return 0;
 }
 
+extern struct block_device_operations ide_fops[];
 /*
- * ide_geninit() is called exactly *once* for each major, from genhd.c,
- * at the beginning of the initial partition check for the drives.
+ * ide_geninit() is called exactly *once* for each interface.
  */
-void ide_geninit (struct gendisk *gd)
+void ide_geninit (ide_hwif_t *hwif)
 {
 	unsigned int unit;
-	ide_hwif_t *hwif = gd->real_devices;
+	struct gendisk *gd = hwif->gd;
 
-	for (unit = 0; unit < gd->nr_real; ++unit) {
+	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		ide_drive_t *drive = &hwif->drives[unit];
 
-		drive->part[0].nr_sects = current_capacity(drive);
-		if (!drive->present || (drive->media != ide_disk && drive->media != ide_floppy) ||
-		    drive->driver == NULL || !drive->part[0].nr_sects)
-			drive->part[0].start_sect = -1; /* skip partition check */
+		if (!drive->present)
+			continue;
+		if (drive->media!=ide_disk && drive->media!=ide_floppy)
+			continue;
+		register_disk(gd,MKDEV(hwif->major,unit<<PARTN_BITS),
+#ifdef CONFIG_BLK_DEV_ISAPNP
+			(drive->forced_geom && drive->noprobe) ? 1 :
+#endif /* CONFIG_BLK_DEV_ISAPNP */
+			1<<PARTN_BITS, ide_fops,
+			current_capacity(drive));
 	}
 }
 
@@ -669,7 +680,7 @@
  * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it,
  * we set a timer to poll at 50ms intervals.
  */
-static ide_startstop_t do_reset1 (ide_drive_t *drive, int  do_not_try_atapi)
+static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
 {
 	unsigned int unit;
 	unsigned long flags;
@@ -1213,7 +1224,7 @@
  * the driver.  This makes the driver much more friendlier to shared IRQs
  * than previous designs, while remaining 100% (?) SMP safe and capable.
  */
-static void ide_do_request (ide_hwgroup_t *hwgroup)
+static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
 {
 	struct blk_dev_struct *bdev;
 	ide_drive_t	*drive;
@@ -1272,14 +1283,25 @@
 		drive->service_start = jiffies;
 
 		bdev = &blk_dev[hwif->major];
-		if( bdev->request_queue.plugged )	/* FIXME: paranoia */
+		if ( bdev->request_queue.plugged )	/* FIXME: paranoia */
 			printk("%s: Huh? nuking plugged queue\n", drive->name);
 		bdev->request_queue.current_request = hwgroup->rq = drive->queue.current_request;
+		/*
+		 * Some systems have trouble with IDE IRQs arriving while
+		 * the driver is still setting things up.  So, here we disable
+		 * the IRQ used by this interface while the request is being started.
+		 * This may look bad at first, but pretty much the same thing
+		 * happens anyway when any interrupt comes in, IDE or otherwise
+		 *  -- the kernel masks the IRQ while it is being handled.
+		 */
+		if (hwif->irq != masked_irq)
+			disable_irq_nosync(hwif->irq);
 		spin_unlock(&io_request_lock);
-		if (!hwif->serialized)	/* play it safe with buggy hardware */
-			ide__sti();
+		ide__sti();	/* allow other IRQs while we start this request */
 		startstop = start_request(drive);
 		spin_lock_irq(&io_request_lock);
+		if (hwif->irq != masked_irq)
+			enable_irq(hwif->irq);
 		if (startstop == ide_stopped)
 			hwgroup->busy = 0;
 	}
@@ -1297,69 +1319,69 @@
 
 void do_ide0_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[0].hwgroup);
+	ide_do_request (ide_hwifs[0].hwgroup, 0);
 }
 
 #if MAX_HWIFS > 1
 void do_ide1_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[1].hwgroup);
+	ide_do_request (ide_hwifs[1].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 1 */
 
 #if MAX_HWIFS > 2
 void do_ide2_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[2].hwgroup);
+	ide_do_request (ide_hwifs[2].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 2 */
 
 #if MAX_HWIFS > 3
 void do_ide3_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[3].hwgroup);
+	ide_do_request (ide_hwifs[3].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 3 */
 
 #if MAX_HWIFS > 4
 void do_ide4_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[4].hwgroup);
+	ide_do_request (ide_hwifs[4].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 4 */
 
 #if MAX_HWIFS > 5
 void do_ide5_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[5].hwgroup);
+	ide_do_request (ide_hwifs[5].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 5 */
 
 #if MAX_HWIFS > 6
 void do_ide6_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[6].hwgroup);
+	ide_do_request (ide_hwifs[6].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 6 */
 
 #if MAX_HWIFS > 7
 void do_ide7_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[7].hwgroup);
+	ide_do_request (ide_hwifs[7].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 7 */
 
 #if MAX_HWIFS > 8
 void do_ide8_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[8].hwgroup);
+	ide_do_request (ide_hwifs[8].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 8 */
 
 #if MAX_HWIFS > 9
 void do_ide9_request (request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[9].hwgroup);
+	ide_do_request (ide_hwifs[9].hwgroup, 0);
 }
 #endif /* MAX_HWIFS > 9 */
 
@@ -1445,7 +1467,7 @@
 				hwgroup->busy = 0;
 		}
 	}
-	ide_do_request(hwgroup);
+	ide_do_request(hwgroup, 0);
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 
@@ -1593,7 +1615,7 @@
 	if (startstop == ide_stopped) {
 		if (hwgroup->handler == NULL) {	/* paranoia */
 			hwgroup->busy = 0;
-			ide_do_request(hwgroup);
+			ide_do_request(hwgroup, hwif->irq);
 		} else {
 			printk("%s: ide_intr: huh? expected NULL handler on exit\n", drive->name);
 		}
@@ -1608,6 +1630,9 @@
 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) {
@@ -1616,7 +1641,11 @@
 			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;
@@ -1698,7 +1727,7 @@
 		rq->next = cur_rq->next;
 		cur_rq->next = rq;
 	}
-	ide_do_request(hwgroup);
+	ide_do_request(hwgroup, 0);
 	spin_unlock_irqrestore(&io_request_lock, flags);
 	if (action == ide_wait) {
 		down(&sem);			/* wait for it to be serviced */
@@ -1751,11 +1780,10 @@
 		drive->part[p].nr_sects   = 0;
 	};
 
-	drive->part[0].nr_sects = current_capacity(drive);
-	if ((drive->media != ide_disk && drive->media != ide_floppy) ||
-	     drive->driver == NULL || !drive->part[0].nr_sects)
-		drive->part[0].start_sect = -1;
-	resetup_one_dev(HWIF(drive)->gd, drive->select.b.unit);
+	grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
+			(drive->media != ide_disk &&
+			 drive->media != ide_floppy) ? 1 : 1<<PARTN_BITS,
+				current_capacity(drive));
 
 	drive->busy = 0;
 	wake_up(&drive->wqueue);
@@ -2677,6 +2705,7 @@
  *				for chipsets that are ATA-66 capable, but
  *				the ablity to bit test for detection is
  *				currently unknown.
+ * "ide=reverse"	: Formerly called to pci sub-system, but now local.
  *
  * "splitfifo=betweenChan"
  *			: FIFO Configuration of VIA 82c586(<nothing>,"A"or"B").
@@ -2727,6 +2756,14 @@
 	}
 #endif /* CONFIG_BLK_DEV_IDEDOUBLER */
 
+#ifdef CONFIG_BLK_DEV_IDEPCI
+	if (!strcmp(s, "ide=reverse")) {
+		ide_scan_direction = 1;
+		printk("ide: Enabled support for IDE inverse scan order.\n");
+		return 0;
+	}
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+
 	init_ide_data ();
 
 	/*
@@ -3060,7 +3097,7 @@
 	if (pci_present())
 	{
 #ifdef CONFIG_BLK_DEV_IDEPCI
-		ide_scan_pcibus();
+		ide_scan_pcibus(ide_scan_direction);
 #else
 #ifdef CONFIG_BLK_DEV_RZ1000
 		{
@@ -3366,7 +3403,6 @@
 EXPORT_SYMBOL(drive_is_flashcard);
 EXPORT_SYMBOL(ide_timer_expiry);
 EXPORT_SYMBOL(ide_intr);
-EXPORT_SYMBOL(ide_geninit);
 EXPORT_SYMBOL(ide_fops);
 EXPORT_SYMBOL(ide_get_queue);
 EXPORT_SYMBOL(do_ide0_request);
@@ -3448,6 +3484,7 @@
 int __init ide_init (void)
 {
 	static char banner_printed = 0;
+	int i;
 
 	if (!banner_printed) {
 		printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
@@ -3459,6 +3496,12 @@
 	initializing = 1;
 	ide_init_builtin_drivers();
 	initializing = 0;
+
+	for (i = 0; i < MAX_HWIFS; ++i) {
+		ide_hwif_t  *hwif = &ide_hwifs[i];
+		if (hwif->present)
+			ide_geninit(hwif);
+	}
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.3.39/linux/drivers/block/loop.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/loop.c	Tue Jan 18 18:54:21 2000
@@ -759,6 +759,8 @@
 	memset(loop_blksizes, 0, max_loop * sizeof(int));
 	blk_size[MAJOR_NR] = loop_sizes;
 	blksize_size[MAJOR_NR] = loop_blksizes;
+	for (i=0; i < max_loop; i++)
+		register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &lo_fops, 0);
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.3.39/linux/drivers/block/md.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/md.c	Tue Jan 18 18:54:21 2000
@@ -77,16 +77,12 @@
 
 int md_size[MAX_MD_DEV]={0, };
 
-static void md_geninit (struct gendisk *);
-
 static struct gendisk md_gendisk=
 {
   MD_MAJOR,
   "md",
   0,
   1,
-  MAX_MD_DEV,
-  md_geninit,
   md_hd_struct,
   md_size,
   MAX_MD_DEV,
@@ -909,22 +905,20 @@
 }
 #endif
 
-static void md_geninit (struct gendisk *gdisk)
+static void md_geninit (void)
 {
   int i;
   
+  blksize_size[MD_MAJOR] = md_blocksizes;
+  max_readahead[MD_MAJOR] = md_maxreadahead;
   for(i=0;i<MAX_MD_DEV;i++)
   {
     md_blocksizes[i] = 1024;
     md_maxreadahead[i] = MD_DEFAULT_DISK_READAHEAD;
-    md_gendisk.part[i].start_sect=-1; /* avoid partition check */
-    md_gendisk.part[i].nr_sects=0;
     md_dev[i].pers=NULL;
+    register_disk(&md_gendisk, MKDEV(MAJOR_NR,i), 1, &md_fops, 0);
   }
 
-  blksize_size[MD_MAJOR] = md_blocksizes;
-  max_readahead[MD_MAJOR] = md_maxreadahead;
-
 #ifdef CONFIG_PROC_FS
 	create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL);
 #endif
@@ -1265,6 +1259,7 @@
 #ifdef CONFIG_MD_RAID5
   raid5_init ();
 #endif
+  md_geninit();
   return (0);
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.3.39/linux/drivers/block/nbd.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/nbd.c	Tue Jan 18 18:54:21 2000
@@ -489,6 +489,8 @@
 		nbd_blksize_bits[i] = 10;
 		nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
 		nbd_sizes[i] = nbd_bytesizes[i] >> nbd_blksize_bits[i];
+		register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &nbd_fops,
+				nbd_bytesizes[i]>>9);
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.3.39/linux/drivers/block/paride/pd.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/paride/pd.c	Tue Jan 18 18:54:21 2000
@@ -263,7 +263,6 @@
 #ifdef MODULE
 void cleanup_module( void );
 #endif
-static void pd_geninit(struct gendisk *ignored);
 static int pd_open(struct inode *inode, struct file *file);
 static void do_pd_request(request_queue_t * q);
 static int pd_ioctl(struct inode *inode,struct file *file,
@@ -345,8 +344,6 @@
         PD_NAME,        /* Major name */
         PD_BITS,        /* Bits to shift to get real from partition */
         PD_PARTNS,      /* Number of partitions per real */
-        PD_UNITS,       /* maximum number of real */
-        pd_geninit,     /* init function */
         pd_hd,          /* hd struct */
         pd_sizes,       /* block sizes */
         0,              /* number */
@@ -401,26 +398,25 @@
 	pd_gendisk.major = major;
 	pd_gendisk.major_name = name;
 	pd_gendisk.next = gendisk_head;
-        gendisk_head = &pd_gendisk;
+	gendisk_head = &pd_gendisk;
 
-        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_blocksizes[i] = 1024;
+	blksize_size[MAJOR_NR] = pd_blocksizes;
 
-        printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
-                name,name,PD_VERSION,major,cluster,nice);
-	
-        return 0;
-}
-
-static void pd_geninit (struct gendisk *ignored)
-
-{	pd_init_units();
+	printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
+		name,name,PD_VERSION,major,cluster,nice);
+	pd_init_units();
+	pd_valid = 0;
 	pd_gendisk.nr_real = pd_detect();
+	pd_valid = 1;
 
 #ifdef MODULE
-        if (!pd_gendisk.nr_real) cleanup_module();
+        if (!pd_gendisk.nr_real) {
+		cleanup_module();
+		return -1;
+	}
 #endif
-
+        return 0;
 }
 
 static int pd_open (struct inode *inode, struct file *file)
@@ -502,8 +498,6 @@
 {       kdev_t devp;
 	int	unit;
 
-	struct super_block *sb;
-
         devp = inode->i_rdev;
 	unit = DEVICE_NR(devp);
 
@@ -566,8 +560,8 @@
                 pd_hd[minor].nr_sects = 0;
         }
 
-	pd_identify(unit);
-        resetup_one_dev(&pd_gendisk,unit);
+	if (pd_identify(unit))
+		grok_partitions(&pd_gendisk,unit,1<<PD_BITS,PD.capacity);
 
         pd_valid = 1;
         wake_up(&pd_wait_open);
@@ -590,20 +584,7 @@
          paride_init();
        } 
 #endif
-
-        err = pd_init();
-        if (err) return err;
-
-	pd_geninit(&pd_gendisk);
-
-        if (!pd_gendisk.nr_real)  return -1;
-
-        pd_valid = 0;
-	for (unit=0;unit<PD_UNITS;unit++) 
-          if (PD.present) resetup_one_dev(&pd_gendisk,unit);
-        pd_valid = 1;
-
-        return 0;
+        return pd_init();
 }
 
 void    cleanup_module(void)
@@ -815,21 +796,19 @@
 
         if (PD.capacity) pd_init_dev_parms(unit);
         if (!PD.standby) pd_standby_off(unit);
-
-	pd_hd[unit<<PD_BITS].nr_sects = PD.capacity;
-	pd_hd[unit<<PD_BITS].start_sect = 0;
 	
         return 1;
 }
 
 static int pd_probe_drive( int unit )
-
-{	if (PD.drive == -1) {
-	  for (PD.drive=0;PD.drive<=1;PD.drive++)
-	     if (pd_identify(unit)) return 1;
-	  return 0;
-	  }
-	else return pd_identify(unit);
+{
+	if (PD.drive == -1) {
+		for (PD.drive=0;PD.drive<=1;PD.drive++)
+			if (pd_identify(unit))
+				return 1;
+		return 0;
+	}
+	return pd_identify(unit);
 }
 
 static int pd_detect( void )
@@ -856,15 +835,18 @@
                         k = unit+1;
                 } else pi_release(PI);
             }
+	for (unit=0;unit<PD_UNITS;unit++)
+		register_disk(&pd_gendisk,MKDEV(MAJOR_NR,unit<<PD_BITS),
+				PD_PARTNS,&pd_fops,
+				PD.present?PD.capacity:0);
 
 /* We lie about the number of drives found, as the generic partition
    scanner assumes that the drives are numbered sequentially from 0.
    This can result in some bogus error messages if non-sequential
    drive numbers are used.
 */
-	
-	if (k) return k; 
-
+	if (k)
+		return k; 
         printk("%s: no valid drive found\n",name);
         return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- v2.3.39/linux/drivers/block/paride/pf.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/paride/pf.c	Tue Jan 18 18:54:21 2000
@@ -360,6 +360,8 @@
         
 	for (i=0;i<PF_UNITS;i++) pf_blocksizes[i] = 1024;
 	blksize_size[MAJOR_NR] = pf_blocksizes;
+	for (i=0;i<PF_UNITS;i++)
+		register_disk(NULL, MKDEV(MAJOR_NR, i), 1, &pf_fops, 0);
 
         return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/block/pdc202xx.c linux/drivers/block/pdc202xx.c
--- v2.3.39/linux/drivers/block/pdc202xx.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/pdc202xx.c	Fri Jan 14 00:50:53 2000
@@ -227,7 +227,7 @@
 	unsigned short		EP;
 	byte CLKSPD		= IN_BYTE(high_16 + 0x11);
 	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-	byte udma_66		= ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+	byte udma_66		= ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
 	byte udma_33		= ultra ? (inb(high_16 + 0x001f) & 1) : 0;
 
 	/*
@@ -661,8 +661,6 @@
 
 	if (hwif->dma_base) {
 		hwif->dmaproc = &pdc202xx_dmaproc;
-		hwif->drives[0].autotune = 0;
-		hwif->drives[1].autotune = 0;
 	} else {
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/piix.c linux/drivers/block/piix.c
--- v2.3.39/linux/drivers/block/piix.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/piix.c	Fri Jan 14 00:50:53 2000
@@ -200,7 +200,7 @@
 	int			u_speed;
 
 	byte maslave		= hwif->channel ? 0x42 : 0x40;
-	byte udma_66		= ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+	byte udma_66		= ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
 	int ultra		= ((dev->device == PCI_DEVICE_ID_INTEL_82371AB) ||
 				   (dev->device == PCI_DEVICE_ID_INTEL_82801AA_1)) ? 1 : 0;
 	int ultra66		= (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1) ? 1 :  0; 
diff -u --recursive --new-file v2.3.39/linux/drivers/block/ps2esdi.c linux/drivers/block/ps2esdi.c
--- v2.3.39/linux/drivers/block/ps2esdi.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/ps2esdi.c	Tue Jan 18 18:54:21 2000
@@ -68,7 +68,7 @@
 
 int ps2esdi_init(void);
 
-static void ps2esdi_geninit(struct gendisk *ignored);
+static void ps2esdi_geninit(void);
 
 static void do_ps2esdi_request(request_queue_t * q);
 
@@ -160,8 +160,6 @@
 	"ed",			/* Major name */
 	6,			/* Bits to shift to get real from partition */
 	1 << 6,			/* Number of partitions per real disk */
-	MAX_HD,			/* maximum number of real disks */
-	ps2esdi_geninit,	/* init function */
 	ps2esdi,		/* hd struct */
 	ps2esdi_sizes,		/* block sizes */
 	0,			/* number */
@@ -186,8 +184,8 @@
 	/* some minor housekeeping - setup the global gendisk structure */
 	ps2esdi_gendisk.next = gendisk_head;
 	gendisk_head = &ps2esdi_gendisk;
+	ps2esdi_geninit();
 	return 0;
-
 }				/* ps2esdi_init */
 
 #ifdef MODULE
@@ -291,7 +289,7 @@
 }
 
 /* ps2 esdi specific initialization - called thru the gendisk chain */
-static void __init ps2esdi_geninit(struct gendisk *ignored)
+static void __init ps2esdi_geninit(void)
 {
 	/*
 	   The first part contains the initialization code
@@ -414,21 +412,21 @@
 
 	ps2esdi_gendisk.nr_real = ps2esdi_drives;
 
-	for (i = 0; i < ps2esdi_drives; i++) {
-		ps2esdi[i << 6].nr_sects =
-		    ps2esdi_info[i].head *
-		    ps2esdi_info[i].sect *
-		    ps2esdi_info[i].cyl;
-		ps2esdi_valid[i] = 1;
-	}
 	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;
-}				/* ps2esdi_geninit */
 
+	for (i = 0; i < ps2esdi_drives; i++) {
+		register_disk(&ps2esdi_gendisk,MKDEV(MAJOR_NR,i<<6),1<<6,
+				&ps2esdi_fops,
+				ps2esdi_info[i].head * ps2esdi_info[i].sect *
+				ps2esdi_info[i].cyl);
+		ps2esdi_valid[i] = 1;
+	}
+}
 
 static void __init ps2esdi_get_device_cfg(void)
 {
@@ -1189,9 +1187,8 @@
 		ps2esdi_gendisk.part[start + partition].nr_sects = 0;
 	}
 
-	ps2esdi_gendisk.part[start].nr_sects = ps2esdi_info[target].head *
-		ps2esdi_info[target].cyl * ps2esdi_info[target].sect;
-	resetup_one_dev(&ps2esdi_gendisk, target);
+	grok_partitions(&ps2esdi_gendisk, target, 1<<6, 
+		ps2esdi_info[target].head * ps2esdi_info[target].cyl * ps2esdi_info[target].sect);
 
 	ps2esdi_valid[target] = 1;
 	wake_up(&ps2esdi_wait_open);
diff -u --recursive --new-file v2.3.39/linux/drivers/block/raid0.c linux/drivers/block/raid0.c
--- v2.3.39/linux/drivers/block/raid0.c	Fri May  8 00:17:13 1998
+++ linux/drivers/block/raid0.c	Thu Jan 20 10:44:46 2000
@@ -182,6 +182,12 @@
   block=*rsector >> 1;
   hash=data->hash_table+(block/data->smallest->size);
 
+  if (hash - data->hash_table > data->nr_zones) 
+  { 
+	  printk(KERN_DEBUG "raid0_map: invalid block %ul\n", block);
+	  return -1;
+  }
+
   /* Sanity check */
   if ((chunk_size*2)<(*rsector % (chunk_size*2))+size)
   {
diff -u --recursive --new-file v2.3.39/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.39/linux/drivers/block/rd.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/block/rd.c	Tue Jan 18 18:54:21 2000
@@ -429,6 +429,15 @@
 	blksize_size[MAJOR_NR] = rd_blocksizes;		/* Avoid set_blocksize() check */
 	blk_size[MAJOR_NR] = rd_kbsize;			/* Size of the RAM disk in kB  */
 
+	for (i = 0; i < NUM_RAMDISKS; i++)
+		register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &fd_fops, rd_size<<1);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* We ought to separate initrd operations here */
+	register_disk(NULL, MKDEV(MAJOR_NR,INITRD_MINOR), 1, &fd_fops, rd_size<<1);
+#endif
+
+		/* rd_size is given in kB */
 	printk("RAMDISK driver initialized: "
 	       "%d RAM disks of %dK size %d blocksize\n",
 	       NUM_RAMDISKS, rd_size, rd_blocksize);
diff -u --recursive --new-file v2.3.39/linux/drivers/block/sis5513.c linux/drivers/block/sis5513.c
--- v2.3.39/linux/drivers/block/sis5513.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/block/sis5513.c	Fri Jan 14 00:50:53 2000
@@ -222,7 +222,7 @@
 extern char *ide_xfer_verbose (byte xfer_rate);
 
 /*
- * ((id->word93 & 0x2000) && (HWIF(drive)->udma_four))
+ * ((id->hw_config & 0x2000) && (HWIF(drive)->udma_four))
  */
 static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
@@ -235,7 +235,7 @@
 
 	byte speed		= 0x00, unmask = 0xE0, four_two = 0x00;
 	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-	byte udma_66		= ((id->word93 & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+	byte udma_66		= ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
 
 	if (host_dev) {
 		switch(host_dev->device) {
@@ -472,6 +472,7 @@
 
 		host_dev = host;
 		printk(SiSHostChipInfo[i].name);
+		printk("\n");
 		if (SiSHostChipInfo[i].flags & SIS5513_FLAG_LATENCY) {
 			if (latency != 0x10)
 				pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x10);
diff -u --recursive --new-file v2.3.39/linux/drivers/block/via82cxxx.c linux/drivers/block/via82cxxx.c
--- v2.3.39/linux/drivers/block/via82cxxx.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/block/via82cxxx.c	Fri Jan 14 00:50:53 2000
@@ -546,8 +546,6 @@
 	hwif->tuneproc = &via82cxxx_tune_drive;
 	if (hwif->dma_base) {
 		hwif->dmaproc = &via82cxxx_dmaproc;
-		hwif->drives[0].autotune = 0;
-		hwif->drives[1].autotune = 0;
 	} else {
 		hwif->autodma = 0;
 		hwif->drives[0].autotune = 1;
diff -u --recursive --new-file v2.3.39/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.3.39/linux/drivers/block/xd.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/block/xd.c	Tue Jan 18 18:54:21 2000
@@ -135,12 +135,6 @@
 	"xd",		/* Major name */
 	6,		/* Bits to shift to get real from partition */
 	1 << 6,		/* Number of partitions per real */
-	XD_MAXDRIVES,	/* maximum number of real */
-#ifdef MODULE
-	NULL,		/* called from init_module */
-#else
-        xd_geninit,     /* init function */
-#endif
 	xd_struct,	/* hd struct */
 	xd_sizes,	/* block sizes */
 	0,		/* number */
@@ -181,6 +175,7 @@
 	read_ahead[MAJOR_NR] = 8;	/* 8 sector (4kB) read ahead */
 	xd_gendisk.next = gendisk_head;
 	gendisk_head = &xd_gendisk;
+	xd_geninit();
 
 	return 0;
 }
@@ -210,16 +205,21 @@
 
 /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */
 /* and set up the "raw" device entries in the table */
-static void __init xd_geninit (struct gendisk *ignored)
+static void __init xd_geninit (void)
 {
 	u_char i,controller;
 	unsigned int address;
 
+	for(i=0;i<(XD_MAXDRIVES << 6);i++) xd_blocksizes[i] = 1024;
+	blksize_size[MAJOR_NR] = xd_blocksizes;
+
 	if (xd_detect(&controller,&address)) {
 
-		printk("Detected a%s controller (type %d) at address %06x\n",xd_sigs[controller].name,controller,address);
+		printk("Detected a%s controller (type %d) at address %06x\n",
+			xd_sigs[controller].name,controller,address);
 		if (check_region(xd_iobase,4)) {
-			printk("xd: Ports at 0x%x are not available\n",xd_iobase);
+			printk("xd: Ports at 0x%x are not available\n",
+				xd_iobase);
 			return;
 		}
 		request_region(xd_iobase,4,"xd");
@@ -227,9 +227,12 @@
 			xd_sigs[controller].init_controller(address);
 		xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
 		
-		printk("Detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
+		printk("Detected %d hard drive%s (using IRQ%d & DMA%d)\n",
+			xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
 		for (i = 0; i < xd_drives; i++)
-			printk(" xd%c: CHS=%d/%d/%d\n",'a'+i,xd_info[i].cylinders,xd_info[i].heads,xd_info[i].sectors);
+			printk(" xd%c: CHS=%d/%d/%d\n",'a'+i,
+				xd_info[i].cylinders,xd_info[i].heads,
+				xd_info[i].sectors);
 
 	}
 	if (xd_drives) {
@@ -244,14 +247,14 @@
 	}
 
 	for (i = 0; i < xd_drives; i++) {
-		xd_struct[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors;
 		xd_valid[i] = 1;
+		register_disk(&xd_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6, &xd_fops,
+				xd_info[i].heads * xd_info[i].cylinders *
+				xd_info[i].sectors);
 	}
 
 	xd_gendisk.nr_real = xd_drives;
 
-	for(i=0;i<(XD_MAXDRIVES << 6);i++) xd_blocksizes[i] = 1024;
-	blksize_size[MAJOR_NR] = xd_blocksizes;
 }
 
 /* xd_open: open a device */
@@ -406,8 +409,8 @@
 		xd_gendisk.part[minor].nr_sects = 0;
 	};
 
-	xd_gendisk.part[start].nr_sects = xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors;
-	resetup_one_dev(&xd_gendisk,target);
+	grok_partitions(&xd_gendisk, target, 1<<6,
+			xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors);
 
 	xd_valid[target] = 1;
 	wake_up(&xd_wait_open);
@@ -1145,27 +1148,26 @@
 int init_module(void)
 {
 	int i,count = 0;
-	int error = xd_init();
-	if (!error)
-	{
-		printk(KERN_INFO "XD: Loaded as a module.\n");
-		for (i = 4; i > 0; i--)
-			if(((xd[i] = xd[i-1]) >= 0) && !count)
-				count = i;
-		if((xd[0] = count))
-			xd_setup(NULL, xd);
-		xd_geninit(&(struct gendisk) { 0,0,0,0,0,0,0,0,0,0,0 });
-		if (!xd_drives) {
-					/* no drives detected - unload module */
-			unregister_blkdev(MAJOR_NR, "xd");
-			xd_done();
-			return (-1);
-		}
-		for (i = 0; i < xd_drives; i++)
-			resetup_one_dev(&xd_gendisk, i);
+	int error;
+
+	for (i = 4; i > 0; i--)
+		if(((xd[i] = xd[i-1]) >= 0) && !count)
+			count = i;
+	if((xd[0] = count))
+		xd_setup(NULL, xd);
+
+	if (error = xd_init())
+		return error;
+
+	printk(KERN_INFO "XD: Loaded as a module.\n");
+	if (!xd_drives) {
+		/* no drives detected - unload module */
+		unregister_blkdev(MAJOR_NR, "xd");
+		xd_done();
+		return (-1);
 	}
         
-	return error;
+	return 0;
 }
 
 void cleanup_module(void)
diff -u --recursive --new-file v2.3.39/linux/drivers/block/xd.h linux/drivers/block/xd.h
--- v2.3.39/linux/drivers/block/xd.h	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/xd.h	Sun Jan 16 19:33:03 2000
@@ -109,7 +109,7 @@
 #endif /* MODULE */
 static u_char xd_detect (u_char *controller, unsigned int *address);
 static u_char xd_initdrives (void (*init_drive)(u_char drive));
-static void xd_geninit (struct gendisk *);
+static void xd_geninit (void);
 
 static int xd_open (struct inode *inode,struct file *file);
 static void do_xd_request (request_queue_t * q);
diff -u --recursive --new-file v2.3.39/linux/drivers/cdrom/aztcd.c linux/drivers/cdrom/aztcd.c
--- v2.3.39/linux/drivers/cdrom/aztcd.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/cdrom/aztcd.c	Tue Jan 18 18:54:21 2000
@@ -1796,6 +1796,7 @@
 	blksize_size[MAJOR_NR] = aztcd_blocksizes;
 #endif
 	read_ahead[MAJOR_NR] = 4;
+	register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &azt_fops, 0);
 
         if ((azt_port==0x1f0)||(azt_port==0x170))  
 	   request_region(azt_port, 8, "aztcd");  /*IDE-interface*/
diff -u --recursive --new-file v2.3.39/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.3.39/linux/drivers/cdrom/cdrom.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/cdrom/cdrom.c	Tue Jan 18 18:54:21 2000
@@ -353,6 +353,8 @@
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
 	cdi->next = topCdromPtr; 	
 	topCdromPtr = cdi;
+	/*FIXME:as soon as we'll switch to real thing, pass device number here*/
+	register_disk(NULL, cdi->dev, 1, &cdrom_fops, 0);
 	return 0;
 }
 #undef ENSURE
@@ -380,6 +382,7 @@
 		prev->next = cdi->next;
 	else
 		topCdromPtr = cdi->next;
+/*	unregister_disk();	*/
 	cdi->ops->n_minors--;
 	cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
 	return 0;
diff -u --recursive --new-file v2.3.39/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c
--- v2.3.39/linux/drivers/cdrom/gscd.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/cdrom/gscd.c	Tue Jan 18 18:54:21 2000
@@ -1082,6 +1082,7 @@
         gscdPresent = 1;
 
 	request_region(gscd_port, 4, "gscd");
+	register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &gscd_fops, 0);
 
         printk (KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n" );
 	return 0;
diff -u --recursive --new-file v2.3.39/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v2.3.39/linux/drivers/cdrom/optcd.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/cdrom/optcd.c	Tue Jan 18 18:54:21 2000
@@ -2072,6 +2072,7 @@
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
 	read_ahead[MAJOR_NR] = 4;
 	request_region(optcd_port, 4, "optcd");
+	register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &opt_fops, 0);
 
 	printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
 	return 0;
diff -u --recursive --new-file v2.3.39/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.3.39/linux/drivers/cdrom/sjcd.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/cdrom/sjcd.c	Tue Jan 18 18:54:21 2000
@@ -1478,6 +1478,7 @@
   
   blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
   read_ahead[ MAJOR_NR ] = 4;
+  register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &sjcd_fops, 0);
   
   if( check_region( sjcd_base, 4 ) ){
     printk( "SJCD: Init failed, I/O port (%X) is already in use\n",
diff -u --recursive --new-file v2.3.39/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.3.39/linux/drivers/cdrom/sonycd535.c	Tue Jan 11 22:31:39 2000
+++ linux/drivers/cdrom/sonycd535.c	Tue Jan 18 18:54:21 2000
@@ -798,9 +798,6 @@
 	Byte status[2];
 	Byte cmd[2];
 
-	if (!sony_inuse) {
-		cdu_open(NULL, NULL);
-	}
 	while (1) {
 		/*
 		 * The beginning here is stolen from the hard disk driver.  I hope
@@ -1396,7 +1393,6 @@
 {
 	Byte status[2], cmd_buff[2];
 
-
 	if (sony_inuse)
 		return -EBUSY;
 	if (check_drive_status() != 0)
@@ -1638,6 +1634,7 @@
 		return -EIO;
 	}
 	request_region(sony535_cd_base_io, 4, CDU535_HANDLE);
+	register_disk(NULL, MKDEV(MAJOR_NR,0), 1, &cdu_fops, 0);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.3.39/linux/drivers/char/Config.in	Tue Jan  4 13:57:16 2000
+++ linux/drivers/char/Config.in	Thu Jan 20 10:44:46 2000
@@ -22,33 +22,35 @@
 fi
 bool 'Non-standard serial port support' CONFIG_SERIAL_NONSTANDARD
 if [ "$CONFIG_SERIAL_NONSTANDARD" = "y" ]; then
+   tristate '  Computone IntelliPort Plus serial support' CONFIG_COMPUTONE
    tristate '  Comtrol Rocketport support' CONFIG_ROCKETPORT
-   tristate '  Digiboard Intelligent Async Support' CONFIG_DIGIEPCA
-   if [ "$CONFIG_DIGIEPCA" = "n" ]; then
-      tristate '  Digiboard PC/Xx Support' CONFIG_DIGI
-   fi
    tristate '  Cyclades async mux support' CONFIG_CYCLADES
    if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_CYCLADES" != "n" ]; then
       bool '    Cyclades-Z interrupt mode operation (EXPERIMENTAL)' CONFIG_CYZ_INTR
    fi
-   bool '  Stallion multiport serial support' CONFIG_STALDRV
-   if [ "$CONFIG_STALDRV" = "y" ]; then
-     tristate '    Stallion EasyIO or EC8/32 support' CONFIG_STALLION
-     tristate '    Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
+   tristate '  Digiboard Intelligent Async Support' CONFIG_DIGIEPCA
+   if [ "$CONFIG_DIGIEPCA" = "n" ]; then
+      tristate '  Digiboard PC/Xx Support' CONFIG_DIGI
+   fi
+   tristate '  Hayes ESP serial port support' CONFIG_ESPSERIAL
+   tristate 'Moxa Intellio support' CONFIG_MOXA_INTELLIO
+   tristate 'Moxa SmartIO support' CONFIG_MOXA_SMARTIO
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      dep_tristate '  Multi-Tech multiport card support (EXPERIMENTAL)' CONFIG_ISI m
    fi
+   dep_tristate '  Microgate SyncLink card support' CONFIG_SYNCLINK m
+   dep_tristate '  HDLC line discipline support' CONFIG_N_HDLC m
    tristate '  SDL RISCom/8 card support' CONFIG_RISCOM8
-   tristate '  Computone IntelliPort Plus serial support' CONFIG_COMPUTONE
    tristate '  Specialix IO8+ card support' CONFIG_SPECIALIX
    if [ "$CONFIG_SPECIALIX" != "n" ]; then
       bool '  Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
    fi 
    tristate '  Specialix SX (and SI) card support' CONFIG_SX
-   tristate '  Hayes ESP serial port support' CONFIG_ESPSERIAL
-   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      dep_tristate '  Multi-Tech multiport card support (EXPERIMENTAL)' CONFIG_ISI m
+   bool '  Stallion multiport serial support' CONFIG_STALDRV
+   if [ "$CONFIG_STALDRV" = "y" ]; then
+     tristate '    Stallion EasyIO or EC8/32 support' CONFIG_STALLION
+     tristate '    Stallion EC8/64, ONboard, Brumby support' CONFIG_ISTALLION
    fi
-   dep_tristate '  Microgate SyncLink card support' CONFIG_SYNCLINK m
-   dep_tristate '  HDLC line discipline support' CONFIG_N_HDLC m
 fi
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
@@ -216,7 +218,7 @@
   dep_tristate '  3dlabs GMX 2000' CONFIG_DRM_GAMMA m
 fi
 
-if [ "$CONFIG_PCMCIA" != "n" ]; then
+if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
    source drivers/char/pcmcia/Config.in
 fi
 
diff -u --recursive --new-file v2.3.39/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.3.39/linux/drivers/char/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/drivers/char/Makefile	Thu Jan 20 10:44:46 2000
@@ -95,6 +95,22 @@
   endif
 endif
 
+ifeq ($(CONFIG_MOXA_SMARTIO),y)
+L_OBJS += mxser.o
+else
+  ifeq ($(CONFIG_MOXA_SMARTIO),m)
+  M_OBJS += mxser.o
+  endif
+endif
+
+ifeq ($(CONFIG_MOXA_INTELLIO),y)
+L_OBJS += moxa.o
+else
+  ifeq ($(CONFIG_MOXA_INTELLIO),m)
+  M_OBJS += moxa.o
+  endif
+endif
+
 ifeq ($(CONFIG_DIGI),y)
 O_OBJS += pcxx.o
 else
diff -u --recursive --new-file v2.3.39/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- v2.3.39/linux/drivers/char/acquirewdt.c	Tue Jul  6 19:16:55 1999
+++ linux/drivers/char/acquirewdt.c	Thu Jan 20 10:44:46 2000
@@ -219,7 +219,7 @@
 	misc_register(&acq_miscdev);
 	request_region(WDT_STOP, 1, "Acquire WDT");
 	request_region(WDT_START, 1, "Acquire WDT");
-	unregister_reboot_notifier(&acq_notifier);
+	register_reboot_notifier(&acq_notifier);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.3.39/linux/drivers/char/cyclades.c	Sun Nov  7 16:37:34 1999
+++ linux/drivers/char/cyclades.c	Mon Jan 17 22:19:08 2000
@@ -1,7 +1,7 @@
 #undef	BLOCKMOVE
 #define	Z_WAKE
 static char rcsid[] =
-"$Revision: 2.3.2.2 $$Date: 1999/10/01 11:27:43 $";
+"$Revision: 2.3.2.4 $$Date: 2000/01/17 09:19:40 $";
 
 /*
  *  linux/drivers/char/cyclades.c
@@ -9,8 +9,9 @@
  * This file contains the driver for the Cyclades Cyclom-Y multiport
  * serial boards.
  *
- * Initially written by Randolph Bentson (bentson@grieg.seaslug.org).
- * Maintained by Ivan Passos (ivan@cyclades.com).
+ * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
+ * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
+ * Currently maintained by Ivan Passos <ivan@cyclades.com>.
  *
  * For Technical support and installation problems, please send e-mail
  * to support@cyclades.com.
@@ -30,10 +31,21 @@
  *   void cleanup_module(void);
  *
  * $Log: cyclades.c,v $
+ * Revision 2.3.2.4   2000/01/17 09:19:40 ivan
+ * Fixed SMP locking in Cyclom-Y interrupt handler.
+ *
+ * Revision 2.3.2.3   1999/12/28 12:11:39 ivan
+ * Added a new cyclades_card field called nports to allow the driver to
+ * know the exact number of ports found by the Z firmware after its load;
+ * RX buffer contention prevention logic on interrupt op mode revisited
+ * (Cyclades-Z only);
+ * Revisited printk's for Z debug;
+ * Driver now makes sure that the constant SERIAL_XMIT_SIZE is defined;
+ *
  * Revision 2.3.2.2   1999/10/01 11:27:43 ivan
- * Fixed bug in cyz_poll that would make all ports but port 0
+ * Fixed bug in cyz_poll that would make all ports but port 0 
  * unable to transmit/receive data (Cyclades-Z only);
- * Implemented logic to prevent the RX buffer from being stuck with
+ * Implemented logic to prevent the RX buffer from being stuck with data
  * due to a driver / firmware race condition in interrupt op mode
  * (Cyclades-Z only);
  * Fixed bug in block_til_ready logic that would lead to a system crash;
@@ -598,25 +610,6 @@
 
 #define cy_min(a,b) (((a)<(b))?(a):(b))
 
-#if 0
-/******** 
- * For the next two macros, it is assumed that the buffer size is a 
- * power of 2 
- ********/
-
-#define CHARS_IN_BUF(buf_ctrl) \
-    ((cy_readl(&buf_ctrl->rx_put) - \
-      cy_readl(&buf_ctrl->rx_get) + \
-      cy_readl(&buf_ctrl->rx_bufsize)) & \
-		  (cy_readl(&buf_ctrl->rx_bufsize) - 1))
-
-#define SPACE_IN_BUF(buf_ctrl) \
-    ((cy_readl(&buf_ctrl->tx_get) - \
-      cy_readl(&buf_ctrl->tx_put) + \
-      cy_readl(&buf_ctrl->tx_bufsize) - 1) & \
-		  (cy_readl(&buf_ctrl->tx_bufsize) - 1))
-#endif
-
 /*
  * Include section 
  */
@@ -997,10 +990,12 @@
     }
 #ifdef CONFIG_CYZ_INTR
     if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event)) {
-	cyz_rx_full_timer[info->line].expires = jiffies + 1;
-	cyz_rx_full_timer[info->line].function = cyz_rx_restart;
-	cyz_rx_full_timer[info->line].data = (unsigned long)info;
-	add_timer(&cyz_rx_full_timer[info->line]);
+	if (cyz_rx_full_timer[info->line].function == NULL) {
+	    cyz_rx_full_timer[info->line].expires = jiffies + 1;
+	    cyz_rx_full_timer[info->line].function = cyz_rx_restart;
+	    cyz_rx_full_timer[info->line].data = (unsigned long)info;
+	    add_timer(&cyz_rx_full_timer[info->line]);
+	}
     }
 #endif
     if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event)) {
@@ -1172,7 +1167,6 @@
                     info->last_active = jiffies;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
-		    spin_unlock(&cinfo->card_lock);
 
                     /* if there is nowhere to put the data, discard it */
                     if(info->tty == 0){
@@ -1301,7 +1295,6 @@
                         queue_task(&tty->flip.tqueue, &tq_timer);
                     }
                     /* end of service */
-		    spin_lock(&cinfo->card_lock);
                     cy_writeb((u_long)base_addr+(CyRIR<<index), (save_xir & 0x3f));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));
 		    spin_unlock(&cinfo->card_lock);
@@ -1323,23 +1316,18 @@
                     i = channel + chip * 4 + cinfo->first_line;
                     save_car = cy_readb(base_addr+(CyCAR<<index));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), save_xir);
-		    spin_unlock(&cinfo->card_lock);
 
                     /* validate the port# (as configured and open) */
                     if( (i < 0) || (NR_PORTS <= i) ){
-			spin_lock(&cinfo->card_lock);
                         cy_writeb((u_long)base_addr+(CySRER<<index),
                              cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
-			spin_unlock(&cinfo->card_lock);
                         goto txend;
                     }
                     info = &cy_port[i];
                     info->last_active = jiffies;
                     if(info->tty == 0){
-			spin_lock(&cinfo->card_lock);
                         cy_writeb((u_long)base_addr+(CySRER<<index),
                              cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
-			spin_unlock(&cinfo->card_lock);
                         goto txdone;
                     }
 
@@ -1371,27 +1359,21 @@
 
                     while (char_count-- > 0){
 			if (!info->xmit_cnt){
-			    spin_lock(&cinfo->card_lock);
                             cy_writeb((u_long)base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxMpty);
-			    spin_unlock(&cinfo->card_lock);
 			    goto txdone;
 			}
 			if (info->xmit_buf == 0){
-			    spin_lock(&cinfo->card_lock);
                             cy_writeb((u_long)base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxMpty);
-			    spin_unlock(&cinfo->card_lock);
                             goto txdone;
 			}
 			if (info->tty->stopped || info->tty->hw_stopped){
-			    spin_lock(&cinfo->card_lock);
                             cy_writeb((u_long)base_addr+(CySRER<<index),
 				cy_readb(base_addr+(CySRER<<index)) & 
 					~CyTxMpty);
-			    spin_unlock(&cinfo->card_lock);
                             goto txdone;
 			}
                         /* Because the Embedded Transmit Commands have
@@ -1433,7 +1415,6 @@
                     }
         txend:
                     /* end of service */
-		    spin_lock(&cinfo->card_lock);
                     cy_writeb((u_long)base_addr+(CyTIR<<index), 
 			      (save_xir & 0x3f));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), (save_car));
@@ -1454,7 +1435,6 @@
 
                     mdm_change = cy_readb(base_addr+(CyMISR<<index));
                     mdm_status = cy_readb(base_addr+(CyMSVR1<<index));
-		    spin_unlock(&cinfo->card_lock);
 
                     if(info->tty == 0){/* no place for data, ignore it*/
                         ;
@@ -1489,11 +1469,9 @@
                                     /* cy_start isn't used
 				         because... !!! */
                                     info->tty->hw_stopped = 0;
-				  spin_lock(&cinfo->card_lock);
                                   cy_writeb((u_long)base_addr+(CySRER<<index),
                                        cy_readb(base_addr+(CySRER<<index)) | 
                                        CyTxMpty);
-				  spin_unlock(&cinfo->card_lock);
                                     cy_sched_event(info,
 				        Cy_EVENT_WRITE_WAKEUP);
                                 }
@@ -1502,11 +1480,9 @@
                                     /* cy_stop isn't used
 				         because ... !!! */
                                     info->tty->hw_stopped = 1;
-				  spin_lock(&cinfo->card_lock);
                                   cy_writeb((u_long)base_addr+(CySRER<<index),
                                        cy_readb(base_addr+(CySRER<<index)) & 
                                        ~CyTxMpty);
-				  spin_unlock(&cinfo->card_lock);
                                 }
                             }
                         }
@@ -1516,7 +1492,6 @@
                         }
                     }
                     /* end of service */
-		    spin_lock(&cinfo->card_lock);
                     cy_writeb((u_long)base_addr+(CyMIR<<index), 
 			      (save_xir & 0x3f));
                     cy_writeb((u_long)base_addr+(CyCAR<<index), save_car);
@@ -1538,7 +1513,6 @@
 /******** Start of block of Cyclades-Z specific code *********/
 /***********************************************************/
 
-
 static int
 cyz_fetch_msg( struct cyclades_card *cinfo,
 	    uclong *channel, ucchar *cmd, uclong *param)
@@ -1592,7 +1566,7 @@
                                (cinfo->ctl_addr))->pci_doorbell);
     while( (cy_readl(pci_doorbell) & 0xff) != 0){
         if (index++ == 1000){
-            return(-1);
+	    return((int)(cy_readl(pci_doorbell) & 0xff));
         }
 	udelay(50L);
     }
@@ -1604,7 +1578,8 @@
 } /* cyz_issue_cmd */
 
 static void
-cyz_handle_rx(struct cyclades_port *info, volatile struct BUF_CTRL *buf_ctrl)
+cyz_handle_rx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
+	      volatile struct BUF_CTRL *buf_ctrl)
 {
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
@@ -1614,14 +1589,12 @@
 #else
   char data;
 #endif
-  volatile uclong rx_put, rx_get, rx_bufsize;
-
-/* Removed due to compilation problems in Alpha systems */
-//    if ((char_count = CHARS_IN_BUF(buf_ctrl))){
+  volatile uclong rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
 
-    rx_get = cy_readl(&buf_ctrl->rx_get);
+    rx_get = new_rx_get = cy_readl(&buf_ctrl->rx_get);
     rx_put = cy_readl(&buf_ctrl->rx_put);
     rx_bufsize = cy_readl(&buf_ctrl->rx_bufsize);
+    rx_bufaddr = cy_readl(&buf_ctrl->rx_bufaddr);
     if (rx_put >= rx_get)
 	char_count = rx_put - rx_get;
     else
@@ -1640,7 +1613,7 @@
 #endif
 	if(tty == 0){
 	    /* flush received characters */
-	    rx_get = (rx_get + char_count) & (rx_bufsize - 1);
+	    new_rx_get = (new_rx_get + char_count) & (rx_bufsize - 1);
 	    info->rflush_count++;
 	}else{
 #ifdef BLOCKMOVE
@@ -1648,19 +1621,18 @@
 	       for performance, but because of buffer boundaries, there
 	       may be several steps to the operation */
 	    while(0 < (small_count = 
-		       cy_min((rx_bufsize - rx_get),
+		       cy_min((rx_bufsize - new_rx_get),
 		       cy_min((TTY_FLIPBUF_SIZE - tty->flip.count), char_count))
 		 )) {
 		memcpy_fromio(tty->flip.char_buf_ptr,
 			      (char *)(cinfo->base_addr
-				       + cy_readl(&buf_ctrl->rx_bufaddr)
-				       + rx_get),
+				       + rx_bufaddr + new_rx_get),
 			      small_count);
 
 		tty->flip.char_buf_ptr += small_count;
 		memset(tty->flip.flag_buf_ptr, TTY_NORMAL, small_count);
 		tty->flip.flag_buf_ptr += small_count;
-		rx_get = (rx_get + small_count) & (rx_bufsize - 1);
+		new_rx_get = (new_rx_get + small_count) & (rx_bufsize - 1);
 		char_count -= small_count;
 		info->icount.rx += small_count;
 		info->idle_stats.recv_bytes += small_count;
@@ -1669,14 +1641,10 @@
 #else
 	    while(char_count--){
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE){
-#ifdef CONFIG_CYZ_INTR
-		    cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
-#endif
 		    break;
 		}
-		data = cy_readb(cinfo->base_addr +
-			cy_readl(&buf_ctrl->rx_bufaddr) + rx_get);
-		rx_get = (rx_get + 1) & (rx_bufsize - 1);
+		data = cy_readb(cinfo->base_addr + rx_bufaddr + new_rx_get);
+		new_rx_get = (new_rx_get + 1) & (rx_bufsize - 1);
 		tty->flip.count++;
 		*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 		*tty->flip.char_buf_ptr++ = data;
@@ -1684,16 +1652,29 @@
 		info->icount.rx++;
 	    }
 #endif
+#ifdef CONFIG_CYZ_INTR
+	    /* Recalculate the number of chars in the RX buffer and issue
+	       a cmd in case it's higher than the RX high water mark */
+	    rx_put = cy_readl(&buf_ctrl->rx_put);
+	    if (rx_put >= rx_get)
+		char_count = rx_put - rx_get;
+	    else
+		char_count = rx_put - rx_get + rx_bufsize;
+	    if(char_count >= cy_readl(&buf_ctrl->rx_threshold)) {
+		cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
+	    }
+#endif
 	    info->idle_stats.recv_idle = jiffies;
 	    queue_task(&tty->flip.tqueue, &tq_timer);
 	}
 	/* Update rx_get */
-	cy_writel(&buf_ctrl->rx_get, rx_get);
+	cy_writel(&buf_ctrl->rx_get, new_rx_get);
     }
 }
 
 static void
-cyz_handle_tx(struct cyclades_port *info, volatile struct BUF_CTRL *buf_ctrl)
+cyz_handle_tx(struct cyclades_port *info, volatile struct CH_CTRL *ch_ctrl,
+	      volatile struct BUF_CTRL *buf_ctrl)
 {
   struct cyclades_card *cinfo = &cy_card[info->card];
   struct tty_struct *tty = info->tty;
@@ -1702,14 +1683,15 @@
 #ifdef BLOCKMOVE
   int small_count;
 #endif
-  volatile uclong tx_put, tx_get, tx_bufsize;
+  volatile uclong tx_put, tx_get, tx_bufsize, tx_bufaddr;
 
-/* Removed due to compilation problems in Alpha systems */
-//    if ((char_count = SPACE_IN_BUF(buf_ctrl))){
+    if (info->xmit_cnt <= 0)	/* Nothing to transmit */
+	return;
 
     tx_get = cy_readl(&buf_ctrl->tx_get);
     tx_put = cy_readl(&buf_ctrl->tx_put);
     tx_bufsize = cy_readl(&buf_ctrl->tx_bufsize);
+    tx_bufaddr = cy_readl(&buf_ctrl->tx_bufaddr);
     if (tx_put >= tx_get)
 	char_count = tx_get - tx_put - 1 + tx_bufsize;
     else
@@ -1724,8 +1706,7 @@
 	if(info->x_char) { /* send special char */
 	    data = info->x_char;
 
-	    cy_writeb((cinfo->base_addr + 
-		cy_readl(&buf_ctrl->tx_bufaddr) + tx_put), data);
+	    cy_writeb((cinfo->base_addr + tx_bufaddr + tx_put), data);
 	    tx_put = (tx_put + 1) & (tx_bufsize - 1);
 	    info->x_char = 0;
 	    char_count--;
@@ -1739,8 +1720,7 @@
 		   cy_min ((SERIAL_XMIT_SIZE - info->xmit_tail),
 			cy_min(info->xmit_cnt, char_count))))){
 
-	    memcpy_toio((char *)(cinfo->base_addr
-				 + cy_readl(&buf_ctrl->tx_bufaddr) + tx_put),
+	    memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr + tx_put),
 			&info->xmit_buf[info->xmit_tail],
 			small_count);
 
@@ -1759,8 +1739,7 @@
 	    info->xmit_cnt--;
 	    info->xmit_tail = (info->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
 
-	    cy_writeb(cinfo->base_addr + 
-		cy_readl(&buf_ctrl->tx_bufaddr) + tx_put, data);
+	    cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
 	    tx_put = (tx_put + 1) & (tx_bufsize - 1);
 	    char_count--;
 	    info->icount.tx++;
@@ -1801,6 +1780,11 @@
     fw_ver = cy_readl(&board_ctrl->fw_version);
     hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0);
 
+#ifdef CONFIG_CYZ_INTR
+    if (!cinfo->nports)
+	cinfo->nports = (int) cy_readl(&board_ctrl->n_channel);
+#endif
+
     while(cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
 	special_count = 0;
 	delta_count = 0;
@@ -1873,7 +1857,7 @@
 		printk("cyz_interrupt: rcvd intr, card %d, port %ld\n\r", 
 			info->card, channel);
 #endif
-		cyz_handle_rx(info, buf_ctrl);
+		cyz_handle_rx(info, ch_ctrl, buf_ctrl);
 		break;
 	    case C_CM_TXBEMPTY:
 	    case C_CM_TXLOWWM:
@@ -1883,7 +1867,7 @@
 		printk("cyz_interrupt: xmit intr, card %d, port %ld\n\r", 
 			info->card, channel);
 #endif
-		cyz_handle_tx(info, buf_ctrl);
+		cyz_handle_tx(info, ch_ctrl, buf_ctrl);
 		break;
 #endif /* CONFIG_CYZ_INTR */
 	    case C_CM_FATAL:
@@ -1932,12 +1916,16 @@
     int retval;
     int card = info->card;
     uclong channel = (info->line) - (cy_card[card].first_line);
+    unsigned long flags;
 
-    cyz_rx_full_timer[info->card].expires = jiffies + HZ;
+    CY_LOCK(info, flags);
     retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK2, 0L);
     if (retval != 0){
-	printk("cyc:cyz_rx_restart retval was %x\n", retval);
+	printk("cyc:cyz_rx_restart retval on ttyC%d was %x\n", 
+	       info->line, retval);
     }
+    cyz_rx_full_timer[info->line].function = NULL;
+    CY_UNLOCK(info, flags);
 }
 
 #else /* CONFIG_CYZ_INTR */
@@ -1962,27 +1950,28 @@
 	if (!IS_CYC_Z(*cinfo)) continue;
 	if (!ISZLOADED(*cinfo)) continue;
 
+	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
+	zfw_ctrl = (struct ZFW_CTRL *)
+		   (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
+	board_ctrl = &(zfw_ctrl->board_ctrl);
+
 	/* Skip first polling cycle to avoid racing conditions with the FW */
 	if (!cinfo->intr_enabled) {
+	    cinfo->nports = (int) cy_readl(&board_ctrl->n_channel);
 	    cinfo->intr_enabled = 1;
 	    continue;
 	}
 
-	firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS);
-	zfw_ctrl = (struct ZFW_CTRL *)
-		   (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr));
-	board_ctrl = &(zfw_ctrl->board_ctrl);
-
 	cyz_handle_cmd(cinfo);
 
-	for (port = 0; port < cy_readl(&board_ctrl->n_channel); port++){
+	for (port = 0 ; port < cinfo->nports ; port++) {
 	    info = &cy_port[ port + cinfo->first_line ];
             tty = info->tty;
 	    ch_ctrl = &(zfw_ctrl->ch_ctrl[port]);
 	    buf_ctrl = &(zfw_ctrl->buf_ctrl[port]);
 
-	    cyz_handle_rx(info, buf_ctrl);
-	    cyz_handle_tx(info, buf_ctrl);
+	    cyz_handle_rx(info, ch_ctrl, buf_ctrl);
+	    cyz_handle_tx(info, ch_ctrl, buf_ctrl);
 	}
 	/* poll every 'cyz_polling_cycle' period */
 	cyz_timerlist.expires = jiffies + cyz_polling_cycle;
@@ -2141,13 +2130,15 @@
 
 	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
 	if (retval != 0){
-	    printk("cyc:startup(1) retval was %x\n", retval);
+	    printk("cyc:startup(1) retval on ttyC%d was %x\n",
+		   info->line, retval);
 	}
 
 	/* Flush RX buffers before raising DTR and RTS */
 	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_RX, 0L);
 	if (retval != 0){
-	    printk("cyc:startup(2) retval was %x\n", retval);
+	    printk("cyc:startup(2) retval on ttyC%d was %x\n",
+		   info->line, retval);
 	}
 
 	/* set timeout !!! */
@@ -2157,7 +2148,8 @@
 	retval = cyz_issue_cmd(&cy_card[info->card],
 	    channel, C_CM_IOCTLM, 0L);
 	if (retval != 0){
-	    printk("cyc:startup(3) retval was %x\n", retval);
+	    printk("cyc:startup(3) retval on ttyC%d was %x\n",
+		   info->line, retval);
 	}
 #ifdef CY_DEBUG_DTR
 	    printk("cyc:startup raising Z DTR\n");
@@ -2219,7 +2211,8 @@
 	CY_LOCK(info, flags);
 	    retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_INTBACK, 0L);
 	    if (retval != 0){
-		printk("cyc:start_xmit retval was %x\n", retval);
+		printk("cyc:start_xmit retval on ttyC%d was %x\n",
+		       info->line, retval);
 	    }
 	CY_UNLOCK(info, flags);
 #else /* CONFIG_CYZ_INTR */
@@ -2329,7 +2322,8 @@
 		retval = cyz_issue_cmd(&cy_card[info->card],
 			channel, C_CM_IOCTLM, 0L);
 		if (retval != 0){
-		    printk("cyc:shutdown retval was %x\n", retval);
+		    printk("cyc:shutdown retval on ttyC%d was %x\n",
+			   info->line, retval);
 		}
 #ifdef CY_DEBUG_DTR
 		printk("cyc:shutdown dropping Z DTR\n");
@@ -2513,16 +2507,21 @@
 	ch_ctrl = zfw_ctrl->ch_ctrl;
 
 	while (1) {
-	    cy_writel(&ch_ctrl[channel].rs_control,
-               cy_readl(&ch_ctrl[channel].rs_control) | C_RS_RTS | C_RS_DTR);
-	    retval = cyz_issue_cmd(&cy_card[info->card],
-		    channel, C_CM_IOCTLM, 0L);
-	    if (retval != 0){
-		printk("cyc:block_til_ready retval was %x\n", retval);
-	    }
+	    if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		(tty->termios->c_cflag & CBAUD)){
+		cy_writel(&ch_ctrl[channel].rs_control,
+			cy_readl(&ch_ctrl[channel].rs_control) |
+			(C_RS_RTS | C_RS_DTR));
+		retval = cyz_issue_cmd(&cy_card[info->card],
+				       channel, C_CM_IOCTLM, 0L);
+		if (retval != 0){
+		    printk("cyc:block_til_ready retval on ttyC%d was %x\n",
+			   info->line, retval);
+		}
 #ifdef CY_DEBUG_DTR
-		    printk("cyc:block_til_ready raising Z DTR\n");
+		printk("cyc:block_til_ready raising Z DTR\n");
 #endif
+	    }
 
 	    set_current_state(TASK_INTERRUPTIBLE);
 	    if (tty_hung_up_p(filp)
@@ -2894,7 +2893,8 @@
 	    retval = cyz_issue_cmd(&cy_card[info->card], channel, 
 				   C_CM_IOCTLW, 0L);
 	    if (retval != 0){
-		printk("cyc:cy_close retval was %x\n", retval);
+		printk("cyc:cy_close retval on ttyC%d was %x\n",
+		       info->line, retval);
 	    }
 	    CY_UNLOCK(info, flags);
 	    interruptible_sleep_on(&info->shutdown_wait);
@@ -3501,8 +3501,8 @@
 
 	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_IOCTL, 0L);
 	if (retval != 0){
-	    printk("cyc:set_line_char retval at %d was %x\n",
-	        __LINE__, retval);
+	    printk("cyc:set_line_char retval on ttyC%d was %x\n",
+		   info->line, retval);
 	}
 
 	/* CD sensitivity */
@@ -3528,8 +3528,8 @@
 
 	retval = cyz_issue_cmd( &cy_card[card], channel, C_CM_IOCTLM, 0L);
 	if (retval != 0){
-	    printk("cyc:set_line_char retval at %d was %x\n",
-	        __LINE__, retval);
+	    printk("cyc:set_line_char(2) retval on ttyC%d was %x\n",
+		   info->line, retval);
 	}
 
 	if (info->tty){
@@ -3905,8 +3905,8 @@
         retval = cyz_issue_cmd(&cy_card[info->card],
 				    channel, C_CM_IOCTLM,0L);
 	if (retval != 0){
-	    printk("cyc:set_modem_info retval at %d was %x\n",
-	        __LINE__, retval);
+	    printk("cyc:set_modem_info retval on ttyC%d was %x\n",
+		   info->line, retval);
 	}
 	CY_UNLOCK(info, flags);
     }
@@ -3957,16 +3957,16 @@
 		(info->line) - (cy_card[info->card].first_line),
 		C_CM_SET_BREAK, 0L);
 	    if (retval != 0) {
-		printk("cyc:cy_break (set) retval at %d was %x\n",
-		        __LINE__, retval);
+		printk("cyc:cy_break (set) retval on ttyC%d was %x\n",
+		       info->line, retval);
 	    }
 	} else {
 	    retval = cyz_issue_cmd(&cy_card[info->card],
 		(info->line) - (cy_card[info->card].first_line),
 		C_CM_CLR_BREAK, 0L);
 	    if (retval != 0) {
-		printk("cyc:cy_break (clr) retval at %d was %x\n",
-		        __LINE__, retval);
+		printk("cyc:cy_break (clr) retval on ttyC%d was %x\n",
+		       info->line, retval);
 	    }
 	}
     }
@@ -4579,7 +4579,8 @@
 	CY_LOCK(info, flags);
 	retval = cyz_issue_cmd(&cy_card[card], channel, C_CM_FLUSH_TX, 0L);
 	if (retval != 0) {
-	    printk("cyc: flush_buffer retval was %x\n", retval);
+	    printk("cyc: flush_buffer retval on ttyC%d was %x\n",
+		   info->line, retval);
 	}
 	CY_UNLOCK(info, flags);
     }
@@ -5474,6 +5475,8 @@
 			     cy_card[board].ctl_addr)->mail_box_0);
 		nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8;
 		cinfo->intr_enabled = 0;
+		cinfo->nports = 0; /* Will be correctly set later, after 
+				      Z FW is loaded */
 		spin_lock_init(&cinfo->card_lock);
                 for (port = cinfo->first_line ;
                      port < cinfo->first_line + nports;
@@ -5510,9 +5513,6 @@
                     info->x_char = 0;
                     info->event = 0;
                     info->count = 0;
-#ifdef CY_DEBUG_COUNT
-//        printk("cyc:cy_init(1) setting Z count to 0\n");
-#endif
                     info->blocked_open = 0;
                     info->default_threshold = 0;
                     info->default_timeout = 0;
@@ -5535,13 +5535,17 @@
                     info->jiffies[1] = 0;
                     info->jiffies[2] = 0;
                     info->rflush_count = 0;
+#ifdef CONFIG_CYZ_INTR
+		    cyz_rx_full_timer[port].function = NULL;
+#endif
                 }
                 continue;
             }else{ /* Cyclom-Y of some kind*/
                 index = cinfo->bus_index;
 		spin_lock_init(&cinfo->card_lock);
+		cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips;
                 for (port = cinfo->first_line ;
-                     port < cinfo->first_line + 4*cinfo->num_chips ;
+                     port < cinfo->first_line + cinfo->nports ;
                      port++)
                 {
                     info = &cy_port[port];
@@ -5586,9 +5590,6 @@
                     info->x_char = 0;
                     info->event = 0;
                     info->count = 0;
-#ifdef CY_DEBUG_COUNT
-//        printk("cyc:cy_init(2) setting Y count to 0\n");
-#endif
                     info->blocked_open = 0;
                     info->default_threshold = 0;
                     info->default_timeout = 0;
diff -u --recursive --new-file v2.3.39/linux/drivers/char/keyboard.c linux/drivers/char/keyboard.c
--- v2.3.39/linux/drivers/char/keyboard.c	Thu Nov 11 20:11:34 1999
+++ linux/drivers/char/keyboard.c	Thu Jan 20 09:48:48 2000
@@ -61,7 +61,9 @@
 #define KBD_DEFLOCK 0
 #endif
 
+void (*kbd_ledfunc)(unsigned int led) = NULL;
 EXPORT_SYMBOL(handle_scancode);
+EXPORT_SYMBOL(kbd_ledfunc);
 
 extern void ctrl_alt_del(void);
 
@@ -904,6 +906,7 @@
 	if (leds != ledstate) {
 		ledstate = leds;
 		kbd_leds(leds);
+		if (kbd_ledfunc) kbd_ledfunc(leds);
 	}
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/char/moxa.c linux/drivers/char/moxa.c
--- v2.3.39/linux/drivers/char/moxa.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/moxa.c	Thu Jan 20 10:44:46 2000
@@ -0,0 +1,3320 @@
+/*****************************************************************************/
+/*
+ *           moxa.c  -- MOXA Intellio family multiport serial driver.
+ *
+ *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com.tw).
+ *
+ *      This code is loosely based on the Linux serial driver, written by
+ *      Linus Torvalds, Theodore T'so and others.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    MOXA Intellio Series Driver
+ *      for             : LINUX
+ *      date            : 1999/1/7
+ *      version         : 5.1
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/config.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/serial.h>
+#include <linux/tty_driver.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#define		MOXA_VERSION		"5.1k"
+
+#define MOXAMAJOR       172
+#define MOXACUMAJOR     173
+
+#define put_to_user(arg1, arg2) put_user(arg1, (unsigned long *)arg2)
+#define get_from_user(arg1, arg2) get_user(arg1, (unsigned int *)arg2)
+
+#define MAX_BOARDS 		4	/* Don't change this value */
+#define MAX_PORTS_PER_BOARD	32	/* Don't change this value */
+#define MAX_PORTS 		128	/* Don't change this value */
+
+/*
+ *    Define the Moxa PCI vendor and device IDs.
+ */
+#define MOXA_BUS_TYPE_ISA		0
+#define MOXA_BUS_TYPE_PCI		1
+
+#ifndef	PCI_VENDOR_ID_MOXA
+#define	PCI_VENDOR_ID_MOXA	0x1393
+#endif
+#ifndef PCI_DEVICE_ID_CP204J
+#define PCI_DEVICE_ID_CP204J	0x2040
+#endif
+#ifndef PCI_DEVICE_ID_C218
+#define PCI_DEVICE_ID_C218	0x2180
+#endif
+#ifndef PCI_DEVICE_ID_C320
+#define PCI_DEVICE_ID_C320	0x3200
+#endif
+
+enum {
+	MOXA_BOARD_C218_PCI = 1,
+	MOXA_BOARD_C218_ISA,
+	MOXA_BOARD_C320_PCI,
+	MOXA_BOARD_C320_ISA,
+	MOXA_BOARD_CP204J,
+};
+
+static char *moxa_brdname[] =
+{
+	"C218 Turbo PCI series",
+	"C218 Turbo ISA series",
+	"C320 Turbo PCI series",
+	"C320 Turbo ISA series",
+	"CP-204J series",
+};
+
+typedef struct {
+	unsigned short vendor_id;
+	unsigned short device_id;
+	unsigned short board_type;
+} moxa_pciinfo;
+
+static moxa_pciinfo moxa_pcibrds[] =
+{
+	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C218, MOXA_BOARD_C218_PCI},
+	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C320, MOXA_BOARD_C320_PCI},
+	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_CP204J, MOXA_BOARD_CP204J},
+};
+
+typedef struct _moxa_isa_board_conf {
+	int boardType;
+	int numPorts;
+	unsigned long baseAddr;
+} moxa_isa_board_conf;
+
+static moxa_isa_board_conf moxa_isa_boards[] =
+{
+/*       {MOXA_BOARD_C218_ISA,8,0xDC000}, */
+};
+
+typedef struct _moxa_pci_devinfo {
+	ushort busNum;
+	ushort devNum;
+} moxa_pci_devinfo;
+
+typedef struct _moxa_board_conf {
+	int boardType;
+	int numPorts;
+	unsigned long baseAddr;
+	int busType;
+	moxa_pci_devinfo pciInfo;
+} moxa_board_conf;
+
+static moxa_board_conf moxa_boards[MAX_BOARDS];
+static unsigned long moxaBaseAddr[MAX_BOARDS];
+
+struct moxa_str {
+	int type;
+	int port;
+	int close_delay;
+	unsigned short closing_wait;
+	int count;
+	int blocked_open;
+	int event;
+	int asyncflags;
+	long session;
+	long pgrp;
+	unsigned long statusflags;
+	struct tty_struct *tty;
+	struct termios normal_termios;
+	struct termios callout_termios;
+	wait_queue_head_t open_wait;
+	wait_queue_head_t close_wait;
+	struct tq_struct tqueue;
+};
+
+struct mxser_mstatus {
+	tcflag_t cflag;
+	int cts;
+	int dsr;
+	int ri;
+	int dcd;
+};
+
+static struct mxser_mstatus GMStatus[MAX_PORTS];
+
+/* statusflags */
+#define TXSTOPPED	0x1
+#define LOWWAIT 	0x2
+#define EMPTYWAIT	0x4
+#define THROTTLE	0x8
+
+/* event */
+#define MOXA_EVENT_HANGUP	1
+
+#define SERIAL_DO_RESTART
+
+
+#define SERIAL_TYPE_NORMAL	1
+#define SERIAL_TYPE_CALLOUT	2
+
+#define WAKEUP_CHARS		256
+
+#define PORTNO(x)		(MINOR((x)->device) - (x)->driver.minor_start)
+
+static int verbose = 0;
+static int ttymajor = MOXAMAJOR;
+static int calloutmajor = MOXACUMAJOR;
+#ifdef MODULE
+/* Variables for insmod */
+static int baseaddr[] 	= 	{0, 0, 0, 0};
+static int type[]	=	{0, 0, 0, 0};
+static int numports[] 	=	{0, 0, 0, 0};
+
+MODULE_AUTHOR("William Chen");
+MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
+MODULE_PARM(type, "1-4i");
+MODULE_PARM(baseaddr, "1-4i");
+MODULE_PARM(numports, "1-4i");
+MODULE_PARM(ttymajor, "i");
+MODULE_PARM(calloutmajor, "i");
+MODULE_PARM(verbose, "i");
+
+#endif				//MODULE
+
+static struct tty_driver moxaDriver;
+static struct tty_driver moxaCallout;
+static struct tty_struct *moxaTable[MAX_PORTS + 1];
+static struct termios *moxaTermios[MAX_PORTS + 1];
+static struct termios *moxaTermiosLocked[MAX_PORTS + 1];
+static struct moxa_str moxaChannels[MAX_PORTS];
+static int moxaRefcount;
+static unsigned char *moxaXmitBuff;
+static int moxaTimer_on;
+static struct timer_list moxaTimer;
+static int moxaEmptyTimer_on[MAX_PORTS];
+static struct timer_list moxaEmptyTimer[MAX_PORTS];
+static struct semaphore moxaBuffSem;
+
+int moxa_init(void);
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+#endif
+/*
+ * static functions:
+ */
+static int moxa_get_PCI_conf(struct pci_dev *, int, moxa_board_conf *);
+static void do_moxa_softint(void *);
+static int moxa_open(struct tty_struct *, struct file *);
+static void moxa_close(struct tty_struct *, struct file *);
+static int moxa_write(struct tty_struct *, int, const unsigned char *, int);
+static int moxa_write_room(struct tty_struct *);
+static void moxa_flush_buffer(struct tty_struct *);
+static int moxa_chars_in_buffer(struct tty_struct *);
+static void moxa_flush_chars(struct tty_struct *);
+static void moxa_put_char(struct tty_struct *, unsigned char);
+static int moxa_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long);
+static void moxa_throttle(struct tty_struct *);
+static void moxa_unthrottle(struct tty_struct *);
+static void moxa_set_termios(struct tty_struct *, struct termios *);
+static void moxa_stop(struct tty_struct *);
+static void moxa_start(struct tty_struct *);
+static void moxa_hangup(struct tty_struct *);
+static void moxa_poll(unsigned long);
+static void set_tty_param(struct tty_struct *);
+static int block_till_ready(struct tty_struct *, struct file *,
+			    struct moxa_str *);
+static void setup_empty_event(struct tty_struct *);
+static void check_xmit_empty(unsigned long);
+static void shut_down(struct moxa_str *);
+static void receive_data(struct moxa_str *);
+/*
+ * moxa board interface functions:
+ */
+static void MoxaDriverInit(void);
+static int MoxaDriverIoctl(unsigned int, unsigned long, int);
+static int MoxaDriverPoll(void);
+static int MoxaPortsOfCard(int);
+static int MoxaPortIsValid(int);
+static void MoxaPortEnable(int);
+static void MoxaPortDisable(int);
+static long MoxaPortGetMaxBaud(int);
+static long MoxaPortSetBaud(int, long);
+static int MoxaPortSetTermio(int, struct termios *);
+static int MoxaPortGetLineOut(int, int *, int *);
+static void MoxaPortLineCtrl(int, int, int);
+static void MoxaPortFlowCtrl(int, int, int, int, int, int);
+static int MoxaPortLineStatus(int);
+static int MoxaPortDCDChange(int);
+static int MoxaPortDCDON(int);
+static void MoxaPortFlushData(int, int);
+static int MoxaPortWriteData(int, unsigned char *, int);
+static int MoxaPortReadData(int, unsigned char *, int);
+static int MoxaPortTxQueue(int);
+static int MoxaPortRxQueue(int);
+static int MoxaPortTxFree(int);
+static void MoxaPortTxDisable(int);
+static void MoxaPortTxEnable(int);
+static int MoxaPortResetBrkCnt(int);
+static void MoxaPortSendBreak(int, int);
+static int moxa_get_serial_info(struct moxa_str *, struct serial_struct *);
+static int moxa_set_serial_info(struct moxa_str *, struct serial_struct *);
+static void MoxaSetFifo(int port, int enable);
+
+#ifdef MODULE
+int init_module(void)
+{
+	int ret;
+
+	if (verbose)
+		printk("Loading module moxa ...\n");
+	ret = moxa_init();
+	if (verbose)
+		printk("Done\n");
+	return (ret);
+}
+
+void cleanup_module(void)
+{
+	int i;
+
+	if (verbose)
+		printk("Unloading module moxa ...\n");
+
+	if (moxaTimer_on)
+		del_timer(&moxaTimer);
+
+	for (i = 0; i < MAX_PORTS; i++)
+		if (moxaEmptyTimer_on[i])
+			del_timer(&moxaEmptyTimer[i]);
+
+	if (tty_unregister_driver(&moxaCallout))
+		printk("Couldn't unregister MOXA Intellio family callout driver\n");
+	if (tty_unregister_driver(&moxaDriver))
+		printk("Couldn't unregister MOXA Intellio family serial driver\n");
+	if (verbose)
+		printk("Done\n");
+
+}
+#endif
+
+int moxa_init(void)
+{
+	int i, n, numBoards;
+	struct moxa_str *ch;
+	int ret1, ret2;
+
+	printk(KERN_INFO "MOXA Intellio family driver version %s\n", MOXA_VERSION);
+
+	init_MUTEX(&moxaBuffSem);
+	memset(&moxaDriver, 0, sizeof(struct tty_driver));
+	memset(&moxaCallout, 0, sizeof(struct tty_driver));
+	moxaDriver.magic = TTY_DRIVER_MAGIC;
+	moxaDriver.name = "ttya";
+	moxaDriver.major = ttymajor;
+	moxaDriver.minor_start = 0;
+	moxaDriver.num = MAX_PORTS + 1;
+	moxaDriver.type = TTY_DRIVER_TYPE_SERIAL;
+	moxaDriver.subtype = SERIAL_TYPE_NORMAL;
+	moxaDriver.init_termios = tty_std_termios;
+	moxaDriver.init_termios.c_iflag = 0;
+	moxaDriver.init_termios.c_oflag = 0;
+	moxaDriver.init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+	moxaDriver.init_termios.c_lflag = 0;
+	moxaDriver.flags = TTY_DRIVER_REAL_RAW;
+	moxaDriver.refcount = &moxaRefcount;
+	moxaDriver.table = moxaTable;
+	moxaDriver.termios = moxaTermios;
+	moxaDriver.termios_locked = moxaTermiosLocked;
+
+	moxaDriver.open = moxa_open;
+	moxaDriver.close = moxa_close;
+	moxaDriver.write = moxa_write;
+	moxaDriver.write_room = moxa_write_room;
+	moxaDriver.flush_buffer = moxa_flush_buffer;
+	moxaDriver.chars_in_buffer = moxa_chars_in_buffer;
+	moxaDriver.flush_chars = moxa_flush_chars;
+	moxaDriver.put_char = moxa_put_char;
+	moxaDriver.ioctl = moxa_ioctl;
+	moxaDriver.throttle = moxa_throttle;
+	moxaDriver.unthrottle = moxa_unthrottle;
+	moxaDriver.set_termios = moxa_set_termios;
+	moxaDriver.stop = moxa_stop;
+	moxaDriver.start = moxa_start;
+	moxaDriver.hangup = moxa_hangup;
+
+	moxaCallout = moxaDriver;
+	moxaCallout.name = "ttyA";
+	moxaCallout.major = calloutmajor;
+	moxaCallout.subtype = SERIAL_TYPE_CALLOUT;
+
+	moxaXmitBuff = 0;
+
+	for (i = 0, ch = moxaChannels; i < MAX_PORTS; i++, ch++) {
+		ch->type = PORT_16550A;
+		ch->port = i;
+		ch->tqueue.routine = do_moxa_softint;
+		ch->tqueue.data = ch;
+		ch->tty = 0;
+		ch->close_delay = 5 * HZ / 10;
+		ch->closing_wait = 30 * HZ;
+		ch->count = 0;
+		ch->blocked_open = 0;
+		ch->callout_termios = moxaCallout.init_termios;
+		ch->normal_termios = moxaDriver.init_termios;
+		init_waitqueue_head(&ch->open_wait);
+		init_waitqueue_head(&ch->close_wait);
+	}
+
+	for (i = 0; i < MAX_BOARDS; i++) {
+		moxa_boards[i].boardType = 0;
+		moxa_boards[i].numPorts = 0;
+		moxa_boards[i].baseAddr = 0;
+		moxa_boards[i].busType = 0;
+		moxa_boards[i].pciInfo.busNum = 0;
+		moxa_boards[i].pciInfo.devNum = 0;
+	}
+	MoxaDriverInit();
+	printk("Tty devices major number = %d, callout devices major number = %d\n", ttymajor, calloutmajor);
+
+	ret1 = 0;
+	ret2 = 0;
+	if ((ret1 = tty_register_driver(&moxaDriver))) {
+		printk(KERN_ERR "Couldn't install MOXA Smartio family driver !\n");
+	} else if ((ret2 = tty_register_driver(&moxaCallout))) {
+		tty_unregister_driver(&moxaDriver);
+		printk(KERN_ERR "Couldn't install MOXA Smartio family callout driver !\n");
+	}
+	if (ret1 || ret2) {
+		return -1;
+	}
+	for (i = 0; i < MAX_PORTS; i++) {
+		init_timer(&moxaEmptyTimer[i]);
+		moxaEmptyTimer[i].function = check_xmit_empty;
+		moxaEmptyTimer[i].data = (unsigned long) & moxaChannels[i];
+		moxaEmptyTimer_on[i] = 0;
+	}
+
+	init_timer(&moxaTimer);
+	moxaTimer.function = moxa_poll;
+	moxaTimer.expires = jiffies + (HZ / 50);
+	moxaTimer_on = 1;
+	add_timer(&moxaTimer);
+
+	/* Find the boards defined in source code */
+	numBoards = 0;
+	for (i = 0; i < MAX_BOARDS; i++) {
+		if ((moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA) ||
+		 (moxa_isa_boards[i].boardType == MOXA_BOARD_C320_ISA)) {
+			moxa_boards[numBoards].boardType = moxa_isa_boards[i].boardType;
+			if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
+				moxa_boards[numBoards].numPorts = 8;
+			else
+				moxa_boards[numBoards].numPorts = moxa_isa_boards[i].numPorts;
+			moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
+			moxa_boards[numBoards].baseAddr = moxa_isa_boards[i].baseAddr;
+			if (verbose)
+				printk("Board %2d: %s board(baseAddr=%lx)\n",
+				       numBoards + 1,
+				       moxa_brdname[moxa_boards[numBoards].boardType - 1],
+				       moxa_boards[numBoards].baseAddr);
+			numBoards++;
+		}
+	}
+	/* Find the boards defined form module args. */
+#ifdef MODULE
+	for (i = 0; i < MAX_BOARDS; i++) {
+		if ((type[i] == MOXA_BOARD_C218_ISA) ||
+		    (type[i] == MOXA_BOARD_C320_ISA)) {
+			if (verbose)
+				printk("Board %2d: %s board(baseAddr=%lx)\n",
+				       numBoards + 1,
+				       moxa_brdname[type[i] - 1],
+				       (unsigned long) baseaddr[i]);
+			if (numBoards >= MAX_BOARDS) {
+				if (verbose)
+					printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
+				continue;
+			}
+			moxa_boards[numBoards].boardType = type[i];
+			if (moxa_isa_boards[i].boardType == MOXA_BOARD_C218_ISA)
+				moxa_boards[numBoards].numPorts = 8;
+			else
+				moxa_boards[numBoards].numPorts = numports[i];
+			moxa_boards[numBoards].busType = MOXA_BUS_TYPE_ISA;
+			moxa_boards[numBoards].baseAddr = baseaddr[i];
+			numBoards++;
+		}
+	}
+#endif
+	/* Find PCI boards here */
+#ifdef CONFIG_PCI
+	if (pci_present()) {
+		struct pci_dev *p = NULL;
+		n = sizeof(moxa_pcibrds) / sizeof(moxa_pciinfo);
+		i = 0;
+		while (i < n) {
+			while((p = pci_find_device(moxa_pcibrds[i].vendor_id, moxa_pcibrds[i].device_id, p))!=NULL)
+			{
+				if (numBoards >= MAX_BOARDS) {
+					if (verbose)
+						printk("More than %d MOXA Intellio family boards found. Board is ignored.", MAX_BOARDS);
+				} else {
+					moxa_get_PCI_conf(p, moxa_pcibrds[i].board_type,
+						&moxa_boards[numBoards]);
+					numBoards++;
+				}
+			}
+			i++;
+		}
+	}
+#endif
+	for (i = 0; i < numBoards; i++) {
+		moxaBaseAddr[i] = (unsigned long) ioremap((unsigned long) moxa_boards[i].baseAddr, 0x4000);
+	}
+
+	return (0);
+}
+
+static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf * board)
+{
+	unsigned int val;
+
+	board->baseAddr = p->resource[2].start;
+	board->boardType = board_type;
+	switch (board_type) {
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+		board->numPorts = 8;
+		break;
+
+	case MOXA_BOARD_CP204J:
+		board->numPorts = 4;
+		break;
+	default:
+		board->numPorts = 0;
+		break;
+	}
+	board->busType = MOXA_BUS_TYPE_PCI;
+	board->pciInfo.busNum = p->bus->number;
+	board->pciInfo.devNum = p->devfn >> 3;
+
+	return (0);
+}
+
+static void do_moxa_softint(void *private_)
+{
+	struct moxa_str *ch = (struct moxa_str *) private_;
+	struct tty_struct *tty;
+
+	if (!ch || !(tty = ch->tty))
+		return;
+	if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) {
+		tty_hangup(tty);
+		wake_up_interruptible(&ch->open_wait);
+		ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
+	}
+}
+
+static int moxa_open(struct tty_struct *tty, struct file *filp)
+{
+	struct moxa_str *ch;
+	int port;
+	int retval;
+	unsigned long page;
+
+	port = PORTNO(tty);
+	if (port == MAX_PORTS) {
+		MOD_INC_USE_COUNT;
+		return (0);
+	}
+	if (!MoxaPortIsValid(port)) {
+		tty->driver_data = NULL;
+		return (-ENODEV);
+	}
+	down(&moxaBuffSem);
+	if (!moxaXmitBuff) {
+		page = get_free_page(GFP_KERNEL);
+		if (!page) {
+			up(&moxaBuffSem);
+			return (-ENOMEM);
+		}
+		if (moxaXmitBuff)
+			free_page(page);
+		else
+			moxaXmitBuff = (unsigned char *) page;
+	}
+	up(&moxaBuffSem);
+
+	MOD_INC_USE_COUNT;
+	ch = &moxaChannels[port];
+	ch->count++;
+	tty->driver_data = ch;
+	ch->tty = tty;
+	if (ch->count == 1 && (ch->asyncflags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = ch->normal_termios;
+		else
+			*tty->termios = ch->callout_termios;
+	}
+	ch->session = current->session;
+	ch->pgrp = current->pgrp;
+	if (!(ch->asyncflags & ASYNC_INITIALIZED)) {
+		ch->statusflags = 0;
+		set_tty_param(tty);
+		MoxaPortLineCtrl(ch->port, 1, 1);
+		MoxaPortEnable(ch->port);
+		ch->asyncflags |= ASYNC_INITIALIZED;
+	}
+	retval = block_till_ready(tty, filp, ch);
+
+	moxa_unthrottle(tty);
+
+	if (ch->type == PORT_16550A) {
+		MoxaSetFifo(ch->port, 1);
+	} else {
+		MoxaSetFifo(ch->port, 0);
+	}
+
+	return (retval);
+}
+
+static void moxa_close(struct tty_struct *tty, struct file *filp)
+{
+	struct moxa_str *ch;
+	int port;
+
+	port = PORTNO(tty);
+	if (port == MAX_PORTS) {
+		MOD_DEC_USE_COUNT;
+		return;
+	}
+	if (!MoxaPortIsValid(port)) {
+#ifdef SERIAL_DEBUG_CLOSE
+		printk("Invalid portno in moxa_close\n");
+#endif
+		tty->driver_data = NULL;
+		return;
+	}
+	if (tty->driver_data == NULL) {
+		return;
+	}
+	if (tty_hung_up_p(filp)) {
+		MOD_DEC_USE_COUNT;
+		return;
+	}
+	ch = (struct moxa_str *) tty->driver_data;
+
+	if ((tty->count == 1) && (ch->count != 1)) {
+		printk("moxa_close: bad serial port count; tty->count is 1, "
+		       "ch->count is %d\n", ch->count);
+		ch->count = 1;
+	}
+	if (--ch->count < 0) {
+		printk("moxa_close: bad serial port count, minor=%d\n",
+		       MINOR(tty->device));
+		ch->count = 0;
+	}
+	if (ch->count) {
+		MOD_DEC_USE_COUNT;
+		return;
+	}
+	ch->asyncflags |= ASYNC_CLOSING;
+
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (ch->asyncflags & ASYNC_NORMAL_ACTIVE)
+		ch->normal_termios = *tty->termios;
+	if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE)
+		ch->callout_termios = *tty->termios;
+	if (ch->asyncflags & ASYNC_INITIALIZED) {
+		setup_empty_event(tty);
+		tty_wait_until_sent(tty, 30 * HZ);	/* 30 seconds timeout */
+		moxaEmptyTimer_on[ch->port] = 0;
+		del_timer(&moxaEmptyTimer[ch->port]);
+	}
+	shut_down(ch);
+	MoxaPortFlushData(port, 2);
+
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	ch->event = 0;
+	ch->tty = 0;
+	if (ch->blocked_open) {
+		if (ch->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(ch->close_delay);
+		}
+		wake_up_interruptible(&ch->open_wait);
+	}
+	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
+			    ASYNC_CLOSING);
+	wake_up_interruptible(&ch->close_wait);
+	MOD_DEC_USE_COUNT;
+}
+
+static int moxa_write(struct tty_struct *tty, int from_user,
+		      const unsigned char *buf, int count)
+{
+	struct moxa_str *ch;
+	int len, port;
+	unsigned long flags;
+	unsigned char *temp;
+
+	ch = (struct moxa_str *) tty->driver_data;
+	if (ch == NULL)
+		return (0);
+	port = ch->port;
+	save_flags(flags);
+	cli();
+	if (from_user) {
+		copy_from_user(moxaXmitBuff, buf, count);
+		temp = moxaXmitBuff;
+	} else
+		temp = (unsigned char *) buf;
+	len = MoxaPortWriteData(port, temp, count);
+	restore_flags(flags);
+	/*********************************************
+	if ( !(ch->statusflags & LOWWAIT) &&
+	     ((len != count) || (MoxaPortTxFree(port) <= 100)) )
+	************************************************/
+	ch->statusflags |= LOWWAIT;
+	return (len);
+}
+
+static int moxa_write_room(struct tty_struct *tty)
+{
+	struct moxa_str *ch;
+
+	if (tty->stopped)
+		return (0);
+	ch = (struct moxa_str *) tty->driver_data;
+	if (ch == NULL)
+		return (0);
+	return (MoxaPortTxFree(ch->port));
+}
+
+static void moxa_flush_buffer(struct tty_struct *tty)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+
+	if (ch == NULL)
+		return;
+	MoxaPortFlushData(ch->port, 1);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup) (tty);
+	wake_up_interruptible(&tty->write_wait);
+}
+
+static int moxa_chars_in_buffer(struct tty_struct *tty)
+{
+	int chars;
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+
+	/*
+	 * Sigh...I have to check if driver_data is NULL here, because
+	 * if an open() fails, the TTY subsystem eventually calls
+	 * tty_wait_until_sent(), which calls the driver's chars_in_buffer()
+	 * routine.  And since the open() failed, we return 0 here.  TDJ
+	 */
+	if (ch == NULL)
+		return (0);
+	chars = MoxaPortTxQueue(ch->port);
+	if (chars) {
+		/*
+		 * Make it possible to wakeup anything waiting for output
+		 * in tty_ioctl.c, etc.
+		 */
+		if (!(ch->statusflags & EMPTYWAIT))
+			setup_empty_event(tty);
+	}
+	return (chars);
+}
+
+static void moxa_flush_chars(struct tty_struct *tty)
+{
+	/*
+	 * Don't think I need this, because this is called to empty the TX
+	 * buffer for the 16450, 16550, etc.
+	 */
+}
+
+static void moxa_put_char(struct tty_struct *tty, unsigned char c)
+{
+	struct moxa_str *ch;
+	int port;
+	unsigned long flags;
+
+	ch = (struct moxa_str *) tty->driver_data;
+	if (ch == NULL)
+		return;
+	port = ch->port;
+	save_flags(flags);
+	cli();
+	moxaXmitBuff[0] = c;
+	MoxaPortWriteData(port, moxaXmitBuff, 1);
+	restore_flags(flags);
+	/************************************************
+	if ( !(ch->statusflags & LOWWAIT) && (MoxaPortTxFree(port) <= 100) )
+	*************************************************/
+	ch->statusflags |= LOWWAIT;
+}
+
+static int moxa_ioctl(struct tty_struct *tty, struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+	register int port;
+	int retval, dtr, rts;
+	unsigned long flag;
+
+	port = PORTNO(tty);
+	if ((port != MAX_PORTS) && (!ch))
+		return (-EINVAL);
+
+	switch (cmd) {
+	case TCSBRK:		/* SVID version: non-zero arg --> no break */
+		retval = tty_check_change(tty);
+		if (retval)
+			return (retval);
+		setup_empty_event(tty);
+		tty_wait_until_sent(tty, 0);
+		if (!arg)
+			MoxaPortSendBreak(ch->port, 0);
+		return (0);
+	case TCSBRKP:		/* support for POSIX tcsendbreak() */
+		retval = tty_check_change(tty);
+		if (retval)
+			return (retval);
+		setup_empty_event(tty);
+		tty_wait_until_sent(tty, 0);
+		MoxaPortSendBreak(ch->port, arg);
+		return (0);
+	case TIOCGSOFTCAR:
+		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+	case TIOCSSOFTCAR:
+		if(get_user(retval, (unsigned long *) arg))
+			return -EFAULT;
+		arg = retval;
+		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
+					 (arg ? CLOCAL : 0));
+		if (C_CLOCAL(tty))
+			ch->asyncflags &= ~ASYNC_CHECK_CD;
+		else
+			ch->asyncflags |= ASYNC_CHECK_CD;
+		return (0);
+	case TIOCMGET:
+		flag = 0;
+		MoxaPortGetLineOut(ch->port, &dtr, &rts);
+		if (dtr)
+			flag |= TIOCM_DTR;
+		if (rts)
+			flag |= TIOCM_RTS;
+		dtr = MoxaPortLineStatus(ch->port);
+		if (dtr & 1)
+			flag |= TIOCM_CTS;
+		if (dtr & 2)
+			flag |= TIOCM_DSR;
+		if (dtr & 4)
+			flag |= TIOCM_CD;
+		return put_user(flag, (unsigned int *) arg);
+	case TIOCMBIS:
+		if(get_user(retval, (unsigned int *) arg))
+			return -EFAULT;
+		MoxaPortGetLineOut(ch->port, &dtr, &rts);
+		if (retval & TIOCM_RTS)
+			rts = 1;
+		if (retval & TIOCM_DTR)
+			dtr = 1;
+		MoxaPortLineCtrl(ch->port, dtr, rts);
+		return (0);
+	case TIOCMBIC:
+		if(get_user(retval, (unsigned int *) arg))
+			return -EFAULT;
+		MoxaPortGetLineOut(ch->port, &dtr, &rts);
+		if (retval & TIOCM_RTS)
+			rts = 0;
+		if (retval & TIOCM_DTR)
+			dtr = 0;
+		MoxaPortLineCtrl(ch->port, dtr, rts);
+		return (0);
+	case TIOCMSET:
+		if(get_user(retval, (unsigned long *) arg))
+			return -EFAULT;
+		dtr = rts = 0;
+		if (retval & TIOCM_RTS)
+			rts = 1;
+		if (retval & TIOCM_DTR)
+			dtr = 1;
+		MoxaPortLineCtrl(ch->port, dtr, rts);
+		return (0);
+	case TIOCGSERIAL:
+		return (moxa_get_serial_info(ch, (struct serial_struct *) arg));
+
+	case TIOCSSERIAL:
+		return (moxa_set_serial_info(ch, (struct serial_struct *) arg));
+	default:
+		retval = MoxaDriverIoctl(cmd, arg, port);
+	}
+	return (retval);
+}
+
+static void moxa_throttle(struct tty_struct *tty)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+
+	ch->statusflags |= THROTTLE;
+}
+
+static void moxa_unthrottle(struct tty_struct *tty)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+
+	ch->statusflags &= ~THROTTLE;
+}
+
+static void moxa_set_termios(struct tty_struct *tty,
+			     struct termios *old_termios)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+
+	if (ch == NULL)
+		return;
+	set_tty_param(tty);
+	if (!(old_termios->c_cflag & CLOCAL) &&
+	    (tty->termios->c_cflag & CLOCAL))
+		wake_up_interruptible(&ch->open_wait);
+}
+
+static void moxa_stop(struct tty_struct *tty)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+
+	if (ch == NULL)
+		return;
+	MoxaPortTxDisable(ch->port);
+	ch->statusflags |= TXSTOPPED;
+}
+
+
+static void moxa_start(struct tty_struct *tty)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+
+	if (ch == NULL)
+		return;
+
+	if (!(ch->statusflags & TXSTOPPED))
+		return;
+
+	MoxaPortTxEnable(ch->port);
+	ch->statusflags &= ~TXSTOPPED;
+}
+
+static void moxa_hangup(struct tty_struct *tty)
+{
+	struct moxa_str *ch = (struct moxa_str *) tty->driver_data;
+
+	moxa_flush_buffer(tty);
+	shut_down(ch);
+	ch->event = 0;
+	ch->count = 0;
+	ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
+	ch->tty = 0;
+	wake_up_interruptible(&ch->open_wait);
+}
+
+static void moxa_poll(unsigned long ignored)
+{
+	register int card;
+	struct moxa_str *ch;
+	struct tty_struct *tp;
+	int i, ports;
+
+	moxaTimer_on = 0;
+	del_timer(&moxaTimer);
+
+	if (MoxaDriverPoll() < 0) {
+		moxaTimer.function = moxa_poll;
+		moxaTimer.expires = jiffies + (HZ / 50);
+		moxaTimer_on = 1;
+		add_timer(&moxaTimer);
+		return;
+	}
+	for (card = 0; card < MAX_BOARDS; card++) {
+		if ((ports = MoxaPortsOfCard(card)) <= 0)
+			continue;
+		ch = &moxaChannels[card * MAX_PORTS_PER_BOARD];
+		for (i = 0; i < ports; i++, ch++) {
+			if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)
+				continue;
+			if (!(ch->statusflags & THROTTLE) &&
+			    (MoxaPortRxQueue(ch->port) > 0))
+				receive_data(ch);
+			if ((tp = ch->tty) == 0)
+				continue;
+			if (ch->statusflags & LOWWAIT) {
+				if (MoxaPortTxQueue(ch->port) <= WAKEUP_CHARS) {
+					if (!tp->stopped) {
+						ch->statusflags &= ~LOWWAIT;
+						if ((tp->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+						  tp->ldisc.write_wakeup)
+							(tp->ldisc.write_wakeup) (tp);
+						wake_up_interruptible(&tp->write_wait);
+					}
+				}
+			}
+			if (!I_IGNBRK(tp) && (MoxaPortResetBrkCnt(ch->port) > 0)) {
+				tty_insert_flip_char(tp, 0, TTY_BREAK);
+				tty_schedule_flip(tp);
+			}
+			if (MoxaPortDCDChange(ch->port)) {
+				if (ch->asyncflags & ASYNC_CHECK_CD) {
+					if (MoxaPortDCDON(ch->port))
+						wake_up_interruptible(&ch->open_wait);
+					else {
+						set_bit(MOXA_EVENT_HANGUP, &ch->event);
+						queue_task(&ch->tqueue, &tq_scheduler);
+					}
+				}
+			}
+		}
+	}
+
+	moxaTimer.function = moxa_poll;
+	moxaTimer.expires = jiffies + (HZ / 50);
+	moxaTimer_on = 1;
+	add_timer(&moxaTimer);
+}
+
+/******************************************************************************/
+
+static void set_tty_param(struct tty_struct *tty)
+{
+	register struct termios *ts;
+	struct moxa_str *ch;
+	int rts, cts, txflow, rxflow, xany;
+
+	ch = (struct moxa_str *) tty->driver_data;
+	ts = tty->termios;
+	if (ts->c_cflag & CLOCAL)
+		ch->asyncflags &= ~ASYNC_CHECK_CD;
+	else
+		ch->asyncflags |= ASYNC_CHECK_CD;
+	rts = cts = txflow = rxflow = xany = 0;
+	if (ts->c_cflag & CRTSCTS)
+		rts = cts = 1;
+	if (ts->c_iflag & IXON)
+		txflow = 1;
+	if (ts->c_iflag & IXOFF)
+		rxflow = 1;
+	if (ts->c_iflag & IXANY)
+		xany = 1;
+	MoxaPortFlowCtrl(ch->port, rts, cts, txflow, rxflow, xany);
+	MoxaPortSetTermio(ch->port, ts);
+}
+
+static int block_till_ready(struct tty_struct *tty, struct file *filp,
+			    struct moxa_str *ch)
+{
+	DECLARE_WAITQUEUE(wait,current);
+	unsigned long flags;
+	int retval;
+	int do_clocal = C_CLOCAL(tty);
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) || (ch->asyncflags & ASYNC_CLOSING)) {
+		if (ch->asyncflags & ASYNC_CLOSING)
+			interruptible_sleep_on(&ch->close_wait);
+#ifdef SERIAL_DO_RESTART
+		if (ch->asyncflags & ASYNC_HUP_NOTIFY)
+			return (-EAGAIN);
+		else
+			return (-ERESTARTSYS);
+#else
+		return (-EAGAIN);
+#endif
+	}
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (ch->asyncflags & ASYNC_NORMAL_ACTIVE)
+			return (-EBUSY);
+		if ((ch->asyncflags & ASYNC_CALLOUT_ACTIVE) &&
+		    (ch->asyncflags & ASYNC_SESSION_LOCKOUT) &&
+		    (ch->session != current->session))
+			return (-EBUSY);
+		if ((ch->asyncflags & ASYNC_CALLOUT_ACTIVE) &&
+		    (ch->asyncflags & ASYNC_PGRP_LOCKOUT) &&
+		    (ch->pgrp != current->pgrp))
+			return (-EBUSY);
+		ch->asyncflags |= ASYNC_CALLOUT_ACTIVE;
+		return (0);
+	}
+	/*
+	 * If non-blocking mode is set, then make the check up front
+	 * and then exit.
+	 */
+	if (filp->f_flags & O_NONBLOCK) {
+		if (ch->asyncflags & ASYNC_CALLOUT_ACTIVE)
+			return (-EBUSY);
+		ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
+		return (0);
+	}
+	/*
+	 * Block waiting for the carrier detect and the line to become free
+	 */
+	retval = 0;
+	add_wait_queue(&ch->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: ttys%d, count = %d\n",
+	       ch->line, ch->count);
+#endif
+	save_flags(flags);
+	cli();
+	if (!tty_hung_up_p(filp))
+		ch->count--;
+	restore_flags(flags);
+	ch->blocked_open++;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		if (tty_hung_up_p(filp) ||
+		    !(ch->asyncflags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (ch->asyncflags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(ch->asyncflags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(ch->asyncflags & ASYNC_CLOSING) && (do_clocal ||
+						MoxaPortDCDON(ch->port)))
+			break;
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&ch->open_wait, &wait);
+	if (!tty_hung_up_p(filp))
+		ch->count++;
+	ch->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       ch->line, ch->count);
+#endif
+	if (retval)
+		return (retval);
+	ch->asyncflags |= ASYNC_NORMAL_ACTIVE;
+	return (0);
+}
+
+static void setup_empty_event(struct tty_struct *tty)
+{
+	struct moxa_str *ch = tty->driver_data;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	ch->statusflags |= EMPTYWAIT;
+	moxaEmptyTimer_on[ch->port] = 0;
+	del_timer(&moxaEmptyTimer[ch->port]);
+	moxaEmptyTimer[ch->port].expires = jiffies + HZ;
+	moxaEmptyTimer_on[ch->port] = 1;
+	add_timer(&moxaEmptyTimer[ch->port]);
+	restore_flags(flags);
+}
+
+static void check_xmit_empty(unsigned long data)
+{
+	struct moxa_str *ch;
+
+	ch = (struct moxa_str *) data;
+	moxaEmptyTimer_on[ch->port] = 0;
+	del_timer(&moxaEmptyTimer[ch->port]);
+	if (ch->tty && (ch->statusflags & EMPTYWAIT)) {
+		if (MoxaPortTxQueue(ch->port) == 0) {
+			ch->statusflags &= ~EMPTYWAIT;
+			if ((ch->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+			    ch->tty->ldisc.write_wakeup)
+				(ch->tty->ldisc.write_wakeup) (ch->tty);
+			wake_up_interruptible(&ch->tty->write_wait);
+			return;
+		}
+		moxaEmptyTimer[ch->port].expires = jiffies + HZ;
+		moxaEmptyTimer_on[ch->port] = 1;
+		add_timer(&moxaEmptyTimer[ch->port]);
+	} else
+		ch->statusflags &= ~EMPTYWAIT;
+}
+
+static void shut_down(struct moxa_str *ch)
+{
+	struct tty_struct *tp;
+
+	if (!(ch->asyncflags & ASYNC_INITIALIZED))
+		return;
+
+	tp = ch->tty;
+
+	MoxaPortDisable(ch->port);
+
+	/*
+	 * If we're a modem control device and HUPCL is on, drop RTS & DTR.
+	 */
+	if (tp->termios->c_cflag & HUPCL)
+		MoxaPortLineCtrl(ch->port, 0, 0);
+
+	ch->asyncflags &= ~ASYNC_INITIALIZED;
+}
+
+static void receive_data(struct moxa_str *ch)
+{
+	struct tty_struct *tp;
+	struct termios *ts;
+	int i, count, rc, space;
+	unsigned char *charptr, *flagptr;
+	unsigned long flags;
+
+	ts = 0;
+	tp = ch->tty;
+	if (tp)
+		ts = tp->termios;
+	/**************************************************
+	if ( !tp || !ts || !(ts->c_cflag & CREAD) ) {
+	*****************************************************/
+	if (!tp || !ts) {
+		MoxaPortFlushData(ch->port, 0);
+		return;
+	}
+	space = TTY_FLIPBUF_SIZE - tp->flip.count;
+	if (space <= 0)
+		return;
+	charptr = tp->flip.char_buf_ptr;
+	flagptr = tp->flip.flag_buf_ptr;
+	rc = tp->flip.count;
+	save_flags(flags);
+	cli();
+	count = MoxaPortReadData(ch->port, charptr, space);
+	restore_flags(flags);
+	for (i = 0; i < count; i++)
+		*flagptr++ = 0;
+	charptr += count;
+	rc += count;
+	tp->flip.count = rc;
+	tp->flip.char_buf_ptr = charptr;
+	tp->flip.flag_buf_ptr = flagptr;
+	tty_schedule_flip(ch->tty);
+}
+
+#define Magic_code	0x404
+
+/*
+ *    System Configuration
+ */
+/*
+ *    for C218 BIOS initialization
+ */
+#define C218_ConfBase	0x800
+#define C218_status	(C218_ConfBase + 0)	/* BIOS running status    */
+#define C218_diag	(C218_ConfBase + 2)	/* diagnostic status      */
+#define C218_key	(C218_ConfBase + 4)	/* WORD (0x218 for C218) */
+#define C218DLoad_len	(C218_ConfBase + 6)	/* WORD           */
+#define C218check_sum	(C218_ConfBase + 8)	/* BYTE           */
+#define C218chksum_ok	(C218_ConfBase + 0x0a)	/* BYTE (1:ok)            */
+#define C218_TestRx	(C218_ConfBase + 0x10)	/* 8 bytes for 8 ports    */
+#define C218_TestTx	(C218_ConfBase + 0x18)	/* 8 bytes for 8 ports    */
+#define C218_RXerr	(C218_ConfBase + 0x20)	/* 8 bytes for 8 ports    */
+#define C218_ErrFlag	(C218_ConfBase + 0x28)	/* 8 bytes for 8 ports    */
+
+#define C218_LoadBuf	0x0F00
+#define C218_KeyCode	0x218
+#define CP204J_KeyCode	0x204
+
+/*
+ *    for C320 BIOS initialization
+ */
+#define C320_ConfBase	0x800
+#define C320_LoadBuf	0x0f00
+#define STS_init	0x05	/* for C320_status        */
+
+#define C320_status	C320_ConfBase + 0	/* BIOS running status    */
+#define C320_diag	C320_ConfBase + 2	/* diagnostic status      */
+#define C320_key	C320_ConfBase + 4	/* WORD (0320H for C320) */
+#define C320DLoad_len	C320_ConfBase + 6	/* WORD           */
+#define C320check_sum	C320_ConfBase + 8	/* WORD           */
+#define C320chksum_ok	C320_ConfBase + 0x0a	/* WORD (1:ok)            */
+#define C320bapi_len	C320_ConfBase + 0x0c	/* WORD           */
+#define C320UART_no	C320_ConfBase + 0x0e	/* WORD           */
+
+#define C320_KeyCode	0x320
+
+#define FixPage_addr	0x0000	/* starting addr of static page  */
+#define DynPage_addr	0x2000	/* starting addr of dynamic page */
+#define C218_start	0x3000	/* starting addr of C218 BIOS prg */
+#define Control_reg	0x1ff0	/* select page and reset control */
+#define HW_reset	0x80
+
+/*
+ *    Function Codes
+ */
+#define FC_CardReset	0x80
+#define FC_ChannelReset 1	/* C320 firmware not supported */
+#define FC_EnableCH	2
+#define FC_DisableCH	3
+#define FC_SetParam	4
+#define FC_SetMode	5
+#define FC_SetRate	6
+#define FC_LineControl	7
+#define FC_LineStatus	8
+#define FC_XmitControl	9
+#define FC_FlushQueue	10
+#define FC_SendBreak	11
+#define FC_StopBreak	12
+#define FC_LoopbackON	13
+#define FC_LoopbackOFF	14
+#define FC_ClrIrqTable	15
+#define FC_SendXon	16
+#define FC_SetTermIrq	17	/* C320 firmware not supported */
+#define FC_SetCntIrq	18	/* C320 firmware not supported */
+#define FC_SetBreakIrq	19
+#define FC_SetLineIrq	20
+#define FC_SetFlowCtl	21
+#define FC_GenIrq	22
+#define FC_InCD180	23
+#define FC_OutCD180	24
+#define FC_InUARTreg	23
+#define FC_OutUARTreg	24
+#define FC_SetXonXoff	25
+#define FC_OutCD180CCR	26
+#define FC_ExtIQueue	27
+#define FC_ExtOQueue	28
+#define FC_ClrLineIrq	29
+#define FC_HWFlowCtl	30
+#define FC_GetClockRate 35
+#define FC_SetBaud	36
+#define FC_SetDataMode  41
+#define FC_GetCCSR      43
+#define FC_GetDataError 45
+#define FC_RxControl	50
+#define FC_ImmSend	51
+#define FC_SetXonState	52
+#define FC_SetXoffState	53
+#define FC_SetRxFIFOTrig 54
+#define FC_SetTxFIFOCnt 55
+#define FC_UnixRate	56
+#define FC_UnixResetTimer 57
+
+#define	RxFIFOTrig1	0
+#define	RxFIFOTrig4	1
+#define	RxFIFOTrig8	2
+#define	RxFIFOTrig14	3
+
+/*
+ *    Dual-Ported RAM
+ */
+#define DRAM_global	0
+#define INT_data	(DRAM_global + 0)
+#define Config_base	(DRAM_global + 0x108)
+
+#define IRQindex	(INT_data + 0)
+#define IRQpending	(INT_data + 4)
+#define IRQtable	(INT_data + 8)
+
+/*
+ *    Interrupt Status
+ */
+#define IntrRx		0x01	/* receiver data O.K.             */
+#define IntrTx		0x02	/* transmit buffer empty  */
+#define IntrFunc	0x04	/* function complete              */
+#define IntrBreak	0x08	/* received break         */
+#define IntrLine	0x10	/* line status change
+				   for transmitter                */
+#define IntrIntr	0x20	/* received INTR code             */
+#define IntrQuit	0x40	/* received QUIT code             */
+#define IntrEOF 	0x80	/* received EOF code              */
+
+#define IntrRxTrigger 	0x100	/* rx data count reach tigger value */
+#define IntrTxTrigger 	0x200	/* tx data count below trigger value */
+
+#define Magic_no	(Config_base + 0)
+#define Card_model_no	(Config_base + 2)
+#define Total_ports	(Config_base + 4)
+#define Module_cnt	(Config_base + 8)
+#define Module_no	(Config_base + 10)
+#define Timer_10ms	(Config_base + 14)
+#define Disable_IRQ	(Config_base + 20)
+#define TMS320_PORT1	(Config_base + 22)
+#define TMS320_PORT2	(Config_base + 24)
+#define TMS320_CLOCK	(Config_base + 26)
+
+/*
+ *    DATA BUFFER in DRAM
+ */
+#define Extern_table	0x400	/* Base address of the external table
+				   (24 words *    64) total 3K bytes
+				   (24 words * 128) total 6K bytes */
+#define Extern_size	0x60	/* 96 bytes                       */
+#define RXrptr		0x00	/* read pointer for RX buffer     */
+#define RXwptr		0x02	/* write pointer for RX buffer    */
+#define TXrptr		0x04	/* read pointer for TX buffer     */
+#define TXwptr		0x06	/* write pointer for TX buffer    */
+#define HostStat	0x08	/* IRQ flag and general flag      */
+#define FlagStat	0x0A
+#define FlowControl	0x0C	/* B7 B6 B5 B4 B3 B2 B1 B0              */
+					/*  x  x  x  x  |  |  |  |            */
+					/*              |  |  |  + CTS flow   */
+					/*              |  |  +--- RTS flow   */
+					/*              |  +------ TX Xon/Xoff */
+					/*              +--------- RX Xon/Xoff */
+#define Break_cnt	0x0E	/* received break count   */
+#define CD180TXirq	0x10	/* if non-0: enable TX irq        */
+#define RX_mask 	0x12
+#define TX_mask 	0x14
+#define Ofs_rxb 	0x16
+#define Ofs_txb 	0x18
+#define Page_rxb	0x1A
+#define Page_txb	0x1C
+#define EndPage_rxb	0x1E
+#define EndPage_txb	0x20
+#define Data_error	0x22
+#define RxTrigger	0x28
+#define TxTrigger	0x2a
+
+#define rRXwptr 	0x34
+#define Low_water	0x36
+
+#define FuncCode	0x40
+#define FuncArg 	0x42
+#define FuncArg1	0x44
+
+#define C218rx_size	0x2000	/* 8K bytes */
+#define C218tx_size	0x8000	/* 32K bytes */
+
+#define C218rx_mask	(C218rx_size - 1)
+#define C218tx_mask	(C218tx_size - 1)
+
+#define C320p8rx_size	0x2000
+#define C320p8tx_size	0x8000
+#define C320p8rx_mask	(C320p8rx_size - 1)
+#define C320p8tx_mask	(C320p8tx_size - 1)
+
+#define C320p16rx_size	0x2000
+#define C320p16tx_size	0x4000
+#define C320p16rx_mask	(C320p16rx_size - 1)
+#define C320p16tx_mask	(C320p16tx_size - 1)
+
+#define C320p24rx_size	0x2000
+#define C320p24tx_size	0x2000
+#define C320p24rx_mask	(C320p24rx_size - 1)
+#define C320p24tx_mask	(C320p24tx_size - 1)
+
+#define C320p32rx_size	0x1000
+#define C320p32tx_size	0x1000
+#define C320p32rx_mask	(C320p32rx_size - 1)
+#define C320p32tx_mask	(C320p32tx_size - 1)
+
+#define Page_size	0x2000
+#define Page_mask	(Page_size - 1)
+#define C218rx_spage	3
+#define C218tx_spage	4
+#define C218rx_pageno	1
+#define C218tx_pageno	4
+#define C218buf_pageno	5
+
+#define C320p8rx_spage	3
+#define C320p8tx_spage	4
+#define C320p8rx_pgno	1
+#define C320p8tx_pgno	4
+#define C320p8buf_pgno	5
+
+#define C320p16rx_spage 3
+#define C320p16tx_spage 4
+#define C320p16rx_pgno	1
+#define C320p16tx_pgno	2
+#define C320p16buf_pgno 3
+
+#define C320p24rx_spage 3
+#define C320p24tx_spage 4
+#define C320p24rx_pgno	1
+#define C320p24tx_pgno	1
+#define C320p24buf_pgno 2
+
+#define C320p32rx_spage 3
+#define C320p32tx_ofs	C320p32rx_size
+#define C320p32tx_spage 3
+#define C320p32buf_pgno 1
+
+/*
+ *    Host Status
+ */
+#define WakeupRx	0x01
+#define WakeupTx	0x02
+#define WakeupBreak	0x08
+#define WakeupLine	0x10
+#define WakeupIntr	0x20
+#define WakeupQuit	0x40
+#define WakeupEOF	0x80	/* used in VTIME control */
+#define WakeupRxTrigger	0x100
+#define WakeupTxTrigger	0x200
+/*
+ *    Flag status
+ */
+#define Rx_over		0x01
+#define Xoff_state	0x02
+#define Tx_flowOff	0x04
+#define Tx_enable	0x08
+#define CTS_state	0x10
+#define DSR_state	0x20
+#define DCD_state	0x80
+/*
+ *    FlowControl
+ */
+#define CTS_FlowCtl	1
+#define RTS_FlowCtl	2
+#define Tx_FlowCtl	4
+#define Rx_FlowCtl	8
+#define IXM_IXANY	0x10
+
+#define LowWater	128
+
+#define DTR_ON		1
+#define RTS_ON		2
+#define CTS_ON		1
+#define DSR_ON		2
+#define DCD_ON		8
+
+/* mode definition */
+#define	MX_CS8		0x03
+#define	MX_CS7		0x02
+#define	MX_CS6		0x01
+#define	MX_CS5		0x00
+
+#define	MX_STOP1	0x00
+#define	MX_STOP15	0x04
+#define	MX_STOP2	0x08
+
+#define	MX_PARNONE	0x00
+#define	MX_PAREVEN	0x40
+#define	MX_PARODD	0xC0
+
+/*
+ *    Query
+ */
+#define QueryPort	MAX_PORTS
+
+
+
+struct mon_str {
+	int tick;
+	int rxcnt[MAX_PORTS];
+	int txcnt[MAX_PORTS];
+};
+typedef struct mon_str mon_st;
+
+#define 	DCD_changed	0x01
+#define 	DCD_oldstate	0x80
+
+static unsigned char moxaBuff[10240];
+static unsigned long moxaIntNdx[MAX_BOARDS];
+static unsigned long moxaIntPend[MAX_BOARDS];
+static unsigned long moxaIntTable[MAX_BOARDS];
+static char moxaChkPort[MAX_PORTS];
+static char moxaLineCtrl[MAX_PORTS];
+static unsigned long moxaTableAddr[MAX_PORTS];
+static long moxaCurBaud[MAX_PORTS];
+static char moxaDCDState[MAX_PORTS];
+static char moxaLowChkFlag[MAX_PORTS];
+static int moxaLowWaterChk;
+static int moxaCard;
+static mon_st moxaLog;
+static int moxaFuncTout;
+static ushort moxaBreakCnt[MAX_PORTS];
+
+static void moxadelay(int);
+static void moxafunc(unsigned long, int, ushort);
+static void wait_finish(unsigned long);
+static void low_water_check(unsigned long);
+static int moxaloadbios(int, unsigned char *, int);
+static int moxafindcard(int);
+static int moxaload320b(int, unsigned char *, int);
+static int moxaloadcode(int, unsigned char *, int);
+static int moxaloadc218(int, unsigned long, int);
+static int moxaloadc320(int, unsigned long, int, int *);
+
+/*****************************************************************************
+ *	Driver level functions: 					     *
+ *	1. MoxaDriverInit(void);					     *
+ *	2. MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);   *
+ *	3. MoxaDriverPoll(void);					     *
+ *****************************************************************************/
+void MoxaDriverInit(void)
+{
+	int i;
+
+	moxaFuncTout = HZ / 2;	/* 500 mini-seconds */
+	moxaCard = 0;
+	moxaLog.tick = 0;
+	moxaLowWaterChk = 0;
+	for (i = 0; i < MAX_PORTS; i++) {
+		moxaChkPort[i] = 0;
+		moxaLowChkFlag[i] = 0;
+		moxaLineCtrl[i] = 0;
+		moxaLog.rxcnt[i] = 0;
+		moxaLog.txcnt[i] = 0;
+	}
+}
+
+#define	MOXA		0x400
+#define MOXA_GET_IQUEUE 	(MOXA + 1)	/* get input buffered count */
+#define MOXA_GET_OQUEUE 	(MOXA + 2)	/* get output buffered count */
+#define MOXA_INIT_DRIVER	(MOXA + 6)	/* moxaCard=0 */
+#define MOXA_LOAD_BIOS		(MOXA + 9)	/* download BIOS */
+#define MOXA_FIND_BOARD		(MOXA + 10)	/* Check if MOXA card exist? */
+#define MOXA_LOAD_C320B		(MOXA + 11)	/* download 320B firmware */
+#define MOXA_LOAD_CODE		(MOXA + 12)	/* download firmware */
+#define MOXA_GETDATACOUNT       (MOXA + 23)
+#define MOXA_GET_IOQUEUE	(MOXA + 27)
+#define MOXA_FLUSH_QUEUE	(MOXA + 28)
+#define MOXA_GET_CONF		(MOXA + 35)	/* configuration */
+#define MOXA_GET_MAJOR          (MOXA + 63)
+#define MOXA_GET_CUMAJOR        (MOXA + 64)
+#define MOXA_GETMSTATUS         (MOXA + 65)
+
+
+struct moxaq_str {
+	int inq;
+	int outq;
+};
+
+struct dl_str {
+	char *buf;
+	int len;
+	int cardno;
+};
+
+static struct moxaq_str temp_queue[MAX_PORTS];
+static struct dl_str dltmp;
+
+void MoxaPortFlushData(int port, int mode)
+{
+	unsigned long ofsAddr;
+	if ((mode < 0) || (mode > 2))
+		return;
+	ofsAddr = moxaTableAddr[port];
+	moxafunc(ofsAddr, FC_FlushQueue, mode);
+	if (mode != 1) {
+		moxaLowChkFlag[port] = 0;
+		low_water_check(ofsAddr);
+	}
+}
+
+int MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port)
+{
+	int i;
+	int status;
+	int MoxaPortTxQueue(int), MoxaPortRxQueue(int);
+
+	if (port == QueryPort) {
+		if ((cmd != MOXA_GET_CONF) && (cmd != MOXA_INIT_DRIVER) &&
+		    (cmd != MOXA_LOAD_BIOS) && (cmd != MOXA_FIND_BOARD) && (cmd != MOXA_LOAD_C320B) &&
+		 (cmd != MOXA_LOAD_CODE) && (cmd != MOXA_GETDATACOUNT) &&
+		  (cmd != MOXA_GET_IOQUEUE) && (cmd != MOXA_GET_MAJOR) &&
+		    (cmd != MOXA_GET_CUMAJOR) && (cmd != MOXA_GETMSTATUS))
+			return (-EINVAL);
+	}
+	switch (cmd) {
+	case MOXA_GET_CONF:
+		if(copy_to_user((void *)arg, &moxa_boards, MAX_BOARDS * sizeof(moxa_board_conf)))
+			return -EFAULT;
+		return (0);
+	case MOXA_INIT_DRIVER:
+		if ((int) arg == 0x404)
+			MoxaDriverInit();
+		return (0);
+	case MOXA_GETDATACOUNT:
+		moxaLog.tick = jiffies;
+		if(copy_to_user((void *)arg, &moxaLog, sizeof(mon_st)))
+			return -EFAULT;
+		return (0);
+	case MOXA_FLUSH_QUEUE:
+		MoxaPortFlushData(port, arg);
+		return (0);
+	case MOXA_GET_IOQUEUE:
+		for (i = 0; i < MAX_PORTS; i++) {
+			if (moxaChkPort[i]) {
+				temp_queue[i].inq = MoxaPortRxQueue(i);
+				temp_queue[i].outq = MoxaPortTxQueue(i);
+			}
+		}
+		if(copy_to_user((void *)arg, temp_queue, sizeof(struct moxaq_str) * MAX_PORTS))
+			return -EFAULT;
+		return (0);
+	case MOXA_LOAD_BIOS:
+		if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str)))
+			return -EFAULT;
+		i = moxaloadbios(dltmp.cardno, dltmp.buf, dltmp.len);
+		return (i);
+	case MOXA_FIND_BOARD:
+		if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str)))
+			return -EFAULT;
+		return moxafindcard(dltmp.cardno);
+	case MOXA_LOAD_C320B:
+		if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str)))
+			return -EFAULT;
+		moxaload320b(dltmp.cardno, dltmp.buf, dltmp.len);
+		return (0);
+	case MOXA_LOAD_CODE:
+		if(copy_from_user(&dltmp, (void *)arg, sizeof(struct dl_str)))
+			return -EFAULT; 
+		i = moxaloadcode(dltmp.cardno, dltmp.buf, dltmp.len);
+		if (i == -1)
+			return (-EFAULT);
+		return (i);
+	case MOXA_GET_OQUEUE:
+		i = MoxaPortTxQueue(port);
+		return put_user(i, (unsigned long *) arg);
+	case MOXA_GET_IQUEUE:
+		i = MoxaPortRxQueue(port);
+		return put_user(i, (unsigned long *) arg);
+	case MOXA_GET_MAJOR:
+		if(copy_to_user((void *)arg, &ttymajor, sizeof(int)))
+			return -EFAULT;
+		return 0;
+	case MOXA_GET_CUMAJOR:
+		if(copy_to_user((void *)arg, &calloutmajor, sizeof(int)))
+			return -EFAULT;
+		return 0;
+	case MOXA_GETMSTATUS:
+		for (i = 0; i < MAX_PORTS; i++) {
+			GMStatus[i].ri = 0;
+			GMStatus[i].dcd = 0;
+			GMStatus[i].dsr = 0;
+			GMStatus[i].cts = 0;
+			if (!moxaChkPort[i]) {
+				continue;
+			} else {
+				status = MoxaPortLineStatus(moxaChannels[i].port);
+				if (status & 1)
+					GMStatus[i].cts = 1;
+				if (status & 2)
+					GMStatus[i].dsr = 1;
+				if (status & 4)
+					GMStatus[i].dcd = 1;
+			}
+
+			if (!moxaChannels[i].tty || !moxaChannels[i].tty->termios)
+				GMStatus[i].cflag = moxaChannels[i].normal_termios.c_cflag;
+			else
+				GMStatus[i].cflag = moxaChannels[i].tty->termios->c_cflag;
+		}
+		if(copy_to_user((void *)arg, GMStatus, sizeof(struct mxser_mstatus) * MAX_PORTS))
+			return -EFAULT;
+		return 0;
+
+	}
+	return (-ENOIOCTLCMD);
+}
+
+int MoxaDriverPoll(void)
+{
+	register ushort temp;
+	register int card;
+	unsigned long ip, ofsAddr;
+	int port, p, ports;
+
+	if (moxaCard == 0)
+		return (-1);
+	for (card = 0; card < MAX_BOARDS; card++) {
+		if ((ports = moxa_boards[card].numPorts) == 0)
+			continue;
+		if (readb(moxaIntPend[card]) == 0xff) {
+			ip = moxaIntTable[card] + readb(moxaIntNdx[card]);
+			p = card * MAX_PORTS_PER_BOARD;
+			ports <<= 1;
+			for (port = 0; port < ports; port += 2, p++) {
+				if ((temp = readw(ip + port)) != 0) {
+					writew(0, ip + port);
+					ofsAddr = moxaTableAddr[p];
+					if (temp & IntrTx)
+						writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat);
+					if (temp & IntrBreak) {
+						moxaBreakCnt[p]++;
+					}
+					if (temp & IntrLine) {
+						if (readb(ofsAddr + FlagStat) & DCD_state) {
+							if ((moxaDCDState[p] & DCD_oldstate) == 0)
+								moxaDCDState[p] = (DCD_oldstate |
+										   DCD_changed);
+						} else {
+							if (moxaDCDState[p] & DCD_oldstate)
+								moxaDCDState[p] = DCD_changed;
+						}
+					}
+				}
+			}
+			writeb(0, moxaIntPend[card]);
+		}
+		if (moxaLowWaterChk) {
+			p = card * MAX_PORTS_PER_BOARD;
+			for (port = 0; port < ports; port++, p++) {
+				if (moxaLowChkFlag[p]) {
+					moxaLowChkFlag[p] = 0;
+					ofsAddr = moxaTableAddr[p];
+					low_water_check(ofsAddr);
+				}
+			}
+		}
+	}
+	moxaLowWaterChk = 0;
+	return (0);
+}
+
+/*****************************************************************************
+ *	Card level function:						     *
+ *	1. MoxaPortsOfCard(int cardno); 				     *
+ *****************************************************************************/
+int MoxaPortsOfCard(int cardno)
+{
+
+	if (moxa_boards[cardno].boardType == 0)
+		return (0);
+	return (moxa_boards[cardno].numPorts);
+}
+
+/*****************************************************************************
+ *	Port level functions:						     *
+ *	1.  MoxaPortIsValid(int port);					     *
+ *	2.  MoxaPortEnable(int port);					     *
+ *	3.  MoxaPortDisable(int port);					     *
+ *	4.  MoxaPortGetMaxBaud(int port);				     *
+ *	5.  MoxaPortGetCurBaud(int port);				     *
+ *	6.  MoxaPortSetBaud(int port, long baud);			     *
+ *	7.  MoxaPortSetMode(int port, int databit, int stopbit, int parity); *
+ *	8.  MoxaPortSetTermio(int port, unsigned char *termio); 	     *
+ *	9.  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);      *
+ *	10. MoxaPortLineCtrl(int port, int dtrState, int rtsState);	     *
+ *	11. MoxaPortFlowCtrl(int port, int rts, int cts, int rx, int tx,int xany);    *
+ *	12. MoxaPortLineStatus(int port);				     *
+ *	13. MoxaPortDCDChange(int port);				     *
+ *	14. MoxaPortDCDON(int port);					     *
+ *	15. MoxaPortFlushData(int port, int mode);	                     *
+ *	16. MoxaPortWriteData(int port, unsigned char * buffer, int length); *
+ *	17. MoxaPortReadData(int port, unsigned char * buffer, int length);  *
+ *	18. MoxaPortTxBufSize(int port);				     *
+ *	19. MoxaPortRxBufSize(int port);				     *
+ *	20. MoxaPortTxQueue(int port);					     *
+ *	21. MoxaPortTxFree(int port);					     *
+ *	22. MoxaPortRxQueue(int port);					     *
+ *	23. MoxaPortRxFree(int port);					     *
+ *	24. MoxaPortTxDisable(int port);				     *
+ *	25. MoxaPortTxEnable(int port); 				     *
+ *	26. MoxaPortGetBrkCnt(int port);				     *
+ *	27. MoxaPortResetBrkCnt(int port);				     *
+ *	28. MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);	     *
+ *	29. MoxaPortIsTxHold(int port); 				     *
+ *	30. MoxaPortSendBreak(int port, int ticks);			     *
+ *****************************************************************************/
+/*
+ *    Moxa Port Number Description:
+ *
+ *      MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
+ *      the port number using in MOXA driver functions will be 0 to 31 for
+ *      first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
+ *      to 127 for fourth. For example, if you setup three MOXA boards,
+ *      first board is C218, second board is C320-16 and third board is
+ *      C320-32. The port number of first board (C218 - 8 ports) is from
+ *      0 to 7. The port number of second board (C320 - 16 ports) is form
+ *      32 to 47. The port number of third board (C320 - 32 ports) is from
+ *      64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
+ *      127 will be invalid.
+ *
+ *
+ *      Moxa Functions Description:
+ *
+ *      Function 1:     Driver initialization routine, this routine must be
+ *                      called when initialized driver.
+ *      Syntax:
+ *      void MoxaDriverInit();
+ *
+ *
+ *      Function 2:     Moxa driver private IOCTL command processing.
+ *      Syntax:
+ *      int  MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
+ *
+ *           unsigned int cmd   : IOCTL command
+ *           unsigned long arg  : IOCTL argument
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0  (OK)
+ *                      -EINVAL
+ *                      -ENOIOCTLCMD
+ *
+ *
+ *      Function 3:     Moxa driver polling process routine.
+ *      Syntax:
+ *      int  MoxaDriverPoll(void);
+ *
+ *           return:    0       ; polling O.K.
+ *                      -1      : no any Moxa card.             
+ *
+ *
+ *      Function 4:     Get the ports of this card.
+ *      Syntax:
+ *      int  MoxaPortsOfCard(int cardno);
+ *
+ *           int cardno         : card number (0 - 3)
+ *
+ *           return:    0       : this card is invalid
+ *                      8/16/24/32
+ *
+ *
+ *      Function 5:     Check this port is valid or invalid
+ *      Syntax:
+ *      int  MoxaPortIsValid(int port);
+ *           int port           : port number (0 - 127, ref port description)
+ *
+ *           return:    0       : this port is invalid
+ *                      1       : this port is valid
+ *
+ *
+ *      Function 6:     Enable this port to start Tx/Rx data.
+ *      Syntax:
+ *      void MoxaPortEnable(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *
+ *      Function 7:     Disable this port
+ *      Syntax:
+ *      void MoxaPortDisable(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *
+ *      Function 8:     Get the maximun available baud rate of this port.
+ *      Syntax:
+ *      long MoxaPortGetMaxBaud(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0       : this port is invalid
+ *                      38400/57600/115200 bps
+ *
+ *
+ *      Function 9:     Get the current baud rate of this port.
+ *      Syntax:
+ *      long MoxaPortGetCurBaud(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0       : this port is invalid
+ *                      50 - 115200 bps
+ *
+ *
+ *      Function 10:    Setting baud rate of this port.
+ *      Syntax:
+ *      long MoxaPortSetBaud(int port, long baud);
+ *           int port           : port number (0 - 127)
+ *           long baud          : baud rate (50 - 115200)
+ *
+ *           return:    0       : this port is invalid or baud < 50
+ *                      50 - 115200 : the real baud rate set to the port, if
+ *                                    the argument baud is large than maximun
+ *                                    available baud rate, the real setting
+ *                                    baud rate will be the maximun baud rate.
+ *
+ *
+ *      Function 11:    Setting the data-bits/stop-bits/parity of this port
+ *      Syntax:
+ *      int  MoxaPortSetMode(int port, int databits, int stopbits, int parity);
+ *           int port           : port number (0 - 127)
+ *           int databits       : data bits (8/7/6/5)
+ *           int stopbits       : stop bits (2/1/0, 0 show 1.5 stop bits)
+ int parity     : parity (0:None,1:Odd,2:Even,3:Mark,4:Space)
+ *
+ *           return:    -1      : invalid parameter
+ *                      0       : setting O.K.
+ *
+ *
+ *      Function 12:    Configure the port.
+ *      Syntax:
+ *      int  MoxaPortSetTermio(int port, struct termios *termio);
+ *           int port           : port number (0 - 127)
+ *           struct termios * termio : termio structure pointer
+ *
+ *           return:    -1      : this port is invalid or termio == NULL
+ *                      0       : setting O.K.
+ *
+ *
+ *      Function 13:    Get the DTR/RTS state of this port.
+ *      Syntax:
+ *      int  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
+ *           int port           : port number (0 - 127)
+ *           int * dtrState     : pointer to INT to receive the current DTR
+ *                                state. (if NULL, this function will not
+ *                                write to this address)
+ *           int * rtsState     : pointer to INT to receive the current RTS
+ *                                state. (if NULL, this function will not
+ *                                write to this address)
+ *
+ *           return:    -1      : this port is invalid
+ *                      0       : O.K.
+ *
+ *
+ *      Function 14:    Setting the DTR/RTS output state of this port.
+ *      Syntax:
+ *      void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
+ *           int port           : port number (0 - 127)
+ *           int dtrState       : DTR output state (0: off, 1: on)
+ *           int rtsState       : RTS output state (0: off, 1: on)
+ *
+ *
+ *      Function 15:    Setting the flow control of this port.
+ *      Syntax:
+ *      void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
+ *                            int txFlow,int xany);
+ *           int port           : port number (0 - 127)
+ *           int rtsFlow        : H/W RTS flow control (0: no, 1: yes)
+ *           int ctsFlow        : H/W CTS flow control (0: no, 1: yes)
+ *           int rxFlow         : S/W Rx XON/XOFF flow control (0: no, 1: yes)
+ *           int txFlow         : S/W Tx XON/XOFF flow control (0: no, 1: yes)
+ *           int xany           : S/W XANY flow control (0: no, 1: yes)
+ *
+ *
+ *      Function 16:    Get ths line status of this port
+ *      Syntax:
+ *      int  MoxaPortLineStatus(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    Bit 0 - CTS state (0: off, 1: on)
+ *                      Bit 1 - DSR state (0: off, 1: on)
+ *                      Bit 2 - DCD state (0: off, 1: on)
+ *
+ *
+ *      Function 17:    Check the DCD state has changed since the last read
+ *                      of this function.
+ *      Syntax:
+ *      int  MoxaPortDCDChange(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0       : no changed
+ *                      1       : DCD has changed
+ *
+ *
+ *      Function 18:    Check ths current DCD state is ON or not.
+ *      Syntax:
+ *      int  MoxaPortDCDON(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0       : DCD off
+ *                      1       : DCD on
+ *
+ *
+ *      Function 19:    Flush the Rx/Tx buffer data of this port.
+ *      Syntax:
+ *      void MoxaPortFlushData(int port, int mode);
+ *           int port           : port number (0 - 127)
+ *           int mode    
+ *                      0       : flush the Rx buffer 
+ *                      1       : flush the Tx buffer 
+ *                      2       : flush the Rx and Tx buffer 
+ *
+ *
+ *      Function 20:    Write data.
+ *      Syntax:
+ *      int  MoxaPortWriteData(int port, unsigned char * buffer, int length);
+ *           int port           : port number (0 - 127)
+ *           unsigned char * buffer     : pointer to write data buffer.
+ *           int length         : write data length
+ *
+ *           return:    0 - length      : real write data length
+ *
+ *
+ *      Function 21:    Read data.
+ *      Syntax:
+ *      int  MoxaPortReadData(int port, unsigned char * buffer, int length);
+ *           int port           : port number (0 - 127)
+ *           unsigned char * buffer     : pointer to read data buffer.
+ *           int length         : read data buffer length
+ *
+ *           return:    0 - length      : real read data length
+ *
+ *
+ *      Function 22:    Get the Tx buffer size of this port
+ *      Syntax:
+ *      int  MoxaPortTxBufSize(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Tx buffer size
+ *
+ *
+ *      Function 23:    Get the Rx buffer size of this port
+ *      Syntax:
+ *      int  MoxaPortRxBufSize(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Rx buffer size
+ *
+ *
+ *      Function 24:    Get the Tx buffer current queued data bytes
+ *      Syntax:
+ *      int  MoxaPortTxQueue(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Tx buffer current queued data bytes
+ *
+ *
+ *      Function 25:    Get the Tx buffer current free space
+ *      Syntax:
+ *      int  MoxaPortTxFree(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Tx buffer current free space
+ *
+ *
+ *      Function 26:    Get the Rx buffer current queued data bytes
+ *      Syntax:
+ *      int  MoxaPortRxQueue(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Rx buffer current queued data bytes
+ *
+ *
+ *      Function 27:    Get the Rx buffer current free space
+ *      Syntax:
+ *      int  MoxaPortRxFree(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    ..      : Rx buffer current free space
+ *
+ *
+ *      Function 28:    Disable port data transmission.
+ *      Syntax:
+ *      void MoxaPortTxDisable(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *
+ *      Function 29:    Enable port data transmission.
+ *      Syntax:
+ *      void MoxaPortTxEnable(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *
+ *      Function 30:    Get the received BREAK signal count.
+ *      Syntax:
+ *      int  MoxaPortGetBrkCnt(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0 - ..  : BREAK signal count
+ *
+ *
+ *      Function 31:    Get the received BREAK signal count and reset it.
+ *      Syntax:
+ *      int  MoxaPortResetBrkCnt(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0 - ..  : BREAK signal count
+ *
+ *
+ *      Function 32:    Set the S/W flow control new XON/XOFF value, default
+ *                      XON is 0x11 & XOFF is 0x13.
+ *      Syntax:
+ *      void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue);
+ *           int port           : port number (0 - 127)
+ *           int xonValue       : new XON value (0 - 255)
+ *           int xoffValue      : new XOFF value (0 - 255)
+ *
+ *
+ *      Function 33:    Check this port's transmission is hold by remote site
+ *                      because the flow control.
+ *      Syntax:
+ *      int  MoxaPortIsTxHold(int port);
+ *           int port           : port number (0 - 127)
+ *
+ *           return:    0       : normal
+ *                      1       : hold by remote site
+ *
+ *
+ *      Function 34:    Send out a BREAK signal.
+ *      Syntax:
+ *      void MoxaPortSendBreak(int port, int ms100);
+ *           int port           : port number (0 - 127)
+ *           int ms100          : break signal time interval.
+ *                                unit: 100 mini-second. if ms100 == 0, it will
+ *                                send out a about 250 ms BREAK signal.
+ *
+ */
+int MoxaPortIsValid(int port)
+{
+
+	if (moxaCard == 0)
+		return (0);
+	if (moxaChkPort[port] == 0)
+		return (0);
+	return (1);
+}
+
+void MoxaPortEnable(int port)
+{
+	unsigned long ofsAddr;
+	int MoxaPortLineStatus(int);
+	short lowwater = 512;
+
+	ofsAddr = moxaTableAddr[port];
+	writew(lowwater, ofsAddr + Low_water);
+	moxaBreakCnt[port] = 0;
+	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
+		moxafunc(ofsAddr, FC_SetBreakIrq, 0);
+	} else {
+		writew(readw(ofsAddr + HostStat) | WakeupBreak, ofsAddr + HostStat);
+	}
+
+	moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
+	moxafunc(ofsAddr, FC_FlushQueue, 2);
+
+	moxafunc(ofsAddr, FC_EnableCH, Magic_code);
+	MoxaPortLineStatus(port);
+}
+
+void MoxaPortDisable(int port)
+{
+	unsigned long ofsAddr;
+
+	ofsAddr = moxaTableAddr[port];
+	moxafunc(ofsAddr, FC_SetFlowCtl, 0);	/* disable flow control */
+	moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
+	writew(0, ofsAddr + HostStat);
+	moxafunc(ofsAddr, FC_DisableCH, Magic_code);
+}
+
+long MoxaPortGetMaxBaud(int port)
+{
+	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI))
+		return (460800L);
+	else
+		return (921600L);
+}
+
+
+long MoxaPortSetBaud(int port, long baud)
+{
+	unsigned long ofsAddr;
+	long max, clock;
+	unsigned int val;
+
+	if ((baud < 50L) || ((max = MoxaPortGetMaxBaud(port)) == 0))
+		return (0);
+	ofsAddr = moxaTableAddr[port];
+	if (baud > max)
+		baud = max;
+	if (max == 38400L)
+		clock = 614400L;	/* for 9.8304 Mhz : max. 38400 bps */
+	else if (max == 57600L)
+		clock = 691200L;	/* for 11.0592 Mhz : max. 57600 bps */
+	else
+		clock = 921600L;	/* for 14.7456 Mhz : max. 115200 bps */
+	val = clock / baud;
+	moxafunc(ofsAddr, FC_SetBaud, val);
+	baud = clock / val;
+	moxaCurBaud[port] = baud;
+	return (baud);
+}
+
+int MoxaPortSetTermio(int port, struct termios *termio)
+{
+	unsigned long ofsAddr;
+	tcflag_t cflag;
+	long baud;
+	tcflag_t mode = 0;
+
+	if (moxaChkPort[port] == 0 || termio == 0)
+		return (-1);
+	ofsAddr = moxaTableAddr[port];
+	cflag = termio->c_cflag;	/* termio->c_cflag */
+
+	mode = termio->c_cflag & CSIZE;
+	if (mode == CS5)
+		mode = MX_CS5;
+	else if (mode == CS6)
+		mode = MX_CS6;
+	else if (mode == CS7)
+		mode = MX_CS7;
+	else if (mode == CS8)
+		mode = MX_CS8;
+
+	if (termio->c_cflag & CSTOPB) {
+		if (mode == MX_CS5)
+			mode |= MX_STOP15;
+		else
+			mode |= MX_STOP2;
+	} else
+		mode |= MX_STOP1;
+
+	if (termio->c_cflag & PARENB) {
+		if (termio->c_cflag & PARODD)
+			mode |= MX_PARODD;
+		else
+			mode |= MX_PAREVEN;
+	} else
+		mode |= MX_PARNONE;
+
+	moxafunc(ofsAddr, FC_SetDataMode, (ushort) mode);
+
+	cflag &= (CBAUD | CBAUDEX);
+#ifndef B921600
+#define	B921600	(B460800+1)
+#endif
+	switch (cflag) {
+	case B921600:
+		baud = 921600L;
+		break;
+	case B460800:
+		baud = 460800L;
+		break;
+	case B230400:
+		baud = 230400L;
+		break;
+	case B115200:
+		baud = 115200L;
+		break;
+	case B57600:
+		baud = 57600L;
+		break;
+	case B38400:
+		baud = 38400L;
+		break;
+	case B19200:
+		baud = 19200L;
+		break;
+	case B9600:
+		baud = 9600L;
+		break;
+	case B4800:
+		baud = 4800L;
+		break;
+	case B2400:
+		baud = 2400L;
+		break;
+	case B1800:
+		baud = 1800L;
+		break;
+	case B1200:
+		baud = 1200L;
+		break;
+	case B600:
+		baud = 600L;
+		break;
+	case B300:
+		baud = 300L;
+		break;
+	case B200:
+		baud = 200L;
+		break;
+	case B150:
+		baud = 150L;
+		break;
+	case B134:
+		baud = 134L;
+		break;
+	case B110:
+		baud = 110L;
+		break;
+	case B75:
+		baud = 75L;
+		break;
+	case B50:
+		baud = 50L;
+		break;
+	default:
+		baud = 0;
+	}
+	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
+		if (baud == 921600L)
+			return (-1);
+	}
+	MoxaPortSetBaud(port, baud);
+
+	if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
+		writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
+		writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
+		writeb(FC_SetXonXoff, ofsAddr + FuncCode);
+		wait_finish(ofsAddr);
+
+	}
+	return (0);
+}
+
+int MoxaPortGetLineOut(int port, int *dtrState, int *rtsState)
+{
+
+	if (!MoxaPortIsValid(port))
+		return (-1);
+	if (dtrState) {
+		if (moxaLineCtrl[port] & DTR_ON)
+			*dtrState = 1;
+		else
+			*dtrState = 0;
+	}
+	if (rtsState) {
+		if (moxaLineCtrl[port] & RTS_ON)
+			*rtsState = 1;
+		else
+			*rtsState = 0;
+	}
+	return (0);
+}
+
+void MoxaPortLineCtrl(int port, int dtr, int rts)
+{
+	unsigned long ofsAddr;
+	int mode;
+
+	ofsAddr = moxaTableAddr[port];
+	mode = 0;
+	if (dtr)
+		mode |= DTR_ON;
+	if (rts)
+		mode |= RTS_ON;
+	moxaLineCtrl[port] = mode;
+	moxafunc(ofsAddr, FC_LineControl, mode);
+}
+
+void MoxaPortFlowCtrl(int port, int rts, int cts, int txflow, int rxflow, int txany)
+{
+	unsigned long ofsAddr;
+	int mode;
+
+	ofsAddr = moxaTableAddr[port];
+	mode = 0;
+	if (rts)
+		mode |= RTS_FlowCtl;
+	if (cts)
+		mode |= CTS_FlowCtl;
+	if (txflow)
+		mode |= Tx_FlowCtl;
+	if (rxflow)
+		mode |= Rx_FlowCtl;
+	if (txany)
+		mode |= IXM_IXANY;
+	moxafunc(ofsAddr, FC_SetFlowCtl, mode);
+}
+
+int MoxaPortLineStatus(int port)
+{
+	unsigned long ofsAddr;
+	int val;
+
+	ofsAddr = moxaTableAddr[port];
+	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
+		moxafunc(ofsAddr, FC_LineStatus, 0);
+		val = readw(ofsAddr + FuncArg);
+	} else {
+		val = readw(ofsAddr + FlagStat) >> 4;
+	}
+	val &= 0x0B;
+	if (val & 8) {
+		val |= 4;
+		if ((moxaDCDState[port] & DCD_oldstate) == 0)
+			moxaDCDState[port] = (DCD_oldstate | DCD_changed);
+	} else {
+		if (moxaDCDState[port] & DCD_oldstate)
+			moxaDCDState[port] = DCD_changed;
+	}
+	val &= 7;
+	return (val);
+}
+
+int MoxaPortDCDChange(int port)
+{
+	int n;
+
+	if (moxaChkPort[port] == 0)
+		return (0);
+	n = moxaDCDState[port];
+	moxaDCDState[port] &= ~DCD_changed;
+	n &= DCD_changed;
+	return (n);
+}
+
+int MoxaPortDCDON(int port)
+{
+	int n;
+
+	if (moxaChkPort[port] == 0)
+		return (0);
+	if (moxaDCDState[port] & DCD_oldstate)
+		n = 1;
+	else
+		n = 0;
+	return (n);
+}
+
+
+/*
+   int MoxaDumpMem(int port, unsigned char * buffer, int len)
+   {
+   int          i;
+   unsigned long                baseAddr,ofsAddr,ofs;
+
+   baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
+   ofs = baseAddr + DynPage_addr + pageofs;
+   if (len > 0x2000L)
+   len = 0x2000L;
+   for (i = 0; i < len; i++)
+   buffer[i] = readb(ofs+i);
+   }
+ */
+
+
+int MoxaPortWriteData(int port, unsigned char * buffer, int len)
+{
+	int c, total, i;
+	ushort tail;
+	int cnt;
+	ushort head, tx_mask, spage, epage;
+	ushort pageno, pageofs, bufhead;
+	unsigned long baseAddr, ofsAddr, ofs;
+
+	ofsAddr = moxaTableAddr[port];
+	baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
+	tx_mask = readw(ofsAddr + TX_mask);
+	spage = readw(ofsAddr + Page_txb);
+	epage = readw(ofsAddr + EndPage_txb);
+	tail = readw(ofsAddr + TXwptr);
+	head = readw(ofsAddr + TXrptr);
+	c = (head > tail) ? (head - tail - 1)
+	    : (head - tail + tx_mask);
+	if (c > len)
+		c = len;
+	moxaLog.txcnt[port] += c;
+	total = c;
+	if (spage == epage) {
+		bufhead = readw(ofsAddr + Ofs_txb);
+		writew(spage, baseAddr + Control_reg);
+		while (c > 0) {
+			if (head > tail)
+				len = head - tail - 1;
+			else
+				len = tx_mask + 1 - tail;
+			len = (c > len) ? len : c;
+			ofs = baseAddr + DynPage_addr + bufhead + tail;
+			for (i = 0; i < len; i++)
+				writeb(*buffer++, ofs + i);
+			tail = (tail + len) & tx_mask;
+			c -= len;
+		}
+		writew(tail, ofsAddr + TXwptr);
+	} else {
+		len = c;
+		pageno = spage + (tail >> 13);
+		pageofs = tail & Page_mask;
+		do {
+			cnt = Page_size - pageofs;
+			if (cnt > c)
+				cnt = c;
+			c -= cnt;
+			writeb(pageno, baseAddr + Control_reg);
+			ofs = baseAddr + DynPage_addr + pageofs;
+			for (i = 0; i < cnt; i++)
+				writeb(*buffer++, ofs + i);
+			if (c == 0) {
+				writew((tail + len) & tx_mask, ofsAddr + TXwptr);
+				break;
+			}
+			if (++pageno == epage)
+				pageno = spage;
+			pageofs = 0;
+		} while (1);
+	}
+	writeb(1, ofsAddr + CD180TXirq);	/* start to send */
+	return (total);
+}
+
+int MoxaPortReadData(int port, unsigned char * buffer, int space)
+{
+	register ushort head, pageofs;
+	int i, count, cnt, len, total, remain;
+	ushort tail, rx_mask, spage, epage;
+	ushort pageno, bufhead;
+	unsigned long baseAddr, ofsAddr, ofs;
+
+	ofsAddr = moxaTableAddr[port];
+	baseAddr = moxaBaseAddr[port / MAX_PORTS_PER_BOARD];
+	head = readw(ofsAddr + RXrptr);
+	tail = readw(ofsAddr + RXwptr);
+	rx_mask = readw(ofsAddr + RX_mask);
+	spage = readw(ofsAddr + Page_rxb);
+	epage = readw(ofsAddr + EndPage_rxb);
+	count = (tail >= head) ? (tail - head)
+	    : (tail - head + rx_mask + 1);
+	if (count == 0)
+		return (0);
+
+	total = (space > count) ? count : space;
+	remain = count - total;
+	moxaLog.rxcnt[port] += total;
+	count = total;
+	if (spage == epage) {
+		bufhead = readw(ofsAddr + Ofs_rxb);
+		writew(spage, baseAddr + Control_reg);
+		while (count > 0) {
+			if (tail >= head)
+				len = tail - head;
+			else
+				len = rx_mask + 1 - head;
+			len = (count > len) ? len : count;
+			ofs = baseAddr + DynPage_addr + bufhead + head;
+			for (i = 0; i < len; i++)
+				*buffer++ = readb(ofs + i);
+			head = (head + len) & rx_mask;
+			count -= len;
+		}
+		writew(head, ofsAddr + RXrptr);
+	} else {
+		len = count;
+		pageno = spage + (head >> 13);
+		pageofs = head & Page_mask;
+		do {
+			cnt = Page_size - pageofs;
+			if (cnt > count)
+				cnt = count;
+			count -= cnt;
+			writew(pageno, baseAddr + Control_reg);
+			ofs = baseAddr + DynPage_addr + pageofs;
+			for (i = 0; i < cnt; i++)
+				*buffer++ = readb(ofs + i);
+			if (count == 0) {
+				writew((head + len) & rx_mask, ofsAddr + RXrptr);
+				break;
+			}
+			if (++pageno == epage)
+				pageno = spage;
+			pageofs = 0;
+		} while (1);
+	}
+	if ((readb(ofsAddr + FlagStat) & Xoff_state) && (remain < LowWater)) {
+		moxaLowWaterChk = 1;
+		moxaLowChkFlag[port] = 1;
+	}
+	return (total);
+}
+
+
+int MoxaPortTxQueue(int port)
+{
+	unsigned long ofsAddr;
+	ushort rptr, wptr, mask;
+	int len;
+
+	ofsAddr = moxaTableAddr[port];
+	rptr = readw(ofsAddr + TXrptr);
+	wptr = readw(ofsAddr + TXwptr);
+	mask = readw(ofsAddr + TX_mask);
+	len = (wptr - rptr) & mask;
+	return (len);
+}
+
+int MoxaPortTxFree(int port)
+{
+	unsigned long ofsAddr;
+	ushort rptr, wptr, mask;
+	int len;
+
+	ofsAddr = moxaTableAddr[port];
+	rptr = readw(ofsAddr + TXrptr);
+	wptr = readw(ofsAddr + TXwptr);
+	mask = readw(ofsAddr + TX_mask);
+	len = mask - ((wptr - rptr) & mask);
+	return (len);
+}
+
+int MoxaPortRxQueue(int port)
+{
+	unsigned long ofsAddr;
+	ushort rptr, wptr, mask;
+	int len;
+
+	ofsAddr = moxaTableAddr[port];
+	rptr = readw(ofsAddr + RXrptr);
+	wptr = readw(ofsAddr + RXwptr);
+	mask = readw(ofsAddr + RX_mask);
+	len = (wptr - rptr) & mask;
+	return (len);
+}
+
+
+void MoxaPortTxDisable(int port)
+{
+	unsigned long ofsAddr;
+
+	ofsAddr = moxaTableAddr[port];
+	moxafunc(ofsAddr, FC_SetXoffState, Magic_code);
+}
+
+void MoxaPortTxEnable(int port)
+{
+	unsigned long ofsAddr;
+
+	ofsAddr = moxaTableAddr[port];
+	moxafunc(ofsAddr, FC_SetXonState, Magic_code);
+}
+
+
+int MoxaPortResetBrkCnt(int port)
+{
+	ushort cnt;
+	cnt = moxaBreakCnt[port];
+	moxaBreakCnt[port] = 0;
+	return (cnt);
+}
+
+
+void MoxaPortSendBreak(int port, int ms100)
+{
+	unsigned long ofsAddr;
+
+	ofsAddr = moxaTableAddr[port];
+	if (ms100) {
+		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
+		moxadelay(ms100 * (HZ / 10));
+	} else {
+		moxafunc(ofsAddr, FC_SendBreak, Magic_code);
+		moxadelay(HZ / 4);	/* 250 ms */
+	}
+	moxafunc(ofsAddr, FC_StopBreak, Magic_code);
+}
+
+static int moxa_get_serial_info(struct moxa_str *info,
+				struct serial_struct *retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return (-EFAULT);
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = info->type;
+	tmp.line = info->port;
+	tmp.port = 0;
+	tmp.irq = 0;
+	tmp.flags = info->asyncflags;
+	tmp.baud_base = 921600;
+	tmp.close_delay = info->close_delay;
+	tmp.closing_wait = info->closing_wait;
+	tmp.custom_divisor = 0;
+	tmp.hub6 = 0;
+	if(copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
+		return -EFAULT;
+	return (0);
+}
+
+
+static int moxa_set_serial_info(struct moxa_str *info,
+				struct serial_struct *new_info)
+{
+	struct serial_struct new_serial;
+
+	if(copy_from_user(&new_serial, new_info, sizeof(new_serial)))
+		return -EFAULT;
+
+	if ((new_serial.irq != 0) ||
+	    (new_serial.port != 0) ||
+//           (new_serial.type != info->type) ||
+	    (new_serial.custom_divisor != 0) ||
+	    (new_serial.baud_base != 921600))
+		return (-EPERM);
+
+	if (!suser()) {
+		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (info->asyncflags & ~ASYNC_USR_MASK)))
+			return (-EPERM);
+	} else {
+		info->close_delay = new_serial.close_delay * HZ / 100;
+		info->closing_wait = new_serial.closing_wait * HZ / 100;
+	}
+
+	new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
+	new_serial.flags |= (info->asyncflags & ASYNC_FLAGS);
+
+	if (new_serial.type == PORT_16550A) {
+		MoxaSetFifo(info->port, 1);
+	} else {
+		MoxaSetFifo(info->port, 0);
+	}
+
+	info->type = new_serial.type;
+	return (0);
+}
+
+
+
+/*****************************************************************************
+ *	Static local functions: 					     *
+ *****************************************************************************/
+/*
+ * moxadelay - delays a specified number ticks
+ */
+static void moxadelay(int tick)
+{
+	unsigned long st, et;
+
+	st = jiffies;
+	et = st + tick;
+	while (jiffies < et);
+}
+
+static void moxafunc(unsigned long ofsAddr, int cmd, ushort arg)
+{
+
+	writew(arg, ofsAddr + FuncArg);
+	writew(cmd, ofsAddr + FuncCode);
+	wait_finish(ofsAddr);
+}
+
+static void wait_finish(unsigned long ofsAddr)
+{
+	unsigned long i, j;
+
+	i = jiffies;
+	while (readw(ofsAddr + FuncCode) != 0) {
+		j = jiffies;
+		if ((j - i) > moxaFuncTout) {
+			return;
+		}
+	}
+}
+
+static void low_water_check(unsigned long ofsAddr)
+{
+	int len;
+	ushort rptr, wptr, mask;
+
+	if (readb(ofsAddr + FlagStat) & Xoff_state) {
+		rptr = readw(ofsAddr + RXrptr);
+		wptr = readw(ofsAddr + RXwptr);
+		mask = readw(ofsAddr + RX_mask);
+		len = (wptr - rptr) & mask;
+		if (len <= Low_water)
+			moxafunc(ofsAddr, FC_SendXon, 0);
+	}
+}
+
+static int moxaloadbios(int cardno, unsigned char *tmp, int len)
+{
+	unsigned long baseAddr;
+	int i;
+
+	if(copy_from_user(moxaBuff, tmp, len))
+		return -EFAULT;
+	baseAddr = moxaBaseAddr[cardno];
+	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
+	moxadelay(1);		/* delay 10 ms */
+	for (i = 0; i < 4096; i++)
+		writeb(0, baseAddr + i);	/* clear fix page */
+	for (i = 0; i < len; i++)
+		writeb(moxaBuff[i], baseAddr + i);	/* download BIOS */
+	writeb(0, baseAddr + Control_reg);	/* restart */
+	return (0);
+}
+
+static int moxafindcard(int cardno)
+{
+	unsigned long baseAddr;
+	ushort tmp;
+
+	baseAddr = moxaBaseAddr[cardno];
+	switch (moxa_boards[cardno].boardType) {
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+		if ((tmp = readw(baseAddr + C218_key)) != C218_KeyCode) {
+			return (-1);
+		}
+		break;
+	case MOXA_BOARD_CP204J:
+		if ((tmp = readw(baseAddr + C218_key)) != CP204J_KeyCode) {
+			return (-1);
+		}
+		break;
+	default:
+		if ((tmp = readw(baseAddr + C320_key)) != C320_KeyCode) {
+			return (-1);
+		}
+		if ((tmp = readw(baseAddr + C320_status)) != STS_init) {
+			return (-2);
+		}
+	}
+	return (0);
+}
+
+static int moxaload320b(int cardno, unsigned char * tmp, int len)
+{
+	unsigned long baseAddr;
+	int i;
+
+	if(copy_from_user(moxaBuff, tmp, len))
+		return -EFAULT;
+	baseAddr = moxaBaseAddr[cardno];
+	writew(len - 7168 - 2, baseAddr + C320bapi_len);
+	writeb(1, baseAddr + Control_reg);	/* Select Page 1 */
+	for (i = 0; i < 7168; i++)
+		writeb(moxaBuff[i], baseAddr + DynPage_addr + i);
+	writeb(2, baseAddr + Control_reg);	/* Select Page 2 */
+	for (i = 0; i < (len - 7168); i++)
+		writeb(moxaBuff[i + 7168], baseAddr + DynPage_addr + i);
+	return (0);
+}
+
+static int moxaloadcode(int cardno, unsigned char * tmp, int len)
+{
+	unsigned long baseAddr, ofsAddr;
+	int retval, port, i;
+
+	if(copy_from_user(moxaBuff, tmp, len))
+		return -EFAULT;
+	baseAddr = moxaBaseAddr[cardno];
+	switch (moxa_boards[cardno].boardType) {
+	case MOXA_BOARD_C218_ISA:
+	case MOXA_BOARD_C218_PCI:
+	case MOXA_BOARD_CP204J:
+		retval = moxaloadc218(cardno, baseAddr, len);
+		if (retval)
+			return (retval);
+		port = cardno * MAX_PORTS_PER_BOARD;
+		for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
+			moxaChkPort[port] = 1;
+			moxaCurBaud[port] = 9600L;
+			moxaDCDState[port] = 0;
+			moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
+			ofsAddr = moxaTableAddr[port];
+			writew(C218rx_mask, ofsAddr + RX_mask);
+			writew(C218tx_mask, ofsAddr + TX_mask);
+			writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
+			writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
+
+			writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
+			writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
+
+		}
+		break;
+	default:
+		retval = moxaloadc320(cardno, baseAddr, len,
+				      &moxa_boards[cardno].numPorts);
+		if (retval)
+			return (retval);
+		port = cardno * MAX_PORTS_PER_BOARD;
+		for (i = 0; i < moxa_boards[cardno].numPorts; i++, port++) {
+			moxaChkPort[port] = 1;
+			moxaCurBaud[port] = 9600L;
+			moxaDCDState[port] = 0;
+			moxaTableAddr[port] = baseAddr + Extern_table + Extern_size * i;
+			ofsAddr = moxaTableAddr[port];
+			if (moxa_boards[cardno].numPorts == 8) {
+				writew(C320p8rx_mask, ofsAddr + RX_mask);
+				writew(C320p8tx_mask, ofsAddr + TX_mask);
+				writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
+				writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
+				writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
+				writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
+
+			} else if (moxa_boards[cardno].numPorts == 16) {
+				writew(C320p16rx_mask, ofsAddr + RX_mask);
+				writew(C320p16tx_mask, ofsAddr + TX_mask);
+				writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
+				writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
+				writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
+				writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
+
+			} else if (moxa_boards[cardno].numPorts == 24) {
+				writew(C320p24rx_mask, ofsAddr + RX_mask);
+				writew(C320p24tx_mask, ofsAddr + TX_mask);
+				writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
+				writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
+				writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
+				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
+			} else if (moxa_boards[cardno].numPorts == 32) {
+				writew(C320p32rx_mask, ofsAddr + RX_mask);
+				writew(C320p32tx_mask, ofsAddr + TX_mask);
+				writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
+				writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
+				writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
+				writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
+				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
+			}
+		}
+		break;
+	}
+	return (0);
+}
+
+static int moxaloadc218(int cardno, unsigned long baseAddr, int len)
+{
+	char retry;
+	int i, j, len1, len2;
+	ushort usum, *ptr, keycode;
+
+	if (moxa_boards[cardno].boardType == MOXA_BOARD_CP204J)
+		keycode = CP204J_KeyCode;
+	else
+		keycode = C218_KeyCode;
+	usum = 0;
+	len1 = len >> 1;
+	ptr = (ushort *) moxaBuff;
+	for (i = 0; i < len1; i++)
+		usum += *(ptr + i);
+	retry = 0;
+	do {
+		len1 = len >> 1;
+		j = 0;
+		while (len1) {
+			len2 = (len1 > 2048) ? 2048 : len1;
+			len1 -= len2;
+			for (i = 0; i < len2 << 1; i++)
+				writeb(moxaBuff[i + j], baseAddr + C218_LoadBuf + i);
+			j += i;
+
+			writew(len2, baseAddr + C218DLoad_len);
+			writew(0, baseAddr + C218_key);
+			for (i = 0; i < 100; i++) {
+				if (readw(baseAddr + C218_key) == keycode)
+					break;
+				moxadelay(1);	/* delay 10 ms */
+			}
+			if (readw(baseAddr + C218_key) != keycode) {
+				return (-1);
+			}
+		}
+		writew(0, baseAddr + C218DLoad_len);
+		writew(usum, baseAddr + C218check_sum);
+		writew(0, baseAddr + C218_key);
+		for (i = 0; i < 100; i++) {
+			if (readw(baseAddr + C218_key) == keycode)
+				break;
+			moxadelay(1);	/* delay 10 ms */
+		}
+		retry++;
+	} while ((readb(baseAddr + C218chksum_ok) != 1) && (retry < 3));
+	if (readb(baseAddr + C218chksum_ok) != 1) {
+		return (-1);
+	}
+	writew(0, baseAddr + C218_key);
+	for (i = 0; i < 100; i++) {
+		if (readw(baseAddr + Magic_no) == Magic_code)
+			break;
+		moxadelay(1);	/* delay 10 ms */
+	}
+	if (readw(baseAddr + Magic_no) != Magic_code) {
+		return (-1);
+	}
+	writew(1, baseAddr + Disable_IRQ);
+	writew(0, baseAddr + Magic_no);
+	for (i = 0; i < 100; i++) {
+		if (readw(baseAddr + Magic_no) == Magic_code)
+			break;
+		moxadelay(1);	/* delay 10 ms */
+	}
+	if (readw(baseAddr + Magic_no) != Magic_code) {
+		return (-1);
+	}
+	moxaCard = 1;
+	moxaIntNdx[cardno] = baseAddr + IRQindex;
+	moxaIntPend[cardno] = baseAddr + IRQpending;
+	moxaIntTable[cardno] = baseAddr + IRQtable;
+	return (0);
+}
+
+static int moxaloadc320(int cardno, unsigned long baseAddr, int len, int *numPorts)
+{
+	ushort usum;
+	int i, j, wlen, len2, retry;
+	ushort *uptr;
+
+	usum = 0;
+	wlen = len >> 1;
+	uptr = (ushort *) moxaBuff;
+	for (i = 0; i < wlen; i++)
+		usum += uptr[i];
+	retry = 0;
+	j = 0;
+	do {
+		while (wlen) {
+			if (wlen > 2048)
+				len2 = 2048;
+			else
+				len2 = wlen;
+			wlen -= len2;
+			len2 <<= 1;
+			for (i = 0; i < len2; i++)
+				writeb(moxaBuff[j + i], baseAddr + C320_LoadBuf + i);
+			len2 >>= 1;
+			j += i;
+			writew(len2, baseAddr + C320DLoad_len);
+			writew(0, baseAddr + C320_key);
+			for (i = 0; i < 10; i++) {
+				if (readw(baseAddr + C320_key) == C320_KeyCode)
+					break;
+				moxadelay(1);
+			}
+			if (readw(baseAddr + C320_key) != C320_KeyCode)
+				return (-1);
+		}
+		writew(0, baseAddr + C320DLoad_len);
+		writew(usum, baseAddr + C320check_sum);
+		writew(0, baseAddr + C320_key);
+		for (i = 0; i < 10; i++) {
+			if (readw(baseAddr + C320_key) == C320_KeyCode)
+				break;
+			moxadelay(1);
+		}
+		retry++;
+	} while ((readb(baseAddr + C320chksum_ok) != 1) && (retry < 3));
+	if (readb(baseAddr + C320chksum_ok) != 1)
+		return (-1);
+	writew(0, baseAddr + C320_key);
+	for (i = 0; i < 600; i++) {
+		if (readw(baseAddr + Magic_no) == Magic_code)
+			break;
+		moxadelay(1);
+	}
+	if (readw(baseAddr + Magic_no) != Magic_code)
+		return (-100);
+
+	if (moxa_boards[cardno].busType == MOXA_BUS_TYPE_PCI) {		/* ASIC board */
+		writew(0x3800, baseAddr + TMS320_PORT1);
+		writew(0x3900, baseAddr + TMS320_PORT2);
+		writew(28499, baseAddr + TMS320_CLOCK);
+	} else {
+		writew(0x3200, baseAddr + TMS320_PORT1);
+		writew(0x3400, baseAddr + TMS320_PORT2);
+		writew(19999, baseAddr + TMS320_CLOCK);
+	}
+	writew(1, baseAddr + Disable_IRQ);
+	writew(0, baseAddr + Magic_no);
+	for (i = 0; i < 500; i++) {
+		if (readw(baseAddr + Magic_no) == Magic_code)
+			break;
+		moxadelay(1);
+	}
+	if (readw(baseAddr + Magic_no) != Magic_code)
+		return (-102);
+
+	j = readw(baseAddr + Module_cnt);
+	if (j <= 0)
+		return (-101);
+	*numPorts = j * 8;
+	writew(j, baseAddr + Module_no);
+	writew(0, baseAddr + Magic_no);
+	for (i = 0; i < 600; i++) {
+		if (readw(baseAddr + Magic_no) == Magic_code)
+			break;
+		moxadelay(1);
+	}
+	if (readw(baseAddr + Magic_no) != Magic_code)
+		return (-102);
+	moxaCard = 1;
+	moxaIntNdx[cardno] = baseAddr + IRQindex;
+	moxaIntPend[cardno] = baseAddr + IRQpending;
+	moxaIntTable[cardno] = baseAddr + IRQtable;
+	return (0);
+}
+
+long MoxaPortGetCurBaud(int port)
+{
+
+	if (moxaChkPort[port] == 0)
+		return (0);
+	return (moxaCurBaud[port]);
+}
+
+static void MoxaSetFifo(int port, int enable)
+{
+	unsigned long ofsAddr = moxaTableAddr[port];
+
+	if (!enable) {
+		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
+		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
+	} else {
+		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
+		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
+	}
+}
+
+#if 0
+int MoxaPortSetMode(int port, int databits, int stopbits, int parity)
+{
+	unsigned long ofsAddr;
+	int val;
+
+	val = 0;
+	switch (databits) {
+	case 5:
+		val |= 0;
+		break;
+	case 6:
+		val |= 1;
+		break;
+	case 7:
+		val |= 2;
+		break;
+	case 8:
+		val |= 3;
+		break;
+	default:
+		return (-1);
+	}
+	switch (stopbits) {
+	case 0:
+		val |= 0;
+		break;		/* stop bits 1.5 */
+	case 1:
+		val |= 0;
+		break;
+	case 2:
+		val |= 4;
+		break;
+	default:
+		return (-1);
+	}
+	switch (parity) {
+	case 0:
+		val |= 0x00;
+		break;		/* None  */
+	case 1:
+		val |= 0x08;
+		break;		/* Odd   */
+	case 2:
+		val |= 0x18;
+		break;		/* Even  */
+	case 3:
+		val |= 0x28;
+		break;		/* Mark  */
+	case 4:
+		val |= 0x38;
+		break;		/* Space */
+	default:
+		return (-1);
+	}
+	ofsAddr = moxaTableAddr[port];
+	moxafunc(ofsAddr, FC_SetMode, val);
+	return (0);
+}
+
+int MoxaPortTxBufSize(int port)
+{
+	unsigned long ofsAddr;
+	int size;
+
+	ofsAddr = moxaTableAddr[port];
+	size = readw(ofsAddr + TX_mask);
+	return (size);
+}
+
+int MoxaPortRxBufSize(int port)
+{
+	unsigned long ofsAddr;
+	int size;
+
+	ofsAddr = moxaTableAddr[port];
+	size = readw(ofsAddr + RX_mask);
+	return (size);
+}
+
+int MoxaPortRxFree(int port)
+{
+	unsigned long ofsAddr;
+	ushort rptr, wptr, mask;
+	int len;
+
+	ofsAddr = moxaTableAddr[port];
+	rptr = readw(ofsAddr + RXrptr);
+	wptr = readw(ofsAddr + RXwptr);
+	mask = readw(ofsAddr + RX_mask);
+	len = mask - ((wptr - rptr) & mask);
+	return (len);
+}
+int MoxaPortGetBrkCnt(int port)
+{
+	return (moxaBreakCnt[port]);
+}
+
+void MoxaPortSetXonXoff(int port, int xonValue, int xoffValue)
+{
+	unsigned long ofsAddr;
+
+	ofsAddr = moxaTableAddr[port];
+	writew(xonValue, ofsAddr + FuncArg);
+	writew(xoffValue, ofsAddr + FuncArg1);
+	writew(FC_SetXonXoff, ofsAddr + FuncCode);
+	wait_finish(ofsAddr);
+}
+
+int MoxaPortIsTxHold(int port)
+{
+	unsigned long ofsAddr;
+	int val;
+
+	ofsAddr = moxaTableAddr[port];
+	if ((moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_ISA) ||
+	    (moxa_boards[port / MAX_PORTS_PER_BOARD].boardType == MOXA_BOARD_C320_PCI)) {
+		moxafunc(ofsAddr, FC_GetCCSR, 0);
+		val = readw(ofsAddr + FuncArg);
+		if (val & 0x04)
+			return (1);
+	} else {
+		if (readw(ofsAddr + FlagStat) & Tx_flowOff)
+			return (1);
+	}
+	return (0);
+}
+#endif
diff -u --recursive --new-file v2.3.39/linux/drivers/char/mxser.c linux/drivers/char/mxser.c
--- v2.3.39/linux/drivers/char/mxser.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/mxser.c	Thu Jan 20 10:44:46 2000
@@ -0,0 +1,2451 @@
+/*****************************************************************************/
+/*
+ *          mxser.c  -- MOXA Smartio family multiport serial driver.
+ *
+ *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com.tw).
+ *
+ *      This code is loosely based on the Linux serial driver, written by
+ *      Linus Torvalds, Theodore T'so and others.
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    MOXA Smartio Family Serial Driver
+ *
+ *      Copyright (C) 1999,2000  Moxa Technologies Co., LTD.
+ *
+ *      for             : LINUX 2.0.X, 2.2.X
+ *      date            : 1999/07/22
+ *      version         : 1.1 
+ *      
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/smp_lock.h>
+#include <linux/pci.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#define		MXSER_VERSION			"1.1kern"
+
+#define		MXSERMAJOR	 	174
+#define		MXSERCUMAJOR		175
+
+
+#define	MXSER_EVENT_TXLOW	 1
+#define	MXSER_EVENT_HANGUP	 2
+
+
+#define 	SERIAL_DO_RESTART
+
+#define 	MXSER_BOARDS		4	/* Max. boards */
+#define 	MXSER_PORTS		32	/* Max. ports */
+#define 	MXSER_PORTS_PER_BOARD	8	/* Max. ports per board */
+#define 	MXSER_ISR_PASS_LIMIT	256
+
+#define		MXSER_ERR_IOADDR	-1
+#define		MXSER_ERR_IRQ		-2
+#define		MXSER_ERR_IRQ_CONFLIT	-3
+#define		MXSER_ERR_VECTOR	-4
+
+#define 	SERIAL_TYPE_NORMAL	1
+#define 	SERIAL_TYPE_CALLOUT	2
+
+#define 	WAKEUP_CHARS		256
+
+#define 	UART_MCR_AFE		0x20
+#define 	UART_LSR_SPECIAL	0x1E
+
+#define PORTNO(x)		(MINOR((x)->device) - (x)->driver.minor_start)
+
+#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ *    Define the Moxa PCI vendor and device IDs.
+ */
+
+#ifndef	PCI_VENDOR_ID_MOXA
+#define	PCI_VENDOR_ID_MOXA	0x1393
+#endif
+#ifndef PCI_DEVICE_ID_C168
+#define PCI_DEVICE_ID_C168	0x1680
+#endif
+#ifndef PCI_DEVICE_ID_C104
+#define PCI_DEVICE_ID_C104	0x1040
+#endif
+
+#define C168_ASIC_ID    1
+#define C104_ASIC_ID    2
+#define CI104J_ASIC_ID  5
+
+enum {
+	MXSER_BOARD_C168_ISA = 1,
+	MXSER_BOARD_C104_ISA,
+	MXSER_BOARD_CI104J,
+	MXSER_BOARD_C168_PCI,
+	MXSER_BOARD_C104_PCI,
+};
+
+static char *mxser_brdname[] =
+{
+	"C168 series",
+	"C104 series",
+	"CI-104J series",
+	"C168H/PCI series",
+	"C104H/PCI series",
+};
+
+static int mxser_numports[] =
+{
+	8,
+	4,
+	4,
+	8,
+	4,
+};
+
+/*
+ *    MOXA ioctls
+ */
+#define 	MOXA		0x400
+#define 	MOXA_GETDATACOUNT     (MOXA + 23)
+#define		MOXA_GET_CONF         (MOXA + 35)
+#define 	MOXA_DIAGNOSE         (MOXA + 50)
+#define 	MOXA_CHKPORTENABLE    (MOXA + 60)
+#define 	MOXA_HighSpeedOn      (MOXA + 61)
+#define         MOXA_GET_MAJOR        (MOXA + 63)
+#define         MOXA_GET_CUMAJOR      (MOXA + 64)
+#define         MOXA_GETMSTATUS       (MOXA + 65)
+
+typedef struct {
+	unsigned short vendor_id;
+	unsigned short device_id;
+	unsigned short board_type;
+} mxser_pciinfo;
+
+static mxser_pciinfo mxser_pcibrds[] =
+{
+	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C168, MXSER_BOARD_C168_PCI},
+	{PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_C104, MXSER_BOARD_C104_PCI},
+};
+
+typedef struct _moxa_pci_info {
+	unsigned short busNum;
+	unsigned short devNum;
+} moxa_pci_info;
+
+static int ioaddr[MXSER_BOARDS] = {0, 0, 0, 0};
+static int ttymajor = MXSERMAJOR;
+static int calloutmajor = MXSERCUMAJOR;
+static int verbose = 0;
+
+/* Variables for insmod */
+
+MODULE_AUTHOR("William Chen");
+MODULE_DESCRIPTION("MOXA Smartio Family Multiport Board Device Driver");
+MODULE_PARM(ioaddr, "1-4i");
+MODULE_PARM(ttymajor, "i");
+MODULE_PARM(calloutmajor, "i");
+MODULE_PARM(verbose, "i");
+
+struct mxser_hwconf {
+	int board_type;
+	int ports;
+	int irq;
+	int vector;
+	int vector_mask;
+	int uart_type;
+	int ioaddr[MXSER_PORTS_PER_BOARD];
+	int baud_base[MXSER_PORTS_PER_BOARD];
+	moxa_pci_info pciInfo;
+};
+
+struct mxser_struct {
+	int port;
+	int base;		/* port base address */
+	int irq;		/* port using irq no. */
+	int vector;		/* port irq vector */
+	int vectormask;		/* port vector mask */
+	int rx_trigger;		/* Rx fifo trigger level */
+	int baud_base;		/* max. speed */
+	int flags;		/* defined in tty.h */
+	int type;		/* UART type */
+	struct tty_struct *tty;
+	int read_status_mask;
+	int ignore_status_mask;
+	int xmit_fifo_size;
+	int custom_divisor;
+	int x_char;		/* xon/xoff character */
+	int close_delay;
+	unsigned short closing_wait;
+	int IER;		/* Interrupt Enable Register */
+	int MCR;		/* Modem control register */
+	unsigned long event;
+	int count;		/* # of fd on device */
+	int blocked_open;	/* # of blocked opens */
+	long session;		/* Session of opening process */
+	long pgrp;		/* pgrp of opening process */
+	unsigned char *xmit_buf;
+	int xmit_head;
+	int xmit_tail;
+	int xmit_cnt;
+	struct tq_struct tqueue;
+	struct termios normal_termios;
+	struct termios callout_termios;
+	wait_queue_head_t open_wait;
+	wait_queue_head_t close_wait;
+	wait_queue_head_t delta_msr_wait;
+	struct async_icount icount;	/* kernel counters for the 4 input interrupts */
+};
+
+struct mxser_log {
+	int tick;
+	int rxcnt[MXSER_PORTS];
+	int txcnt[MXSER_PORTS];
+};
+
+struct mxser_mstatus {
+	tcflag_t cflag;
+	int cts;
+	int dsr;
+	int ri;
+	int dcd;
+};
+
+static struct mxser_mstatus GMStatus[MXSER_PORTS];
+
+static int mxserBoardCAP[MXSER_BOARDS] =
+{
+	0, 0, 0, 0
+       /*  0x180, 0x280, 0x200, 0x320   */
+};
+
+
+static struct tty_driver mxvar_sdriver, mxvar_cdriver;
+static int mxvar_refcount;
+static struct mxser_struct mxvar_table[MXSER_PORTS];
+static struct tty_struct *mxvar_tty[MXSER_PORTS + 1];
+static struct termios *mxvar_termios[MXSER_PORTS + 1];
+static struct termios *mxvar_termios_locked[MXSER_PORTS + 1];
+static struct mxser_log mxvar_log;
+static int mxvar_diagflag;
+/*
+ * mxvar_tmp_buf is used as a temporary buffer by serial_write. We need
+ * to lock it in case the memcpy_fromfs blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static unsigned char *mxvar_tmp_buf = 0;
+static struct semaphore mxvar_tmp_buf_sem;
+
+/*
+ * This is used to figure out the divisor speeds and the timeouts
+ */
+static int mxvar_baud_table[] =
+{
+	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+	9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 0};
+
+struct mxser_hwconf mxsercfg[MXSER_BOARDS];
+
+/*
+ * static functions:
+ */
+
+#ifdef MODULE
+int init_module(void);
+void cleanup_module(void);
+#endif
+
+static void mxser_getcfg(int board, struct mxser_hwconf *hwconf);
+int mxser_init(void);
+static int mxser_get_ISA_conf(int, struct mxser_hwconf *);
+static int mxser_get_PCI_conf(int, int, int, struct mxser_hwconf *);
+static void mxser_do_softint(void *);
+static int mxser_open(struct tty_struct *, struct file *);
+static void mxser_close(struct tty_struct *, struct file *);
+static int mxser_write(struct tty_struct *, int, const unsigned char *, int);
+static int mxser_write_room(struct tty_struct *);
+static void mxser_flush_buffer(struct tty_struct *);
+static int mxser_chars_in_buffer(struct tty_struct *);
+static void mxser_flush_chars(struct tty_struct *);
+static void mxser_put_char(struct tty_struct *, unsigned char);
+static int mxser_ioctl(struct tty_struct *, struct file *, uint, ulong);
+static int mxser_ioctl_special(unsigned int, unsigned long);
+static void mxser_throttle(struct tty_struct *);
+static void mxser_unthrottle(struct tty_struct *);
+static void mxser_set_termios(struct tty_struct *, struct termios *);
+static void mxser_stop(struct tty_struct *);
+static void mxser_start(struct tty_struct *);
+static void mxser_hangup(struct tty_struct *);
+static void mxser_interrupt(int, void *, struct pt_regs *);
+static inline void mxser_receive_chars(struct mxser_struct *, int *);
+static inline void mxser_transmit_chars(struct mxser_struct *);
+static inline void mxser_check_modem_status(struct mxser_struct *, int);
+static int mxser_block_til_ready(struct tty_struct *, struct file *, struct mxser_struct *);
+static int mxser_startup(struct mxser_struct *);
+static void mxser_shutdown(struct mxser_struct *);
+static int mxser_change_speed(struct mxser_struct *, struct termios *old_termios);
+static int mxser_get_serial_info(struct mxser_struct *, struct serial_struct *);
+static int mxser_set_serial_info(struct mxser_struct *, struct serial_struct *);
+static int mxser_get_lsr_info(struct mxser_struct *, unsigned int *);
+static void mxser_send_break(struct mxser_struct *, int);
+static int mxser_get_modem_info(struct mxser_struct *, unsigned int *);
+static int mxser_set_modem_info(struct mxser_struct *, unsigned int, unsigned int *);
+
+/*
+ * The MOXA C168/C104 serial driver boot-time initialization code!
+ */
+
+
+#ifdef MODULE
+int init_module(void)
+{
+	int ret;
+
+	if (verbose)
+		printk("Loading module mxser ...\n");
+	ret = mxser_init();
+	if (verbose)
+		printk("Done.\n");
+	return (ret);
+}
+
+void cleanup_module(void)
+{
+	int i, err = 0;
+
+
+	if (verbose)
+		printk("Unloading module mxser ...\n");
+	if ((err |= tty_unregister_driver(&mxvar_cdriver)))
+		printk("Couldn't unregister MOXA Smartio family callout driver\n");
+	if ((err |= tty_unregister_driver(&mxvar_sdriver)))
+		printk("Couldn't unregister MOXA Smartio family serial driver\n");
+
+	for (i = 0; i < MXSER_BOARDS; i++) {
+		if (mxsercfg[i].board_type == -1)
+			continue;
+		else {
+			free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);
+		}
+	}
+
+	if (verbose)
+		printk("Done.\n");
+
+}
+#endif
+
+
+int mxser_initbrd(int board, struct mxser_hwconf *hwconf)
+{
+	struct mxser_struct *info;
+	unsigned long flags;
+	int retval;
+	int i, n;
+
+	init_MUTEX(&mxvar_tmp_buf_sem);
+	
+	n = board * MXSER_PORTS_PER_BOARD;
+	info = &mxvar_table[n];
+	for (i = 0; i < hwconf->ports; i++, n++, info++) {
+		if (verbose) {
+			printk("        ttyM%d/cum%d at 0x%04x ", n, n, hwconf->ioaddr[i]);
+			if (hwconf->baud_base[i] == 115200)
+				printk(" max. baud rate up to 115200 bps.\n");
+			else
+				printk(" max. baud rate up to 921600 bps.\n");
+		}
+		info->port = n;
+		info->base = hwconf->ioaddr[i];
+		info->irq = hwconf->irq;
+		info->vector = hwconf->vector;
+		info->vectormask = hwconf->vector_mask;
+		info->rx_trigger = 14;
+		info->baud_base = hwconf->baud_base[i];
+		info->flags = ASYNC_SHARE_IRQ;
+		info->type = hwconf->uart_type;
+		if ((info->type == PORT_16450) || (info->type == PORT_8250))
+			info->xmit_fifo_size = 1;
+		else
+			info->xmit_fifo_size = 16;
+		info->custom_divisor = hwconf->baud_base[i] * 16;
+		info->close_delay = 5 * HZ / 10;
+		info->closing_wait = 30 * HZ;
+		info->tqueue.routine = mxser_do_softint;
+		info->tqueue.data = info;
+		info->callout_termios = mxvar_cdriver.init_termios;
+		info->normal_termios = mxvar_sdriver.init_termios;
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
+		init_waitqueue_head(&info->delta_msr_wait);
+	}
+
+	/*
+	 * Allocate the IRQ if necessary
+	 */
+	save_flags(flags);
+
+	n = board * MXSER_PORTS_PER_BOARD;
+	info = &mxvar_table[n];
+
+	cli();
+	retval = request_irq(hwconf->irq, mxser_interrupt, IRQ_T(info),
+			     "mxser", info);
+	if (retval) {
+		restore_flags(flags);
+		printk("Board %d: %s", board, mxser_brdname[hwconf->board_type - 1]);
+		printk("  Request irq fail,IRQ (%d) may be conflit with another device.\n", info->irq);
+		return (retval);
+	}
+	restore_flags(flags);
+
+	return 0;
+}
+
+
+static void mxser_getcfg(int board, struct mxser_hwconf *hwconf)
+{
+	mxsercfg[board] = *hwconf;
+}
+
+static int mxser_get_PCI_conf(int busnum, int devnum, int board_type, struct mxser_hwconf *hwconf)
+{
+	int i;
+	unsigned int val, ioaddress;
+
+	hwconf->board_type = board_type;
+	hwconf->ports = mxser_numports[board_type - 1];
+	pcibios_read_config_dword(busnum, devnum, PCI_BASE_ADDRESS_2, &val);
+	if (val == 0xffffffff)
+		return (MXSER_ERR_IOADDR);
+	else
+		ioaddress = val & 0xffffffc;
+	for (i = 0; i < hwconf->ports; i++)
+		hwconf->ioaddr[i] = ioaddress + 8 * i;
+
+	pcibios_read_config_dword(busnum, devnum, PCI_BASE_ADDRESS_3, &val);
+	if (val == 0xffffffff)
+		return (MXSER_ERR_VECTOR);
+	else
+		ioaddress = val & 0xffffffc;
+	hwconf->vector = ioaddress;
+
+	pcibios_read_config_dword(busnum, devnum, PCI_INTERRUPT_LINE, &val);
+	if (val == 0xffffffff)
+		return (MXSER_ERR_IRQ);
+	else
+		hwconf->irq = val & 0xff;
+
+	hwconf->uart_type = PORT_16550A;
+	hwconf->vector_mask = 0;
+	for (i = 0; i < hwconf->ports; i++) {
+		hwconf->vector_mask |= (1 << i);
+		hwconf->baud_base[i] = 921600;
+	}
+	return (0);
+}
+
+int mxser_init(void)
+{
+	int i, m, retval, b;
+	int n, index;
+	int ret1, ret2;
+	unsigned char busnum, devnum;
+	struct mxser_hwconf hwconf;
+
+	printk("MOXA Smartio family driver version %s\n", MXSER_VERSION);
+
+	/* Initialize the tty_driver structure */
+
+	memset(&mxvar_sdriver, 0, sizeof(struct tty_driver));
+	mxvar_sdriver.magic = TTY_DRIVER_MAGIC;
+	mxvar_sdriver.name = "ttyM";
+	mxvar_sdriver.major = ttymajor;
+	mxvar_sdriver.minor_start = 0;
+	mxvar_sdriver.num = MXSER_PORTS + 1;
+	mxvar_sdriver.type = TTY_DRIVER_TYPE_SERIAL;
+	mxvar_sdriver.subtype = SERIAL_TYPE_NORMAL;
+	mxvar_sdriver.init_termios = tty_std_termios;
+	mxvar_sdriver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	mxvar_sdriver.flags = TTY_DRIVER_REAL_RAW;
+	mxvar_sdriver.refcount = &mxvar_refcount;
+	mxvar_sdriver.table = mxvar_tty;
+	mxvar_sdriver.termios = mxvar_termios;
+	mxvar_sdriver.termios_locked = mxvar_termios_locked;
+
+	mxvar_sdriver.open = mxser_open;
+	mxvar_sdriver.close = mxser_close;
+	mxvar_sdriver.write = mxser_write;
+	mxvar_sdriver.put_char = mxser_put_char;
+	mxvar_sdriver.flush_chars = mxser_flush_chars;
+	mxvar_sdriver.write_room = mxser_write_room;
+	mxvar_sdriver.chars_in_buffer = mxser_chars_in_buffer;
+	mxvar_sdriver.flush_buffer = mxser_flush_buffer;
+	mxvar_sdriver.ioctl = mxser_ioctl;
+	mxvar_sdriver.throttle = mxser_throttle;
+	mxvar_sdriver.unthrottle = mxser_unthrottle;
+	mxvar_sdriver.set_termios = mxser_set_termios;
+	mxvar_sdriver.stop = mxser_stop;
+	mxvar_sdriver.start = mxser_start;
+	mxvar_sdriver.hangup = mxser_hangup;
+
+	/*
+	 * The callout device is just like normal device except for
+	 * major number and the subtype code.
+	 */
+	mxvar_cdriver = mxvar_sdriver;
+	mxvar_cdriver.name = "cum";
+	mxvar_cdriver.major = calloutmajor;
+	mxvar_cdriver.subtype = SERIAL_TYPE_CALLOUT;
+
+	printk("Tty devices major number = %d, callout devices major number = %d\n", ttymajor, calloutmajor);
+
+	mxvar_diagflag = 0;
+	memset(mxvar_table, 0, MXSER_PORTS * sizeof(struct mxser_struct));
+	memset(&mxvar_log, 0, sizeof(struct mxser_log));
+
+
+	m = 0;
+	/* Start finding ISA boards here */
+	for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
+		int cap;
+		if (!(cap = mxserBoardCAP[b]))
+			continue;
+
+		retval = mxser_get_ISA_conf(cap, &hwconf);
+
+		if (retval != 0)
+			printk("Found MOXA %s board (CAP=0x%x)\n",
+			       mxser_brdname[hwconf.board_type - 1],
+			       ioaddr[b]);
+
+		if (retval <= 0) {
+			if (retval == MXSER_ERR_IRQ)
+				printk("Invalid interrupt number,board not configured\n");
+			else if (retval == MXSER_ERR_IRQ_CONFLIT)
+				printk("Invalid interrupt number,board not configured\n");
+			else if (retval == MXSER_ERR_VECTOR)
+				printk("Invalid interrupt vector,board not configured\n");
+			else if (retval == MXSER_ERR_IOADDR)
+				printk("Invalid I/O address,board not configured\n");
+
+			continue;
+		}
+		hwconf.pciInfo.busNum = 0;
+		hwconf.pciInfo.devNum = 0;
+
+		if (mxser_initbrd(m, &hwconf) < 0)
+			continue;
+
+		mxser_getcfg(m, &hwconf);
+
+		m++;
+	}
+
+	/* Start finding ISA boards from module arg */
+	for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) {
+		int cap;
+		if (!(cap = ioaddr[b]))
+			continue;
+
+		retval = mxser_get_ISA_conf(cap, &hwconf);
+
+		if (retval != 0)
+			printk("Found MOXA %s board (CAP=0x%x)\n",
+			       mxser_brdname[hwconf.board_type - 1],
+			       ioaddr[b]);
+
+		if (retval <= 0) {
+			if (retval == MXSER_ERR_IRQ)
+				printk("Invalid interrupt number,board not configured\n");
+			else if (retval == MXSER_ERR_IRQ_CONFLIT)
+				printk("Invalid interrupt number,board not configured\n");
+			else if (retval == MXSER_ERR_VECTOR)
+				printk("Invalid interrupt vector,board not configured\n");
+			else if (retval == MXSER_ERR_IOADDR)
+				printk("Invalid I/O address,board not configured\n");
+
+			continue;
+		}
+		hwconf.pciInfo.busNum = 0;
+		hwconf.pciInfo.devNum = 0;
+
+		if (mxser_initbrd(m, &hwconf) < 0)
+			continue;
+
+		mxser_getcfg(m, &hwconf);
+
+		m++;
+	}
+
+	/* start finding PCI board here */
+
+#ifdef CONFIG_PCI
+	if (pci_present()) 
+	{
+		n = sizeof(mxser_pcibrds) / sizeof(mxser_pciinfo);
+		index = 0;
+		b = 0;
+		while (b < n) {
+			if (pcibios_find_device(mxser_pcibrds[b].vendor_id,
+					      mxser_pcibrds[b].device_id,
+						index,
+						&busnum,
+						&devnum) != 0) {
+				b++;
+				index = 0;
+				continue;
+			}
+			hwconf.pciInfo.busNum = busnum;
+			hwconf.pciInfo.devNum = devnum;
+			printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n", mxser_brdname[mxser_pcibrds[b].board_type - 1], busnum, devnum >> 3);
+			index++;
+			if (m >= MXSER_BOARDS) {
+				printk("Too many Smartio family boards find (maximum %d),board not configured\n", MXSER_BOARDS);
+			} else {
+				retval = mxser_get_PCI_conf(busnum, devnum,
+				   mxser_pcibrds[b].board_type, &hwconf);
+				if (retval < 0) {
+					if (retval == MXSER_ERR_IRQ)
+						printk("Invalid interrupt number,board not configured\n");
+					else if (retval == MXSER_ERR_IRQ_CONFLIT)
+						printk("Invalid interrupt number,board not configured\n");
+					else if (retval == MXSER_ERR_VECTOR)
+						printk("Invalid interrupt vector,board not configured\n");
+					else if (retval == MXSER_ERR_IOADDR)
+						printk("Invalid I/O address,board not configured\n");
+					continue;
+
+				}
+				if (mxser_initbrd(m, &hwconf) < 0)
+					continue;
+				mxser_getcfg(m, &hwconf);
+				m++;
+
+			}
+
+		}
+	}
+#endif
+
+	for (i = m; i < MXSER_BOARDS; i++) {
+		mxsercfg[i].board_type = -1;
+	}
+
+
+	ret1 = 0;
+	ret2 = 0;
+	if (!(ret1 = tty_register_driver(&mxvar_sdriver))) {
+		if (!(ret2 = tty_register_driver(&mxvar_cdriver))) {
+			return 0;
+		} else {
+			tty_unregister_driver(&mxvar_sdriver);
+			printk("Couldn't install MOXA Smartio family callout driver !\n");
+		}
+	} else
+		printk("Couldn't install MOXA Smartio family driver !\n");
+
+
+	if (ret1 || ret2) {
+		for (i = 0; i < MXSER_BOARDS; i++) {
+			if (mxsercfg[i].board_type == -1)
+				continue;
+			else {
+				free_irq(mxsercfg[i].irq, &mxvar_table[i * MXSER_PORTS_PER_BOARD]);
+			}
+		}
+		return -1;
+	}
+	return (0);
+}
+
+static void mxser_do_softint(void *private_)
+{
+	struct mxser_struct *info = (struct mxser_struct *) private_;
+	struct tty_struct *tty;
+
+	tty = info->tty;
+	if (!tty)
+		return;
+	if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) {
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		    tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup) (tty);
+		wake_up_interruptible(&tty->write_wait);
+	}
+	if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) {
+		tty_hangup(tty);
+	}
+}
+
+/*
+ * This routine is called whenever a serial port is opened.  It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain.   It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+
+static int mxser_open(struct tty_struct *tty, struct file *filp)
+{
+	struct mxser_struct *info;
+	int retval, line;
+	unsigned long page;
+
+	line = PORTNO(tty);
+	if (line == MXSER_PORTS)
+		return (0);
+	if ((line < 0) || (line > MXSER_PORTS))
+		return (-ENODEV);
+	info = mxvar_table + line;
+	if (!info->base)
+		return (-ENODEV);
+
+	info->count++;
+	tty->driver_data = info;
+	info->tty = tty;
+
+	if (!mxvar_tmp_buf) {
+		page = get_free_page(GFP_KERNEL);
+		if (!page)
+			return (-ENOMEM);
+		if (mxvar_tmp_buf)
+			free_page(page);
+		else
+			mxvar_tmp_buf = (unsigned char *) page;
+	}
+	/*
+	 * Start up serial port
+	 */
+	retval = mxser_startup(info);
+	if (retval)
+		return (retval);
+
+	retval = mxser_block_til_ready(tty, filp, info);
+	if (retval)
+		return (retval);
+
+	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->normal_termios;
+		else
+			*tty->termios = info->callout_termios;
+		mxser_change_speed(info, 0);
+	}
+	info->session = current->session;
+	info->pgrp = current->pgrp;
+
+	MOD_INC_USE_COUNT;
+
+	return (0);
+}
+
+/*
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ */
+
+static void mxser_close(struct tty_struct *tty, struct file *filp)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+	unsigned long timeout;
+
+	if (PORTNO(tty) == MXSER_PORTS)
+		return;
+	if (!info)
+		return;
+
+	save_flags(flags);
+	cli();
+
+	if (tty_hung_up_p(filp)) {
+		restore_flags(flags);
+		MOD_DEC_USE_COUNT;
+		return;
+	}
+	if ((tty->count == 1) && (info->count != 1)) {
+		/*
+		 * Uh, oh.        tty->count is 1, which means that the tty
+		 * structure will be freed.  Info->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("mxser_close: bad serial port count; tty->count is 1, "
+		       "info->count is %d\n", info->count);
+		info->count = 1;
+	}
+	if (--info->count < 0) {
+		printk("mxser_close: bad serial port count for ttys%d: %d\n",
+		       info->port, info->count);
+		info->count = 0;
+	}
+	if (info->count) {
+		restore_flags(flags);
+		MOD_DEC_USE_COUNT;
+		return;
+	}
+	info->flags |= ASYNC_CLOSING;
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ASYNC_NORMAL_ACTIVE)
+		info->normal_termios = *tty->termios;
+	if (info->flags & ASYNC_CALLOUT_ACTIVE)
+		info->callout_termios = *tty->termios;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the receive line status interrupts, and tell the
+	 * interrupt driver to stop checking the data ready bit in the
+	 * line status register.
+	 */
+	info->IER &= ~UART_IER_RLSI;
+	/* by William
+	   info->read_status_mask &= ~UART_LSR_DR;
+	 */
+	if (info->flags & ASYNC_INITIALIZED) {
+		outb(info->IER, info->base + UART_IER);
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important if there is a transmit FIFO!
+		 */
+		timeout = jiffies + HZ;
+		while (!(inb(info->base + UART_LSR) & UART_LSR_TEMT)) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(5);
+			if (jiffies > timeout)
+				break;
+		}
+	}
+	mxser_shutdown(info);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = 0;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(info->close_delay);
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
+			 ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	restore_flags(flags);
+
+	MOD_DEC_USE_COUNT;
+}
+
+static int mxser_write(struct tty_struct *tty, int from_user,
+		       const unsigned char *buf, int count)
+{
+	int c, total = 0;
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+
+	if (!tty || !info->xmit_buf || !mxvar_tmp_buf)
+		return (0);
+
+	if (from_user)
+		down(&mxvar_tmp_buf_sem);
+	save_flags(flags);
+	while (1) {
+		cli();
+		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				   SERIAL_XMIT_SIZE - info->xmit_head));
+		if (c <= 0)
+			break;
+
+		if (from_user) {
+			copy_from_user(mxvar_tmp_buf, buf, c);
+			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				    SERIAL_XMIT_SIZE - info->xmit_head));
+			memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
+		} else
+			memcpy(info->xmit_buf + info->xmit_head, buf, c);
+		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+		info->xmit_cnt += c;
+		restore_flags(flags);
+		buf += c;
+		count -= c;
+		total += c;
+	}
+	if (from_user)
+		up(&mxvar_tmp_buf_sem);
+	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
+	    !(info->IER & UART_IER_THRI)) {
+		info->IER |= UART_IER_THRI;
+		outb(info->IER, info->base + UART_IER);
+	}
+	restore_flags(flags);
+	return (total);
+}
+
+static void mxser_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+
+	if (!tty || !info->xmit_buf)
+		return;
+
+	save_flags(flags);
+	cli();
+	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
+		restore_flags(flags);
+		return;
+	}
+	info->xmit_buf[info->xmit_head++] = ch;
+	info->xmit_head &= SERIAL_XMIT_SIZE - 1;
+	info->xmit_cnt++;
+	/********************************************** why ??? ***********
+	if ( !tty->stopped && !tty->hw_stopped &&
+	     !(info->IER & UART_IER_THRI) ) {
+	    info->IER |= UART_IER_THRI;
+	    outb(info->IER, info->base + UART_IER);
+	}
+	*****************************************************************/
+	restore_flags(flags);
+}
+
+static void mxser_flush_chars(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+
+	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+	    !info->xmit_buf)
+		return;
+
+	save_flags(flags);
+	cli();
+	info->IER |= UART_IER_THRI;
+	outb(info->IER, info->base + UART_IER);
+	restore_flags(flags);
+}
+
+static int mxser_write_room(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	int ret;
+
+	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
+	if (ret < 0)
+		ret = 0;
+	return (ret);
+}
+
+static int mxser_chars_in_buffer(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+
+	return (info->xmit_cnt);
+}
+
+static void mxser_flush_buffer(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	restore_flags(flags);
+	wake_up_interruptible(&tty->write_wait);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup) (tty);
+}
+
+static int mxser_ioctl(struct tty_struct *tty, struct file *file,
+		       unsigned int cmd, unsigned long arg)
+{
+	unsigned long flags;
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	int retval;
+	struct async_icount cprev, cnow;	/* kernel counter temps */
+	struct serial_icounter_struct *p_cuser;		/* user space */
+	unsigned long templ;
+
+	if (PORTNO(tty) == MXSER_PORTS)
+		return (mxser_ioctl_special(cmd, arg));
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCMIWAIT) &&
+	    (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+			return (-EIO);
+	}
+	switch (cmd) {
+	case TCSBRK:		/* SVID version: non-zero arg --> no break */
+		retval = tty_check_change(tty);
+		if (retval)
+			return (retval);
+		tty_wait_until_sent(tty, 0);
+		if (!arg)
+			mxser_send_break(info, HZ / 4);		/* 1/4 second */
+		return (0);
+	case TCSBRKP:		/* support for POSIX tcsendbreak() */
+		retval = tty_check_change(tty);
+		if (retval)
+			return (retval);
+		tty_wait_until_sent(tty, 0);
+		mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
+		return (0);
+	case TIOCGSOFTCAR:
+		return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+	case TIOCSSOFTCAR:
+		if(get_user(templ, (unsigned long *) arg))
+			return -EFAULT;
+		arg = templ;
+		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL) |
+					 (arg ? CLOCAL : 0));
+		return (0);
+	case TIOCMGET:
+		return (mxser_get_modem_info(info, (unsigned int *) arg));
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		return (mxser_set_modem_info(info, cmd, (unsigned int *) arg));
+	case TIOCGSERIAL:
+		return (mxser_get_serial_info(info, (struct serial_struct *) arg));
+	case TIOCSSERIAL:
+		return (mxser_set_serial_info(info, (struct serial_struct *) arg));
+	case TIOCSERGETLSR:	/* Get line status register */
+		return (mxser_get_lsr_info(info, (unsigned int *) arg));
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
+		 * - mask passed in arg for lines of interest
+		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+	case TIOCMIWAIT:
+		save_flags(flags);
+		cli();
+		cprev = info->icount;	/* note the counters on entry */
+		restore_flags(flags);
+		while (1) {
+			interruptible_sleep_on(&info->delta_msr_wait);
+			/* see if a signal did it */
+			if (signal_pending(current))
+				return (-ERESTARTSYS);
+			save_flags(flags);
+			cli();
+			cnow = info->icount;	/* atomic copy */
+			restore_flags(flags);
+			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+			  cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+				return (-EIO);	/* no change => error */
+			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+			((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+			 ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+			((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) {
+				return (0);
+			}
+			cprev = cnow;
+		}
+		/* NOTREACHED */
+		/*
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+	case TIOCGICOUNT:
+		save_flags(flags);
+		cli();
+		cnow = info->icount;
+		restore_flags(flags);
+		p_cuser = (struct serial_icounter_struct *) arg;
+		if(put_user(cnow.cts, &p_cuser->cts))
+			return -EFAULT;
+		if(put_user(cnow.dsr, &p_cuser->dsr))
+			return -EFAULT;
+		if(put_user(cnow.rng, &p_cuser->rng))
+			return -EFAULT;
+		return put_user(cnow.dcd, &p_cuser->dcd);
+	case MOXA_HighSpeedOn:
+		return put_user(info->baud_base != 115200 ? 1 : 0, (int *) arg);
+	default:
+		return (-ENOIOCTLCMD);
+	}
+	return (0);
+}
+
+static int mxser_ioctl_special(unsigned int cmd, unsigned long arg)
+{
+	int i, result, status;
+
+	switch (cmd) {
+	case MOXA_GET_CONF:
+		if(copy_to_user((struct mxser_hwconf *) arg, mxsercfg,
+			     sizeof(struct mxser_hwconf) * 4))
+			     	return -EFAULT;
+		return 0;
+	case MOXA_GET_MAJOR:
+		if(copy_to_user((int *) arg, &ttymajor, sizeof(int)))
+			return -EFAULT;
+		return 0;
+
+	case MOXA_GET_CUMAJOR:
+		if(copy_to_user((int *) arg, &calloutmajor, sizeof(int)))
+			return -EFAULT;
+		return 0;
+
+	case MOXA_CHKPORTENABLE:
+		result = 0;
+		for (i = 0; i < MXSER_PORTS; i++) {
+			if (mxvar_table[i].base)
+				result |= (1 << i);
+		}
+		return put_user(result, (unsigned long *) arg);
+	case MOXA_GETDATACOUNT:
+		if(copy_to_user((struct mxser_log *) arg, &mxvar_log, sizeof(mxvar_log)))
+			return -EFAULT;
+		return (0);
+	case MOXA_GETMSTATUS:
+		for (i = 0; i < MXSER_PORTS; i++) {
+			GMStatus[i].ri = 0;
+			if (!mxvar_table[i].base) {
+				GMStatus[i].dcd = 0;
+				GMStatus[i].dsr = 0;
+				GMStatus[i].cts = 0;
+				continue;
+			}
+			if (!mxvar_table[i].tty || !mxvar_table[i].tty->termios)
+				GMStatus[i].cflag = mxvar_table[i].normal_termios.c_cflag;
+			else
+				GMStatus[i].cflag = mxvar_table[i].tty->termios->c_cflag;
+
+			status = inb(mxvar_table[i].base + UART_MSR);
+			if (status & 0x80 /*UART_MSR_DCD */ )
+				GMStatus[i].dcd = 1;
+			else
+				GMStatus[i].dcd = 0;
+
+			if (status & 0x20 /*UART_MSR_DSR */ )
+				GMStatus[i].dsr = 1;
+			else
+				GMStatus[i].dsr = 0;
+
+
+			if (status & 0x10 /*UART_MSR_CTS */ )
+				GMStatus[i].cts = 1;
+			else
+				GMStatus[i].cts = 0;
+		}
+		if(copy_to_user((struct mxser_mstatus *) arg, GMStatus,
+			     sizeof(struct mxser_mstatus) * MXSER_PORTS))
+			return -EFAULT;
+		return 0;
+	default:
+		return (-ENOIOCTLCMD);
+	}
+	return (0);
+}
+
+/*
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ */
+static void mxser_throttle(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+
+	if (I_IXOFF(tty)) {
+		info->x_char = STOP_CHAR(tty);
+		save_flags(flags);
+		cli();
+		outb(info->IER, 0);
+		info->IER |= UART_IER_THRI;
+		outb(info->IER, info->base + UART_IER);		/* force Tx interrupt */
+		restore_flags(flags);
+	}
+	if (info->tty->termios->c_cflag & CRTSCTS) {
+		info->MCR &= ~UART_MCR_RTS;
+		save_flags(flags);
+		cli();
+		outb(info->MCR, info->base + UART_MCR);
+		restore_flags(flags);
+	}
+}
+
+static void mxser_unthrottle(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else {
+			info->x_char = START_CHAR(tty);
+			save_flags(flags);
+			cli();
+			outb(info->IER, 0);
+			info->IER |= UART_IER_THRI;	/* force Tx interrupt */
+			outb(info->IER, info->base + UART_IER);
+			restore_flags(flags);
+		}
+	}
+	if (info->tty->termios->c_cflag & CRTSCTS) {
+		info->MCR |= UART_MCR_RTS;
+		save_flags(flags);
+		cli();
+		outb(info->MCR, info->base + UART_MCR);
+		restore_flags(flags);
+	}
+}
+
+static void mxser_set_termios(struct tty_struct *tty,
+			      struct termios *old_termios)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+
+/* 8-2-99 by William
+   if ( (tty->termios->c_cflag == old_termios->c_cflag) &&
+   (RELEVANT_IFLAG(tty->termios->c_iflag) ==
+   RELEVANT_IFLAG(old_termios->c_iflag)) )
+   return;
+
+   mxser_change_speed(info, old_termios);
+
+   if ( (old_termios->c_cflag & CRTSCTS) &&
+   !(tty->termios->c_cflag & CRTSCTS) ) {
+   tty->hw_stopped = 0;
+   mxser_start(tty);
+   }
+ */
+	if ((tty->termios->c_cflag != old_termios->c_cflag) ||
+	    (RELEVANT_IFLAG(tty->termios->c_iflag) !=
+	     RELEVANT_IFLAG(old_termios->c_iflag))) {
+
+		mxser_change_speed(info, old_termios);
+
+		if ((old_termios->c_cflag & CRTSCTS) &&
+		    !(tty->termios->c_cflag & CRTSCTS)) {
+			tty->hw_stopped = 0;
+			mxser_start(tty);
+		}
+	}
+/* Handle sw stopped */
+	if ((old_termios->c_iflag & IXON) &&
+	    !(tty->termios->c_iflag & IXON)) {
+		tty->stopped = 0;
+		mxser_start(tty);
+	}
+}
+
+/*
+ * mxser_stop() and mxser_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ */
+static void mxser_stop(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	if (info->IER & UART_IER_THRI) {
+		info->IER &= ~UART_IER_THRI;
+		outb(info->IER, info->base + UART_IER);
+	}
+	restore_flags(flags);
+}
+
+static void mxser_start(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	if (info->xmit_cnt && info->xmit_buf &&
+	    !(info->IER & UART_IER_THRI)) {
+		info->IER |= UART_IER_THRI;
+		outb(info->IER, info->base + UART_IER);
+	}
+	restore_flags(flags);
+}
+
+/*
+ * This routine is called by tty_hangup() when a hangup is signaled.
+ */
+void mxser_hangup(struct tty_struct *tty)
+{
+	struct mxser_struct *info = (struct mxser_struct *) tty->driver_data;
+
+	mxser_flush_buffer(tty);
+	mxser_shutdown(info);
+	info->event = 0;
+	info->count = 0;
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
+	info->tty = 0;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * This is the serial driver's generic interrupt routine
+ */
+static void mxser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int status, i;
+	struct mxser_struct *info;
+	struct mxser_struct *port;
+	int max, irqbits, bits, msr;
+	int pass_counter = 0;
+
+	port = 0;
+	for (i = 0; i < MXSER_BOARDS; i++) {
+		if (dev_id == &(mxvar_table[i * MXSER_PORTS_PER_BOARD])) {
+			port = dev_id;
+			break;
+		}
+	}
+
+	if (i == MXSER_BOARDS)
+		return;
+	if (port == 0)
+		return;
+	max = mxser_numports[mxsercfg[i].board_type - 1];
+
+	while (1) {
+		irqbits = inb(port->vector) & port->vectormask;
+		if (irqbits == port->vectormask)
+			break;
+		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
+			if (irqbits == port->vectormask)
+				break;
+			if (bits & irqbits)
+				continue;
+			info = port + i;
+			if (!info->tty ||
+			  (inb(info->base + UART_IIR) & UART_IIR_NO_INT))
+				continue;
+			status = inb(info->base + UART_LSR) & info->read_status_mask;
+			if (status & UART_LSR_DR)
+				mxser_receive_chars(info, &status);
+			msr = inb(info->base + UART_MSR);
+			if (msr & UART_MSR_ANY_DELTA)
+				mxser_check_modem_status(info, msr);
+			if (status & UART_LSR_THRE) {
+/* 8-2-99 by William
+   if ( info->x_char || (info->xmit_cnt > 0) )
+ */
+				mxser_transmit_chars(info);
+			}
+		}
+		if (pass_counter++ > MXSER_ISR_PASS_LIMIT) {
+#if 0
+			printk("MOXA Smartio/Indusrtio family driver interrupt loop break\n");
+#endif
+			break;	/* Prevent infinite loops */
+		}
+	}
+}
+
+static inline void mxser_receive_chars(struct mxser_struct *info,
+					 int *status)
+{
+	struct tty_struct *tty = info->tty;
+	unsigned char ch;
+	int ignored = 0;
+	int cnt = 0;
+
+	do {
+		ch = inb(info->base + UART_RX);
+		if (*status & info->ignore_status_mask) {
+			if (++ignored > 100)
+				break;
+		} else {
+			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+				break;
+			tty->flip.count++;
+			if (*status & UART_LSR_SPECIAL) {
+				if (*status & UART_LSR_BI) {
+					*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+					if (info->flags & ASYNC_SAK)
+						do_SAK(tty);
+				} else if (*status & UART_LSR_PE) {
+					*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+				} else if (*status & UART_LSR_FE) {
+					*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+				} else if (*status & UART_LSR_OE) {
+					*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+				} else
+					*tty->flip.flag_buf_ptr++ = 0;
+			} else
+				*tty->flip.flag_buf_ptr++ = 0;
+			*tty->flip.char_buf_ptr++ = ch;
+			cnt++;
+		}
+		*status = inb(info->base + UART_LSR) & info->read_status_mask;
+	} while (*status & UART_LSR_DR);
+	mxvar_log.rxcnt[info->port] += cnt;
+	queue_task(&tty->flip.tqueue, &tq_timer);
+
+}
+
+static inline void mxser_transmit_chars(struct mxser_struct *info)
+{
+	int count, cnt;
+
+	if (info->x_char) {
+		outb(info->x_char, info->base + UART_TX);
+		info->x_char = 0;
+		mxvar_log.txcnt[info->port]++;
+		return;
+	}
+	if ((info->xmit_cnt <= 0) || info->tty->stopped ||
+	    info->tty->hw_stopped) {
+		info->IER &= ~UART_IER_THRI;
+		outb(info->IER, info->base + UART_IER);
+		return;
+	}
+	cnt = info->xmit_cnt;
+	count = info->xmit_fifo_size;
+	do {
+		outb(info->xmit_buf[info->xmit_tail++], info->base + UART_TX);
+		info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+		if (--info->xmit_cnt <= 0)
+			break;
+	} while (--count > 0);
+	mxvar_log.txcnt[info->port] += (cnt - info->xmit_cnt);
+
+	if (info->xmit_cnt < WAKEUP_CHARS) {
+		set_bit(MXSER_EVENT_TXLOW, &info->event);
+		queue_task(&info->tqueue, &tq_scheduler);
+	}
+	if (info->xmit_cnt <= 0) {
+		info->IER &= ~UART_IER_THRI;
+		outb(info->IER, info->base + UART_IER);
+	}
+}
+
+static inline void mxser_check_modem_status(struct mxser_struct *info,
+					      int status)
+{
+
+	/* update input line counters */
+	if (status & UART_MSR_TERI)
+		info->icount.rng++;
+	if (status & UART_MSR_DDSR)
+		info->icount.dsr++;
+	if (status & UART_MSR_DDCD)
+		info->icount.dcd++;
+	if (status & UART_MSR_DCTS)
+		info->icount.cts++;
+	wake_up_interruptible(&info->delta_msr_wait);
+
+	if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
+		if (status & UART_MSR_DCD)
+			wake_up_interruptible(&info->open_wait);
+		else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+			   (info->flags & ASYNC_CALLOUT_NOHUP)))
+			set_bit(MXSER_EVENT_HANGUP, &info->event);
+		queue_task(&info->tqueue, &tq_scheduler);
+
+	}
+	if (info->flags & ASYNC_CTS_FLOW) {
+		if (info->tty->hw_stopped) {
+			if (status & UART_MSR_CTS) {
+				info->tty->hw_stopped = 0;
+				info->IER |= UART_IER_THRI;
+				outb(info->IER, info->base + UART_IER);
+
+				set_bit(MXSER_EVENT_TXLOW, &info->event);
+				queue_task(&info->tqueue, &tq_scheduler);
+			}
+		} else {
+			if (!(status & UART_MSR_CTS)) {
+				info->tty->hw_stopped = 1;
+				info->IER &= ~UART_IER_THRI;
+				outb(info->IER, info->base + UART_IER);
+			}
+		}
+	}
+}
+
+static int mxser_block_til_ready(struct tty_struct *tty, struct file *filp,
+				 struct mxser_struct *info)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int retval;
+	int do_clocal = 0;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		if (info->flags & ASYNC_HUP_NOTIFY)
+			return (-EAGAIN);
+		else
+			return (-ERESTARTSYS);
+#else
+		return (-EAGAIN);
+#endif
+	}
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (info->flags & ASYNC_NORMAL_ACTIVE)
+			return (-EBUSY);
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (info->session != current->session))
+			return (-EBUSY);
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (info->pgrp != current->pgrp))
+			return (-EBUSY);
+		info->flags |= ASYNC_CALLOUT_ACTIVE;
+		return (0);
+	}
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		if (info->flags & ASYNC_CALLOUT_ACTIVE)
+			return (-EBUSY);
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return (0);
+	}
+	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (info->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, info->count is dropped by one, so that
+	 * mxser_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+	add_wait_queue(&info->open_wait, &wait);
+	save_flags(flags);
+	cli();
+	if (!tty_hung_up_p(filp))
+		info->count--;
+	restore_flags(flags);
+	info->blocked_open++;
+	while (1) {
+		save_flags(flags);
+		cli();
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE))
+			outb(inb(info->base + UART_MCR) | UART_MCR_DTR | UART_MCR_RTS,
+			     info->base + UART_MCR);
+		restore_flags(flags);
+		current->state = TASK_INTERRUPTIBLE;
+		if (tty_hung_up_p(filp) || !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(info->flags & ASYNC_CLOSING) &&
+		    (do_clocal || (inb(info->base + UART_MSR) & UART_MSR_DCD)))
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+		schedule();
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&info->open_wait, &wait);
+	if (!tty_hung_up_p(filp))
+		info->count++;
+	info->blocked_open--;
+	if (retval)
+		return (retval);
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return (0);
+}
+
+static int mxser_startup(struct mxser_struct *info)
+{
+	unsigned long flags;
+	unsigned long page;
+
+	page = get_free_page(GFP_KERNEL);
+	if (!page)
+		return (-ENOMEM);
+
+	save_flags(flags);
+	cli();
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		free_page(page);
+		restore_flags(flags);
+		return (0);
+	}
+	if (!info->base || !info->type) {
+		if (info->tty)
+			set_bit(TTY_IO_ERROR, &info->tty->flags);
+		free_page(page);
+		restore_flags(flags);
+		return (0);
+	}
+	if (info->xmit_buf)
+		free_page(page);
+	else
+		info->xmit_buf = (unsigned char *) page;
+
+	/*
+	 * Clear the FIFO buffers and disable them
+	 * (they will be reenabled in mxser_change_speed())
+	 */
+	if (info->xmit_fifo_size == 16)
+		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+		     info->base + UART_FCR);
+
+	/*
+	 * At this point there's no way the LSR could still be 0xFF;
+	 * if it is, then bail out, because there's likely no UART
+	 * here.
+	 */
+	if (inb(info->base + UART_LSR) == 0xff) {
+		restore_flags(flags);
+		if (suser()) {
+			if (info->tty)
+				set_bit(TTY_IO_ERROR, &info->tty->flags);
+			return (0);
+		} else
+			return (-ENODEV);
+	}
+	/*
+	 * Clear the interrupt registers.
+	 */
+	(void) inb(info->base + UART_LSR);
+	(void) inb(info->base + UART_RX);
+	(void) inb(info->base + UART_IIR);
+	(void) inb(info->base + UART_MSR);
+
+	/*
+	 * Now, initialize the UART
+	 */
+	outb(UART_LCR_WLEN8, info->base + UART_LCR);	/* reset DLAB */
+	info->MCR = UART_MCR_DTR | UART_MCR_RTS;
+	outb(info->MCR, info->base + UART_MCR);
+
+	/*
+	 * Finally, enable interrupts
+	 */
+	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
+	outb(info->IER, info->base + UART_IER);		/* enable interrupts */
+
+	/*
+	 * And clear the interrupt registers again for luck.
+	 */
+	(void) inb(info->base + UART_LSR);
+	(void) inb(info->base + UART_RX);
+	(void) inb(info->base + UART_IIR);
+	(void) inb(info->base + UART_MSR);
+
+	if (info->tty)
+		test_and_clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+	/*
+	 * and set the speed of the serial port
+	 */
+	mxser_change_speed(info, 0);
+
+	info->flags |= ASYNC_INITIALIZED;
+	restore_flags(flags);
+	return (0);
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts maybe disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void mxser_shutdown(struct mxser_struct *info)
+{
+	unsigned long flags;
+
+	if (!(info->flags & ASYNC_INITIALIZED))
+		return;
+
+	save_flags(flags);
+	cli();			/* Disable interrupts */
+
+	/*
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+	wake_up_interruptible(&info->delta_msr_wait);
+
+	/*
+	 * Free the IRQ, if necessary
+	 */
+	if (info->xmit_buf) {
+		free_page((unsigned long) info->xmit_buf);
+		info->xmit_buf = 0;
+	}
+	info->IER = 0;
+	outb(0x00, info->base + UART_IER);	/* disable all intrs */
+
+	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
+		info->MCR &= ~(UART_MCR_DTR | UART_MCR_RTS);
+	outb(info->MCR, info->base + UART_MCR);
+
+	/* clear Rx/Tx FIFO's */
+	outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT), info->base + UART_FCR);
+	/* read data port to reset things */
+	(void) inb(info->base + UART_RX);
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	info->flags &= ~ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+/*
+ * This routine is called to set the UART divisor registers to match
+ * the specified baud rate for a serial port.
+ */
+static int mxser_change_speed(struct mxser_struct *info,
+			      struct termios *old_termios)
+{
+	int quot = 0;
+	unsigned cflag, cval, fcr;
+	int i;
+	int ret = 0;
+	unsigned long flags;
+
+	if (!info->tty || !info->tty->termios)
+		return ret;
+	cflag = info->tty->termios->c_cflag;
+	if (!(info->base))
+		return ret;
+
+#ifndef B921600
+#define B921600 (B460800 +1)
+#endif
+	switch (cflag & (CBAUD | CBAUDEX)) {
+	case B921600:
+		i = 20;
+		break;
+	case B460800:
+		i = 19;
+		break;
+	case B230400:
+		i = 18;
+		break;
+	case B115200:
+		i = 17;
+		break;
+	case B57600:
+		i = 16;
+		break;
+	case B38400:
+		i = 15;
+		break;
+	case B19200:
+		i = 14;
+		break;
+	case B9600:
+		i = 13;
+		break;
+	case B4800:
+		i = 12;
+		break;
+	case B2400:
+		i = 11;
+		break;
+	case B1800:
+		i = 10;
+		break;
+	case B1200:
+		i = 9;
+		break;
+	case B600:
+		i = 8;
+		break;
+	case B300:
+		i = 7;
+		break;
+	case B200:
+		i = 6;
+		break;
+	case B150:
+		i = 5;
+		break;
+	case B134:
+		i = 4;
+		break;
+	case B110:
+		i = 3;
+		break;
+	case B75:
+		i = 2;
+		break;
+	case B50:
+		i = 1;
+		break;
+	default:
+		i = 0;
+		break;
+	}
+
+	if (i == 15) {
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			i = 16;	/* 57600 bps */
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			i = 17;	/* 115200 bps */
+
+#ifdef ASYNC_SPD_SHI
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			i = 18;
+#endif
+
+#ifdef ASYNC_SPD_WARP
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			i = 19;
+#endif
+	}
+	if (mxvar_baud_table[i] == 134) {
+		quot = (2 * info->baud_base / 269);
+	} else if (mxvar_baud_table[i]) {
+		quot = info->baud_base / mxvar_baud_table[i];
+		if (!quot && old_termios) {
+			/* re-calculate */
+			info->tty->termios->c_cflag &= ~CBAUD;
+			info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+			switch (info->tty->termios->c_cflag & (CBAUD | CBAUDEX)) {
+			case B921600:
+				i = 20;
+				break;
+			case B460800:
+				i = 19;
+				break;
+			case B230400:
+				i = 18;
+				break;
+			case B115200:
+				i = 17;
+				break;
+			case B57600:
+				i = 16;
+				break;
+			case B38400:
+				i = 15;
+				break;
+			case B19200:
+				i = 14;
+				break;
+			case B9600:
+				i = 13;
+				break;
+			case B4800:
+				i = 12;
+				break;
+			case B2400:
+				i = 11;
+				break;
+			case B1800:
+				i = 10;
+				break;
+			case B1200:
+				i = 9;
+				break;
+			case B600:
+				i = 8;
+				break;
+			case B300:
+				i = 7;
+				break;
+			case B200:
+				i = 6;
+				break;
+			case B150:
+				i = 5;
+				break;
+			case B134:
+				i = 4;
+				break;
+			case B110:
+				i = 3;
+				break;
+			case B75:
+				i = 2;
+				break;
+			case B50:
+				i = 1;
+				break;
+			default:
+				i = 0;
+				break;
+			}
+			if (i == 15) {
+				if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+					i = 16;		/* 57600 bps */
+				if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+					i = 17;		/* 115200 bps */
+#ifdef ASYNC_SPD_SHI
+				if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+					i = 18;
+#endif
+#ifdef ASYNC_SPD_WARP
+				if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+					i = 19;
+#endif
+			}
+			if (mxvar_baud_table[i] == 134) {
+				quot = (2 * info->baud_base / 269);
+			} else if (mxvar_baud_table[i]) {
+				quot = info->baud_base / mxvar_baud_table[i];
+				if (quot == 0)
+					quot = 1;
+			} else {
+				quot = 0;
+			}
+		} else if (quot == 0)
+			quot = 1;
+	} else {
+		quot = 0;
+	}
+
+	if (quot) {
+		info->MCR |= UART_MCR_DTR;
+		save_flags(flags);
+		cli();
+		outb(info->MCR, info->base + UART_MCR);
+		restore_flags(flags);
+	} else {
+		info->MCR &= ~UART_MCR_DTR;
+		save_flags(flags);
+		cli();
+		outb(info->MCR, info->base + UART_MCR);
+		restore_flags(flags);
+		return ret;
+	}
+	/* byte size and parity */
+	switch (cflag & CSIZE) {
+	case CS5:
+		cval = 0x00;
+		break;
+	case CS6:
+		cval = 0x01;
+		break;
+	case CS7:
+		cval = 0x02;
+		break;
+	case CS8:
+		cval = 0x03;
+		break;
+	default:
+		cval = 0x00;
+		break;		/* too keep GCC shut... */
+	}
+	if (cflag & CSTOPB)
+		cval |= 0x04;
+	if (cflag & PARENB)
+		cval |= UART_LCR_PARITY;
+	if (!(cflag & PARODD))
+		cval |= UART_LCR_EPAR;
+	if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
+		fcr = 0;
+	} else {
+		fcr = UART_FCR_ENABLE_FIFO;
+		switch (info->rx_trigger) {
+		case 1:
+			fcr |= UART_FCR_TRIGGER_1;
+			break;
+		case 4:
+			fcr |= UART_FCR_TRIGGER_4;
+			break;
+		case 8:
+			fcr |= UART_FCR_TRIGGER_8;
+			break;
+		default:
+			fcr |= UART_FCR_TRIGGER_14;
+		}
+	}
+
+	/* CTS flow control flag and modem status interrupts */
+	info->IER &= ~UART_IER_MSI;
+	info->MCR &= ~UART_MCR_AFE;
+	if (cflag & CRTSCTS) {
+		info->flags |= ASYNC_CTS_FLOW;
+		info->IER |= UART_IER_MSI;
+		if (info->type == PORT_16550A)
+			info->MCR |= UART_MCR_AFE;
+	} else {
+		info->flags &= ~ASYNC_CTS_FLOW;
+	}
+	outb(info->MCR, info->base + UART_MCR);
+	if (cflag & CLOCAL)
+		info->flags &= ~ASYNC_CHECK_CD;
+	else {
+		info->flags |= ASYNC_CHECK_CD;
+		info->IER |= UART_IER_MSI;
+	}
+	outb(info->IER, info->base + UART_IER);
+
+	/*
+	 * Set up parity check flag
+	 */
+	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+	if (I_INPCK(info->tty))
+		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
+		info->read_status_mask |= UART_LSR_BI;
+
+	info->ignore_status_mask = 0;
+#if 0
+	/* This should be safe, but for some broken bits of hardware... */
+	if (I_IGNPAR(info->tty)) {
+		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+		info->read_status_mask |= UART_LSR_PE | UART_LSR_FE;
+	}
+#endif
+	if (I_IGNBRK(info->tty)) {
+		info->ignore_status_mask |= UART_LSR_BI;
+		info->read_status_mask |= UART_LSR_BI;
+		/*
+		 * If we're ignore parity and break indicators, ignore
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(info->tty)) {
+			info->ignore_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;
+			info->read_status_mask |= UART_LSR_OE | UART_LSR_PE | UART_LSR_FE;
+		}
+	}
+	save_flags(flags);
+	cli();
+	outb(cval | UART_LCR_DLAB, info->base + UART_LCR);	/* set DLAB */
+	outb(quot & 0xff, info->base + UART_DLL);	/* LS of divisor */
+	outb(quot >> 8, info->base + UART_DLM);		/* MS of divisor */
+	outb(cval, info->base + UART_LCR);	/* reset DLAB */
+	outb(fcr, info->base + UART_FCR);	/* set fcr */
+	restore_flags(flags);
+
+	return ret;
+}
+
+/*
+ * ------------------------------------------------------------
+ * friends of mxser_ioctl()
+ * ------------------------------------------------------------
+ */
+static int mxser_get_serial_info(struct mxser_struct *info,
+				 struct serial_struct *retinfo)
+{
+	struct serial_struct tmp;
+
+	if (!retinfo)
+		return (-EFAULT);
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = info->type;
+	tmp.line = info->port;
+	tmp.port = info->base;
+	tmp.irq = info->irq;
+	tmp.flags = info->flags;
+	tmp.baud_base = info->baud_base;
+	tmp.close_delay = info->close_delay;
+	tmp.closing_wait = info->closing_wait;
+	tmp.custom_divisor = info->custom_divisor;
+	tmp.hub6 = 0;
+	copy_to_user(retinfo, &tmp, sizeof(*retinfo));
+	return (0);
+}
+
+static int mxser_set_serial_info(struct mxser_struct *info,
+				 struct serial_struct *new_info)
+{
+	struct serial_struct new_serial;
+	unsigned int flags;
+	int retval = 0;
+
+	if (!new_info || !info->base)
+		return (-EFAULT);
+	copy_from_user(&new_serial, new_info, sizeof(new_serial));
+
+	if ((new_serial.irq != info->irq) ||
+	    (new_serial.port != info->base) ||
+	    (new_serial.type != info->type) ||
+	    (new_serial.custom_divisor != info->custom_divisor) ||
+	    (new_serial.baud_base != info->baud_base))
+		return (-EPERM);
+
+	flags = info->flags & ASYNC_SPD_MASK;
+
+	if (!suser()) {
+		if ((new_serial.baud_base != info->baud_base) ||
+		    (new_serial.close_delay != info->close_delay) ||
+		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
+		     (info->flags & ~ASYNC_USR_MASK)))
+			return (-EPERM);
+		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+	} else {
+		/*
+		 * OK, past this point, all the error checking has been done.
+		 * At this point, we start making changes.....
+		 */
+		info->flags = ((info->flags & ~ASYNC_FLAGS) |
+			       (new_serial.flags & ASYNC_FLAGS));
+		info->close_delay = new_serial.close_delay * HZ / 100;
+		info->closing_wait = new_serial.closing_wait * HZ / 100;
+	}
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		if (flags != (info->flags & ASYNC_SPD_MASK)) {
+			mxser_change_speed(info, 0);
+		}
+	} else
+		retval = mxser_startup(info);
+	return (retval);
+}
+
+/*
+ * mxser_get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ *          is emptied.  On bus types like RS485, the transmitter must
+ *          release the bus after transmitting. This must be done when
+ *          the transmit shift register is empty, not be done when the
+ *          transmit holding register is empty.  This functionality
+ *          allows an RS485 driver to be written in user space.
+ */
+static int mxser_get_lsr_info(struct mxser_struct *info, unsigned int *value)
+{
+	unsigned char status;
+	unsigned int result;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	status = inb(info->base + UART_LSR);
+	restore_flags(flags);
+	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
+	put_user(result, value);
+	return (0);
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+static void mxser_send_break(struct mxser_struct *info, int duration)
+{
+	unsigned long flags;
+	if (!info->base)
+		return;
+	current->state = TASK_INTERRUPTIBLE;
+	save_flags(flags);
+	cli();
+	outb(inb(info->base + UART_LCR) | UART_LCR_SBC, info->base + UART_LCR);
+	schedule_timeout(duration);
+	outb(inb(info->base + UART_LCR) & ~UART_LCR_SBC, info->base + UART_LCR);
+	restore_flags(flags);
+}
+
+static int mxser_get_modem_info(struct mxser_struct *info,
+				unsigned int *value)
+{
+	unsigned char control, status;
+	unsigned int result;
+	unsigned long flags;
+
+	control = info->MCR;
+	save_flags(flags);
+	cli();
+	status = inb(info->base + UART_MSR);
+	if (status & UART_MSR_ANY_DELTA)
+		mxser_check_modem_status(info, status);
+	restore_flags(flags);
+	result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
+	    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
+	    ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
+	    ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
+	    ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
+	    ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
+	put_user(result, value);
+	return (0);
+}
+
+static int mxser_set_modem_info(struct mxser_struct *info, unsigned int cmd,
+				unsigned int *value)
+{
+	unsigned int arg;
+	unsigned long flags;
+
+	if(get_user(arg, value))
+		return -EFAULT;
+	switch (cmd) {
+	case TIOCMBIS:
+		if (arg & TIOCM_RTS)
+			info->MCR |= UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR |= UART_MCR_DTR;
+		break;
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			info->MCR &= ~UART_MCR_RTS;
+		if (arg & TIOCM_DTR)
+			info->MCR &= ~UART_MCR_DTR;
+		break;
+	case TIOCMSET:
+		info->MCR = ((info->MCR & ~(UART_MCR_RTS | UART_MCR_DTR)) |
+			     ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) |
+			     ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0));
+		break;
+	default:
+		return (-EINVAL);
+	}
+	save_flags(flags);
+	cli();
+	outb(info->MCR, info->base + UART_MCR);
+	restore_flags(flags);
+	return (0);
+}
+
+static int mxser_read_register(int, unsigned short *);
+static int mxser_program_mode(int);
+static void mxser_normal_mode(int);
+
+static int mxser_get_ISA_conf(int cap, struct mxser_hwconf *hwconf)
+{
+	int id, i, bits;
+	unsigned short regs[16], irq;
+	unsigned char scratch, scratch2;
+
+	id = mxser_read_register(cap, regs);
+	if (id == C168_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_C168_ISA;
+	else if (id == C104_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_C104_ISA;
+	else if (id == CI104J_ASIC_ID)
+		hwconf->board_type = MXSER_BOARD_CI104J;
+	else
+		return (0);
+	irq = regs[9] & 0x0F;
+	irq = irq | (irq << 4);
+	irq = irq | (irq << 8);
+	if ((irq != regs[9]) || ((id == 1) && (irq != regs[10]))) {
+		return (MXSER_ERR_IRQ_CONFLIT);
+	}
+	if (!irq) {
+		return (MXSER_ERR_IRQ);
+	}
+	for (i = 0; i < 8; i++)
+		hwconf->ioaddr[i] = (int) regs[i + 1] & 0xFFF8;
+	hwconf->irq = (int) (irq & 0x0F);
+	if ((regs[12] & 0x80) == 0) {
+		return (MXSER_ERR_VECTOR);
+	}
+	hwconf->vector = (int) regs[11];	/* interrupt vector */
+	if (id == 1)
+		hwconf->vector_mask = 0x00FF;
+	else
+		hwconf->vector_mask = 0x000F;
+	for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
+		if (regs[12] & bits)
+			hwconf->baud_base[i] = 921600;
+		else
+			hwconf->baud_base[i] = 115200;
+	}
+	scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
+	outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);
+	outb(0, cap + UART_EFR);	/* EFR is the same as FCR */
+	outb(scratch2, cap + UART_LCR);
+	outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);
+	scratch = inb(cap + UART_IIR);
+	if (scratch & 0xC0)
+		hwconf->uart_type = PORT_16550A;
+	else
+		hwconf->uart_type = PORT_16450;
+	if (id == 1)
+		hwconf->ports = 8;
+	else
+		hwconf->ports = 4;
+	return (hwconf->ports);
+}
+
+#define CHIP_SK 	0x01	/* Serial Data Clock  in Eprom */
+#define CHIP_DO 	0x02	/* Serial Data Output in Eprom */
+#define CHIP_CS 	0x04	/* Serial Chip Select in Eprom */
+#define CHIP_DI 	0x08	/* Serial Data Input  in Eprom */
+#define EN_CCMD 	0x000	/* Chip's command register     */
+#define EN0_RSARLO	0x008	/* Remote start address reg 0  */
+#define EN0_RSARHI	0x009	/* Remote start address reg 1  */
+#define EN0_RCNTLO	0x00A	/* Remote byte count reg WR    */
+#define EN0_RCNTHI	0x00B	/* Remote byte count reg WR    */
+#define EN0_DCFG	0x00E	/* Data configuration reg WR   */
+#define EN0_PORT	0x010	/* Rcv missed frame error counter RD */
+#define ENC_PAGE0	0x000	/* Select page 0 of chip registers   */
+#define ENC_PAGE3	0x0C0	/* Select page 3 of chip registers   */
+static int mxser_read_register(int port, unsigned short *regs)
+{
+	int i, k, value, id;
+	unsigned int j;
+
+	id = mxser_program_mode(port);
+	if (id < 0)
+		return (id);
+	for (i = 0; i < 14; i++) {
+		k = (i & 0x3F) | 0x180;
+		for (j = 0x100; j > 0; j >>= 1) {
+			outb(CHIP_CS, port);
+			if (k & j) {
+				outb(CHIP_CS | CHIP_DO, port);
+				outb(CHIP_CS | CHIP_DO | CHIP_SK, port);	/* A? bit of read */
+			} else {
+				outb(CHIP_CS, port);
+				outb(CHIP_CS | CHIP_SK, port);	/* A? bit of read */
+			}
+		}
+		(void) inb(port);
+		value = 0;
+		for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
+			outb(CHIP_CS, port);
+			outb(CHIP_CS | CHIP_SK, port);
+			if (inb(port) & CHIP_DI)
+				value |= j;
+		}
+		regs[i] = value;
+		outb(0, port);
+	}
+	mxser_normal_mode(port);
+	return (id);
+}
+
+static int mxser_program_mode(int port)
+{
+	int id, i, j, n;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	outb(0, port);
+	outb(0, port);
+	outb(0, port);
+	(void) inb(port);
+	(void) inb(port);
+	outb(0, port);
+	(void) inb(port);
+	restore_flags(flags);
+	id = inb(port + 1) & 0x1F;
+	if ((id != C168_ASIC_ID) && (id != C104_ASIC_ID) && (id != CI104J_ASIC_ID))
+		return (-1);
+	for (i = 0, j = 0; i < 4; i++) {
+		n = inb(port + 2);
+		if (n == 'M') {
+			j = 1;
+		} else if ((j == 1) && (n == 1)) {
+			j = 2;
+			break;
+		} else
+			j = 0;
+	}
+	if (j != 2)
+		id = -2;
+	return (id);
+}
+
+static void mxser_normal_mode(int port)
+{
+	int i, n;
+
+	outb(0xA5, port + 1);
+	outb(0x80, port + 3);
+	outb(12, port + 0);	/* 9600 bps */
+	outb(0, port + 1);
+	outb(0x03, port + 3);	/* 8 data bits */
+	outb(0x13, port + 4);	/* loop back mode */
+	for (i = 0; i < 16; i++) {
+		n = inb(port + 5);
+		if ((n & 0x61) == 0x60)
+			break;
+		if ((n & 1) == 1)
+			(void) inb(port);
+	}
+	outb(0x00, port + 4);
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/char/pcmcia/Config.in linux/drivers/char/pcmcia/Config.in
--- v2.3.39/linux/drivers/char/pcmcia/Config.in	Tue Jan  4 13:57:16 2000
+++ linux/drivers/char/pcmcia/Config.in	Mon Jan 17 22:22:52 2000
@@ -2,10 +2,7 @@
 # PCMCIA character device configuration
 #
 
-mainmenu_option next_comment
-comment 'PCMCIA character device support'
-
-if [ "$CONFIG_SERIAL" = "n" -o "$CONFIG_PCMCIA" = "n" ]; then
+if [ "$CONFIG_SERIAL" = "n" ]; then
    define_bool CONFIG_PCMCIA_SERIAL n
 else
    if [ "$CONFIG_SERIAL" = "m" -o "$CONFIG_PCMCIA" = "m" ]; then
@@ -15,14 +12,19 @@
    fi
 fi
 
-dep_tristate '  PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS $CONFIG_PCMCIA_SERIAL
-if [ "$CONFIG_CARDBUS" = "y" ]; then
-   dep_tristate '  CardBus serial device support' CONFIG_PCMCIA_SERIAL_CB $CONFIG_PCMCIA_SERIAL
-fi
+if [ "$CONFIG_PCMCIA_SERIAL" != "n" ]; then
+   mainmenu_option next_comment
+   comment 'PCMCIA character device support'
 
-if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" -o \
-     "$CONFIG_PCMCIA_SERIAL_CB" = "y" ]; then
-   define_bool CONFIG_PCMCIA_CHRDEV y
-fi
+   dep_tristate 'PCMCIA serial device support' CONFIG_PCMCIA_SERIAL_CS $CONFIG_PCMCIA_SERIAL
+   if [ "$CONFIG_CARDBUS" = "y" ]; then
+      dep_tristate 'CardBus serial device support' CONFIG_PCMCIA_SERIAL_CB $CONFIG_PCMCIA_SERIAL
+   fi
 
-endmenu
+   if [ "$CONFIG_PCMCIA_SERIAL_CS" = "y" -o \
+        "$CONFIG_PCMCIA_SERIAL_CB" = "y" ]; then
+      define_bool CONFIG_PCMCIA_CHRDEV y
+   fi
+
+   endmenu
+fi
diff -u --recursive --new-file v2.3.39/linux/drivers/char/pcmcia/serial_cb.c linux/drivers/char/pcmcia/serial_cb.c
--- v2.3.39/linux/drivers/char/pcmcia/serial_cb.c	Thu Nov 11 20:11:34 1999
+++ linux/drivers/char/pcmcia/serial_cb.c	Tue Jan 18 22:29:17 2000
@@ -2,7 +2,7 @@
 
     A driver for CardBus serial devices
 
-    serial_cb.c 1.14 1999/11/11 02:18:08
+    serial_cb.c 1.15 1999/11/24 02:52:06
 
     Copyright 1998, 1999 by Donald Becker and David Hinds
     
@@ -39,7 +39,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"serial_cb.c 1.14 1999/11/11 02:18:08 (David Hinds)";
+"serial_cb.c 1.15 1999/11/24 02:52:06 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -56,8 +56,9 @@
 
     pcibios_read_config_word(bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &a);
     pcibios_read_config_word(bus, devfn, PCI_SUBSYSTEM_ID, &b);
-    if ((a == 0x13a2) && (b == 0x8007)) {
-	/* Ositech Jack of Spades */
+    if (((a == 0x13a2) && (b == 0x8007)) ||
+	((a == 0x1420) && (b == 0x8003))) {
+	/* Ositech, Psion 83c175-based cards */
 	DEBUG(0, "  83c175 NVCTL_m = 0x%4.4x.\n", inl(ioaddr+0x80));
 	outl(0x4C00, ioaddr + 0x80);
 	outl(0x4C80, ioaddr + 0x80);
diff -u --recursive --new-file v2.3.39/linux/drivers/char/pcmcia/serial_cs.c linux/drivers/char/pcmcia/serial_cs.c
--- v2.3.39/linux/drivers/char/pcmcia/serial_cs.c	Thu Nov 11 20:11:34 1999
+++ linux/drivers/char/pcmcia/serial_cs.c	Tue Jan 18 22:29:17 2000
@@ -2,7 +2,7 @@
 
     A driver for PCMCIA serial devices
 
-    serial_cs.c 1.114 1999/11/11 00:54:46
+    serial_cs.c 1.117 1999/12/11 03:59:18
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -58,7 +58,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"serial_cs.c 1.114 1999/11/11 00:54:46 (David Hinds)";
+"serial_cs.c 1.117 1999/12/11 03:59:18 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -100,6 +100,7 @@
 #define MULTI_COUNT (sizeof(multi_id)/sizeof(multi_id_t))
 
 typedef struct serial_info_t {
+    dev_link_t	link;
     int		ndev;
     int		multi;
     int		slave;
@@ -138,6 +139,7 @@
 
 static dev_link_t *serial_attach(void)
 {
+    serial_info_t *info;
     client_reg_t client_reg;
     dev_link_t *link;
     int i, ret;
@@ -145,8 +147,11 @@
     DEBUG(0, "serial_attach()\n");
 
     /* Create new serial device */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    memset(link, 0, sizeof(struct dev_link_t));
+    info = kmalloc(sizeof(*info), GFP_KERNEL);
+    if (!info) return NULL;
+    memset(info, 0, sizeof(*info));
+    link = &info->link; link->priv = info;
+
     link->release.function = &serial_release;
     link->release.data = (u_long)link;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
@@ -165,8 +170,6 @@
 	link->conf.Status = CCSR_AUDIO_ENA;
     }
     link->conf.IntType = INT_MEMORY_AND_IO;
-    link->priv = kmalloc(sizeof(struct serial_info_t), GFP_KERNEL);
-    memset(link->priv, 0, sizeof(struct serial_info_t));
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -201,6 +204,7 @@
 
 static void serial_detach(dev_link_t *link)
 {
+    serial_info_t *info = link->priv;
     dev_link_t **linkp;
     long flags;
     int ret;
@@ -232,8 +236,7 @@
     
     /* Unlink device structure, free bits */
     *linkp = link->next;
-    kfree_s(link->priv, sizeof(serial_info_t));
-    kfree_s(link, sizeof(struct dev_link_t));
+    kfree(info);
     
 } /* serial_detach */
 
@@ -326,7 +329,8 @@
 	if (cf->vpp1.present & (1<<CISTPL_POWER_VNOM))
 	    link->conf.Vpp1 = link->conf.Vpp2 =
 		cf->vpp1.param[CISTPL_POWER_VNOM]/10000;
-	if ((cf->io.nwin > 0) && ((cf->io.win[0].base & 0xf) == 8)) {
+	if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) &&
+	    (cf->io.win[0].base != 0)) {
 	    link->conf.ConfigIndex = cf->index;
 	    link->io.BasePort1 = cf->io.win[0].base;
 	    link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
@@ -347,6 +351,7 @@
 	    link->conf.ConfigIndex = cf->index;
 	    for (j = 0; j < 5; j++) {
 		link->io.BasePort1 = base[j];
+		link->io.IOAddrLines = base[j] ? 16 : 3;
 		i = CardServices(RequestIO, link->handle,
 				 &link->io);
 		if (i == CS_SUCCESS) goto found_port;
@@ -470,18 +475,14 @@
 
 void serial_config(dev_link_t *link)
 {
-    client_handle_t handle;
-    serial_info_t *info;
+    client_handle_t handle = link->handle;
+    serial_info_t *info = link->priv;
     tuple_t tuple;
     u_short buf[128];
     cisparse_t parse;
     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
     int i, last_ret, last_fn;
 
-    sti();
-    handle = link->handle;
-    info = link->priv;
-    
     DEBUG(0, "serial_config(0x%p)\n", link);
     
     tuple.TupleData = (cisdata_t *)buf;
@@ -571,8 +572,6 @@
     dev_link_t *link = (dev_link_t *)arg;
     serial_info_t *info = link->priv;
     int i;
-    
-    sti();
     
     DEBUG(0, "serial_release(0x%p)\n", link);
 
diff -u --recursive --new-file v2.3.39/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.3.39/linux/drivers/char/pcwd.c	Fri Jan  7 19:13:21 2000
+++ linux/drivers/char/pcwd.c	Thu Jan 20 10:44:46 2000
@@ -34,6 +34,8 @@
  * 971222       Changed open/close for temperature handling
  *              Michael Meskes <meskes@debian.org>.
  * 980112       Used minor numbers from include/linux/miscdevice.h
+ * 990403       Clear reset status after reading control status register in 
+ *              pcwd_showprevstate(). [Marc Boucher <marc@mbsi.ca>]
  * 990605	Made changes to code to support Firmware 1.22a, added
  *		fairly useless proc entry.
  * 990610	removed said useless proc code for the merge <alan>
@@ -183,8 +185,10 @@
 
 	if (revision == PCWD_REVISION_A)
 		initial_status = card_status = inb(current_readport);
-	else
+	else {
 		initial_status = card_status = inb(current_readport + 1);
+		outb_p(0x00, current_readport + 1); /* clear reset status */
+	}
 
 	if (revision == PCWD_REVISION_A) {
 		if (card_status & WD_WDRST)
diff -u --recursive --new-file v2.3.39/linux/drivers/char/radio-cadet.c linux/drivers/char/radio-cadet.c
--- v2.3.39/linux/drivers/char/radio-cadet.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/char/radio-cadet.c	Thu Jan 20 10:44:46 2000
@@ -39,6 +39,7 @@
 static __u8 rdsin=0,rdsout=0,rdsstat=0;
 static unsigned char rdsbuf[RDS_BUFFER];
 static int cadet_lock=0;
+static int cadet_probe(void);
 
 /*
  * Signal Strength Threshold Values
diff -u --recursive --new-file v2.3.39/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.3.39/linux/drivers/char/tty_io.c	Fri Oct 22 13:21:48 1999
+++ linux/drivers/char/tty_io.c	Thu Jan 20 10:44:46 2000
@@ -344,7 +344,7 @@
 	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
 }
 
-static long long tty_lseek(struct file * file,	long long offset, int orig)
+static loff_t tty_lseek(struct file * file, loff_t offset, int orig)
 {
 	return -ESPIPE;
 }
@@ -2216,6 +2216,12 @@
         rs_8xx_init();
 #endif /* CONFIG_8xx */
 	pty_init();
+#ifdef CONFIG_MOXA_SMARTIO
+	mxser_init();
+#endif	
+#ifdef CONFIG_MOXA_INTELLIO
+	moxa_init();
+#endif	
 #ifdef CONFIG_VT
 	vcs_init();
 #endif
diff -u --recursive --new-file v2.3.39/linux/drivers/char/vc_screen.c linux/drivers/char/vc_screen.c
--- v2.3.39/linux/drivers/char/vc_screen.c	Thu Aug  5 14:34:02 1999
+++ linux/drivers/char/vc_screen.c	Tue Jan 11 14:19:17 2000
@@ -59,7 +59,7 @@
 	return size;
 }
 
-static long long vcs_lseek(struct file *file, long long offset, int orig)
+static loff_t vcs_lseek(struct file *file, loff_t offset, int orig)
 {
 	int size = vcs_size(file->f_dentry->d_inode);
 
diff -u --recursive --new-file v2.3.39/linux/drivers/fc4/Makefile linux/drivers/fc4/Makefile
--- v2.3.39/linux/drivers/fc4/Makefile	Mon Mar 15 16:11:29 1999
+++ linux/drivers/fc4/Makefile	Thu Jan 20 10:44:46 2000
@@ -7,8 +7,6 @@
 M_OBJS   :=
 MOD_LIST_NAME := FC4_MODULES
 
-include ../../.config
-
 ifeq ($(CONFIG_FC4),y)
   FC4 = fc.o
   ifeq ($(CONFIG_MODULES),y)
diff -u --recursive --new-file v2.3.39/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
--- v2.3.39/linux/drivers/i2o/i2o_block.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/i2o/i2o_block.c	Thu Jan 20 10:44:46 2000
@@ -738,7 +738,9 @@
 	if (minor >= MAX_I2OB<<4)
 		return -ENODEV;
 	dev=&i2ob_dev[(minor&0xF0)];
-
+	if(dev->i2odev == NULL)
+		return -ENODEV;
+		
 	if(dev->refcnt++==0)
 	{ 
 		u32 msg[6];
@@ -821,7 +823,6 @@
 	i2ob_query_device(dev, 0x0000, 6, &status, 4);
 	i2ob_sizes[unit] = (int)(size>>10);
 	i2ob_hardsizes[unit] = blocksize;
-	i2ob_gendisk.part[unit].nr_sects = i2ob_sizes[unit];
 
 	limit=4096;	/* 8 deep scatter gather */
 
@@ -869,7 +870,7 @@
 	printk(".\n");
 	printk("%s: Maximum sectors/read set to %d.\n", 
 		d->dev_name, i2ob_max_sectors[unit]);
-	resetup_one_dev(&i2ob_gendisk, unit>>4);
+	grok_partitions(&i2ob_gendisk, unit>>4, 1<<4, (long)(size>>9));
 	return 0;
 }
 
@@ -1013,14 +1014,6 @@
 	check_media_change:	i2ob_media_change,
 	revalidate:		i2ob_revalidate,
 };
-
-/*
- *	Partitioning
- */
- 
-static void i2ob_geninit(struct gendisk *gd)
-{
-}
 	
 static struct gendisk i2ob_gendisk = 
 {
@@ -1028,8 +1021,6 @@
 	"i2ohd",
 	4,
 	1<<4,
-	MAX_I2OB,
-	i2ob_geninit,
 	i2ob,
 	i2ob_sizes,
 	0,
@@ -1128,6 +1119,9 @@
 	 *	Finally see what is actually plugged in to our controllers
 	 */
 
+	for (i = 0; i < MAX_I2OB; i++)
+		register_disk(&i2ob_gendisk, MKDEV(MAJOR_NR,i<<4), 1<<4,
+			&i2ob_fops, 0);
 	i2ob_probe();
 	
 	register_reboot_notifier(&i2ob_reboot_notifier);
diff -u --recursive --new-file v2.3.39/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
--- v2.3.39/linux/drivers/i2o/i2o_core.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/i2o/i2o_core.c	Thu Jan 13 16:53:52 2000
@@ -2460,7 +2460,7 @@
 #endif
 
 	if(i2o_num_controllers)
-		i2o_init();
+		i2o_sys_init();
 
 	i2o_config_init();
 #ifdef CONFIG_I2O_BLOCK
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/Config.in linux/drivers/ieee1394/Config.in
--- v2.3.39/linux/drivers/ieee1394/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/Config.in	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,24 @@
+# -*- shell-script -*-
+
+if [ "$CONFIG_PCI" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    mainmenu_option next_comment
+    comment 'IEEE 1394 (FireWire) support'
+
+    tristate 'IEEE 1394 (FireWire) support (EXPERIMENTAL)' CONFIG_IEEE1394 $CONFIG_PCI
+
+    if [ "$CONFIG_IEEE1394" != "n" ]; then
+
+	dep_tristate 'Texas Instruments PCILynx support' CONFIG_IEEE1394_PCILYNX $CONFIG_IEEE1394
+	if [ "$CONFIG_IEEE1394_PCILYNX" != "n" ]; then
+	    bool '  Use PCILynx local RAM' CONFIG_IEEE1394_PCILYNX_LOCALRAM
+	fi
+
+	dep_tristate 'Adaptec AIC-5800 (AHA-89xx) support' CONFIG_IEEE1394_AIC5800 $CONFIG_IEEE1394
+	
+	dep_tristate 'OHCI (Open Host Controller Interface) support' CONFIG_IEEE1394_OHCI1394 $CONFIG_IEEE1394
+
+	dep_tristate 'Raw IEEE1394 I/O support' CONFIG_IEEE1394_RAWIO $CONFIG_IEEE1394
+
+    fi
+    endmenu
+fi
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/Makefile linux/drivers/ieee1394/Makefile
--- v2.3.39/linux/drivers/ieee1394/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/Makefile	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,75 @@
+#
+# Makefile for the Linux IEEE 1394 implementation
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile.
+#
+
+SUB_DIRS     :=
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+MOD_LIST_NAME := IEEE1394_MODULES
+
+L_TARGET := ieee1394.a
+L_OBJS   :=
+LX_OBJS  :=
+M_OBJS   :=
+MX_OBJS  :=
+MI_OBJS  :=
+MIX_OBJS :=
+O_OBJS   :=
+OX_OBJS  :=
+
+ifeq ($(CONFIG_IEEE1394),y)
+L_OBJS  += ieee1394.o hosts.o highlevel.o csr.o
+O_TARGET = ieee1394.o
+O_OBJS  += ieee1394_core.o ieee1394_transactions.o
+OX_OBJS += ieee1394_syms.o
+else
+  ifeq ($(CONFIG_IEEE1394),m)
+  M_OBJS  += ieee1394.o
+  O_TARGET = ieee1394.o
+  O_OBJS  += ieee1394_core.o ieee1394_transactions.o hosts.o highlevel.o csr.o
+  OX_OBJS += ieee1394_syms.o
+  endif
+endif
+
+ifeq ($(CONFIG_IEEE1394_PCILYNX),y)
+L_OBJS += pcilynx.o
+else
+  ifeq ($(CONFIG_IEEE1394_PCILYNX),m)
+  M_OBJS += pcilynx.o
+  endif
+endif
+
+ifeq ($(CONFIG_IEEE1394_AIC5800),y)
+L_OBJS += aic5800.o
+else
+  ifeq ($(CONFIG_IEEE1394_AIC5800),m)
+  M_OBJS += aic5800.o
+  endif
+endif
+
+ifeq ($(CONFIG_IEEE1394_OHCI1394),y)
+L_OBJS += ohci1394.o
+else
+  ifeq ($(CONFIG_IEEE1394_OHCI1394),m)
+  M_OBJS += ohci1394.o
+  endif
+endif
+
+
+ifeq ($(CONFIG_IEEE1394_RAWIO),y)
+L_OBJS += raw1394.o
+else
+  ifeq ($(CONFIG_IEEE1394_RAWIO),m)
+  M_OBJS += raw1394.o
+  endif
+endif
+
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/aic5800.c linux/drivers/ieee1394/aic5800.c
--- v2.3.39/linux/drivers/ieee1394/aic5800.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/aic5800.c	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,897 @@
+/*
+ * aic5800.c - Adaptec AIC-5800 PCI-IEEE1394 chip driver
+ * Copyright (C)1999 Emanuel Pirker <epirker@edu.uni-klu.ac.at>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "ieee1394.h"
+#include "aic5800.h"
+
+
+
+/// print general (card independent) information 
+#define PRINT_G(level, fmt, args...) printk(level "aic5800: " fmt "\n" , ## args)
+/// print card specific information 
+#define PRINT(level, card, fmt, args...) printk(level "aic5800-%d: " fmt "\n" , card , ## args)
+
+/// card array 
+static struct aic5800 cards[MAX_AIC5800_CARDS];
+/// holds the number of installed aic5800 cards
+static int num_of_cards = 0;
+
+static int add_card(struct pci_dev *dev);
+static void remove_card(struct aic5800 *aic);
+static int init_driver(void);
+
+
+/*****************************************************************
+ * Auxiliary functions needed to read the EEPROM
+ * Daniel Minitti
+ *****************************************************************/
+#define SEEPDOUT        0x1
+#define SEEPDIN 0x02
+#define SEEPSK  0x04
+#define SEEPCS  0x08
+#define SEEPCYC 0x10
+#define SEEPBUSY        0x20
+
+#define CLOCK_PULSE() {\
+        int cnt=200;\
+        while(cnt-->0 && reg_read(aic, misc_SEEPCTL) & SEEPBUSY);\
+        if (reg_read(aic, misc_SEEPCTL) & SEEPBUSY) printk("BUSY ");\
+        }
+
+static inline unsigned short read_seeprom_word(struct aic5800 *aic,
+                                               int offset) 
+{
+        int i;
+        unsigned char temp;
+        unsigned char read_cmd[3] = {1,1,0};
+        unsigned short rd;
+
+        // send chip select for one clock cycle.
+        reg_write(aic, misc_SEEPCTL, SEEPSK|SEEPCS);
+        CLOCK_PULSE();
+
+        // write start bit (1) & READ op-code (10b)
+        for (i=0; i<sizeof(read_cmd); i++) {
+                temp = SEEPCS | SEEPCYC | read_cmd[i];
+                reg_write(aic, misc_SEEPCTL, temp);
+                CLOCK_PULSE();
+                temp = temp ^ SEEPSK;
+                reg_write(aic, misc_SEEPCTL, temp);
+                CLOCK_PULSE();
+        }
+        // write 8 bit address (MSB --> LSB)
+        for (i=7; i>=0; i--) {
+                temp = offset;
+                temp = (temp >> i) & 1;
+                temp = SEEPCS | SEEPCYC | temp;
+                reg_write(aic, misc_SEEPCTL, temp);
+                CLOCK_PULSE();
+                temp = temp ^ SEEPSK;
+                reg_write(aic, misc_SEEPCTL, temp);
+                CLOCK_PULSE();
+        }
+        // read 16 bit (MSB --> LSB)
+        rd = 0;
+        for (i=0; i<=16; i++) {
+                temp = SEEPCS | SEEPCYC;
+                reg_write(aic, misc_SEEPCTL, temp);
+                CLOCK_PULSE();
+                temp = temp ^ SEEPSK;
+                rd = (rd << 1) | (unsigned short)((reg_read(aic, misc_SEEPCTL)
+& SEEPDIN)>>1);
+                reg_write(aic, misc_SEEPCTL, temp);
+                CLOCK_PULSE();
+        }
+
+        // reset chip select for the next command cycle
+        reg_write(aic, misc_SEEPCTL, SEEPCYC);
+        CLOCK_PULSE();
+        reg_write(aic, misc_SEEPCTL, SEEPCYC | SEEPSK);
+        CLOCK_PULSE();
+        reg_write(aic, misc_SEEPCTL, SEEPCYC);
+        CLOCK_PULSE();
+
+        reg_write(aic, misc_SEEPCTL, 0);
+        CLOCK_PULSE();
+
+        return rd;
+}
+
+#undef DEBUG_SEEPROM
+
+/** Read 64-bit GUID (Global Unique ID) from SEEPROM
+ *
+ * It works well on AHA-8945.
+ * On AHA-8920 it works well only on first time, It returns ffff... on
+ * the other times.
+ *****************************************************************/
+static unsigned long long read_guid(struct aic5800 *aic) 
+{
+        int i;
+        unsigned long long guid;
+
+#ifdef DEBUG_SEEPROM
+        printk("\n");
+        printk("SEEPCTL value = 0x%x\n", reg_read(aic, misc_SEEPCTL));
+#endif
+
+        /* read GUID */
+        guid = 0;
+        for (i=0x10; i<0x14; i++)
+                guid = (guid << 16) | read_seeprom_word(aic,i);
+
+#ifdef DEBUG_SEEPROM
+        for (i=0; i<3; i++)
+                printk("%x ", (unsigned int) read_seeprom_word(aic,i));
+        printk("\nGUID = ");
+        for (i=3; i>=0; i--)
+                printk("%x ", (unsigned int)(guid>>(16*i))&0xffff);
+
+        printk("\nSEEPCTL value = 0x%x\n", reg_read(aic, misc_SEEPCTL));
+#endif
+        return guid;
+}
+
+#undef CLOCK_PULSE()
+
+static int aic_detect(struct hpsb_host_template *tmpl)
+{
+        struct hpsb_host *host;
+        int i;
+
+        init_driver();
+
+        for (i = 0; i < num_of_cards; i++) {
+                host = hpsb_get_host(tmpl, 0);
+                if (host == NULL) {
+                        /* simply don't init more after out of mem */
+                        return i;
+                }
+                host->hostdata = &cards[i];
+                cards[i].host = host;
+        }
+
+        return num_of_cards;
+}
+
+static int aic_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
+{
+    struct aic5800 *aic = host->hostdata;
+    int retval = 0;
+    unsigned long flags;
+    struct hpsb_packet *packet, *lastpacket;
+
+    switch (cmd) {
+    case RESET_BUS:
+	reg_write(aic, misc_PhyControl, 0x00004140 );
+	break;
+
+    case GET_CYCLE_COUNTER:
+	arg = reg_read(aic, misc_CycleTimer);
+	break;
+	
+    case SET_CYCLE_COUNTER:
+	reg_write(aic, misc_CycleTimer, arg);
+	break;
+	
+    case SET_BUS_ID:
+	reg_clear_bits(aic, misc_NodeID, 0xFFC0);
+	reg_set_bits(aic, misc_NodeID, (arg<<6));
+	break;
+	
+    case ACT_CYCLE_MASTER:
+	if (arg) {
+	    /* enable cycleMaster */
+	    reg_set_bits(aic, misc_Control, 0x20000);
+	} else {
+	    /* disable cycleMaster */
+	    reg_clear_bits(aic, misc_Control, 0x20000);
+	};
+	break;
+	
+    case CANCEL_REQUESTS:
+	spin_lock_irqsave(&aic->async_queue_lock, flags);
+	/* stop any chip activity */
+	reg_write( aic, AT_ChannelControl, 0x80000000);
+        packet = aic->async_queue;
+	aic->async_queue = NULL;                
+	spin_unlock_irqrestore(&aic->async_queue_lock, flags);
+
+        while (packet != NULL) {
+            lastpacket = packet;
+            packet = packet->xnext;
+            hpsb_packet_sent(host, lastpacket, ACKX_ABORTED);
+        }
+
+	break;
+
+    case MODIFY_USAGE:
+        if (arg) {
+            MOD_INC_USE_COUNT;
+        } else {
+            MOD_DEC_USE_COUNT;
+        }
+        break;
+
+#if 0
+   case DEBUG_DUMPINFO:
+      PRINT(KERN_INFO, aic->id, AIC5800_DRIVER_NAME);
+      PRINT(KERN_INFO, aic->id, "  Register MMIO base: 0x%p\n", 
+	    aic->registers); 
+      PRINT(KERN_INFO, aic->id, "  NodeID: 0x%x\n", 
+	    reg_read(aic, misc_NodeID) ); 
+      PRINT(KERN_INFO,aic->id, "  #Intr: %lu  BusResets: %lu\n",
+	      aic->NumInterrupts, aic->NumBusResets); 
+      PRINT(KERN_INFO, aic->id, "  TxPackets: %lu    RxPackets: %lu\n",
+	      aic->TxPackets, aic->RxPackets); 
+      PRINT(KERN_INFO,aic->id, "  TxRdy: %lu  ATErr: %lu HdrErr: %lu TcodeErr: %lu SendRej: %lu\n",
+	    aic->TxRdy, aic->ATError, aic->HdrErr, 
+	    aic->TCodeErr, aic->SendRej); 
+      break;
+#endif
+	
+    default:
+	PRINT(KERN_ERR, aic->id, "unknown devctl command %d", cmd);
+	retval = -1;
+    }
+    
+    return retval;
+    
+}
+
+/** Initialize the host adapter chip and corresponding data
+    structures. We reset the chip, enable transmitter, receiver,
+    the physical DMA units, cycle timer, cycle source, reception
+    of selfid packets and initialize several other registers. */
+static int aic_initialize(struct hpsb_host *host)
+{
+    int i;
+    struct aic5800 *aic = host->hostdata;
+
+    /* Reset data structures */
+    aic->async_queue = NULL;
+    spin_lock_init(&aic->async_queue_lock);
+
+    /* Reset the chip */
+    reg_write( aic, misc_Reset, 0x37);
+    udelay(10); // FIXME
+    reg_write( aic, misc_Reset, 0);
+   
+    /* Enable Transmitter/Receiver, enable physDMA,
+     * enable CycleTimer, cycleSource */
+    reg_write( aic, misc_Control, 0x82050003);
+
+    /* Enable reception of SelfID packets */
+    reg_set_bits(aic, misc_PacketControl, 0x20);
+
+    reg_write(aic, AT_InterruptSelect, 0x00F0001);
+    reg_write(aic, AT_BranchSelect, 0x0100010);
+    reg_write(aic, AT_WaitSelect, 0x00F0001);
+    reg_write(aic, misc_ATRetries, reg_read(aic, misc_ATRetries) | 0x7);
+
+    /* initialize AR DMA */
+
+    /* unset run bit */
+    reg_write( aic, AR_ChannelControl, 0x80000000);
+	    
+    /* here we should have 0 iterations because of the code
+       in the DmaAR handler. However, to be sure we do it */
+    i = 0;
+    while (reg_read(aic, AR_ChannelStatus) & 0x400) {
+	i++;
+	if (i>100000) {
+	    PRINT(KERN_ERR, aic->id, 
+		  "Huh! Can't set AR_ChannelControl... card can not receive!");
+	    break;
+	}
+    }
+    
+    (aic->AR_program)->control = ( DMA_CMD_INPUTLAST | DMA_KEY_STREAM0 
+				   | DMA_INTR_ALWAYS | DMA_BRANCH_ALWAYS) 
+	+ AIC5800_ARFIFO_SIZE;
+    (aic->AR_program)->address = virt_to_bus(aic->rcv_page);
+    (aic->AR_program)->branchAddress = virt_to_bus(aic->AR_program);
+    (aic->AR_program)->status = AIC5800_ARFIFO_SIZE;
+    
+    (aic->AR_program+1)->control = DMA_CMD_STOP;
+    (aic->AR_program+1)->address = 0;
+    (aic->AR_program+1)->branchAddress = 0;
+    (aic->AR_program+1)->status = 0;
+    
+    reg_write( aic, AR_CommandPtr, (u32) virt_to_bus(aic->AR_program)); 
+    reg_write( aic, AR_ChannelControl, 0x80008000);
+   
+    /* Enable Interrupts */
+    reg_write(aic, misc_InterruptClear, 0xFFFFFFFF);
+    reg_write(aic, misc_InterruptMask, 0xFFFFFFFF);
+    /*reg_write(aic, misc_InterruptMask, 0x00F1F03F);*/
+
+    return 1;
+}
+
+static void aic_release(struct hpsb_host *host)
+{
+    struct aic5800 *aic;
+        
+    if (host != NULL) {
+	aic = host->hostdata;
+	remove_card(aic);
+    } 
+}
+
+/* This must be called with the async_queue_lock held. */
+static void send_next_async(struct aic5800 *aic)
+{
+    int i;
+    struct hpsb_packet *packet = aic->async_queue;
+
+    /* stop the channel program if it's still running */
+    reg_write( aic, AT_ChannelControl, 0x80000000);
+    
+    /* re-format packet header for AIC-5800 chip */
+    packet->header[1] = (packet->header[1] & 0xFFFF) | 
+	(packet->header[0] & 0xFFFF0000);
+    packet->header[0] = (packet->header[0] & 0xFFFF);
+
+#ifndef __BIG_ENDIAN
+    /* Packet must be byte-swapped in non-big-endian environments, 
+     * see AIC-5800 specification...
+     */
+    { u32 i;
+    for ( i = 0 ; i < packet->header_size/sizeof(u32) ; i++ ) 
+	packet->header[i] = cpu_to_be32( packet->header[i] ); 
+    for ( i = 0 ; i < packet->data_size/sizeof(u32) ; i++ ) 
+	packet->data[i] = cpu_to_be32( packet->data[i] ); 
+    }
+    
+#endif
+    
+    /* typically we use only a few iterations here */
+    i = 0;
+    while (reg_read(aic, AT_ChannelStatus) & 0x400) {
+	i++;
+	if (i>5000) {
+	    PRINT(KERN_ERR, aic->id, 
+		  "runaway loop 1 in send_next_async() - bailing out...");
+	    break;
+	};
+    };
+    
+    /* set data buffer address and packet length */
+    memset(aic->AT_program, 0, MAX_AT_PROGRAM_SIZE * sizeof(struct dma_cmd));
+    
+    if (packet->data_size) {
+	aic->AT_program[0].control = ( DMA_CMD_OUTPUTMORE | DMA_KEY_STREAM0 ) + 
+	    packet -> header_size;
+	aic->AT_program[0].address = virt_to_bus( packet->header );
+	aic->AT_program[1].control = ( DMA_CMD_OUTPUTLAST | DMA_KEY_STREAM0 
+				       | DMA_INTR_ALWAYS ) 
+	    + packet -> data_size;
+	aic->AT_program[1].address = virt_to_bus( packet->data );
+	
+	aic->AT_program[2].control = DMA_CMD_STOP;
+	
+    } else {
+	aic->AT_program[0].control = ( DMA_CMD_OUTPUTLAST | DMA_INTR_ALWAYS | 
+				       DMA_KEY_STREAM0 ) + 
+	    packet -> header_size;
+	aic->AT_program[0].address = virt_to_bus( packet->header );
+	
+	aic->AT_program[1].control = DMA_CMD_STOP;
+    };
+    
+    /* set program start address */
+    reg_write(aic, AT_CommandPtr, (unsigned int) virt_to_bus(aic->AT_program));
+
+    /* typically we use only a few iterations here */
+    i = 0;
+    while (reg_read(aic, AT_CommandPtr) != (unsigned int) 
+	   virt_to_bus(aic->AT_program)) {
+		i++;
+	if (i>5000) {
+	    PRINT(KERN_ERR, aic->id, 
+		  "runaway loop 2 in send_next_async() - bailing out...");
+	    break;
+	};
+    };
+     
+    /* run program */
+    reg_write( aic, AT_ChannelControl, 0x80008000);
+}
+
+
+static int aic_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
+{
+    struct aic5800 *aic = host->hostdata;
+    struct hpsb_packet *p;
+    unsigned long flags;
+
+    if (packet->data_size >= 4096) {
+	PRINT(KERN_ERR, aic->id, "transmit packet data too big (%d)",
+	      packet->data_size);
+	return 0;
+    }
+
+    packet->xnext = NULL;
+    
+    spin_lock_irqsave(&aic->async_queue_lock, flags);
+
+    if (aic->async_queue == NULL) {
+	aic->async_queue = packet;
+	send_next_async(aic);
+    } else {
+	p = aic->async_queue;
+	while (p->xnext != NULL) {
+	    p = p->xnext;
+	}
+	
+	p->xnext = packet;
+    }
+    
+    spin_unlock_irqrestore(&aic->async_queue_lock, flags);
+
+    return 1;
+}
+
+static int get_phy_reg(struct aic5800 *aic, int addr)
+{
+        int retval;
+        int i = 0;
+
+	/* sanity check */
+        if (addr > 15) {
+                PRINT(KERN_ERR, aic->id, __FUNCTION__
+                      ": PHY register address %d out of range", addr);
+                return -1;
+        }
+
+	/* request data from PHY */
+        reg_write(aic, misc_PhyControl, LINK_PHY_READ | LINK_PHY_ADDR(addr));
+
+	/* read data from PhyControl register */
+	/* note that we have to wait until the register is updated */
+        do {
+                retval = reg_read(aic, misc_PhyControl);
+
+                if (i > 10000) {
+                        PRINT(KERN_ERR, aic->id, __FUNCTION__ 
+                              ": runaway loop, aborting");
+                        retval = -1;
+                        break;
+                }
+                i++;
+        } while ((retval & 0xf000000) != LINK_PHY_RADDR(addr));
+
+	/* we don't want a PhyInt interrupt */
+        reg_write(aic, misc_InterruptClear, INT_PhyInt);
+
+        if (retval != -1) {
+                return ((retval & 0xff0000)>>16);
+        } else {
+                return -1;
+        }
+}
+
+static quadlet_t generate_own_selfid(struct aic5800 *aic, int phyid)
+{
+    quadlet_t lsid;
+    char phyreg[7];
+    int i;
+
+    for (i = 1; i < 7; i++) {
+	phyreg[i] = get_phy_reg(aic, i);
+    }
+
+    /* Standard PHY register map */
+    lsid = 0x80400000 | (phyid << 24);
+    lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */
+    lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */
+    lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dep) */
+    lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */
+
+    for (i = 0; i < (phyreg[2] & 0x1f); i++) { /* ports */
+	if (phyreg[3 + i] & 0x4) {
+	    lsid |= (((phyreg[3 + i] & 0x8) | 0x10) >> 3)
+						    << (6 - i*2);
+	} else {
+	    lsid |= 1 << (6 - i*2);
+	}
+    }
+
+    return lsid;
+};
+
+/* moved out to make interrupt routine more readable */
+inline static void handle_selfid(struct aic5800 *aic, struct hpsb_host *host,
+                          int phyid, int isroot, size_t size)
+{
+    quadlet_t *q = aic->rcv_page;
+    quadlet_t lsid;
+
+    /* we need our own self-id packet */
+    lsid = generate_own_selfid(aic, phyid);
+
+    /* unconnected state? only begin and end marker in rcv_page */
+    if (size==8) {
+	hpsb_selfid_received(host, lsid);
+    }
+
+    /* process buffer... AIC's FIFO often contains some strangenesses */
+    while (size > 0) {
+	if (q[0] == 0xe0) {
+	    /* marker */
+	    q += 1;
+	    size -= 4;
+	    continue;
+	};
+	if (q[0] == 0x1) {
+	    /* marker */
+	    q += 1;
+	    size -= 4;
+	    break;
+	};
+
+	if (q[0] == ~q[1]) {
+	    /* correct self-id */
+
+	    if ((q[0] & 0x3f800000) == ((phyid + 1) << 24)) {
+		/* its our turn now! */
+		//PRINT(KERN_INFO, 
+		//      aic->id, "selfid packet 0x%x included", lsid);
+		
+		hpsb_selfid_received(host, lsid);
+	    }
+
+	    //PRINT(KERN_INFO, aic->id, "selfid packet 0x%x rcvd", q[0]);
+	    hpsb_selfid_received(host, q[0]);
+	    q += 2;
+	    size -= 8;
+	    continue;
+	};
+    }
+
+    /* if we are root, our self-id packet is last */
+    if (isroot && phyid != 0) {
+	hpsb_selfid_received(host, lsid);
+    }
+
+    hpsb_selfid_complete(host, phyid, isroot);
+}
+
+static void aic_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+    struct aic5800 *aic = (struct aic5800 *)dev_id;
+    struct hpsb_host *host = aic->host;
+    quadlet_t *q = aic->rcv_page;
+ 
+    int phyid = -1, isroot = 0;
+
+    u32 interruptEvent = reg_read(aic, misc_InterruptEvents);
+    reg_write(aic, misc_InterruptClear, interruptEvent);
+
+    //printk("InterruptEvent 0x%x\n", interruptEvent);
+    if ( (interruptEvent & 0x3f) == 0x3f ) {
+	PRINT(KERN_INFO, aic->id, "Dma Engine Error");
+    };
+
+    if ( interruptEvent & INT_DmaAT ) {
+	if (aic->AT_program[0].status & 0xFFFF) 
+	    PRINT(KERN_INFO, aic->id, "AT: could not transfer %d bytes", 
+		  aic->AT_program[0].status & 0xFFFF);
+    };
+
+    if ( interruptEvent & INT_PhyInt) {
+	PRINT(KERN_INFO, aic->id, "PhyInt");
+    };
+
+    if ( interruptEvent & INT_DmaAR ) {
+	int rcv_bytes;
+	int i;
+
+	/* we calculate the number of received bytes from the
+	   residual count field */
+	rcv_bytes = AIC5800_ARFIFO_SIZE - (aic->AR_program->status & 0xFFFF);
+
+	//PRINT(KERN_INFO, aic->id, "AR_status 0x%x, %d bytes read", aic->AR_program->status, rcv_bytes);
+
+	if ((aic->AR_program->status & 0x84000000) 
+	    && (aic->AR_program->status & 0xFFFF) >= 8 ) {
+
+#ifndef __BIG_ENDIAN 
+	    /* we have to do byte-swapping on non-bigendian architectures */
+	    for (i=0; i< (rcv_bytes / sizeof(quadlet_t)); i++) {
+		*q = be32_to_cpu(*q);
+		q++;
+	    };
+	    q = aic->rcv_page;
+#endif
+
+	    if (*q == 0xe0) {
+		phyid = reg_read(aic, misc_NodeID);
+		isroot = phyid & 0x800000;
+		phyid = phyid & 0x3F;
+		handle_selfid(aic, host, phyid, isroot, rcv_bytes);
+	    } else {
+		hpsb_packet_received(host, aic->rcv_page, rcv_bytes);
+	    };
+	} else {
+	    PRINT(KERN_ERR, aic->id, 
+		  "AR DMA program status value 0x%x is incorrect!",
+		  aic->AR_program->status);
+	};
+    }
+    if ( interruptEvent & INT_BusReset ) {
+	PRINT(KERN_INFO, aic->id, "bus reset occured");
+	if (!host->in_bus_reset) {
+	    hpsb_bus_reset(host);
+	}
+	reg_set_bits(aic, misc_Control, 0x1);
+	aic->NumBusResets++;
+    };
+
+    if (interruptEvent & INT_RcvData ) { 
+	aic->RxPackets++;
+    };
+
+    if (interruptEvent & INT_TxRdy) { 
+	/* async packet sent - transmitter ready */
+	u32 ack;
+	struct hpsb_packet *packet;
+
+	if (aic->async_queue) {
+
+	    spin_lock(&aic->async_queue_lock);
+
+	    
+	    ack = reg_read(aic, AT_ChannelStatus) & 0xF;
+	    
+	    packet = aic->async_queue;
+	    aic->async_queue = packet->xnext;
+	    
+	    if (aic->async_queue != NULL) {
+		send_next_async(aic);
+	    }
+	    spin_unlock(&aic->async_queue_lock);
+	    PRINT(KERN_INFO,aic->id,"packet sent with ack code %d",ack);
+	    hpsb_packet_sent(host, packet, ack);	    
+	} // else 
+	    //PRINT(KERN_INFO,aic->id,"packet sent without async_queue (self-id?)");
+
+	aic->TxRdy++;
+    };
+    if (interruptEvent & INT_ATError ) { 
+	PRINT(KERN_INFO,aic->id,"ATError");
+	aic->ATError++;
+    };
+    if (interruptEvent & INT_SendRej ) { 
+	aic->SendRej++;
+    };
+    if (interruptEvent & INT_HdrErr ) { 
+	aic->HdrErr++;
+    };
+    if (interruptEvent & INT_TCodeErr ) { 
+	PRINT(KERN_INFO,aic->id,"TCodeErr");
+	aic->TCodeErr++;
+    };
+
+    aic->NumInterrupts++;
+
+}
+
+inline static void * quadquadalign(void *buf)
+{
+  if ((unsigned int) buf % 0x10 != 0) {
+	return (void *)(((unsigned int)buf + 0x10) & 0xFFFFFFF0);
+	} else {
+	return buf;
+  };
+}
+
+static int add_card(struct pci_dev *dev)
+{
+#define FAIL(fmt, args...) \
+        PRINT_G(KERN_ERR, fmt , ## args); \
+        num_of_cards--; \
+        remove_card(aic); \
+        return 1;
+
+        struct aic5800 *aic; /* shortcut to currently handled device */
+        unsigned long page;
+
+        if (num_of_cards == MAX_AIC5800_CARDS) {
+                PRINT_G(KERN_WARNING, "cannot handle more than %d cards.  "
+                        "Adjust MAX_AIC5800_CARDS in aic5800.h.",
+                        MAX_AIC5800_CARDS);
+                return 1;
+        }
+
+        aic = &cards[num_of_cards++];
+
+        aic->id = num_of_cards-1;
+        aic->dev = dev;
+
+        if (!request_irq(dev->irq, aic_irq_handler, SA_SHIRQ,
+                         AIC5800_DRIVER_NAME, aic)) {
+                PRINT(KERN_INFO, aic->id, "allocated interrupt %d", dev->irq);
+        } else {
+                FAIL("failed to allocate shared interrupt %d", dev->irq);
+        }
+
+        page = get_free_page(GFP_KERNEL);
+        if (page != 0) {
+                aic->rcv_page = phys_to_virt(page);
+        } else {
+                FAIL("failed to allocate receive buffer");
+        }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
+        aic->registers = ioremap_nocache(dev->base_address[0],
+                                          AIC5800_REGSPACE_SIZE);
+#else
+        aic->registers = ioremap_nocache(dev->resource[0].start,
+                                          AIC5800_REGSPACE_SIZE);
+#endif
+
+        if (aic->registers == NULL) {
+                FAIL("failed to remap registers - card not accessible");
+        }
+
+        PRINT(KERN_INFO, aic->id, "remapped memory space reg 0x%p", 
+	      aic->registers);
+
+        aic->pbuf = kmalloc(AIC5800_PBUF_SIZE, GFP_KERNEL);
+
+        if (!aic->pbuf) {
+                FAIL("failed to allocate program buffer");
+        }
+
+	aic->AT_program = quadquadalign(aic->pbuf);
+	aic->AT_program[2].control = DMA_CMD_STOP;
+
+	aic->AR_program = aic->AT_program + MAX_AT_PROGRAM_SIZE * 
+	    sizeof(struct dma_cmd);
+
+        return 0;
+#undef FAIL
+}
+
+static void remove_card(struct aic5800 *aic)
+{
+    /* Disable interrupts of this controller */
+    reg_write(aic, misc_InterruptMask, 0);
+    /* Free AR buffer */
+    free_page(virt_to_phys(aic->rcv_page));
+    /* Free channel program buffer */
+    kfree(aic->pbuf);
+    /* Free interrupt request */
+    free_irq(aic->dev->irq, aic);
+    /* Unmap register space */
+    iounmap(aic->registers);
+}
+
+static int init_driver()
+{
+        struct pci_dev *dev = NULL;
+        int success = 0;
+
+        if (num_of_cards) {
+                PRINT_G(KERN_DEBUG, __PRETTY_FUNCTION__ " called again");
+                return 0;
+        }
+
+        while ((dev = pci_find_device(PCI_VENDOR_ID_ADAPTEC,
+                                      PCI_DEVICE_ID_ADAPTEC_5800, dev)) 
+               != NULL) {
+                if (add_card(dev) == 0) {
+                        success = 1;
+                }
+        }
+
+        if (success == 0) {
+                PRINT_G(KERN_WARNING, "no operable AIC-5800 based cards found");
+                return -ENXIO;
+        }
+
+        return 0;
+}
+
+/** Prepare our local CSR ROM. This is done by using the software-stored
+    ROM and inserting the GUID read from the EEPROM */
+static size_t get_aic_rom(struct hpsb_host *host, const quadlet_t **ptr)
+{
+    struct aic5800 *aic = host -> hostdata;
+    u64 guid;
+
+    /* Read the GUID from the card's EEPROM and put it into the right
+       place in the CONFIG ROM. */
+    guid = read_guid(aic);
+    aic5800_csr_rom[15] = (u32) (guid >> 32);
+    aic5800_csr_rom[16] = (u32) (guid & 0xFFFF);
+
+    *ptr = aic5800_csr_rom;
+
+    return sizeof(aic5800_csr_rom);
+}
+
+struct hpsb_host_template *get_aic_template(void)
+{
+        static struct hpsb_host_template tmpl;
+        static int initialized = 0;
+
+        if (!initialized) {
+                /* Initialize by field names so that a template structure
+                 * reorganization does not influence this code. */
+                tmpl.name = "aic5800";
+                
+                tmpl.detect_hosts = aic_detect;
+                tmpl.initialize_host = aic_initialize;
+                tmpl.release_host = aic_release;
+                tmpl.get_rom = get_aic_rom;
+                tmpl.transmit_packet = aic_transmit;
+                tmpl.devctl = aic_devctl;
+
+                initialized = 1;
+        }
+
+        return &tmpl;
+}
+
+#ifdef MODULE
+
+/* EXPORT_NO_SYMBOLS; */
+
+MODULE_AUTHOR("Emanuel Pirker <epirker@edu.uni-klu.ac.at>");
+MODULE_DESCRIPTION("Adaptec AIC-5800 PCI-to-IEEE1394 controller driver");
+MODULE_SUPPORTED_DEVICE("aic5800");
+
+void cleanup_module(void)
+{
+        hpsb_unregister_lowlevel(get_aic_template());
+        PRINT_G(KERN_INFO, "removed " AIC5800_DRIVER_NAME " module");
+}
+
+int init_module(void)
+{
+        if (hpsb_register_lowlevel(get_aic_template())) {
+                PRINT_G(KERN_ERR, "registering failed");
+                return -ENXIO;
+        } else {
+                return 0;
+        }
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/aic5800.h linux/drivers/ieee1394/aic5800.h
--- v2.3.39/linux/drivers/ieee1394/aic5800.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/aic5800.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,292 @@
+/*
+**  aic5800.h - Adaptec AIC-5800 PCI-IEEE1394 chip driver header file
+**  Copyright (C)1999 Emanuel Pirker <epirker@edu.uni-klu.ac.at>
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License as published by
+**  the Free Software Foundation; either version 2 of the License, or
+**  (at your option) any later version.
+**
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+**
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+*/
+
+#ifndef AIC5800_H
+#define AIC5800_H
+
+#define AIC5800_DRIVER_NAME      "aic5800"
+
+#define MAX_AIC5800_CARDS        4
+#define AIC5800_REGSPACE_SIZE    512
+#define AIC5800_PBUF_SIZE        512
+
+#define MAX_AT_PROGRAM_SIZE      10
+#define AIC5800_ARFIFO_SIZE      128
+
+struct dma_cmd {
+    u32 control;
+    u32 address;
+    u32 branchAddress;
+    u32 status;
+};
+
+struct aic5800 {
+    int id; /* sequential card number */
+
+    struct pci_dev *dev;
+    
+    /* remapped memory spaces */
+    void *registers;
+    
+    struct hpsb_host *host;
+    
+    int phyid, isroot;
+
+    void *rcv_page;
+    void *pbuf;
+    
+    struct dma_cmd *AT_program;
+    u32 *AT_status;
+    struct dma_cmd *AR_program;
+    u32 *AR_status;
+    int AR_active;
+    
+    struct hpsb_packet *async_queue;
+    spinlock_t async_queue_lock;
+
+    unsigned long NumInterrupts, NumBusResets;
+    unsigned long TxPackets, RxPackets;
+    unsigned long TxErrors, RxErrors;
+    unsigned long TxRdy, ATError, HdrErr, TCodeErr, SendRej;
+
+};
+
+
+/*
+ * Register read and write helper functions.
+ */
+inline static void reg_write(const struct aic5800 *aic, int offset, u32 data)
+{
+        writel(data, aic->registers + offset);
+}
+
+inline static u32 reg_read(const struct aic5800 *aic, int offset)
+{
+        return readl(aic->registers + offset);
+}
+
+inline static void reg_set_bits(const struct aic5800 *aic, int offset,
+                                u32 mask)
+{
+        reg_write(aic, offset, (reg_read(aic, offset) | mask));
+}
+
+inline static void reg_clear_bits(const struct aic5800 *aic, int offset,
+                                  u32 mask)
+{
+        reg_write(aic, offset, (reg_read(aic, offset) & ~mask));
+}
+
+
+/*  AIC-5800 Registers */
+
+#define AT_ChannelControl	0x0
+#define AT_ChannelStatus	0x4
+#define AT_CommandPtr	0xC
+#define AT_InterruptSelect	0x10
+#define AT_BranchSelect	0x14
+#define AT_WaitSelect	0x18
+
+/* Asynchronous receive */
+#define AR_ChannelControl	0x20
+#define AR_ChannelStatus	0x24
+#define AR_CommandPtr	0x2C
+
+/* ITA */
+#define ITA_ChannelControl	0x40
+#define ITA_ChannelStatus	0x44
+#define ITA_CommandPtr	0x4C
+
+/* ITB */
+#define ITB_ChannelControl	0x60
+#define ITB_ChannelStatus	0x64
+#define ITB_CommandPtr	0x6C
+
+/* IRA */
+#define IRA_ChannelControl	0x80
+#define IRA_ChannelStatus	0x84
+#define IRA_CommandPtr	0x8C
+
+/* IRB */
+#define IRB_ChannelControl	0xA0
+#define IRB_ChannelStatus	0xA4
+#define IRB_CommandPtr	0xAC
+
+/* miscellaneous */
+#define misc_Version	0x100
+#define misc_Control	0x104
+#define misc_NodeID	0x108
+#define misc_Reset	0x10C
+#define misc_PacketControl	0x110
+#define misc_Diagnostic	0x114
+#define misc_PhyControl	0x118
+#define misc_ATRetries	0x11C
+#define misc_SSNinterface	0x120
+#define misc_CycleTimer	0x124
+
+/* ITA */
+#define ITA_EventCycle	0x130
+#define ITA_Configuration	0x134
+#define ITA_Bandwidth	0x138
+
+/* ITB */
+#define ITB_EventCycle	0x140
+#define ITB_Configuration	0x144
+#define ITB_Bandwidth	0x148
+
+/* IRA */
+#define IRA_EventCycle	0x150
+#define IRA_Configuration	0x154
+
+/* IRB */
+#define IRB_EventCycle	0x160
+#define IRB_Configuration	0x164
+
+/* RSU */
+#define RSU_Enable	0x170
+#define RSU_Interrupt	0x174
+#define RSU_TablePtr	0x178
+#define RSU_InterruptSet	0x17C
+
+/* misc */
+#define misc_InterruptEvents	0x180
+#define misc_InterruptMask	0x184
+#define misc_InterruptClear	0x188
+#define misc_CardBusEvent	0x1E0
+#define misc_CardBusMask	0x1E4
+#define misc_CardBusState	0x1E8
+#define misc_CardBusForce	0x1EC
+#define misc_SEEPCTL	        0x1F0
+
+/* Interrupts */
+#define INT_DmaAT             1
+#define INT_DmaAR            (1<<1)
+#define INT_DmaITA           (1<<2)
+#define INT_DmaITB           (1<<3)
+#define INT_DmaIRA           (1<<4)
+#define INT_DmaIRB           (1<<5)
+#define INT_PERResponse      (1<<7)
+#define INT_CycleEventITA    (1<<8)
+#define INT_CycleEventITB    (1<<9)
+#define INT_CycleEventIRA    (1<<10)
+#define INT_CycleEventIRB    (1<<11)
+#define INT_BusReset         (1<<12)
+#define INT_CmdReset         (1<<13)
+#define INT_PhyInt           (1<<14)
+#define INT_RcvData          (1<<15)
+#define INT_TxRdy            (1<<16)
+#define INT_CycleStart       (1<<17)
+#define INT_CycleSeconds     (1<<18)
+#define INT_CycleLost        (1<<19)
+#define INT_ATError          (1<<20)
+#define INT_SendRej          (1<<21)
+#define INT_HdrErr           (1<<22)
+#define INT_TCodeErr         (1<<23)
+#define INT_PRQUxferErr      (1<<24)
+#define INT_PWQUxferErr      (1<<25)
+#define INT_RSUxferErr       (1<<26)
+#define INT_RSDone           (1<<27)
+#define INT_PSOutOfRetries   (1<<28)
+#define INT_cycleTooLong     (1<<29)
+
+/* DB DMA constants */
+#define DMA_CMD_OUTPUTMORE  0
+#define DMA_CMD_OUTPUTLAST  0x10000000
+#define DMA_CMD_INPUTMORE   0x20000000
+#define DMA_CMD_INPUTLAST   0x30000000
+#define DMA_CMD_STOREQUAD   0x40000000
+#define DMA_CMD_LOADQUAD    0x50000000
+#define DMA_CMD_NOP         0x60000000
+#define DMA_CMD_STOP        0x70000000
+
+#define DMA_KEY_STREAM0  0
+#define DMA_KEY_STREAM1  (1<<24)
+#define DMA_KEY_STREAM2  (2<<24)
+#define DMA_KEY_STREAM3  (3<<24)
+#define DMA_KEY_REGS     (5<<24)
+#define DMA_KEY_SYSTEM   (6<<24)
+#define DMA_KEY_DEVICE   (7<<24)
+
+#define DMA_INTR_NEVER    0
+#define DMA_INTR_TRUE     (1<<20)
+#define DMA_INTR_FALSE    (2<<20)
+#define DMA_INTR_ALWAYS   (3<<20)
+#define DMA_WAIT_NEVER    0
+#define DMA_WAIT_TRUE     (1<<16)
+#define DMA_WAIT_FALSE    (2<<16)
+#define DMA_WAIT_ALWAYS   (3<<16)
+#define DMA_BRANCH_NEVER    0
+#define DMA_BRANCH_TRUE     (1<<18)
+#define DMA_BRANCH_FALSE    (2<<18)
+#define DMA_BRANCH_ALWAYS   (3<<18)
+
+#define DMA_SPEED_100 0
+#define DMA_SPEED_200 (1<<16)
+#define DMA_SPEED_400 (2<<16)
+
+/* PHY access */
+#define LINK_PHY_READ                     (1<<15)
+#define LINK_PHY_WRITE                    (1<<14)
+#define LINK_PHY_ADDR(addr)               (addr<<8)
+#define LINK_PHY_WDATA(data)              (data)
+#define LINK_PHY_RADDR(addr)              (addr<<24)
+
+quadlet_t aic5800_csr_rom[] = {
+    /* bus info block */
+    0x041ffb82,     // length of bus info block, CRC
+    0x31333934,     // 1394 designator 
+    0xf005a000,     // various capabilites
+    0x0000d189,     // node_vendor_id, chip_id_hi
+    0x401010fc,     // chip_id_lo
+    /* root directory */
+    0x00040e54,     // length of root directory, CRC
+    0x030000d1,     // module_vendor_id
+    0x0c008000,     // various capabilities
+    0x8d000006,     // offset of node unique id leaf
+    0xd1000001,     // offset of unit directory
+    /* unit directory */
+    0x0003e60d,     // length of unit directory, CRC
+    0x12000000,     // unit_spec_id
+    0x13000000,     // unit_sw_version
+    0xd4000004,     // offset of unit dependent directory
+    /* node unique id leaf */
+    0x00026ba7,     // length of leaf, CRC
+    0x0000d189,     // node_vendor_id, chip_id_hi
+    0x401010fc,     // chip_id_lo
+    /* unit dependent directory */
+    0x0002ae47,     // length of directory, CRC
+    0x81000002,     // offset of vendor name leaf
+    0x82000006,     // offset of model name leaf
+    /* vendor name leaf */
+    0x000486a3,     // length of leaf, CRC
+    0x00000000,
+    0x00000000,
+    0x41444150,     // ADAP
+    0x54454300,     // TEC
+    /* model name leaf */
+    0x0004f420,     // length of leaf, CRC
+    0x00000000,
+    0x00000000,
+    0x4148412d,     // AHA-
+    0x38393430      // 8940
+};
+
+#endif
+
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/csr.c linux/drivers/ieee1394/csr.c
--- v2.3.39/linux/drivers/ieee1394/csr.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/csr.c	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,435 @@
+/*
+ * IEEE 1394 for Linux
+ *
+ * CSR implementation, iso/bus manager implementation.
+ *
+ * Copyright (C) 1999 Andreas E. Bombe
+ */
+
+#include <linux/string.h>
+
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394.h"
+#include "highlevel.h"
+
+
+static u16 csr_crc16(unsigned *data, int length)
+{
+        int check=0, i;
+        int shift, sum, next=0;
+
+        for (i = length; i; i--) {
+                for (next = check, shift = 28; shift >= 0; shift -= 4 ) {
+                        sum = ((next >> 12) ^ (*data >> shift)) & 0xf;
+                        next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
+                }
+                check = next & 0xffff;
+                data++;
+        }
+
+        return check;
+}
+
+static void host_reset(struct hpsb_host *host)
+{
+        host->csr.state &= 0x300;
+
+        host->csr.bus_manager_id = 0x3f;
+        host->csr.bandwidth_available = 4915;
+        host->csr.channels_available_hi = ~0;
+        host->csr.channels_available_lo = ~0;
+
+        host->csr.node_ids = host->node_id << 16;
+
+        if (!host->is_root) {
+                /* clear cmstr bit */
+                host->csr.state &= ~0x100;
+        }
+
+        host->csr.topology_map[1]++;
+        host->csr.topology_map[2] = host->node_count << 16 | host->selfid_count;
+        host->csr.topology_map[0] = (host->selfid_count + 2) << 16
+                | csr_crc16(host->csr.topology_map + 1, host->selfid_count + 2);
+
+        /* FIXME - generate speed map */
+        host->csr.speed_map[0] = 0x3f1 << 16 | csr_crc16(host->csr.speed_map+1,
+                                                         0x3f1);
+}
+
+
+static void add_host(struct hpsb_host *host)
+{
+        host->csr.lock = SPIN_LOCK_UNLOCKED;
+
+        host->csr.rom_size = host->template->get_rom(host, &host->csr.rom);
+
+        host->csr.state                 = 0;
+        host->csr.node_ids              = 0;
+        host->csr.split_timeout_hi      = 0;
+        host->csr.split_timeout_lo      = 800 << 19;
+        host->csr.cycle_time            = 0;
+        host->csr.bus_time              = 0;
+        host->csr.bus_manager_id        = 0x3f;
+        host->csr.bandwidth_available   = 4915;
+        host->csr.channels_available_hi = ~0;
+        host->csr.channels_available_lo = ~0;
+}
+
+
+/* Read topology / speed maps and configuration ROM */
+static int read_maps(struct hpsb_host *host, quadlet_t *buffer, u64 addr,
+                     unsigned int length)
+{
+        int csraddr = addr - CSR_REGISTER_BASE;
+        const char *src;
+
+        if (csraddr < CSR_TOPOLOGY_MAP) {
+                if (csraddr + length > CSR_CONFIG_ROM + host->csr.rom_size) {
+                        return RCODE_ADDRESS_ERROR;
+                }
+                src = ((char *)host->csr.rom) + csraddr - CSR_CONFIG_ROM;
+        } else if (csraddr < CSR_SPEED_MAP) {
+                src = ((char *)host->csr.topology_map) + csraddr 
+                        - CSR_TOPOLOGY_MAP;
+        } else {
+                src = ((char *)host->csr.speed_map) + csraddr - CSR_SPEED_MAP;
+        }
+
+        memcpy(buffer, src, length);
+        return RCODE_COMPLETE;
+}
+
+/* Read FCP register space */
+static int read_fcp(struct hpsb_host *host, quadlet_t *buffer, u64 addr,
+                    unsigned int length)
+{
+        int csraddr = addr - CSR_REGISTER_BASE;
+        const char *src;
+
+        if (csraddr + length > CSR_FCP_END) {
+                return RCODE_ADDRESS_ERROR;
+        }
+        src = ((char *)host->csr.fcp_data) + csraddr - CSR_FCP_COMMAND;
+        
+        memcpy(buffer, src, length);
+        return RCODE_COMPLETE;
+}
+
+/* Write FCP register space */
+static int write_fcp(struct hpsb_host *host, quadlet_t *data, u64 addr,
+                     unsigned int length)
+{
+        int csraddr = addr - CSR_REGISTER_BASE;
+        char *dest;
+
+        if (csraddr + length > CSR_FCP_END) {
+                return RCODE_ADDRESS_ERROR;
+        }
+        dest = ((char *)host->csr.fcp_data) + csraddr - CSR_FCP_COMMAND;
+        
+        memcpy(dest, data, length);
+        return RCODE_COMPLETE;
+}
+
+
+#define out if (--length == 0) break
+
+static int read_regs(struct hpsb_host *host, quadlet_t *buf, u64 addr,
+                     unsigned int length)
+{
+        int csraddr = addr - CSR_REGISTER_BASE;
+        int oldcycle;
+        
+        if ((csraddr | length) & 0x3) {
+                return RCODE_TYPE_ERROR;
+        }
+
+        length /= 4;
+
+        switch (csraddr) {
+        case CSR_STATE_CLEAR:
+                *(buf++) = host->csr.state;
+                out;
+        case CSR_STATE_SET:
+                *(buf++) = host->csr.state;
+                out;
+        case CSR_NODE_IDS:
+                *(buf++) = host->csr.node_ids;
+                out;
+
+        case CSR_RESET_START:
+                return RCODE_TYPE_ERROR;
+
+                /* address gap - handled by default below */
+
+        case CSR_SPLIT_TIMEOUT_HI:
+                *(buf++) = host->csr.split_timeout_hi;
+                out;
+        case CSR_SPLIT_TIMEOUT_LO:
+                *(buf++) = host->csr.split_timeout_lo;
+                out;
+
+                /* address gap */
+                return RCODE_ADDRESS_ERROR;
+
+        case CSR_CYCLE_TIME:
+                oldcycle = host->csr.cycle_time;
+                host->csr.cycle_time =
+                        host->template->devctl(host, GET_CYCLE_COUNTER, 0);
+
+                if (oldcycle > host->csr.cycle_time) {
+                        /* cycle time wrapped around */
+                        host->csr.bus_time += 1 << 7;
+                }
+                *(buf++) = host->csr.cycle_time;
+                out;
+        case CSR_BUS_TIME:
+                oldcycle = host->csr.cycle_time;
+                host->csr.cycle_time =
+                        host->template->devctl(host, GET_CYCLE_COUNTER, 0);
+
+                if (oldcycle > host->csr.cycle_time) {
+                        /* cycle time wrapped around */
+                        host->csr.bus_time += (1 << 7);
+                }
+                *(buf++) = host->csr.bus_time | (host->csr.cycle_time >> 25);
+                out;
+
+                /* address gap */
+                return RCODE_ADDRESS_ERROR;
+
+        case CSR_BUSY_TIMEOUT:
+                /* not yet implemented */
+                return RCODE_ADDRESS_ERROR;
+
+        case CSR_BUS_MANAGER_ID:
+                *(buf++) = host->csr.bus_manager_id;
+                out;
+        case CSR_BANDWIDTH_AVAILABLE:
+                *(buf++) = host->csr.bandwidth_available;
+                out;
+        case CSR_CHANNELS_AVAILABLE_HI:
+                *(buf++) = host->csr.channels_available_hi;
+                out;
+        case CSR_CHANNELS_AVAILABLE_LO:
+                *(buf++) = host->csr.channels_available_lo;
+                out;
+
+                /* address gap to end - fall through to default */
+        default:
+                return RCODE_ADDRESS_ERROR;
+        }
+
+        return RCODE_COMPLETE;
+}
+
+static int write_regs(struct hpsb_host *host, quadlet_t *data, u64 addr,
+                      unsigned int length)
+{
+        int csraddr = addr - CSR_REGISTER_BASE;
+        
+        if ((csraddr | length) & 0x3) {
+                return RCODE_TYPE_ERROR;
+        }
+
+        length /= 4;
+
+        switch (csraddr) {
+        case CSR_STATE_CLEAR:
+                /* FIXME FIXME FIXME */
+                printk("doh, someone wants to mess with state clear\n");
+                out;
+        case CSR_STATE_SET:
+                printk("doh, someone wants to mess with state set\n");
+                out;
+
+        case CSR_NODE_IDS:
+                host->csr.node_ids &= NODE_MASK << 16;
+                host->csr.node_ids |= *(data++) & (BUS_MASK << 16);
+                host->node_id = host->csr.node_ids >> 16;
+                host->template->devctl(host, SET_BUS_ID, host->node_id >> 6);
+                out;
+
+        case CSR_RESET_START:
+                /* FIXME - perform command reset */
+                out;
+
+                /* address gap */
+                return RCODE_ADDRESS_ERROR;
+
+        case CSR_SPLIT_TIMEOUT_HI:
+                host->csr.split_timeout_hi = *(data++) & 0x00000007;
+                out;
+        case CSR_SPLIT_TIMEOUT_LO:
+                host->csr.split_timeout_lo = *(data++) & 0xfff80000;
+                out;
+
+                /* address gap */
+                return RCODE_ADDRESS_ERROR;
+
+        case CSR_CYCLE_TIME:
+                /* should only be set by cycle start packet, automatically */
+                host->csr.cycle_time = *data;
+                host->template->devctl(host, SET_CYCLE_COUNTER, *(data++));
+                out;
+        case CSR_BUS_TIME:
+                host->csr.bus_time = *(data++) & 0xffffff80;
+                out;
+
+                /* address gap */
+                return RCODE_ADDRESS_ERROR;
+
+        case CSR_BUSY_TIMEOUT:
+                /* not yet implemented */
+                return RCODE_ADDRESS_ERROR;
+
+        case CSR_BUS_MANAGER_ID:
+        case CSR_BANDWIDTH_AVAILABLE:
+        case CSR_CHANNELS_AVAILABLE_HI:
+        case CSR_CHANNELS_AVAILABLE_LO:
+                /* these are not writable, only lockable */
+                return RCODE_TYPE_ERROR;
+
+                /* address gap to end - fall through */
+        default:
+                return RCODE_ADDRESS_ERROR;
+        }
+
+        return RCODE_COMPLETE;
+}
+
+#undef out
+
+
+/* helper function for lock_regs */
+inline static void compare_swap(quadlet_t *old, quadlet_t data, quadlet_t arg)
+{
+        if (*old == arg) {
+                *old = data;
+        }
+}
+
+static int lock_regs(struct hpsb_host *host, quadlet_t *store, u64 addr, 
+                     quadlet_t data, quadlet_t arg, int extcode)
+{
+        int csraddr = addr - CSR_REGISTER_BASE;
+        unsigned long flags;
+
+        if (csraddr & 0x3) {
+                return RCODE_TYPE_ERROR;
+        }
+
+        if ((csraddr >= CSR_BUS_MANAGER_ID)
+            && (csraddr <= CSR_CHANNELS_AVAILABLE_LO)) {
+                if (extcode == EXTCODE_COMPARE_SWAP) {
+                        spin_lock_irqsave(&host->csr.lock, flags);
+
+                        switch (csraddr) {
+                        case CSR_BUS_MANAGER_ID:
+                                *store = host->csr.bus_manager_id;
+                                compare_swap(&host->csr.bus_manager_id,
+                                             data, arg);
+                                break;
+
+                        case CSR_BANDWIDTH_AVAILABLE:
+                                *store = host->csr.bandwidth_available;
+                                compare_swap(&host->csr.bandwidth_available,
+                                             data, arg);
+                                break;
+
+                        case CSR_CHANNELS_AVAILABLE_HI:
+                                *store = host->csr.channels_available_hi;
+                                compare_swap(&host->csr.channels_available_hi,
+                                             data, arg);
+                                break;
+
+                        case CSR_CHANNELS_AVAILABLE_LO:
+                                *store = host->csr.channels_available_lo;
+                                compare_swap(&host->csr.channels_available_lo,
+                                             data, arg);
+                                break;
+                        }
+
+                        spin_unlock_irqrestore(&host->csr.lock, flags);
+                        return RCODE_COMPLETE;
+                } else {
+                        return RCODE_TYPE_ERROR;
+                }
+        }
+
+        /* no locking for anything else yet */
+        switch (csraddr) {
+        case CSR_STATE_CLEAR:
+        case CSR_STATE_SET:
+        case CSR_RESET_START:
+        case CSR_NODE_IDS:
+        case CSR_SPLIT_TIMEOUT_HI:
+        case CSR_SPLIT_TIMEOUT_LO:
+        case CSR_CYCLE_TIME:
+        case CSR_BUS_TIME:
+                return RCODE_TYPE_ERROR;
+
+        case CSR_BUSY_TIMEOUT:
+                /* not yet implemented - fall through */
+        default:
+                return RCODE_ADDRESS_ERROR;
+        }
+}
+
+
+struct hpsb_highlevel_ops csr_ops = {
+        add_host,
+        NULL,
+        host_reset,
+        NULL
+};
+
+
+struct hpsb_address_ops map_ops = {
+        read_maps,
+        NULL,
+        NULL,
+        NULL
+};
+
+struct hpsb_address_ops fcp_ops = {
+        read_fcp,
+        write_fcp,
+        NULL,
+        NULL
+};
+
+struct hpsb_address_ops reg_ops = {
+        read_regs,
+        write_regs,
+        lock_regs,
+        NULL
+};
+
+
+void init_csr(void)
+{
+        struct hpsb_highlevel *hl;
+
+        hl = hpsb_register_highlevel("standard registers", &csr_ops);
+        if (hl == NULL) {
+                HPSB_ERR("out of memory during ieee1394 initialization");
+                return;
+        }
+
+        hpsb_register_addrspace(hl, &reg_ops, CSR_REGISTER_BASE,
+                                CSR_REGISTER_BASE + CSR_CONFIG_ROM);
+        hpsb_register_addrspace(hl, &map_ops, 
+                                CSR_REGISTER_BASE + CSR_CONFIG_ROM,
+                                CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
+        hpsb_register_addrspace(hl, &fcp_ops,
+                                CSR_REGISTER_BASE + CSR_FCP_COMMAND,
+                                CSR_REGISTER_BASE + CSR_FCP_END);
+        hpsb_register_addrspace(hl, &map_ops,
+                                CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
+                                CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
+        hpsb_register_addrspace(hl, &map_ops,
+                                CSR_REGISTER_BASE + CSR_SPEED_MAP,
+                                CSR_REGISTER_BASE + CSR_SPEED_MAP_END);
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/csr.h linux/drivers/ieee1394/csr.h
--- v2.3.39/linux/drivers/ieee1394/csr.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/csr.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,55 @@
+
+#ifndef _IEEE1394_CSR_H
+#define _IEEE1394_CSR_H
+
+#define CSR_REGISTER_BASE  0xfffff0000000ULL
+
+/* register offsets relative to CSR_REGISTER_BASE */
+#define CSR_STATE_CLEAR           0x0
+#define CSR_STATE_SET             0x4
+#define CSR_NODE_IDS              0x8
+#define CSR_RESET_START           0xc
+#define CSR_SPLIT_TIMEOUT_HI      0x18
+#define CSR_SPLIT_TIMEOUT_LO      0x1c
+#define CSR_CYCLE_TIME            0x200
+#define CSR_BUS_TIME              0x204
+#define CSR_BUSY_TIMEOUT          0x210
+#define CSR_BUS_MANAGER_ID        0x21c
+#define CSR_BANDWIDTH_AVAILABLE   0x220
+#define CSR_CHANNELS_AVAILABLE_HI 0x224
+#define CSR_CHANNELS_AVAILABLE_LO 0x228
+#define CSR_CONFIG_ROM            0x400
+#define CSR_CONFIG_ROM_END        0x800
+#define CSR_FCP_COMMAND           0xB00
+#define CSR_FCP_RESPONSE          0xD00
+#define CSR_FCP_END               0xF00
+#define CSR_TOPOLOGY_MAP          0x1000
+#define CSR_TOPOLOGY_MAP_END      0x1400
+#define CSR_SPEED_MAP             0x2000
+#define CSR_SPEED_MAP_END         0x3000
+
+
+struct csr_control {
+        spinlock_t lock;
+
+        quadlet_t state;
+        quadlet_t node_ids;
+        quadlet_t split_timeout_hi, split_timeout_lo;
+        quadlet_t cycle_time;
+        quadlet_t bus_time;
+        quadlet_t bus_manager_id;
+        quadlet_t bandwidth_available;
+        quadlet_t channels_available_hi, channels_available_lo;
+
+        const quadlet_t *rom;
+        size_t rom_size;
+
+        quadlet_t topology_map[256];
+        quadlet_t speed_map[1024];
+        quadlet_t fcp_data[1024];
+};
+
+
+void init_csr(void);
+
+#endif /* _IEEE1394_CSR_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/highlevel.c linux/drivers/ieee1394/highlevel.c
--- v2.3.39/linux/drivers/ieee1394/highlevel.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/highlevel.c	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,402 @@
+/*
+ * IEEE 1394 for Linux
+ *
+ * Copyright (C) 1999 Andreas E. Bombe
+ */
+
+#include <linux/config.h>
+#include <linux/slab.h>
+
+#include "ieee1394.h"
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "highlevel.h"
+
+
+LIST_HEAD(hl_drivers);
+rwlock_t hl_drivers_lock = RW_LOCK_UNLOCKED;
+
+LIST_HEAD(addr_space);
+rwlock_t addr_space_lock = RW_LOCK_UNLOCKED;
+
+/* addr_space list will have zero and max already included as bounds */
+static struct hpsb_address_ops dummy_ops = { NULL, NULL, NULL, NULL };
+static struct hpsb_address_serve dummy_zero_addr, dummy_max_addr;
+
+struct hpsb_highlevel *hpsb_register_highlevel(const char *name,
+                                               struct hpsb_highlevel_ops *ops)
+{
+        struct hpsb_highlevel *hl;
+
+        hl = (struct hpsb_highlevel *)kmalloc(sizeof(struct hpsb_highlevel),
+                                              GFP_KERNEL);
+        if (hl == NULL) {
+                return NULL;
+        }
+
+        INIT_LIST_HEAD(&hl->hl_list);
+        INIT_LIST_HEAD(&hl->addr_list);
+        hl->name = name;
+        hl->op = ops;
+
+        write_lock_irq(&hl_drivers_lock);
+        hl_all_hosts(hl, 1);
+        list_add_tail(&hl->hl_list, &hl_drivers);
+        write_unlock_irq(&hl_drivers_lock);
+
+        return hl;
+}
+
+void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
+{
+        struct list_head *entry;
+        struct hpsb_address_serve *as;
+
+        if (hl == NULL) {
+                return;
+        }
+
+        write_lock_irq(&addr_space_lock);
+        entry = hl->addr_list.next;
+
+        while (entry != &hl->addr_list) {
+                as = list_entry(entry, struct hpsb_address_serve, addr_list);
+                list_del(&as->as_list);
+                entry = entry->next;
+                kfree(as);
+        }
+        write_unlock_irq(&addr_space_lock);
+
+        write_lock_irq(&hl_drivers_lock);
+        list_del(&hl->hl_list);
+        hl_all_hosts(hl, 0);
+        write_unlock_irq(&hl_drivers_lock);
+
+        kfree(hl);
+}
+
+int hpsb_register_addrspace(struct hpsb_highlevel *hl,
+                            struct hpsb_address_ops *ops, u64 start, u64 end)
+{
+        struct hpsb_address_serve *as;
+        struct list_head *entry;
+        int retval = 0;
+
+        if (((start|end) & 3) || (start >= end) || (end > 0x1000000000000ULL)) {
+                HPSB_ERR(__FUNCTION__ " called with invalid addresses");
+                return 0;
+        }
+
+        as = (struct hpsb_address_serve *)
+                kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL);
+        if (as == NULL) {
+                return 0;
+        }
+
+        INIT_LIST_HEAD(&as->as_list);
+        INIT_LIST_HEAD(&as->addr_list);
+        as->op = ops;
+        as->start = start;
+        as->end = end;
+
+        write_lock_irq(&addr_space_lock);
+        entry = addr_space.next;
+
+        while (list_entry(entry, struct hpsb_address_serve, as_list)->end
+               <= start) {
+                if (list_entry(entry->next, struct hpsb_address_serve, as_list)
+                    ->start >= end) {
+                        list_add(&as->as_list, entry);
+                        list_add_tail(&as->addr_list, &hl->addr_list);
+                        retval = 1;
+                        break;
+                }
+                entry = entry->next;
+        }
+        write_unlock_irq(&addr_space_lock);
+
+        if (retval == 0) {
+                kfree(as);
+        }
+
+        return retval;
+}
+
+
+void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
+                         unsigned int channel)
+{
+        if (channel > 63) {
+                HPSB_ERR(__FUNCTION__ " called with invalid channel");
+                return;
+        }
+
+        if (host->iso_listen_count[channel]++ == 0) {
+                host->template->devctl(host, ISO_LISTEN_CHANNEL, channel);
+        }
+}
+
+void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, 
+                           unsigned int channel)
+{
+        if (channel > 63) {
+                HPSB_ERR(__FUNCTION__ " called with invalid channel");
+                return;
+        }
+
+        if (--host->iso_listen_count[channel] == 0) {
+                host->template->devctl(host, ISO_UNLISTEN_CHANNEL, channel);
+        }
+}
+
+
+#define DEFINE_MULTIPLEXER(Function) \
+void highlevel_##Function(struct hpsb_host *host) \
+{ \
+        struct list_head *entry; \
+        void (*funcptr)(struct hpsb_host*); \
+        read_lock(&hl_drivers_lock); \
+        entry = hl_drivers.next; \
+        while (entry != &hl_drivers) { \
+                funcptr = list_entry(entry, struct hpsb_highlevel, hl_list) \
+                          ->op->Function; \
+                if (funcptr) funcptr(host); \
+                entry = entry->next; \
+        } \
+        read_unlock(&hl_drivers_lock); \
+}
+
+DEFINE_MULTIPLEXER(add_host)
+DEFINE_MULTIPLEXER(remove_host)
+DEFINE_MULTIPLEXER(host_reset)
+#undef DEFINE_MULTIPLEXER
+
+void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data,
+                           unsigned int length)
+{
+        struct list_head *entry;
+        struct hpsb_highlevel *hl;
+        int channel = (data[0] >> 8) & 0x3f;
+
+        read_lock(&hl_drivers_lock);
+        entry = hl_drivers.next;
+
+        while (entry != &hl_drivers) {
+                hl = list_entry(entry, struct hpsb_highlevel, hl_list);
+                if (hl->op->iso_receive) {
+                        hl->op->iso_receive(host, channel, data, length);
+                }
+                entry = entry->next;
+        }
+        read_unlock(&hl_drivers_lock);
+}
+
+
+int highlevel_read(struct hpsb_host *host, quadlet_t *buffer, u64 addr,
+                   unsigned int length)
+{
+        struct hpsb_address_serve *as;
+        struct list_head *entry;
+        unsigned int partlength;
+        int rcode = RCODE_ADDRESS_ERROR;
+
+        if ((addr | length) & 0x3) {
+                /* Addresses or lengths not a multiple of a quadlet pose a big
+                 * problem on little endian machines because we always do this
+                 * in arch endian and swapping would mess it all up.  So we 
+                 * simply don't allow this at all. */
+                return RCODE_TYPE_ERROR;
+        }
+
+        read_lock(&addr_space_lock);
+
+        entry = addr_space.next;
+        as = list_entry(entry, struct hpsb_address_serve, as_list);
+
+        while (as->start <= addr) {
+                if (as->end > addr) {
+                        partlength = MIN((unsigned int)(as->end - addr),
+                                         length);
+
+                        if (as->op->read != NULL) {
+                                rcode = as->op->read(host, buffer, addr,
+                                                     partlength);
+                        } else {
+                                rcode = RCODE_TYPE_ERROR;
+                        }
+
+                        length -= partlength;
+                        addr += partlength;
+
+                        if ((rcode != RCODE_COMPLETE) || !length) {
+                                break;
+                        }
+                }
+
+                entry = entry->next;
+                as = list_entry(entry, struct hpsb_address_serve, as_list);
+        }
+
+        read_unlock(&addr_space_lock);
+
+        if (length && (rcode == RCODE_COMPLETE)) {
+                rcode = RCODE_ADDRESS_ERROR;
+        }
+
+        return rcode;
+}
+
+int highlevel_write(struct hpsb_host *host, quadlet_t *data, u64 addr,
+                    unsigned int length)
+{
+        struct hpsb_address_serve *as;
+        struct list_head *entry;
+        unsigned int partlength;
+        int rcode = RCODE_ADDRESS_ERROR;
+
+        if ((addr | length) & 0x3) {
+                return RCODE_TYPE_ERROR;
+        }
+
+        read_lock(&addr_space_lock);
+
+        entry = addr_space.next;
+        as = list_entry(entry, struct hpsb_address_serve, as_list);
+
+        while (as->start <= addr) {
+                if (as->end > addr) {
+                        partlength = MIN((unsigned int)(as->end - addr),
+                                         length);
+
+                        if (as->op->write != NULL) {
+                                rcode = as->op->write(host, data, addr,
+                                                      partlength);
+                        } else {
+                                rcode = RCODE_TYPE_ERROR;
+                        }
+
+                        length -= partlength;
+                        addr += partlength;
+
+                        if ((rcode != RCODE_COMPLETE) || !length) {
+                                break;
+                        }
+                }
+
+                entry = entry->next;
+                as = list_entry(entry, struct hpsb_address_serve, as_list);
+        }
+
+        read_unlock(&addr_space_lock);
+
+        if (length && (rcode == RCODE_COMPLETE)) {
+                rcode = RCODE_ADDRESS_ERROR;
+        }
+
+        return rcode;
+}
+
+
+int highlevel_lock(struct hpsb_host *host, quadlet_t *store, u64 addr,
+                   quadlet_t data, quadlet_t arg, int ext_tcode)
+{
+        struct hpsb_address_serve *as;
+        struct list_head *entry;
+        int rcode = RCODE_ADDRESS_ERROR;
+
+        read_lock(&addr_space_lock);
+
+        entry = addr_space.next;
+        as = list_entry(entry, struct hpsb_address_serve, as_list);
+
+        while (as->start <= addr) {
+                if (as->end > addr) {
+                        if (as->op->lock != NULL) {
+                                rcode = as->op->lock(host, store, addr, data, 
+                                                     arg, ext_tcode);
+                        } else {
+                                rcode = RCODE_TYPE_ERROR;
+                        }
+
+                        break;
+                }
+
+                entry = entry->next;
+                as = list_entry(entry, struct hpsb_address_serve, as_list);
+        }
+
+        read_unlock(&addr_space_lock);
+
+        return rcode;
+}
+
+int highlevel_lock64(struct hpsb_host *host, octlet_t *store, u64 addr,
+                     octlet_t data, octlet_t arg, int ext_tcode)
+{
+        struct hpsb_address_serve *as;
+        struct list_head *entry;
+        int rcode = RCODE_ADDRESS_ERROR;
+
+        read_lock(&addr_space_lock);
+
+        entry = addr_space.next;
+        as = list_entry(entry, struct hpsb_address_serve, as_list);
+
+        while (as->start <= addr) {
+                if (as->end > addr) {
+                        if (as->op->lock64 != NULL) {
+                                rcode = as->op->lock64(host, store, addr, data, 
+                                                       arg, ext_tcode);
+                        } else {
+                                rcode = RCODE_TYPE_ERROR;
+                        }
+
+                        break;
+                }
+
+                entry = entry->next;
+                as = list_entry(entry, struct hpsb_address_serve, as_list);
+        }
+
+        read_unlock(&addr_space_lock);
+
+        return rcode;
+}
+
+
+
+#ifndef MODULE
+
+void register_builtin_highlevels(void)
+{
+#ifdef CONFIG_IEEE1394_RAWIO
+        {
+                int init_raw1394(void);
+                init_raw1394();
+        }
+#endif
+}
+
+#endif /* !MODULE */
+
+
+void init_hpsb_highlevel(void)
+{
+        INIT_LIST_HEAD(&dummy_zero_addr.as_list);
+        INIT_LIST_HEAD(&dummy_zero_addr.addr_list);
+        INIT_LIST_HEAD(&dummy_max_addr.as_list);
+        INIT_LIST_HEAD(&dummy_max_addr.addr_list);
+
+        dummy_zero_addr.op = dummy_max_addr.op = &dummy_ops;
+
+        dummy_zero_addr.start = dummy_zero_addr.end = 0;
+        dummy_max_addr.start = dummy_max_addr.end = ((u64) 1) << 48;
+
+        list_add_tail(&dummy_zero_addr.as_list, &addr_space);
+        list_add_tail(&dummy_max_addr.as_list, &addr_space);
+
+#ifndef MODULE
+        register_builtin_highlevels();
+#endif
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/highlevel.h linux/drivers/ieee1394/highlevel.h
--- v2.3.39/linux/drivers/ieee1394/highlevel.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/highlevel.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,133 @@
+
+#ifndef IEEE1394_HIGHLEVEL_H
+#define IEEE1394_HIGHLEVEL_H
+
+
+struct hpsb_highlevel {
+        struct list_head hl_list;
+
+        /* List of hpsb_address_serve. */
+        struct list_head addr_list;
+
+        const char *name;
+        struct hpsb_highlevel_ops *op;
+};
+
+
+struct hpsb_address_serve {
+        struct list_head as_list; /* global list */
+        
+        struct list_head addr_list; /* hpsb_highlevel list */
+
+        struct hpsb_address_ops *op;
+
+        /* first address handled and first address behind, quadlet aligned */
+        u64 start, end;
+};
+
+
+/*
+ * The above structs are internal to highlevel driver handling.  Only the
+ * following structures are of interest to actual highlevel drivers.  
+ */
+
+struct hpsb_highlevel_ops {
+        /* Any of the following pointers can legally be NULL, except for
+         * iso_receive which can only be NULL when you don't request
+         * channels. */
+
+        /* New host initialized.  Will also be called during
+         * hpsb_register_highlevel for all hosts already installed. */
+        void (*add_host) (struct hpsb_host *host);
+
+        /* Host about to be removed.  Will also be called during
+         * hpsb_unregister_highlevel once for each host. */
+        void (*remove_host) (struct hpsb_host *host);
+
+        /* Host experienced bus reset with possible configuration changes.  Note
+         * that this one may occur during interrupt/bottom half handling.  You
+         * can not expect to be able to do stock hpsb_reads. */
+        void (*host_reset) (struct hpsb_host *host);
+
+        /* An isochronous packet was received.  Channel contains the channel
+         * number for your convenience, it is also contained in the included
+         * packet header (first quadlet, CRCs are missing).  You may get called
+         * for channel/host combinations you did not request. */
+        void (*iso_receive) (struct hpsb_host *host, int channel,
+                             quadlet_t *data, unsigned int length);
+};
+
+struct hpsb_address_ops {
+        /*
+         * Null function pointers will make the respective operation complete 
+         * with RCODE_TYPE_ERROR.  Makes for easy to implement read-only 
+         * registers (just leave everything but read NULL).
+         *
+         * All functions shall return appropriate IEEE 1394 rcodes.
+         */
+
+        /* These functions have to implement block reads for themselves. */
+        int (*read) (struct hpsb_host *host, quadlet_t *buffer, u64 addr,
+                     unsigned int length);
+        int (*write) (struct hpsb_host *host, quadlet_t *data, u64 addr,
+                      unsigned int length);
+
+        /* Lock transactions: write results of ext_tcode operation into
+         * *store. */
+        int (*lock) (struct hpsb_host *host, quadlet_t *store, u64 addr,
+                     quadlet_t data, quadlet_t arg, int ext_tcode);
+        int (*lock64) (struct hpsb_host *host, octlet_t *store, u64 addr,
+                       octlet_t data, octlet_t arg, int ext_tcode);
+};
+
+
+void init_hpsb_highlevel(void);
+
+void highlevel_add_host(struct hpsb_host *host);
+void highlevel_remove_host(struct hpsb_host *host);
+void highlevel_host_reset(struct hpsb_host *host);
+
+int highlevel_read(struct hpsb_host *host, quadlet_t *buffer, u64 addr,
+                   unsigned int length);
+int highlevel_write(struct hpsb_host *host, quadlet_t *data, u64 addr,
+                    unsigned int length);
+int highlevel_lock(struct hpsb_host *host, quadlet_t *store, u64 addr,
+                   quadlet_t data, quadlet_t arg, int ext_tcode);
+int highlevel_lock64(struct hpsb_host *host, octlet_t *store, u64 addr,
+                     octlet_t data, octlet_t arg, int ext_tcode);
+
+void highlevel_iso_receive(struct hpsb_host *host, quadlet_t *data,
+                           unsigned int length);
+
+
+/*
+ * Register highlevel driver.  The name pointer has to stay valid at all times
+ * because the string is not copied.
+ */
+struct hpsb_highlevel *hpsb_register_highlevel(const char *name,
+                                               struct hpsb_highlevel_ops *ops);
+void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
+
+/*
+ * Register handlers for host address spaces.  Start and end are 48 bit pointers
+ * and have to be quadlet aligned (end points to the first address behind the
+ * handled addresses.  This function can be called multiple times for a single
+ * hpsb_highlevel to implement sparse register sets.  The requested region must
+ * not overlap any previously allocated region, otherwise registering will fail.
+ *
+ * It returns true for successful allocation.  There is no unregister function,
+ * all address spaces are deallocated together with the hpsb_highlevel.
+ */
+int hpsb_register_addrspace(struct hpsb_highlevel *hl,
+                            struct hpsb_address_ops *ops, u64 start, u64 end);
+
+/*
+ * Enable or disable receving a certain isochronous channel through the
+ * iso_receive op.
+ */
+void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, 
+                         unsigned int channel);
+void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
+                           unsigned int channel);
+
+#endif /* IEEE1394_HIGHLEVEL_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/hosts.c linux/drivers/ieee1394/hosts.c
--- v2.3.39/linux/drivers/ieee1394/hosts.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/hosts.c	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,344 @@
+/*
+ * IEEE 1394 for Linux
+ *
+ * Low level (host adapter) management.
+ *
+ * Copyright (C) 1999 Andreas E. Bombe
+ * Copyright (C) 1999 Emanuel Pirker
+ */
+
+#include <linux/config.h>
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/wait.h>
+
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "highlevel.h"
+
+
+static struct hpsb_host_template *templates = NULL;
+spinlock_t templates_lock = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ * The following function is exported for module usage.  It will
+ * be called from high-level drivers such as the raw driver.
+ */
+int hpsb_get_host_list(struct hpsb_host *list[], int list_size)
+{
+    struct hpsb_host *host, **ptr;
+    struct hpsb_host_template *tmpl;
+    int count=0;
+
+    ptr = list;
+
+    for (tmpl = templates ; tmpl != NULL; tmpl = tmpl->next) {
+        for (host = tmpl->hosts; (host != NULL) && (count < list_size); 
+             host = host->next) {
+            *ptr = host;
+            ptr++;
+            count++;
+        }
+    }
+
+    return count;
+}
+
+/*
+ * This function calls the add_host/remove_host hooks for every host currently
+ * registered.  Init == TRUE means add_host.
+ */
+void hl_all_hosts(struct hpsb_highlevel *hl, int init)
+{
+        struct hpsb_host_template *tmpl;
+        struct hpsb_host *host;
+
+        spin_lock(&templates_lock);
+
+        for (tmpl = templates; tmpl != NULL; tmpl = tmpl->next) {
+                for (host = tmpl->hosts; host != NULL; host = host->next) {
+                        if (host->initialized) {
+                                if (init) {
+                                        if (hl->op->add_host) {
+                                                hl->op->add_host(host);
+                                        }
+                                } else {
+                                        if (hl->op->remove_host) {
+                                                hl->op->remove_host(host);
+                                        }
+                                }
+                        }
+                }
+        }
+
+        spin_unlock(&templates_lock);
+}
+
+int hpsb_inc_host_usage(struct hpsb_host *host)
+{
+        struct hpsb_host_template *tmpl;
+        struct hpsb_host *h;
+        int retval = 0;
+
+        spin_lock(&templates_lock);
+
+        for (tmpl = templates; (tmpl != NULL) && !retval; tmpl = tmpl->next) {
+                for (h = tmpl->hosts; h != NULL; h = h->next) {
+                        if (h == host) {
+                                tmpl->devctl(h, MODIFY_USAGE, 1);
+                                retval = 1;
+                                break;
+                        }
+                }
+        }
+
+        spin_unlock(&templates_lock);
+
+        return retval;
+}
+
+void hpsb_dec_host_usage(struct hpsb_host *host)
+{
+        host->template->devctl(host, MODIFY_USAGE, 0);
+}
+
+/*
+ * The following function is exported for module usage.  It will be called from
+ * the detect function of a adapter driver.
+ */
+struct hpsb_host *hpsb_get_host(struct hpsb_host_template *tmpl, 
+                                size_t hd_size)
+{
+        struct hpsb_host *h;
+
+        h = vmalloc(sizeof(struct hpsb_host) + hd_size);
+        if (h == NULL) {
+                return NULL;
+        }
+
+        memset(h, 0, sizeof(struct hpsb_host) + hd_size);
+        h->tlabel_count = 64;
+        INIT_LIST_HEAD(&h->pending_packets);
+        spin_lock_init(&h->pending_pkt_lock);
+        spin_lock_init(&h->tlabel_lock);
+        init_waitqueue_head(&h->tlabel_wait);
+
+        h->timeout_tq.routine = (void (*)(void*))abort_timedouts;
+        h->timeout_tq.data = h;
+
+        h->topology_map = h->csr.topology_map + 3;
+        h->speed_map = h->csr.speed_map + 2;
+
+        h->template = tmpl;
+        if (hd_size) {
+                h->hostdata = &h->embedded_hostdata[0];
+        }
+
+        if (tmpl->hosts == NULL) {
+                tmpl->hosts = h;
+        } else {
+                struct hpsb_host *last = tmpl->hosts;
+
+                while (last->next != NULL) {
+                        last = last->next;
+                }
+                last->next = h;
+        }
+
+        return h;
+}
+
+static void free_all_hosts(struct hpsb_host_template *tmpl)
+{
+        struct hpsb_host *next, *host = tmpl->hosts;
+
+        while (host) {
+                next = host->next;
+                vfree(host);
+                host = next;
+        }
+}
+
+
+static void init_hosts(struct hpsb_host_template *tmpl)
+{
+        int count;
+        struct hpsb_host *host;
+
+        count = tmpl->detect_hosts(tmpl);
+
+        for (host = tmpl->hosts; host != NULL; host = host->next) {
+                if (tmpl->initialize_host(host)) {
+                        host->initialized = 1;
+
+                        highlevel_add_host(host);
+                        reset_host_bus(host);
+
+                        //kernel_thread(hpsb_host_thread, host, 
+                        //              CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+                }
+        }
+
+        tmpl->number_of_hosts = count;
+        HPSB_INFO("detected %d %s adapter%c", count, tmpl->name,
+                  (count != 1 ? 's' : ' '));
+}
+
+static void shutdown_hosts(struct hpsb_host_template *tmpl)
+{
+        struct hpsb_host *host;
+
+        for (host = tmpl->hosts; host != NULL; host = host->next) {
+                if (host->initialized) {
+                        host->initialized = 0;
+                        abort_requests(host);
+
+                        highlevel_remove_host(host);
+
+                        tmpl->release_host(host);
+                        while (test_bit(0, &host->timeout_tq.sync)) {
+                                schedule();
+                        }
+                }
+        }
+        free_all_hosts(tmpl);
+        tmpl->release_host(NULL);
+
+        tmpl->number_of_hosts = 0;
+}
+
+
+static int add_template(struct hpsb_host_template *new)
+{
+        new->next = NULL;
+        new->hosts = NULL;
+        new->number_of_hosts = 0;
+
+        spin_lock(&templates_lock);
+        if (templates == NULL) {
+                templates = new;
+        } else {
+                struct hpsb_host_template *last = templates;
+                while (last->next != NULL) {
+                        last = last->next;
+                }
+                last->next = new;
+        }
+        spin_unlock(&templates_lock);
+
+        return 0;
+}
+
+static int remove_template(struct hpsb_host_template *tmpl)
+{
+        int retval = 0;
+
+        if (tmpl->number_of_hosts) {
+                HPSB_ERR("attempted to remove busy host template "
+                         "of %s at address 0x%p", tmpl->name, tmpl);
+                return 1;
+        }
+
+        spin_lock(&templates_lock);
+        if (templates == tmpl) {
+                templates = tmpl->next;
+        } else {
+                struct hpsb_host_template *t;
+
+                t = templates;
+                while (t->next != tmpl && t->next != NULL) {
+                        t = t->next;
+                }
+
+                if (t->next == NULL) {
+                        HPSB_ERR("attempted to remove unregistered host template "
+                                 "of %s at address 0x%p", tmpl->name, tmpl);
+                        retval = -1;
+                } else {
+                        t->next = tmpl->next;
+                }
+        }
+        spin_unlock(&templates_lock);
+
+        inc_hpsb_generation();
+        return retval;
+}
+
+
+/*
+ * The following two functions are exported symbols for module usage.
+ */
+int hpsb_register_lowlevel(struct hpsb_host_template *tmpl)
+{
+        add_template(tmpl);
+        HPSB_INFO("registered %s driver, initializing now", tmpl->name);
+        init_hosts(tmpl);
+
+        return 0;
+}
+
+void hpsb_unregister_lowlevel(struct hpsb_host_template *tmpl)
+{
+        shutdown_hosts(tmpl);
+
+        if (remove_template(tmpl)) {
+                HPSB_PANIC("remove_template failed on %s", tmpl->name);
+        }
+}
+
+
+
+#ifndef MODULE
+
+/*
+ * This is the init function for builtin lowlevel drivers.  To add new drivers
+ * put their setup code (get and register template) here.  Module only
+ * drivers don't need to touch this.
+ */
+
+#define SETUP_TEMPLATE(name, visname) \
+do {                                                                       \
+        extern struct hpsb_host_template *get_ ## name ## _template(void); \
+        t = get_ ## name ## _template();                                   \
+                                                                           \
+        if (t != NULL) {                                                   \
+                if(!hpsb_register_lowlevel(t)) {                           \
+                        count++;                                           \
+                }                                                          \
+        } else {                                                           \
+                HPSB_WARN(visname " driver returned no host template");    \
+        }                                                                  \
+} while (0)
+
+void __init register_builtin_lowlevels()
+{
+        struct hpsb_host_template *t;
+        int count = 0;
+
+        /* Touch t to avoid warning if no drivers are configured to
+         * be built directly into the kernel. */
+        t = NULL;
+
+#ifdef CONFIG_IEEE1394_PCILYNX
+        SETUP_TEMPLATE(lynx, "Lynx");
+#endif
+
+#ifdef CONFIG_IEEE1394_AIC5800
+        SETUP_TEMPLATE(aic, "AIC-5800");
+#endif
+ 
+#ifdef CONFIG_IEEE1394_OHCI1394
+        SETUP_TEMPLATE(ohci, "OHCI-1394");
+#endif
+
+        HPSB_INFO("%d host adapter%s initialized", count,
+                  (count != 1 ? "s" : ""));
+}
+
+#undef SETUP_TEMPLATE
+
+#endif /* !MODULE */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/hosts.h linux/drivers/ieee1394/hosts.h
--- v2.3.39/linux/drivers/ieee1394/hosts.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/hosts.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,192 @@
+
+#ifndef _IEEE1394_HOSTS_H
+#define _IEEE1394_HOSTS_H
+
+#include <linux/wait.h>
+#include <linux/tqueue.h>
+
+#include "ieee1394_types.h"
+#include "csr.h"
+
+
+struct hpsb_packet;
+
+struct hpsb_host {
+/* private fields (hosts, do not use them) */
+        struct hpsb_host *next;
+
+        struct list_head pending_packets;
+        spinlock_t pending_pkt_lock;
+        struct tq_struct timeout_tq;
+
+        /* A bitmask where a set bit means that this tlabel is in use.
+         * FIXME - should be handled per node instead of per bus. */
+        u32 tlabel_pool[2];
+        int tlabel_count;
+        spinlock_t tlabel_lock;
+        wait_queue_head_t tlabel_wait;
+
+        int reset_retries;
+        quadlet_t *topology_map, *speed_map;
+        struct csr_control csr;
+
+        unsigned char iso_listen_count[64];
+
+/* readonly fields for hosts */
+        struct hpsb_host_template *template;
+
+        int node_count; /* number of identified nodes on this bus */
+        int selfid_count; /* total number of SelfIDs received */
+
+        nodeid_t node_id; /* node ID of this host */
+        nodeid_t irm_id; /* ID of this bus' isochronous resource manager */
+        nodeid_t busmgr_id; /* ID of this bus' bus manager */
+
+        unsigned initialized:1; /* initialized and usable */
+        unsigned in_bus_reset:1; /* in bus reset / SelfID stage */
+        unsigned attempt_root:1; /* attempt to become root during next reset */
+
+        /* this nodes' duties on the bus */
+        unsigned is_root:1;
+        unsigned is_cycmst:1;
+        unsigned is_irm:1;
+        unsigned is_busmgr:1;
+
+/* fields readable and writeable by the hosts */
+
+        void *hostdata;
+        int embedded_hostdata[0];
+};
+
+
+
+enum devctl_cmd {
+        /* Host is requested to reset its bus and cancel all outstanding async
+         * requests.  If arg == 1, it shall also attempt to become root on the
+         * bus.  Return void. */
+        RESET_BUS,
+
+        /* Arg is void, return value is the hardware cycle counter value. */
+        GET_CYCLE_COUNTER,
+
+        /* Set the hardware cycle counter to the value in arg, return void.
+         * FIXME - setting is probably not required. */
+        SET_CYCLE_COUNTER,
+
+        /* Configure hardware for new bus ID in arg, return void. */
+        SET_BUS_ID,
+
+        /* If arg true, start sending cycle start packets, stop if arg == 0.
+         * Return void. */
+        ACT_CYCLE_MASTER,
+
+        /* Cancel all outstanding async requests without resetting the bus.
+         * Return void. */
+        CANCEL_REQUESTS,
+
+        /* Decrease module usage count if arg == 0, increase otherwise.  Return
+         * void. */
+        MODIFY_USAGE,
+
+        /* Start or stop receiving isochronous channel in arg.  Return void.
+         * This acts as an optimization hint, hosts are not required not to
+         * listen on unrequested channels. */
+        ISO_LISTEN_CHANNEL,
+        ISO_UNLISTEN_CHANNEL
+};
+
+struct hpsb_host_template {
+        struct hpsb_host_template *next;
+
+        struct hpsb_host *hosts;
+        int number_of_hosts;
+
+        /* fields above will be ignored and overwritten after registering */
+
+        /* This should be the name of the driver (single word) and must not be
+         * NULL. */
+        const char *name;
+
+        /* This function shall detect all available adapters of this type and
+         * call hpsb_get_host for each one.  The initialize_host function will
+         * be called to actually set up these adapters.  The number of detected
+         * adapters or zero if there are none must be returned.
+         */
+        int (*detect_hosts) (struct hpsb_host_template *template);
+
+        /* After detecting and registering hosts, this function will be called
+         * for every registered host.  It shall set up the host to be fully
+         * functional for bus operations and return 0 for failure.
+         */
+        int (*initialize_host) (struct hpsb_host *host);
+
+        /* To unload modules, this function is provided.  It shall free all
+         * resources this host is using (if host is not NULL) or free all
+         * resources globally allocated by the driver (if host is NULL).
+         */
+        void (*release_host) (struct hpsb_host *host); 
+
+        /* This function must store a pointer to the configuration ROM into the
+         * location referenced to by pointer and return the size of the ROM. It
+         * may not fail.  If any allocation is required, it must be done
+         * earlier.
+         */
+        size_t (*get_rom) (struct hpsb_host *host, const quadlet_t **pointer);
+
+        /* This function shall implement packet transmission based on
+         * packet->type.  It shall CRC both parts of the packet (unless
+         * packet->type == raw) and do byte-swapping as necessary or instruct
+         * the hardware to do so.  It can return immediately after the packet
+         * was queued for sending.  After sending, hpsb_sent_packet() has to be
+         * called.  Return 0 for failure.
+         * NOTE: The function must be callable in interrupt context.
+         */
+        int (*transmit_packet) (struct hpsb_host *host, 
+                                struct hpsb_packet *packet);
+
+        /* This function requests miscellanous services from the driver, see
+         * above for command codes and expected actions.  Return -1 for unknown
+         * command, though that should never happen.
+         */
+        int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
+};
+
+
+
+/* mid level internal use */
+void register_builtin_lowlevels(void);
+
+/* high level internal use */
+struct hpsb_highlevel;
+void hl_all_hosts(struct hpsb_highlevel *hl, int init);
+
+/* 
+ * These functions are for lowlevel (host) driver use.
+ */
+int hpsb_register_lowlevel(struct hpsb_host_template *tmpl);
+void hpsb_unregister_lowlevel(struct hpsb_host_template *tmpl);
+
+/*
+ * Get a initialized host structure with hostdata_size bytes allocated in
+ * embedded_hostdata for free usage.  Returns NULL for failure.  
+ */
+struct hpsb_host *hpsb_get_host(struct hpsb_host_template *tmpl, 
+                                size_t hostdata_size);
+
+/*
+ * Write pointers to all available hpsb_hosts into list.
+ * Return number of host adapters (i.e. elements in list).
+ *
+ * DEPRECATED - register with highlevel instead.
+ */
+int hpsb_get_host_list(struct hpsb_host *list[], int max_list_size);
+
+/*
+ * Increase / decrease host usage counter.  Increase function will return true
+ * only if successful (host still existed).  Decrease function expects host to
+ * exist.
+ */
+int hpsb_inc_host_usage(struct hpsb_host *host);
+void hpsb_dec_host_usage(struct hpsb_host *host);
+
+#endif /* _IEEE1394_HOSTS_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ieee1394.h linux/drivers/ieee1394/ieee1394.h
--- v2.3.39/linux/drivers/ieee1394/ieee1394.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ieee1394.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,66 @@
+/*
+ * Generic IEEE 1394 definitions
+ */
+
+#ifndef _IEEE1394_IEEE1394_H
+#define _IEEE1394_IEEE1394_H
+
+#define TCODE_WRITEQ             0x0
+#define TCODE_WRITEB             0x1
+#define TCODE_WRITE_RESPONSE     0x2
+#define TCODE_READQ              0x4
+#define TCODE_READB              0x5
+#define TCODE_READQ_RESPONSE     0x6
+#define TCODE_READB_RESPONSE     0x7
+#define TCODE_CYCLE_START        0x8
+#define TCODE_LOCK_REQUEST       0x9
+#define TCODE_ISO_DATA           0xa
+#define TCODE_LOCK_RESPONSE      0xb
+
+#define RCODE_COMPLETE           0x0
+#define RCODE_CONFLICT_ERROR     0x4
+#define RCODE_DATA_ERROR         0x5
+#define RCODE_TYPE_ERROR         0x6
+#define RCODE_ADDRESS_ERROR      0x7
+
+#define EXTCODE_MASK_SWAP        0x1
+#define EXTCODE_COMPARE_SWAP     0x2
+#define EXTCODE_FETCH_ADD        0x3
+#define EXTCODE_LITTLE_ADD       0x4
+#define EXTCODE_BOUNDED_ADD      0x5
+#define EXTCODE_WRAP_ADD         0x6
+
+#define ACK_COMPLETE             0x1
+#define ACK_PENDING              0x2
+#define ACK_BUSY_X               0x4
+#define ACK_BUSY_A               0x5
+#define ACK_BUSY_B               0x6
+#define ACK_DATA_ERROR           0xd
+#define ACK_TYPE_ERROR           0xe 
+
+/* Non-standard "ACK codes" for internal use */
+#define ACKX_NONE                -1
+#define ACKX_SEND_ERROR          -2
+#define ACKX_ABORTED             -3
+#define ACKX_TIMEOUT             -4
+
+
+#define SPEED_100                0x0
+#define SPEED_200                0x1
+#define SPEED_400                0x2 
+
+#define SELFID_PWRCL_NO_POWER    0x0
+#define SELFID_PWRCL_PROVIDE_15W 0x1
+#define SELFID_PWRCL_PROVIDE_30W 0x2
+#define SELFID_PWRCL_PROVIDE_45W 0x3
+#define SELFID_PWRCL_USE_1W      0x4
+#define SELFID_PWRCL_USE_3W      0x5
+#define SELFID_PWRCL_USE_6W      0x6
+#define SELFID_PWRCL_USE_10W     0x7
+
+#define SELFID_PORT_CHILD        0x3
+#define SELFID_PORT_PARENT       0x2
+#define SELFID_PORT_NCONN        0x1
+#define SELFID_PORT_NONE         0x0   
+
+#endif /* _IEEE1394_IEEE1394_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ieee1394_core.c linux/drivers/ieee1394/ieee1394_core.c
--- v2.3.39/linux/drivers/ieee1394/ieee1394_core.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ieee1394_core.c	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,698 @@
+/*
+ * IEEE 1394 for Linux
+ *
+ * Core support: hpsb_packet management, packet handling and forwarding to
+ *               csr or lowlevel code
+ *
+ * Copyright (C) 1999 Andreas E. Bombe
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+#include <asm/semaphore.h>
+
+#include "ieee1394_types.h"
+#include "ieee1394.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "highlevel.h"
+#include "ieee1394_transactions.h"
+#include "csr.h"
+
+
+atomic_t hpsb_generation = ATOMIC_INIT(0);
+
+
+static void dump_packet(const char *text, quadlet_t *data, int size)
+{
+        int i;
+
+        size /= 4;
+        size = (size > 4 ? 4 : size);
+
+        printk(KERN_DEBUG "ieee1394: %s", text);
+        for (i = 0; i < size; i++) {
+                printk(" %8.8x", data[i]);
+        }
+        printk("\n");
+}
+
+
+struct hpsb_packet *alloc_hpsb_packet(size_t data_size)
+{
+        struct hpsb_packet *packet = NULL;
+        void *header = NULL, *data = NULL;
+        int kmflags = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL;
+
+        packet = kmalloc(sizeof(struct hpsb_packet), kmflags);
+        header = kmalloc(5 * 4, kmflags);
+        if (header == NULL || packet == NULL) {
+                kfree(header);
+                kfree(packet);
+                return NULL;
+        }
+
+        memset(packet, 0, sizeof(struct hpsb_packet));
+        packet->header = header;
+
+        if (data_size) {
+                data = kmalloc(data_size + 4, kmflags);
+                if (data == NULL) {
+                        kfree(header);
+                        kfree(packet);
+                        return NULL;
+                }
+
+                packet->data = data;
+                packet->data_size = data_size - 4;
+        }
+
+        INIT_LIST_HEAD(&packet->list);
+        sema_init(&packet->state_change, 0);
+        packet->state = unused;
+        packet->generation = get_hpsb_generation();
+
+#ifdef __BIG_ENDIAN
+        /* set default */
+        packet->data_be = 1;
+#endif
+
+        return packet;
+}
+
+void free_hpsb_packet(struct hpsb_packet *packet)
+{
+        if (packet == NULL) {
+                return;
+        }
+
+        kfree(packet->data);
+        kfree(packet->header);
+        kfree(packet);
+}
+
+
+void reset_host_bus(struct hpsb_host *host)
+{
+        if (!host->initialized) {
+                return;
+        }
+
+        hpsb_bus_reset(host);
+        host->template->devctl(host, RESET_BUS, 0);
+}
+
+
+void hpsb_bus_reset(struct hpsb_host *host)
+{
+        if (!host->in_bus_reset) {
+                abort_requests(host);
+                host->in_bus_reset = 1;
+                host->irm_id = -1;
+                host->busmgr_id = -1;
+                host->node_count = 0;
+                host->selfid_count = 0;
+        } else {
+                HPSB_NOTICE(__FUNCTION__ 
+                            " called while bus reset already in progress");
+        }
+}
+
+
+/*
+ * Verify num_of_selfids SelfIDs and return number of nodes.  Return zero in
+ * case verification failed.
+ */
+static int check_selfids(struct hpsb_host *host, unsigned int num_of_selfids)
+{
+        int nodeid = -1;
+        int rest_of_selfids = num_of_selfids;
+        quadlet_t *sidp = host->topology_map;
+        quadlet_t sid = *sidp;
+        int esid_seq = 23;
+        int i;
+
+        while (rest_of_selfids--) {
+                sid = *(sidp++);
+
+                if (!(sid & 0x00800000) /* !extended */) {
+                        nodeid++;
+                        esid_seq = 0;
+
+                        if (((sid >> 24) & NODE_MASK) != nodeid) {
+                                HPSB_INFO("SelfIDs failed monotony check with "
+                                          "%d", (sid >> 24) & NODE_MASK);
+                                return 0;
+                        }
+
+                        /* "if is contender and link active" */
+                        if ((sid & (1<<11)) && (sid & (1<<22))) {
+                                host->irm_id = LOCAL_BUS | ((sid >> 24) 
+                                                            & NODE_MASK);
+                        }
+                } else {
+                        if ((((sid >> 24) & NODE_MASK) != nodeid)
+                            || (((sid >> 20) & 0x7) != esid_seq)) {
+                                HPSB_INFO("SelfIDs failed monotony check with "
+                                          "%d/%d", (sid >> 24) & NODE_MASK,
+                                          (sid >> 20) & 0x7);
+                                return 0;
+                        }
+                        esid_seq++;
+                }
+        }
+
+        sidp--;
+        while (sid & 0x00800000 /* extended */) {
+                /* check that no ports go to a parent */
+                for (i = 2; i < 18; i += 2) {
+                        if ((sid & (0x3 << i)) == (0x2 << i)) {
+                                HPSB_INFO("SelfIDs failed root check on "
+                                          "extended SelfID");
+                                return 0;
+                        }
+                }
+                sid = *(sidp--);
+        }
+
+        for (i = 2; i < 8; i += 2) {
+                if ((sid & (0x3 << i)) == (0x2 << i)) {
+                        HPSB_INFO("SelfIDs failed root check");
+                        return 0;
+                }
+        }
+
+        return nodeid + 1;
+}
+
+void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
+{
+        if (host->in_bus_reset) {
+                printk("including selfid 0x%x\n", sid);
+                host->topology_map[host->selfid_count++] = sid;
+        } else {
+                /* FIXME - info on which host */
+                HPSB_NOTICE("spurious selfid packet (0x%8.8x) received", sid);
+        }
+}
+
+void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
+{
+        
+
+        host->node_id = 0xffc0 | phyid;
+        host->in_bus_reset = 0;
+        host->is_root = isroot;
+
+        host->node_count = check_selfids(host, host->selfid_count);
+        if (!host->node_count) {
+                if (host->reset_retries++ < 20) {
+                        /* selfid stage did not complete without error */
+                        HPSB_NOTICE("error in SelfID stage - resetting");
+                        reset_host_bus(host);
+                        return;
+                } else {
+                        HPSB_NOTICE("stopping out-of-control reset loop");
+                        HPSB_NOTICE("warning - topology map will therefore not "
+                                    "be valid");
+                }
+        }
+
+        /* irm_id is kept up to date by check_selfids() */
+        host->is_irm = (host->irm_id == host->node_id);
+
+        host->reset_retries = 0;
+        inc_hpsb_generation();
+        highlevel_host_reset(host);
+}
+
+
+void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, 
+                      int ackcode)
+{
+        unsigned long flags;
+
+        packet->ack_code = ackcode;
+
+        if (packet->no_waiter) {
+                /* must not have a tlabel allocated */
+                free_hpsb_packet(packet);
+                return;
+        }
+
+        if (ackcode != ACK_PENDING || !packet->expect_response) {
+                packet->state = complete;
+                up(&packet->state_change);
+                up(&packet->state_change);
+                run_task_queue(&packet->complete_tq);
+                return;
+        }
+
+        packet->state = pending;
+        packet->sendtime = jiffies;
+
+        spin_lock_irqsave(&host->pending_pkt_lock, flags);
+        list_add_tail(&packet->list, &host->pending_packets);
+        spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
+
+        up(&packet->state_change);
+        queue_task(&host->timeout_tq, &tq_timer);
+}
+
+int hpsb_send_packet(struct hpsb_packet *packet)
+{
+        struct hpsb_host *host = packet->host;
+
+        if (!host->initialized || host->in_bus_reset 
+            || (packet->generation != get_hpsb_generation())) {
+                return 0;
+        }
+
+        packet->state = queued;
+
+        dump_packet("send packet:", packet->header, packet->header_size);
+
+        return host->template->transmit_packet(host, packet);
+}
+
+static void send_packet_nocare(struct hpsb_packet *packet)
+{
+        if (!hpsb_send_packet(packet)) {
+                free_hpsb_packet(packet);
+        }
+}
+
+
+void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data,
+                            size_t size)
+{
+        struct hpsb_packet *packet = NULL;
+        struct list_head *lh;
+        int tcode_match = 0;
+        int tlabel;
+        unsigned long flags;
+
+        tlabel = (data[0] >> 10) & 0x3f;
+
+        spin_lock_irqsave(&host->pending_pkt_lock, flags);
+
+        lh = host->pending_packets.next;
+        while (lh != &host->pending_packets) {
+                packet = list_entry(lh, struct hpsb_packet, list);
+                if ((packet->tlabel == tlabel)
+                    && (packet->node_id == (data[1] >> 16))){
+                        break;
+                }
+                lh = lh->next;
+        }
+
+        if (lh == &host->pending_packets) {
+                HPSB_INFO("unsolicited response packet received - np");
+                dump_packet("contents:", data, 16);
+                spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
+                return;
+        }
+
+        switch (packet->tcode) {
+        case TCODE_WRITEQ:
+        case TCODE_WRITEB:
+                if (tcode == TCODE_WRITE_RESPONSE) tcode_match = 1;
+                break;
+        case TCODE_READQ:
+                if (tcode == TCODE_READQ_RESPONSE) tcode_match = 1;
+                break;
+        case TCODE_READB:
+                if (tcode == TCODE_READB_RESPONSE) tcode_match = 1;
+                break;
+        case TCODE_LOCK_REQUEST:
+                if (tcode == TCODE_LOCK_RESPONSE) tcode_match = 1;
+                break;
+        }
+
+        if (!tcode_match || (packet->tlabel != tlabel)
+            || (packet->node_id != (data[1] >> 16))) {
+                HPSB_INFO("unsolicited response packet received");
+                dump_packet("contents:", data, 16);
+
+                spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
+                return;
+        }
+
+        list_del(&packet->list);
+
+        spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
+
+        /* FIXME - update size fields? */
+        switch (tcode) {
+        case TCODE_WRITE_RESPONSE:
+                memcpy(packet->header, data, 12);
+                break;
+        case TCODE_READQ_RESPONSE:
+                memcpy(packet->header, data, 16);
+                break;
+        case TCODE_READB_RESPONSE:
+                memcpy(packet->header, data, 16);
+                memcpy(packet->data, data + 4, size - 16);
+                break;
+        case TCODE_LOCK_RESPONSE:
+                memcpy(packet->header, data, 16);
+                memcpy(packet->data, data + 4, (size - 16) > 8 ? 8 : size - 16);
+                break;
+        }
+
+        packet->state = complete;
+        up(&packet->state_change);
+        run_task_queue(&packet->complete_tq);
+}
+
+
+struct hpsb_packet *create_reply_packet(struct hpsb_host *host, quadlet_t *data,
+                                        size_t dsize)
+{
+        struct hpsb_packet *p;
+
+        p = alloc_hpsb_packet(dsize);
+        if (p == NULL) {
+                /* FIXME - send data_error response */
+                return NULL;
+        }
+                
+        p->type = async;
+        p->state = unused;
+        p->host = host;
+        p->node_id = data[1] >> 16;
+        p->tlabel = (data[0] >> 10) & 0x3f;
+        p->no_waiter = 1;
+
+        return p;
+}
+
+#define PREP_REPLY_PACKET(length) \
+                packet = create_reply_packet(host, data, length); \
+                if (packet == NULL) break
+
+inline void swap_quadlets_on_le(quadlet_t *q)
+{
+#ifdef __LITTLE_ENDIAN
+        quadlet_t saved = q[0];
+        q[0] = q[1];
+        q[1] = saved;
+#endif
+}
+
+
+void handle_incoming_packet(struct hpsb_host *host, int tcode, quadlet_t *data,
+                            size_t size)
+{
+        struct hpsb_packet *packet;
+        int length, rcode, extcode;
+        u64 addr;
+
+        /* big FIXME - no error checking is done for an out of bounds length */
+
+        switch (tcode) {
+        case TCODE_WRITEQ:
+                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+                rcode = highlevel_write(host, data+3, addr, 4);
+
+                if (((data[0] >> 16) & NODE_MASK) != NODE_MASK) {
+                        /* not a broadcast write, reply */
+                        PREP_REPLY_PACKET(0);
+                        fill_async_write_resp(packet, rcode);
+                        send_packet_nocare(packet);
+                }
+                break;
+
+        case TCODE_WRITEB:
+                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+                rcode = highlevel_write(host, data+4, addr, data[3]>>16);
+
+                if (((data[0] >> 16) & NODE_MASK) != NODE_MASK) {
+                        /* not a broadcast write, reply */
+                        PREP_REPLY_PACKET(0);
+                        fill_async_write_resp(packet, rcode);
+                        send_packet_nocare(packet);
+                }
+                break;
+
+        case TCODE_READQ:
+                PREP_REPLY_PACKET(0);
+
+                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+                rcode = highlevel_read(host, data, addr, 4);
+                fill_async_readquad_resp(packet, rcode, *data);
+                send_packet_nocare(packet);
+                break;
+
+        case TCODE_READB:
+                length = data[3] >> 16;
+                PREP_REPLY_PACKET(length);
+
+                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+                rcode = highlevel_read(host, packet->data, addr, length);
+                fill_async_readblock_resp(packet, rcode, length);
+                send_packet_nocare(packet);
+                break;
+
+        case TCODE_LOCK_REQUEST:
+                length = data[3] >> 16;
+                extcode = data[3] & 0xffff;
+                addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
+
+                PREP_REPLY_PACKET(8);
+
+                if ((extcode == 0) || (extcode >= 7)) {
+                        /* let switch default handle error */
+                        length = 0;
+                }
+
+                switch (length) {
+                case 4:
+                        rcode = highlevel_lock(host, packet->data, addr, 
+                                               data[4], 0, extcode);
+                        fill_async_lock_resp(packet, rcode, extcode, 4);
+                        break;
+                case 8:
+                        if ((extcode != EXTCODE_FETCH_ADD) 
+                            && (extcode != EXTCODE_LITTLE_ADD)) {
+                                rcode = highlevel_lock(host, packet->data, addr,
+                                                       data[5], data[4], 
+                                                       extcode);
+                                fill_async_lock_resp(packet, rcode, extcode, 4);
+                        } else {
+                                swap_quadlets_on_le(data + 4);
+                                rcode = highlevel_lock64(host,
+                                             (octlet_t *)packet->data, addr,
+                                             *(octlet_t *)(data + 4), 0ULL,
+                                             extcode);
+                                swap_quadlets_on_le(packet->data);
+                                fill_async_lock_resp(packet, rcode, extcode, 8);
+                        }
+                        break;
+                case 16:
+                        swap_quadlets_on_le(data + 4);
+                        swap_quadlets_on_le(data + 6);
+                        rcode = highlevel_lock64(host, (octlet_t *)packet->data,
+                                                 addr, *(octlet_t *)(data + 6),
+                                                 *(octlet_t *)(data + 4), 
+                                                 extcode);
+                        swap_quadlets_on_le(packet->data);
+                        fill_async_lock_resp(packet, rcode, extcode, 8);
+                        break;
+                default:
+                        fill_async_lock_resp(packet, RCODE_TYPE_ERROR,
+                                             extcode, 0);
+                }
+
+                send_packet_nocare(packet);
+                break;
+        }
+
+}
+#undef PREP_REPLY_PACKET
+
+
+void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size)
+{
+        int tcode;
+
+        if (host->in_bus_reset) {
+                HPSB_INFO("received packet during reset; ignoring");
+                return;
+        }
+
+        dump_packet("received packet:", data, size);
+
+        tcode = (data[0] >> 4) & 0xf;
+
+        switch (tcode) {
+        case TCODE_WRITE_RESPONSE:
+        case TCODE_READQ_RESPONSE:
+        case TCODE_READB_RESPONSE:
+        case TCODE_LOCK_RESPONSE:
+                handle_packet_response(host, tcode, data, size);
+                break;
+
+        case TCODE_WRITEQ:
+        case TCODE_WRITEB:
+        case TCODE_READQ:
+        case TCODE_READB:
+        case TCODE_LOCK_REQUEST:
+                handle_incoming_packet(host, tcode, data, size);
+                break;
+
+
+        case TCODE_ISO_DATA:
+                highlevel_iso_receive(host, data, size);
+                break;
+
+        case TCODE_CYCLE_START:
+                /* simply ignore this packet if it is passed on */
+                break;
+
+        default:
+                HPSB_NOTICE("received packet with bogus transaction code %d", 
+                            tcode);
+                break;
+        }
+}
+
+
+void abort_requests(struct hpsb_host *host)
+{
+        unsigned long flags;
+        struct hpsb_packet *packet;
+        struct list_head *lh;
+        LIST_HEAD(llist);
+
+        host->template->devctl(host, CANCEL_REQUESTS, 0);
+
+        spin_lock_irqsave(&host->pending_pkt_lock, flags);
+        list_splice(&host->pending_packets, &llist);
+        INIT_LIST_HEAD(&host->pending_packets);
+        spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
+
+        lh = llist.next;
+
+        while (lh != &llist) {
+                packet = list_entry(lh, struct hpsb_packet, list);
+                lh = lh->next;
+                packet->state = complete;
+                packet->ack_code = ACKX_ABORTED;
+                up(&packet->state_change);
+                run_task_queue(&packet->complete_tq);
+        }
+}
+
+void abort_timedouts(struct hpsb_host *host)
+{
+        unsigned long flags;
+        struct hpsb_packet *packet;
+        unsigned long expire;
+        struct list_head *lh;
+        LIST_HEAD(expiredlist);
+
+        spin_lock_irqsave(&host->csr.lock, flags);
+        expire = (host->csr.split_timeout_hi * 8000 
+                  + (host->csr.split_timeout_lo >> 19))
+                * HZ / 8000;
+        /* Avoid shortening of timeout due to rounding errors: */
+        expire++;
+        spin_unlock_irqrestore(&host->csr.lock, flags);
+
+
+        spin_lock_irqsave(&host->pending_pkt_lock, flags);
+        lh = host->pending_packets.next;
+
+        while (lh != &host->pending_packets) {
+                packet = list_entry(lh, struct hpsb_packet, list);
+                lh = lh->next;
+                if (time_before(packet->sendtime + expire, jiffies)) {
+                        list_del(&packet->list);
+                        list_add(&packet->list, &expiredlist);
+                }
+        }
+
+        if (!list_empty(&host->pending_packets)) {
+                queue_task(&host->timeout_tq, &tq_timer);
+        }
+        spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
+
+        lh = expiredlist.next;
+        while (lh != &expiredlist) {
+                packet = list_entry(lh, struct hpsb_packet, list);
+                lh = lh->next;
+                packet->state = complete;
+                packet->ack_code = ACKX_TIMEOUT;
+                up(&packet->state_change);
+                run_task_queue(&packet->complete_tq);
+        }
+}
+
+
+#if 0
+int hpsb_host_thread(void *hostPointer)
+{
+        struct hpsb_host *host = (struct hpsb_host *)hostPointer;
+
+        /* I don't understand why, but I just want to be on the safe side. */
+        lock_kernel();
+
+        HPSB_INFO(__FUNCTION__ " starting for one %s adapter",
+                  host->template->name);
+
+        exit_mm(current);
+        exit_files(current);
+        exit_fs(current);
+
+        strcpy(current->comm, "ieee1394 thread");
+
+        /* ... but then again, I think the following is safe. */
+        unlock_kernel();
+
+        for (;;) {
+                siginfo_t info;
+                unsigned long signr;
+
+                if (signal_pending(current)) {
+                        spin_lock_irq(&current->sigmask_lock);
+                        signr = dequeue_signal(&current->blocked, &info);
+                        spin_unlock_irq(&current->sigmask_lock);
+
+                        break;
+                }
+
+                abort_timedouts(host);
+        }
+
+        HPSB_INFO(__FUNCTION__ " exiting");
+        return 0;
+}
+#endif
+
+
+#ifndef MODULE
+
+void __init ieee1394_init(void)
+{
+        register_builtin_lowlevels();
+        init_hpsb_highlevel();
+        init_csr();
+}
+
+#else
+
+int init_module(void)
+{
+        init_hpsb_highlevel();
+        init_csr();
+        return 0;
+}
+
+#endif
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ieee1394_core.h linux/drivers/ieee1394/ieee1394_core.h
--- v2.3.39/linux/drivers/ieee1394/ieee1394_core.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ieee1394_core.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,152 @@
+
+#ifndef _IEEE1394_CORE_H
+#define _IEEE1394_CORE_H
+
+#include <linux/tqueue.h>
+#include <asm/semaphore.h>
+#include "hosts.h"
+
+
+struct hpsb_packet {
+        /* This struct is basically read-only for hosts with the exception of
+         * the data buffer contents and xnext - see below. */
+        struct list_head list;
+
+        /* This can be used for host driver internal linking. */
+        struct hpsb_packet *xnext;
+
+        nodeid_t node_id;
+
+        /* Async and Iso types should be clear, raw means send-as-is, do not
+         * CRC!  Byte swapping shall still be done in this case. */
+        enum { async, iso, raw } __attribute__((packed)) type;
+
+        /* Okay, this is core internal and a no care for hosts.
+         * queued   = queued for sending
+         * pending  = sent, waiting for response
+         * complete = processing completed, successful or not
+         * incoming = incoming packet
+         */
+        enum { 
+                unused, queued, pending, complete, incoming 
+        } __attribute__((packed)) state;
+
+        /* These are core internal. */
+        char tlabel;
+        char ack_code;
+        char tcode;
+
+        unsigned expect_response:1;
+        unsigned no_waiter:1;
+
+        /* Data big endianness flag - may vary from request to request.  The
+         * header is always in machine byte order.  */
+        unsigned data_be:1;
+
+        /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
+        unsigned speed_code:2;
+
+        /* --- 16 bytes (one cacheline) --- */
+
+        /* *header and *data are guaranteed to be 32-bit DMAable and may be
+         * overwritten to allow in-place byte swapping.  Neither of these is
+         * CRCed (the sizes also don't include CRC), but contain space for at
+         * least one additional quadlet to allow in-place CRCing.  The memory is
+         * also guaranteed to have physical mapping (virt_to_bus() is meaningful
+         * on these pointers).
+         * NOTE: The 32-bit DMA guarantee is currently not enforced.
+         *       That's a Linux 2.3 issue.  
+         */
+        quadlet_t *header;
+        quadlet_t *data;
+        size_t header_size;
+        size_t data_size;
+
+        /* --- 32 bytes --- */
+
+        struct hpsb_host *host;
+        unsigned int generation;
+
+        /* Very core internal, don't care. */
+        struct semaphore state_change;
+
+        task_queue complete_tq;
+
+        /* Store jiffies for implementing bus timeouts. */
+        unsigned long sendtime;
+};
+
+
+void reset_host_bus(struct hpsb_host *host);
+void abort_timedouts(struct hpsb_host *host);
+void abort_requests(struct hpsb_host *host);
+
+struct hpsb_packet *alloc_hpsb_packet(size_t data_size);
+void free_hpsb_packet(struct hpsb_packet *packet);
+
+
+/*
+ * Generation counter for the complete 1394 subsystem.  Generation gets
+ * incremented on every change in the subsystem (e.g. bus reset).
+ *
+ * Use the functions, not the variable.
+ */
+#include <asm/atomic.h>
+extern atomic_t hpsb_generation;
+
+inline static unsigned int get_hpsb_generation(void)
+{
+        return atomic_read(&hpsb_generation);
+}
+
+inline static void inc_hpsb_generation(void)
+{
+        atomic_inc(&hpsb_generation);
+}
+
+
+/*
+ * Queue packet for transmitting, return 0 for failure.
+ */
+int hpsb_send_packet(struct hpsb_packet *packet);
+
+
+/*
+ * The following functions are exported for host driver module usage.  All of
+ * them are safe to use in interrupt contexts, although some are quite
+ * complicated so you may want to run them in bottom halves instead of calling
+ * them directly.
+ */
+
+/* Notify a bus reset to the core. */
+void hpsb_bus_reset(struct hpsb_host *host);
+
+/*
+ * Hand over received selfid packet to the core.  Complement check (second
+ * quadlet is complement of first) is expected to be done and succesful.
+ */
+void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid);
+
+/* 
+ * Notify completion of SelfID stage to the core and report new physical ID
+ * and whether host is root now.
+ */
+void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot);
+
+/*
+ * Notify core of sending a packet.  Ackcode is the ack code returned for async
+ * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE
+ * for other cases (internal errors that don't justify a panic).  Safe to call
+ * from within a transmit packet routine.
+ */
+void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, int ackcode);
+
+/*
+ * Hand over received packet to the core.  The contents of data are expected to
+ * be the full packet but with the CRCs left out (data block follows header
+ * immediately) and in machine byte order.  *data can be safely overwritten
+ * after this call.
+ */
+void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size);
+
+#endif /* _IEEE1394_CORE_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ieee1394_syms.c linux/drivers/ieee1394/ieee1394_syms.c
--- v2.3.39/linux/drivers/ieee1394/ieee1394_syms.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ieee1394_syms.c	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,59 @@
+/*
+ * IEEE 1394 for Linux
+ *
+ * Exported symbols for module usage.
+ *
+ * Copyright (C) 1999 Andreas E. Bombe
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "ieee1394_transactions.h"
+/* #include "events.h" */
+#include "highlevel.h"
+
+EXPORT_SYMBOL(hpsb_register_lowlevel);
+EXPORT_SYMBOL(hpsb_unregister_lowlevel);
+EXPORT_SYMBOL(hpsb_get_host);
+EXPORT_SYMBOL(hpsb_get_host_list);
+EXPORT_SYMBOL(hpsb_inc_host_usage);
+EXPORT_SYMBOL(hpsb_dec_host_usage);
+
+EXPORT_SYMBOL(alloc_hpsb_packet);
+EXPORT_SYMBOL(free_hpsb_packet);
+EXPORT_SYMBOL(hpsb_send_packet);
+EXPORT_SYMBOL(hpsb_bus_reset);
+EXPORT_SYMBOL(hpsb_selfid_received);
+EXPORT_SYMBOL(hpsb_selfid_complete);
+EXPORT_SYMBOL(hpsb_packet_sent);
+EXPORT_SYMBOL(hpsb_packet_received);
+EXPORT_SYMBOL(hpsb_generation);
+
+EXPORT_SYMBOL(get_tlabel);
+EXPORT_SYMBOL(free_tlabel);
+EXPORT_SYMBOL(hpsb_make_readqpacket);
+EXPORT_SYMBOL(hpsb_make_readbpacket);
+EXPORT_SYMBOL(hpsb_make_writeqpacket);
+EXPORT_SYMBOL(hpsb_make_writebpacket);
+EXPORT_SYMBOL(hpsb_read);
+EXPORT_SYMBOL(hpsb_write);
+EXPORT_SYMBOL(hpsb_lock);
+
+EXPORT_SYMBOL(hpsb_register_highlevel);
+EXPORT_SYMBOL(hpsb_unregister_highlevel);
+EXPORT_SYMBOL(hpsb_register_addrspace);
+EXPORT_SYMBOL(hpsb_listen_channel);
+EXPORT_SYMBOL(hpsb_unlisten_channel);
+EXPORT_SYMBOL(highlevel_read);
+EXPORT_SYMBOL(highlevel_write);
+EXPORT_SYMBOL(highlevel_lock);
+EXPORT_SYMBOL(highlevel_lock64);
+
+/*
+EXPORT_SYMBOL(hpsb_dispatch_event);
+EXPORT_SYMBOL(hpsb_reg_event_handler);
+*/
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ieee1394_transactions.c linux/drivers/ieee1394/ieee1394_transactions.c
--- v2.3.39/linux/drivers/ieee1394/ieee1394_transactions.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ieee1394_transactions.c	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,514 @@
+/*
+ * IEEE 1394 for Linux
+ *
+ * Transaction support.
+ *
+ * Copyright (C) 1999 Andreas E. Bombe
+ */
+
+#include <linux/sched.h>
+#include <asm/errno.h>
+#include <asm/bitops.h>
+
+#include "ieee1394.h"
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "highlevel.h"
+
+
+#define PREP_ASYNC_HEAD_ADDRESS(tc) \
+        packet->tcode = tc; \
+        packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \
+                | (1 << 8) | (tc << 4); \
+        packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
+        packet->header[2] = addr & 0xffffffff
+
+#define PREP_ASYNC_HEAD_RCODE(tc) \
+        packet->tcode = tc; \
+        packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \
+                | (1 << 8) | (tc << 4); \
+        packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \
+        packet->header[2] = 0
+
+
+void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
+{
+        PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
+        packet->header_size = 12;
+        packet->data_size = 0;
+        packet->expect_response = 1;
+}
+
+void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, 
+                              quadlet_t data)
+{
+        PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);
+        packet->header[3] = data;
+        packet->header_size = 16;
+        packet->data_size = 0;
+}
+
+void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length)
+{
+        PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
+        packet->header[3] = length << 16;
+        packet->header_size = 16;
+        packet->data_size = 0;
+        packet->expect_response = 1;
+}
+
+void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, 
+                               int length)
+{
+        if (rcode != RCODE_COMPLETE) {
+                length = 0;
+        }
+
+        PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE);
+        packet->header[3] = length << 16;
+        packet->header_size = 16;
+        packet->data_size = length;
+}
+
+void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data)
+{
+        PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
+        packet->header[3] = data;
+        packet->header_size = 16;
+        packet->data_size = 0;
+        packet->expect_response = 1;
+}
+
+void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length)
+{
+        PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
+        packet->header[3] = length << 16;
+        packet->header_size = 16;
+        packet->data_size = length;
+        packet->expect_response = 1;
+}
+
+void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
+{
+        PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE);
+        packet->header[2] = 0;
+        packet->header_size = 12;
+        packet->data_size = 0;
+}
+
+void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode, 
+                     int length)
+{
+        PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
+        packet->header[3] = (length << 16) | extcode;
+        packet->header_size = 16;
+        packet->data_size = length;
+        packet->expect_response = 1;
+}
+
+void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, 
+                          int length)
+{
+        if (rcode != RCODE_COMPLETE) {
+                length = 0;
+        }
+
+        PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE);
+        packet->header[3] = (length << 16) | extcode;
+        packet->header_size = 16;
+        packet->data_size = length;
+}
+
+void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
+                     int tag, int sync)
+{
+        packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
+                | (TCODE_ISO_DATA << 4) | sync;
+
+        packet->header_size = 4;
+        packet->data_size = length;
+        packet->tcode = TCODE_ISO_DATA;
+}
+
+
+int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait)
+{
+        unsigned long flags;
+        int tlabel;
+
+        while (1) {
+                spin_lock_irqsave(&host->tlabel_lock, flags);
+
+                if (host->tlabel_count) {
+                        host->tlabel_count--;
+
+                        if (host->tlabel_pool[0] != ~0) {
+                                tlabel = ffz(host->tlabel_pool[0]);
+                                host->tlabel_pool[0] |= 1 << tlabel;
+                        } else {
+                                tlabel = ffz(host->tlabel_pool[1]);
+                                host->tlabel_pool[1] |= 1 << tlabel;
+                                tlabel += 32;
+                        }
+                
+                        spin_unlock_irqrestore(&host->tlabel_lock, flags);
+                        return tlabel;
+                }
+
+                spin_unlock_irqrestore(&host->tlabel_lock, flags);
+
+                if (wait) {
+                        sleep_on(&host->tlabel_wait);
+                } else {
+                        return -1;
+                }
+        }
+}
+
+void free_tlabel(struct hpsb_host *host, nodeid_t nodeid, int tlabel)
+{
+        unsigned long flags;
+
+        spin_lock_irqsave(&host->tlabel_lock, flags);
+
+        if (tlabel < 32) {
+                host->tlabel_pool[0] &= ~(1 << tlabel);
+        } else {
+                host->tlabel_pool[1] &= ~(1 << (tlabel-32));
+        }
+
+        host->tlabel_count++;
+
+        spin_unlock_irqrestore(&host->tlabel_lock, flags);
+
+        wake_up(&host->tlabel_wait);
+}
+
+
+
+int hpsb_packet_success(struct hpsb_packet *packet)
+{
+        switch (packet->ack_code) {
+        case ACK_PENDING:
+                switch ((packet->header[1] >> 12) & 0xf) {
+                case RCODE_COMPLETE:
+                        return 0;
+                case RCODE_CONFLICT_ERROR:
+                        return -EAGAIN;
+                case RCODE_DATA_ERROR:
+                        return -EREMOTEIO;
+                case RCODE_TYPE_ERROR:
+                        return -EACCES;
+                case RCODE_ADDRESS_ERROR:
+                        return -EINVAL;
+                default:
+                        HPSB_ERR("received reserved rcode %d from node %d",
+                                 (packet->header[1] >> 12) & 0xf, 
+                                 packet->node_id);
+                        return -EAGAIN;
+                }
+                HPSB_PANIC("reached unreachable code 1 in " __FUNCTION__);
+
+        case ACK_BUSY_X:
+        case ACK_BUSY_A:
+        case ACK_BUSY_B:
+                return -EBUSY;
+
+        case ACK_TYPE_ERROR:
+                return -EACCES;
+
+        case ACK_COMPLETE:
+                if (packet->tcode == TCODE_WRITEQ
+                    || packet->tcode == TCODE_WRITEB) {
+                        return 0;
+                } else {
+                        HPSB_ERR("impossible ack_complete from node %d "
+                                 "(tcode %d)", packet->node_id, packet->tcode);
+                        return -EAGAIN;
+                }
+
+
+        case ACK_DATA_ERROR:
+                if (packet->tcode == TCODE_WRITEB
+                    || packet->tcode == TCODE_LOCK_REQUEST) {
+                        return -EAGAIN;
+                } else {
+                        HPSB_ERR("impossible ack_data_error from node %d "
+                                 "(tcode %d)", packet->node_id, packet->tcode);
+                        return -EAGAIN;
+                }
+
+        case ACKX_NONE:
+        case ACKX_SEND_ERROR:
+        case ACKX_ABORTED:
+        case ACKX_TIMEOUT:
+                /* error while sending */
+                return -EAGAIN;
+
+        default:
+                HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
+                         packet->ack_code, packet->node_id, packet->tcode);
+                return -EAGAIN;
+        }
+
+        HPSB_PANIC("reached unreachable code 2 in " __FUNCTION__);
+}
+
+
+int hpsb_read_trylocal(struct hpsb_host *host, nodeid_t node, u64 addr, 
+                       quadlet_t *buffer, size_t length)
+{
+        if (host->node_id != node) return -1;
+        return highlevel_read(host, buffer, addr, length);
+}
+
+struct hpsb_packet *hpsb_make_readqpacket(struct hpsb_host *host, nodeid_t node,
+                                          u64 addr)
+{
+        struct hpsb_packet *p;
+
+        p = alloc_hpsb_packet(0);
+        if (!p) return NULL;
+
+        p->host = host;
+        p->tlabel = get_tlabel(host, node, 1);
+        p->node_id = node;
+        fill_async_readquad(p, addr);
+
+        return p;
+}
+
+struct hpsb_packet *hpsb_make_readbpacket(struct hpsb_host *host, nodeid_t node,
+                                          u64 addr, size_t length)
+{
+        struct hpsb_packet *p;
+
+        p = alloc_hpsb_packet(length);
+        if (!p) return NULL;
+
+        p->host = host;
+        p->tlabel = get_tlabel(host, node, 1);
+        p->node_id = node;
+        fill_async_readblock(p, addr, length);
+
+        return p;
+}
+
+struct hpsb_packet *hpsb_make_writeqpacket(struct hpsb_host *host,
+                                           nodeid_t node, u64 addr,
+                                           quadlet_t data)
+{
+        struct hpsb_packet *p;
+
+        p = alloc_hpsb_packet(0);
+        if (!p) return NULL;
+
+        p->host = host;
+        p->tlabel = get_tlabel(host, node, 1);
+        p->node_id = node;
+        fill_async_writequad(p, addr, data);
+
+        return p;
+}
+
+struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host,
+                                           nodeid_t node, u64 addr,
+                                           size_t length)
+{
+        struct hpsb_packet *p;
+
+        p = alloc_hpsb_packet(length);
+        if (!p) return NULL;
+
+        p->host = host;
+        p->tlabel = get_tlabel(host, node, 1);
+        p->node_id = node;
+        fill_async_writeblock(p, addr, length);
+
+        return p;
+}
+
+
+/*
+ * FIXME - these functions should probably read from / write to user space to
+ * avoid in kernel buffers for user space callers
+ */
+
+int hpsb_read(struct hpsb_host *host, nodeid_t node, u64 addr,
+              quadlet_t *buffer, size_t length)
+{
+        struct hpsb_packet *packet;
+        int retval = 0;
+        
+        if (length == 0) {
+                return -EINVAL;
+        }
+
+        if (host->node_id == node) {
+                switch(highlevel_read(host, buffer, addr, length)) {
+                case RCODE_COMPLETE:
+                        return 0;
+                case RCODE_TYPE_ERROR:
+                        return -EACCES;
+                case RCODE_ADDRESS_ERROR:
+                default:
+                        return -EINVAL;
+                }
+        }
+
+        if (length & 0x3) {
+                /* FIXME: Lengths not multiple of 4 are not implemented.  Mainly
+                 * there is the problem with little endian machines because we
+                 * always swap to little endian on receive.  If we read 5 bytes
+                 * 12345 we receive them as 12345000 and swap them to 43210005.
+                 * How should we copy that to the caller?  Require *buffer to be
+                 * a full quadlet multiple in length? */
+                return -EACCES;
+        }
+
+        if (length == 4) {
+                packet = hpsb_make_readqpacket(host, node, addr);
+        } else {
+                packet = hpsb_make_readbpacket(host, node, addr, length);
+        }
+
+        if (!packet) {
+                return -ENOMEM;
+        }
+
+        hpsb_send_packet(packet);
+        down(&packet->state_change);
+        down(&packet->state_change);
+        retval = hpsb_packet_success(packet);
+
+        if (retval == 0) {
+                if (length == 4) {
+                        *buffer = packet->header[3];
+                } else {
+                        memcpy(buffer, packet->data, length);
+                }
+        }
+
+        free_tlabel(host, node, packet->tlabel);
+        free_hpsb_packet(packet);
+
+        return retval;
+}
+
+
+int hpsb_write(struct hpsb_host *host, nodeid_t node, u64 addr,
+               quadlet_t *buffer, size_t length)
+{
+        struct hpsb_packet *packet;
+        int retval = 0;
+        
+        if (length == 0) {
+                return -EINVAL;
+        }
+
+        if (host->node_id == node) {
+                switch(highlevel_write(host, buffer, addr, length)) {
+                case RCODE_COMPLETE:
+                        return 0;
+                case RCODE_TYPE_ERROR:
+                        return -EACCES;
+                case RCODE_ADDRESS_ERROR:
+                default:
+                        return -EINVAL;
+                }
+        }
+
+        if (length & 0x3) {
+                /* FIXME: Lengths not multiple of 4 are not implemented.  See function
+                 * hpsb_read for explanation, same reason, different direction. */
+                return -EACCES;
+        }
+
+        if (length == 4) {
+                packet = hpsb_make_writeqpacket(host, node, addr, *buffer);
+        } else {
+                packet = hpsb_make_writebpacket(host, node, addr, length);
+        }
+
+        if (!packet) {
+                return -ENOMEM;
+        }
+
+        if (length != 4) {
+                memcpy(packet->data, buffer, length);
+        }
+
+        hpsb_send_packet(packet);
+        down(&packet->state_change);
+        down(&packet->state_change);
+        retval = hpsb_packet_success(packet);
+
+        free_tlabel(host, node, packet->tlabel);
+        free_hpsb_packet(packet);
+
+        return retval;
+}
+
+
+/* We need a hpsb_lock64 function for the 64 bit equivalent.  Probably. */
+int hpsb_lock(struct hpsb_host *host, nodeid_t node, u64 addr, int extcode,
+              quadlet_t *data, quadlet_t arg)
+{
+        struct hpsb_packet *packet;
+        int retval = 0, length;
+        
+        if (host->node_id == node) {
+                switch(highlevel_lock(host, data, addr, *data, arg, extcode)) {
+                case RCODE_COMPLETE:
+                        return 0;
+                case RCODE_TYPE_ERROR:
+                        return -EACCES;
+                case RCODE_ADDRESS_ERROR:
+                default:
+                        return -EINVAL;
+                }
+        }
+
+        packet = alloc_hpsb_packet(8);
+        if (!packet) {
+                return -ENOMEM;
+        }
+
+        packet->host = host;
+        packet->tlabel = get_tlabel(host, node, 1);
+        packet->node_id = node;
+
+        switch (extcode) {
+        case EXTCODE_MASK_SWAP:
+        case EXTCODE_COMPARE_SWAP:
+        case EXTCODE_BOUNDED_ADD:
+        case EXTCODE_WRAP_ADD:
+                length = 8;
+                packet->data[0] = arg;
+                packet->data[1] = *data;
+                break;
+        case EXTCODE_FETCH_ADD:
+        case EXTCODE_LITTLE_ADD:
+                length = 4;
+                packet->data[0] = *data;
+                break;
+        default:
+                return -EINVAL;
+        }
+        fill_async_lock(packet, addr, extcode, length);
+
+        hpsb_send_packet(packet);
+        down(&packet->state_change);
+        down(&packet->state_change);
+        retval = hpsb_packet_success(packet);
+
+        if (retval == 0) {
+                *data = packet->data[0];
+        }
+
+        free_tlabel(host, node, packet->tlabel);
+        free_hpsb_packet(packet);
+
+        return retval;
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ieee1394_transactions.h linux/drivers/ieee1394/ieee1394_transactions.h
--- v2.3.39/linux/drivers/ieee1394/ieee1394_transactions.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ieee1394_transactions.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,69 @@
+#ifndef _IEEE1394_TRANSACTIONS_H
+#define _IEEE1394_TRANSACTIONS_H
+
+#include "ieee1394_core.h"
+
+
+/*
+ * Utility functions to fill out packet headers.
+ */
+void fill_async_readquad(struct hpsb_packet *packet, u64 addr);
+void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode, 
+                              quadlet_t data);
+void fill_async_readblock(struct hpsb_packet *packet, u64 addr, int length);
+void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, 
+                               int length);
+void fill_async_writequad(struct hpsb_packet *packet, u64 addr, quadlet_t data);
+void fill_async_writeblock(struct hpsb_packet *packet, u64 addr, int length);
+void fill_async_write_resp(struct hpsb_packet *packet, int rcode);
+void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode, 
+                     int length);
+void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode, 
+                          int length);
+void fill_iso_packet(struct hpsb_packet *packet, int length, int channel,
+                     int tag, int sync);
+
+/*
+ * Get and free transaction labels.
+ */
+int get_tlabel(struct hpsb_host *host, nodeid_t nodeid, int wait);
+void free_tlabel(struct hpsb_host *host, nodeid_t nodeid, int tlabel);
+
+struct hpsb_packet *hpsb_make_readqpacket(struct hpsb_host *host, nodeid_t node,
+                                          u64 addr);
+struct hpsb_packet *hpsb_make_readbpacket(struct hpsb_host *host, nodeid_t node,
+                                          u64 addr, size_t length);
+struct hpsb_packet *hpsb_make_writeqpacket(struct hpsb_host *host,
+                                           nodeid_t node, u64 addr,
+                                           quadlet_t data);
+struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host,
+                                           nodeid_t node, u64 addr,
+                                           size_t length);
+
+/*
+ * hpsb_packet_success - Make sense of the ack and reply codes and
+ * return more convenient error codes:
+ * 0           success
+ * -EBUSY      node is busy, try again
+ * -EAGAIN     error which can probably resolved by retry
+ * -EREMOTEIO  node suffers from an internal error
+ * -EACCES     this transaction is not allowed on requested address
+ * -EINVAL     invalid address at node
+ */
+int hpsb_packet_success(struct hpsb_packet *packet);
+
+
+/*
+ * The generic read, write and lock functions.  All recognize the local node ID
+ * and act accordingly.  Read and write automatically use quadlet commands if
+ * length == 4 and and block commands otherwise (however, they do not yet
+ * support lengths that are not a multiple of 4).
+ */
+int hpsb_read(struct hpsb_host *host, nodeid_t node, u64 addr,
+              quadlet_t *buffer, size_t length);
+int hpsb_write(struct hpsb_host *host, nodeid_t node, u64 addr,
+               quadlet_t *buffer, size_t length);
+int hpsb_lock(struct hpsb_host *host, nodeid_t node, u64 addr, int extcode,
+              quadlet_t *data, quadlet_t arg);
+
+#endif /* _IEEE1394_TRANSACTIONS_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ieee1394_types.h linux/drivers/ieee1394/ieee1394_types.h
--- v2.3.39/linux/drivers/ieee1394/ieee1394_types.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ieee1394_types.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,86 @@
+
+#ifndef _IEEE1394_TYPES_H
+#define _IEEE1394_TYPES_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/list.h>
+
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+
+#define DECLARE_WAITQUEUE(name, task) struct wait_queue name = { task, NULL }
+
+typedef struct wait_queue *wait_queue_head_t;
+
+inline static void init_waitqueue_head(wait_queue_head_t *wh)
+{
+        *wh = NULL;
+}
+
+static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
+{
+        __list_add(new, head->prev, head);
+}
+
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
+#include <asm/spinlock.h>
+#else
+#include <linux/spinlock.h>
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+
+typedef __u32 quadlet_t;
+typedef __u64 octlet_t;
+typedef __u16 nodeid_t;
+
+#define BUS_MASK  0xffc0
+#define NODE_MASK 0x003f
+#define LOCAL_BUS 0xffc0
+#define ALL_NODES 0x003f
+
+#define HPSB_PRINT(level, fmt, args...) printk(level "ieee1394: " fmt "\n" , ## args)
+
+#define HPSB_DEBUG(fmt, args...) HPSB_PRINT(KERN_DEBUG, fmt , ## args)
+#define HPSB_INFO(fmt, args...) HPSB_PRINT(KERN_INFO, fmt , ## args)
+#define HPSB_NOTICE(fmt, args...) HPSB_PRINT(KERN_NOTICE, fmt , ## args)
+#define HPSB_WARN(fmt, args...) HPSB_PRINT(KERN_WARNING, fmt , ## args)
+#define HPSB_ERR(fmt, args...) HPSB_PRINT(KERN_ERR, fmt , ## args)
+
+#define HPSB_PANIC(fmt, args...) panic("ieee1394: " fmt "\n" , ## args)
+
+#define HPSB_TRACE() HPSB_PRINT(KERN_INFO, "TRACE - %s, %s(), line %d", __FILE__, __FUNCTION__, __LINE__)
+
+
+#ifdef __BIG_ENDIAN
+
+static __inline__ void *memcpy_le32(u32 *dest, const u32 *src, size_t count)
+{
+        void *tmp = dest;
+
+        count /= 4;
+
+        while (count--) {
+                *dest++ = swab32p(src++);
+        }
+
+        return tmp;
+}
+
+#else
+
+static __inline__ void *memcpy_le32(u32 *dest, const u32 *src, size_t count)
+{
+        return memcpy(dest, src, count);
+}
+
+#endif /* __BIG_ENDIAN */
+
+#endif /* _IEEE1394_TYPES_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ohci1394.c linux/drivers/ieee1394/ohci1394.c
--- v2.3.39/linux/drivers/ieee1394/ohci1394.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ohci1394.c	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,1403 @@
+/*
+ * ti_ohci1394.c - Texas Instruments Ohci1394 driver
+ * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
+ *                        Gord Peters <GordPeters@smarttech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/tqueue.h>
+
+#include "ieee1394.h"
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "ohci1394.h"
+
+#undef CONFIG_PROC_FS
+
+/* print general (card independent) information */
+#define PRINT_G(level, fmt, args...) \
+printk(level "ohci1394: " fmt "\n" , ## args)
+
+/* print card specific information */
+#define PRINT(level, card, fmt, args...) \
+printk(level "ohci1394_%d: " fmt "\n" , card , ## args)
+
+int supported_chips[][2] = {
+    { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394 },
+    { PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_OHCI1394_2 },
+    { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_OHCI1394 },
+    { -1, -1 }
+};
+
+static struct ti_ohci cards[MAX_OHCI1394_CARDS];
+static int num_of_cards = 0;
+
+static int add_card(struct pci_dev *dev);
+static void remove_card(struct ti_ohci *ohci);
+static int init_driver(void);
+
+/***********************************
+ * IEEE-1394 functionality section *
+ ***********************************/
+
+
+#if 0 /* not needed at this time */
+static int get_phy_reg(struct ti_ohci *ohci, int addr) 
+{
+	int timeout=10000;
+	static quadlet_t r;
+
+	if ((addr < 1) || (addr > 15)) {
+		PRINT(KERN_ERR, ohci->id, __FUNCTION__
+		      ": PHY register address %d out of range", addr);
+		return -EFAULT;
+	}
+
+	spin_lock(&ohci->phy_reg_lock);
+
+	/* initiate read request */
+	reg_write(ohci, OHCI1394_PhyControl, 
+		  ((addr<<8)&0x00000f00) | 0x00008000);
+
+	/* wait */
+	while (!(reg_read(ohci, OHCI1394_PhyControl)&0x80000000) && timeout)
+	  timeout--;
+
+
+	if (!timeout) {
+		PRINT(KERN_ERR, ohci->id, "get_phy_reg timeout !!!\n");
+		spin_unlock(&ohci->phy_reg_lock);
+		return -EFAULT;
+	}
+	r = reg_read(ohci, OHCI1394_PhyControl);
+  
+	spin_unlock(&ohci->phy_reg_lock);
+     
+	return (r&0x00ff0000)>>16;
+}
+
+static int set_phy_reg(struct ti_ohci *ohci, int addr, unsigned char data) {
+	int timeout=10000;
+	u32 r;
+
+	if ((addr < 1) || (addr > 15)) {
+		PRINT(KERN_ERR, ohci->id, __FUNCTION__
+		      ": PHY register address %d out of range", addr);
+		return -EFAULT;
+	}
+
+	r = ((addr<<8)&0x00000f00) | 0x00004000 | ((u32)data & 0x000000ff);
+
+	spin_lock(&ohci->phy_reg_lock);
+
+	reg_write(ohci, OHCI1394_PhyControl, r);
+
+	/* wait */
+	while (!(reg_read(ohci, OHCI1394_PhyControl)&0x80000000) && timeout)
+	  timeout--;
+
+	spin_unlock(&ohci->phy_reg_lock);
+
+	if (!timeout) {
+		PRINT(KERN_ERR, ohci->id, "set_phy_reg timeout !!!\n");
+		return -EFAULT;
+	}
+
+	return 0;
+}
+#endif /* unneeded functions */
+
+inline static int handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host,
+				int phyid, int isroot)
+{
+	quadlet_t *q = ohci->self_id_buffer;
+	quadlet_t self_id_count=reg_read(ohci, OHCI1394_SelfIDCount);
+	size_t size;
+	quadlet_t lsid;
+
+	/* Self-id handling seems much easier than for the aic5800 chip.
+	   All the self-id packets, including this device own self-id,
+	   should be correctly arranged in the self_id_buffer at this
+	   stage */
+
+	/* Check status of self-id reception */
+	if ((self_id_count&0x80000000) || 
+	    ((self_id_count&0x00FF0000) != (q[0]&0x00FF0000))) {
+		PRINT(KERN_ERR, ohci->id, 
+		      "Error in reception of self-id packets");
+		return -1;
+	}    
+
+	size = ((self_id_count&0x0000EFFC)>>2) - 1;
+	q++;
+
+	while (size > 0) {
+		if (q[0] == ~q[1]) {
+			printk("-%d- selfid packet 0x%x rcvd\n", 
+			       ohci->id, q[0]);
+			hpsb_selfid_received(host, q[0]);
+			if (((q[0]&0x3f000000)>>24)==phyid) {
+				lsid=q[0];
+				printk("This node self-id is 0x%08x\n",lsid);
+			}
+		} else {
+			printk("-%d- inconsistent selfid 0x%x/0x%x\n", ohci->id,
+			       q[0], q[1]);
+		}
+		q += 2;
+		size -= 2;
+	}
+
+	printk(" calling self-id complete\n");
+
+	hpsb_selfid_complete(host, phyid, isroot);
+	return 0;
+}
+
+static int ohci_detect(struct hpsb_host_template *tmpl)
+{
+	struct hpsb_host *host;
+	int i;
+
+	init_driver();
+
+	for (i = 0; i < num_of_cards; i++) {
+		host = hpsb_get_host(tmpl, 0);
+		if (host == NULL) {
+			/* simply don't init more after out of mem */
+			return i;
+		}
+		host->hostdata = &cards[i];
+		cards[i].host = host;
+	}
+  
+	return num_of_cards;
+}
+
+static int ohci_soft_reset(struct ti_ohci *ohci) {
+	int timeout=10000;
+
+	reg_write(ohci, OHCI1394_HCControlSet, 0x00010000);
+  
+	while ((reg_read(ohci, OHCI1394_HCControlSet)&0x00010000) && timeout) 
+	  timeout--;
+	if (!timeout) {
+		PRINT(KERN_ERR, ohci->id, "soft reset timeout !!!");
+		return -EFAULT;
+	}
+	else PRINT(KERN_INFO, ohci->id, "soft reset finished");
+	return 0;
+}
+
+static int ohci_initialize(struct hpsb_host *host)
+{
+	struct ti_ohci *ohci=host->hostdata;
+	int retval, i;
+
+	spin_lock_init(&ohci->phy_reg_lock);
+  
+	/* Soft reset */
+	if ((retval=ohci_soft_reset(ohci))<0) return retval;
+  
+	/* Set the bus number */
+	reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
+
+	/* Set Link Power Status (LPS) */
+	reg_write(ohci, OHCI1394_HCControlSet, 0x00080000);
+
+	/* Enable posted writes */
+	reg_write(ohci, OHCI1394_HCControlSet, 0x00040000);
+
+	/* Clear link control register */
+	reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
+  
+	/* Enable cycle timer and cycle master */
+	reg_write(ohci, OHCI1394_LinkControlSet, 0x00300000);
+
+	/* Clear interrupt registers */
+	reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+	reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+
+	/* Set up self-id dma buffer */
+	reg_write(ohci, OHCI1394_SelfIDBuffer, 
+		  virt_to_bus(ohci->self_id_buffer));
+
+	/* enable self-id dma */
+	reg_write(ohci, OHCI1394_LinkControlSet, 0x00000200);
+
+	/* Set the configuration ROM mapping register */
+	reg_write(ohci, OHCI1394_ConfigROMmap, 
+		  virt_to_bus(ohci->csr_config_rom));
+
+#if 1				/* Why is this step necessary ? */
+	/* Write the config ROM header */
+	reg_write(ohci, OHCI1394_ConfigROMhdr,0x04040000);
+
+	/* Set bus options */
+	reg_write(ohci, OHCI1394_BusOptions, 0xf064A002);
+#endif
+
+#if 1
+	/* Accept phy packets into AR request context */ 
+	reg_write(ohci, OHCI1394_LinkControlSet, 0x00000400);
+#endif
+
+	/* Enable link */
+	reg_write(ohci, OHCI1394_HCControlSet, 0x00020000);
+
+	/* Initialize IR dma */
+
+	/* make sure the context isn't running, dead, or active */
+	if (!(reg_read(ohci, OHCI1394_IrRcvContextControlSet) & 0x00008F00)) {
+
+                /* initialize IR program */
+                for (i= 0; i < IR_NUM_DESC; i++) {
+
+			/* end of descriptor list? */
+                        if ((i + 1) < IR_NUM_DESC) {
+                                ohci->IR_recv_prg[i]->control=
+                                        (0x283C << 16) | IR_RECV_BUF_SIZE;
+                                ohci->IR_recv_prg[i]->branchAddress=
+                                        (virt_to_bus(ohci->IR_recv_prg[i + 1])
+                                         & 0xfffffff0) | 0x1;
+                        } else {
+                                ohci->IR_recv_prg[i]->control=
+                                        (0x283C << 16) | IR_RECV_BUF_SIZE;
+                                ohci->IR_recv_prg[i]->branchAddress=
+                                        (virt_to_bus(ohci->IR_recv_prg[0])
+                                         & 0xfffffff0) | 0x1;
+                        }
+
+                        ohci->IR_recv_prg[i]->address=
+                                virt_to_bus(ohci->IR_recv_buf[i]);
+                        ohci->IR_recv_prg[i]->status= IR_RECV_BUF_SIZE;
+		}
+
+		/* Tell the controller where the first IR program is */
+		reg_write(ohci, OHCI1394_IrRcvCommandPtr,
+			  virt_to_bus(ohci->IR_recv_prg[0]) | 0x1 );
+
+		/* Set bufferFill, isochHeader, multichannel for IR context */
+		reg_write(ohci, OHCI1394_IrRcvContextControlSet, 0xd0000000);
+
+		/* Set the context match register to match on all tags */
+		reg_write(ohci, OHCI1394_IrRcvContextMatch, 0xf0000000);
+
+		/* Clear the multi channel mask high and low registers */
+		reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);
+		reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
+
+                /* Set up isoRecvIntMask to generate interrupts for context 0
+                   (thanks to Michael Greger for seeing that I forgot this) */
+                reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 0x00000001);
+
+		/* Run IR context */
+		reg_write(ohci, OHCI1394_IrRcvContextControlSet, 0x00008000);
+	}
+
+	/* Initialize AR dma */
+	ohci->AR_resp_prg->control=0x283C << 16 | AR_RESP_BUF_SIZE;
+	ohci->AR_resp_prg->address=virt_to_bus(ohci->AR_resp_buf);
+	ohci->AR_resp_prg->status=AR_RESP_BUF_SIZE;
+	PRINT(KERN_INFO, ohci->id, "AR control: %x",
+	      ohci->AR_resp_prg->control);
+	PRINT(KERN_INFO, ohci->id, "AR status: %x %d",
+	      ohci->AR_resp_prg->status & 0xffff,
+	      ohci->AR_resp_prg->status & 0xffff);
+
+	/* Tell the controller where the AR program is */
+	reg_write(ohci, OHCI1394_AsRspRcvCommandPtr,
+		  virt_to_bus(ohci->AR_resp_prg)|0x00000001);
+
+#if 1
+        /* Accept phy packets into AR request context */
+        reg_write(ohci, OHCI1394_LinkControlSet, 0x00000400);
+#endif
+
+	/* Run AR context */
+	reg_write(ohci, OHCI1394_AsRspRcvContextControlSet, 0x00008000);
+
+#ifndef __BIG_ENDIAN
+	reg_write(ohci, OHCI1394_HCControlSet, 0x40000000);
+#else
+	reg_write(ohci, OHCI1394_HCControlClear, 0x40000000);
+#endif
+
+	/* Enable interrupts */
+	reg_write(ohci, OHCI1394_IntMaskSet, 
+		  OHCI1394_masterIntEnable | 
+		  OHCI1394_phyRegRcvd | 
+		  OHCI1394_busReset | 
+		  OHCI1394_selfIDComplete |
+		  OHCI1394_RSPkt |
+		  OHCI1394_RQPkt |
+		  OHCI1394_ARRS |
+		  OHCI1394_ARRQ |
+		  OHCI1394_respTxComplete |
+		  OHCI1394_reqTxComplete |
+		  OHCI1394_isochRx
+		  );
+
+	return 1;
+}
+
+static void ohci_remove(struct hpsb_host *host)
+{
+	struct ti_ohci *ohci;
+        
+	if (host != NULL) {
+		ohci = host->hostdata;
+		remove_card(ohci);
+	}
+}
+
+
+/* This must be called with the async_queue_lock held. */
+static void send_next_async(struct ti_ohci *ohci)
+{
+	int i=0;
+	struct hpsb_packet *packet = ohci->async_queue;
+	struct dma_cmd prg;
+	quadlet_t *ptr = (quadlet_t *)ohci->AT_req_prg;
+
+	//HPSB_TRACE();
+
+        /* stop the channel program if it's still running */
+        reg_write(ohci, OHCI1394_AsReqTrContextControlClear, 0x8000);
+   
+        /* Wait until it effectively stops */
+        while (reg_read(ohci, OHCI1394_AsReqTrContextControlSet)
+               & 0x400) {
+                i++;
+                if (i>5000) {
+                        PRINT(KERN_ERR, ohci->id, 
+                              "runaway loop in DmaAT. bailing out...");
+                        break;
+                }
+        };
+
+        if (packet->type == async)
+        {
+
+                /* re-format packet header according to ohci specification */
+                packet->header[1] = (packet->header[1] & 0xFFFF) | 
+                        (packet->header[0] & 0xFFFF0000);
+                packet->header[0] = DMA_SPEED_200 |
+                        (packet->header[0] & 0xFFFF);
+
+                if (packet->data_size) { /* block transmit */
+                        prg.control = OUTPUT_MORE_IMMEDIATE | 0x10;
+                        prg.address = 0;
+                        prg.branchAddress = 0;
+                        prg.status = 0;
+                        memcpy(ohci->AT_req_prg, &prg, 16);
+                        memcpy(ohci->AT_req_prg + 1, packet->header, 16);
+                        prg.control = OUTPUT_LAST | packet->data_size;
+                        prg.address = virt_to_bus(packet->data);
+                        memcpy(ohci->AT_req_prg + 2, &prg, 16);
+
+                        reg_write(ohci, OHCI1394_AsReqTrCommandPtr, 
+                                  virt_to_bus(ohci->AT_req_prg)|0x3);
+                }
+                else { /* quadlet transmit */
+                        prg.control = OUTPUT_LAST_IMMEDIATE |
+                                packet->header_size;
+                        prg.address = 0;
+                        prg.branchAddress = 0;
+                        prg.status = 0;
+                        memcpy(ohci->AT_req_prg, &prg, 16);
+                        memcpy(ohci->AT_req_prg + 1, packet->header, 16);
+
+                        PRINT(KERN_INFO, ohci->id,
+                              "dma_cmd: %08x %08x %08x %08x",
+                              *ptr, *(ptr+1), *(ptr+2), *(ptr+3));
+                        PRINT(KERN_INFO, ohci->id,
+                              "header: %08x %08x %08x %08x",
+                              *(ptr+4), *(ptr+5), *(ptr+6), *(ptr+7));
+
+                        reg_write(ohci, OHCI1394_AsReqTrCommandPtr, 
+                                  virt_to_bus(ohci->AT_req_prg)|0x2);
+                }
+
+        }
+        else if (packet->type == raw)
+        {
+                prg.control = OUTPUT_LAST | packet->data_size;
+                prg.address = virt_to_bus(packet->data);
+                prg.branchAddress = 0;
+                prg.status = 0;
+                memcpy(ohci->AT_req_prg, &prg, 16);
+
+                PRINT(KERN_INFO, ohci->id,
+                      "dma_cmd: %08x %08x %08x %08x",
+                      *ptr, *(ptr+1), *(ptr+2), *(ptr+3));
+
+                reg_write(ohci, OHCI1394_AsReqTrCommandPtr, 
+                          virt_to_bus(ohci->AT_req_prg)|0x2);
+        }
+
+	/* run program */
+	reg_write(ohci, OHCI1394_AsReqTrContextControlSet, 0x00008000);
+}
+
+static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
+{
+	struct ti_ohci *ohci = host->hostdata;
+	struct hpsb_packet *p;
+	unsigned long flags;
+
+	if (packet->data_size >= 4096) {
+		PRINT(KERN_ERR, ohci->id, "transmit packet data too big (%d)",
+		      packet->data_size);
+		return 0;
+	}
+
+	//HPSB_TRACE();
+	packet->xnext = NULL;
+    
+	spin_lock_irqsave(&ohci->async_queue_lock, flags);
+
+	if (ohci->async_queue == NULL) {
+		ohci->async_queue = packet;
+		send_next_async(ohci);
+	} else {
+		p = ohci->async_queue;
+		while (p->xnext != NULL) {
+			p = p->xnext;
+		}
+		
+		p->xnext = packet;
+	}
+    
+	spin_unlock_irqrestore(&ohci->async_queue_lock, flags);
+
+	return 1;
+}
+
+static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
+{
+	struct ti_ohci *ohci = host->hostdata;
+	int retval = 0;
+	unsigned long flags;
+        struct hpsb_packet *packet, *lastpacket;
+	u32 r;
+
+	switch (cmd) {
+	      case RESET_BUS:
+		PRINT(KERN_INFO, ohci->id, "resetting bus on request%s",
+		      (host->attempt_root ? " and attempting to become root"
+		       : ""));
+		r = (host->attempt_root) ? 0x000041ff : 0x0000417f;
+		reg_write(ohci, OHCI1394_PhyControl, r);
+		break;
+
+	      case GET_CYCLE_COUNTER:
+		retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+		break;
+	
+	      case SET_CYCLE_COUNTER:
+		reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg);
+		break;
+	
+	      case SET_BUS_ID:
+		PRINT(KERN_ERR, ohci->id, "devctl command SET_BUS_ID err");
+		break;
+
+	      case ACT_CYCLE_MASTER:
+#if 0
+		if (arg) {
+			/* enable cycleTimer, cycleMaster, cycleSource */
+			reg_write(ohci, OHCI1394_LinkControlSet, 0x00700000);
+		} else {
+			/* disable cycleTimer, cycleMaster, cycleSource */
+			reg_write(ohci, OHCI1394_LinkControlClear, 0x00700000);
+		};
+#endif
+		break;
+
+	      case CANCEL_REQUESTS:
+		spin_lock_irqsave(&ohci->async_queue_lock, flags);
+		/* stop any chip activity */
+		reg_write(ohci, OHCI1394_HCControlClear, 0x00020000);
+                packet = ohci->async_queue;
+		ohci->async_queue = NULL;                
+		spin_unlock_irqrestore(&ohci->async_queue_lock, flags);
+
+                while (packet != NULL) {
+                        lastpacket = packet;
+                        packet = packet->xnext;
+                        hpsb_packet_sent(host, lastpacket, ACKX_ABORTED);
+                }
+
+		break;
+
+              case MODIFY_USAGE:
+                if (arg) {
+                        MOD_INC_USE_COUNT;
+                } else {
+                        MOD_DEC_USE_COUNT;
+                }
+                break;
+
+              case ISO_LISTEN_CHANNEL:
+
+                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+
+                if (!test_and_set_bit(arg, &ohci->IR_channel_usage)) {
+                        PRINT(KERN_INFO, ohci->id,
+                              "listening enabled on channel %d", arg);
+
+                        if (arg > 31) {
+                                u32 setMask= 0x00000001;
+                                arg-= 32;
+                                while(arg--) setMask= setMask << 1;
+                                reg_write(ohci, OHCI1394_IRMultiChanMaskHiSet,
+                                          setMask);
+                        } else {
+                                u32 setMask= 0x00000001;
+                                while(arg--) setMask= setMask << 1;
+                                reg_write(ohci, OHCI1394_IRMultiChanMaskLoSet,
+                                          setMask);
+                        }
+
+                }
+
+                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
+                break;
+
+              case ISO_UNLISTEN_CHANNEL:
+
+                spin_lock_irqsave(&ohci->IR_channel_lock, flags);
+
+                if (test_and_clear_bit(arg, &ohci->IR_channel_usage)) {
+                        PRINT(KERN_INFO, ohci->id,
+                              "listening disabled on iso channel %d", arg);
+
+                        if (arg > 31) {
+                                u32 clearMask= 0x00000001;
+                                arg-= 32;
+                                while(arg--) clearMask= clearMask << 1;
+                                reg_write(ohci,
+                                          OHCI1394_IRMultiChanMaskHiClear,
+                                          clearMask);
+                        } else {
+                                u32 clearMask= 0x00000001;
+                                while(arg--) clearMask= clearMask << 1;
+                                reg_write(ohci,
+                                          OHCI1394_IRMultiChanMaskLoClear,
+                                          clearMask);
+                        }
+
+                }
+
+                spin_unlock_irqrestore(&ohci->IR_channel_lock, flags);
+                break;
+
+	      default:
+		PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet\n",
+			cmd);
+		break;
+	}
+	return retval;
+}
+
+/***************************************
+ * IEEE-1394 functionality section END *
+ ***************************************/
+
+
+/********************************************************
+ * Global stuff (interrupt handler, init/shutdown code) *
+ ********************************************************/
+
+static void ohci_irq_handler(int irq, void *dev_id,
+                             struct pt_regs *regs_are_unused)
+{
+	//int i;
+	static quadlet_t event,node_id;
+	struct ti_ohci *ohci = (struct ti_ohci *)dev_id;
+	struct hpsb_host *host = ohci->host;
+	int phyid = -1, isroot = 0;
+
+	event=reg_read(ohci, OHCI1394_IntEventSet);
+
+	/* Clear the interrupt register */
+	reg_write(ohci, OHCI1394_IntEventClear, event);
+
+	/* PRINT(KERN_INFO, ohci->id, "int event %08X mask %08X",
+	   event,reg_read(ohci, OHCI1394_IntMaskSet)); */
+
+	if (event & OHCI1394_busReset) {
+		PRINT(KERN_INFO, ohci->id, "bus reset interrupt");
+		if (!host->in_bus_reset) {
+			hpsb_bus_reset(host);
+		}
+		ohci->NumBusResets++;
+	}
+	if (event & OHCI1394_reqTxComplete) {
+		PRINT(KERN_INFO, ohci->id, "reqTxComplete int received");
+	}
+	if (event & OHCI1394_RQPkt) {
+		PRINT(KERN_INFO, ohci->id, "RQPkt int received");
+	}
+	if (event & OHCI1394_RQPkt) {
+		PRINT(KERN_INFO, ohci->id, "ControlContext: %08X",
+		      reg_read(ohci, OHCI1394_AsReqRcvContextControlSet));
+	}
+	if (event & OHCI1394_RSPkt) {
+		int rcv_bytes;
+		int i=0;
+
+		/* we calculate the number of received bytes from the
+		   residual count field */
+		rcv_bytes = AR_RESP_BUF_SIZE - 
+		  (ohci->AR_resp_prg->status & 0xFFFF);
+
+		PRINT(KERN_INFO, ohci->id, "AR_status 0x%x %d, %d bytes read", 
+		      ohci->AR_resp_prg->status, 
+		      ohci->AR_resp_prg->status & 0xffff, 
+		      rcv_bytes);
+
+		ohci->AR_resp_active = 0;
+
+		if ((ohci->AR_resp_prg->status & 0x84000000) 
+		    && (ohci->AR_resp_prg->status & 0xFFFF) >= 8 ) {
+			hpsb_packet_received(host, ohci->AR_resp_buf, 
+					     rcv_bytes);
+		} else {
+			//HPSB_TRACE();
+			PRINT(KERN_ERR, ohci->id, 
+			      "AR resp DMA program status value 0x%x is incorrect!",
+			      ohci->AR_resp_prg->status);
+		}
+
+
+		/* --------------- FIXME ---------------------------------
+		   this is a complete hack... we stop the dma prg
+		   and start it again so as to reset the dma buffer address
+		   Very slow, very bad design... to change ASAP */
+		  
+		/* stop the channel program if it's still running */
+		reg_write(ohci, OHCI1394_AsRspRcvContextControlClear, 0x8000);
+   
+		/* Wait until it effectively stops */
+		while (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) 
+		       & 0x400) {
+			i++;
+			if (i>5000) {
+				PRINT(KERN_ERR, ohci->id, 
+				      "runaway loop in DmaAT. bailing out...");
+				break;
+			}
+		}
+
+		reg_write(ohci, OHCI1394_AsRspRcvCommandPtr,
+			  virt_to_bus(ohci->AR_resp_prg)|0x00000001);
+		ohci->AR_resp_prg->status=AR_RESP_BUF_SIZE;
+		reg_write(ohci, OHCI1394_AsRspRcvContextControlSet, 0x8000);
+
+		/* ---------------- end of FIXME --------------------------*/
+	}
+	if (event & OHCI1394_isochRx) {
+		quadlet_t isoRecvIntEvent;
+
+		/* ASSUMPTION: We assume there is only one context for now. */
+
+                spin_lock(&ohci->IR_recv_lock);
+
+                /* Clear the isoRecvIntEvent register (very important!) */
+                isoRecvIntEvent= reg_read(ohci, OHCI1394_IsoRecvIntEventSet);
+		reg_write(ohci, OHCI1394_IsoRecvIntEventClear,
+			  isoRecvIntEvent);
+
+                ohci->IR_buf_used++;
+                ohci->IR_buf_next_ind=
+                        (ohci->IR_buf_next_ind + 1) % IR_NUM_DESC;
+
+                /* is buffer processing too slow? (all buffers used) */
+		if (ohci->IR_buf_next_ind == ohci->IR_buf_last_ind) {
+                        int i= 0;
+
+                        /* stop the context */
+			reg_write(ohci,
+				  OHCI1394_IrRcvContextControlClear, 0x8000);
+
+			while (reg_read(ohci, OHCI1394_IrRcvContextControlSet) 
+			       & 0x400) {
+				i++;
+
+				if (i>5000) {
+					PRINT(KERN_ERR, ohci->id, "runaway loop in DmaIR. bailing out...");
+					break;
+				}
+
+			}
+
+                        spin_unlock(&ohci->IR_recv_lock);
+			PRINT(KERN_ERR, ohci->id,
+                              "iso receive processing too slow... stopped");
+			return;
+		}
+
+                /* reset status field of next descriptor */
+                ohci->IR_recv_prg[ohci->IR_buf_next_ind]->status=
+                        IR_RECV_BUF_SIZE;
+
+                spin_unlock(&ohci->IR_recv_lock);
+
+		/* queue bottom half in immediate queue */
+		queue_task(&ohci->IR_pdl_task, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+	}
+	if (event & OHCI1394_selfIDComplete) {
+		if (host->in_bus_reset) {
+			node_id = reg_read(ohci, OHCI1394_NodeID);
+			if (node_id & 0x8000000) { /* NodeID valid */
+				phyid =  node_id & 0x0000003f;
+				isroot = (node_id & 0x40000000) != 0;
+
+				PRINT(KERN_INFO, ohci->id,
+				      "SelfID process finished (phyid %d, %s)",
+				      phyid, (isroot ? "root" : "not root"));
+
+				handle_selfid(ohci, host, phyid, isroot);
+			}
+			else 
+			  PRINT(KERN_ERR, ohci->id, 
+				"SelfID process finished but NodeID"
+				" not valid: %08X",node_id);
+		} 
+		else PRINT(KERN_INFO, ohci->id, 
+			   "phy reg received without reset\n");
+	}
+	if (event & OHCI1394_phyRegRcvd) {
+#if 0
+		if (host->in_bus_reset) {
+			PRINT(KERN_INFO, ohci->id, "PhyControl: %08X", 
+			      reg_read(ohci, OHCI1394_PhyControl));
+		} else printk("-%d- phy reg received without reset\n",
+			      ohci->id);
+#endif
+	}
+	if (event & OHCI1394_reqTxComplete) { 
+		/* async packet sent - transmitter ready */
+		u32 ack;
+		struct hpsb_packet *packet;
+
+		if (ohci->async_queue) {
+
+			spin_lock(&ohci->async_queue_lock);
+	    
+			ack=reg_read(ohci, OHCI1394_AsReqTrContextControlSet) 
+			  & 0xF;
+
+			packet = ohci->async_queue;
+			ohci->async_queue = packet->xnext;
+	    
+			if (ohci->async_queue != NULL) {
+				send_next_async(ohci);
+			}
+			spin_unlock(&ohci->async_queue_lock);
+			PRINT(KERN_INFO,ohci->id,
+			      "packet sent with ack code %d",ack);
+			hpsb_packet_sent(host, packet, ack);	    
+		} else 
+		  PRINT(KERN_INFO,ohci->id,
+			"packet sent without async_queue (self-id?)");
+
+		ohci->TxRdy++;
+	}
+
+	ohci->NumInterrupts++;
+}
+
+/* This is the bottom half that processes iso receive descriptor buffers. */
+static void ohci_ir_proc_desc(void *data)
+{
+	quadlet_t *buf_ptr;
+	struct ti_ohci *ohci= (struct ti_ohci*)data;
+        int bytes_left, data_length;
+        unsigned int idx;
+        unsigned long flags;
+
+        spin_lock_irqsave(&ohci->IR_recv_lock, flags);
+
+        while(ohci->IR_buf_used > 0)
+        {
+                idx= ohci->IR_buf_last_ind;
+
+                /* check to see if a fatal error occurred */
+                if ((ohci->IR_recv_prg[idx]->status >> 16) & 0x800) {
+                        int i= 0;
+
+                        /* stop the context */
+			reg_write(ohci, OHCI1394_IrRcvContextControlClear,
+                                  0x8000);
+
+			while (reg_read(ohci, OHCI1394_IrRcvContextControlSet) 
+			       & 0x400) {
+				i++;
+
+				if (i > 5000) {
+					PRINT(KERN_ERR, ohci->id, "runaway loop in DmaIR. bailing out...");
+					break;
+				}
+
+			}
+
+                        spin_unlock_irqrestore(&ohci->IR_recv_lock, flags);
+                        PRINT(KERN_ERR, ohci->id,
+                              "fatal iso receive error -- status is %d",
+                              ohci->IR_recv_prg[idx]->status & 0x1F);
+                        return;
+                }
+
+                spin_unlock_irqrestore(&ohci->IR_recv_lock, flags);
+
+                buf_ptr= bus_to_virt(ohci->IR_recv_prg[idx]->address);
+                bytes_left= IR_RECV_BUF_SIZE;
+
+                /* are we processing a split packet from last buffer */
+                if (ohci->IR_sp_bytes_left) {
+
+                        if (!ohci->IR_spb_bytes_used) {
+                                /* packet is in process of being dropped */
+                                if (ohci->IR_sp_bytes_left > bytes_left) {
+                                        ohci->IR_sp_bytes_left-= bytes_left;
+                                        bytes_left= 0;
+                                } else {
+                                        buf_ptr= bus_to_virt((unsigned long)
+                                                &((quadlet_t*)ohci->IR_recv_prg
+                                                [idx]->address)
+                                                [ohci->IR_sp_bytes_left / 4]);
+                                        bytes_left-= ohci->IR_sp_bytes_left;
+                                        ohci->IR_sp_bytes_left= 0;
+                                }
+
+                        } else {
+                                /* packet is being assembled */
+                                if (ohci->IR_sp_bytes_left > bytes_left) {
+                                        memcpy(&ohci->IR_spb
+                                               [ohci->IR_spb_bytes_used / 4],
+                                               buf_ptr, bytes_left);
+                                        ohci->IR_spb_bytes_used+= bytes_left;
+                                        ohci->IR_sp_bytes_left-= bytes_left;
+                                        bytes_left= 0;
+                                } else {
+                                        memcpy(&ohci->IR_spb
+                                               [ohci->IR_spb_bytes_used / 4],
+                                               buf_ptr,
+                                               ohci->IR_sp_bytes_left);
+                                        ohci->IR_spb_bytes_used+=
+                                                ohci->IR_sp_bytes_left;
+                                        hpsb_packet_received(ohci->host,
+                                                      ohci->IR_spb,
+                                                      ohci->IR_spb_bytes_used);
+                                        buf_ptr=
+                                                bus_to_virt((unsigned long)
+					       &((quadlet_t*)ohci->IR_recv_prg
+						 [idx]->address)
+					         [ohci->IR_sp_bytes_left / 4]);
+                                        bytes_left-= ohci->IR_sp_bytes_left;
+                                        ohci->IR_sp_bytes_left= 0;
+                                        ohci->IR_spb_bytes_used= 0;
+                                }
+
+                        }
+
+                }
+
+                while(bytes_left > 0) {
+                        data_length= (int)((buf_ptr[0] >> 16) & 0xffff);
+
+                        if (data_length % 4)
+                                data_length+= 4 - (data_length % 4);
+
+                        /* is this a split packet? */
+                        if ( (bytes_left - (data_length + 8)) < 0 ) {
+
+                                if ( (data_length + 8) <=
+                                     IR_SPLIT_PACKET_BUF_SIZE ) {
+                                        memcpy(ohci->IR_spb, buf_ptr,
+                                               bytes_left);
+                                        ohci->IR_spb_bytes_used= bytes_left;
+                                } else {
+                                        PRINT(KERN_ERR, ohci->id, "Packet too large for split packet buffer... dropping it");
+                                        PRINT(KERN_DEBUG, ohci->id, "Header: %8.8x\n", buf_ptr[0]);
+                                        ohci->IR_spb_bytes_used= 0;
+                                }
+
+                                ohci->IR_sp_bytes_left=
+                                        (data_length + 8) - bytes_left;
+                        } else {
+                                hpsb_packet_received(ohci->host, buf_ptr,
+                                                     (data_length + 8));
+                                buf_ptr= bus_to_virt((unsigned long)
+                                               &((quadlet_t*)ohci->IR_recv_prg
+                                                [idx]->address)
+                                                [(IR_RECV_BUF_SIZE - bytes_left
+                                                  + data_length + 8) / 4]);
+                        }
+
+                        bytes_left-= (data_length + 8);
+                }
+
+                spin_lock_irqsave(&ohci->IR_recv_lock, flags);
+                ohci->IR_buf_last_ind= (idx + 1) % IR_NUM_DESC;
+                ohci->IR_buf_used--;
+        }
+
+        spin_unlock_irqrestore(&ohci->IR_recv_lock, flags);
+}
+
+static int add_card(struct pci_dev *dev)
+{
+#define FAIL(fmt, args...) \
+	PRINT_G(KERN_ERR, fmt , ## args); \
+	  num_of_cards--; \
+	    remove_card(ohci); \
+	      return 1;
+
+	struct ti_ohci *ohci;	/* shortcut to currently handled device */
+	int i;
+
+	if (num_of_cards == MAX_OHCI1394_CARDS) {
+		PRINT_G(KERN_WARNING, "cannot handle more than %d cards.  "
+			"Adjust MAX_OHCI1394_CARDS in ti_ohci1394.h.",
+			MAX_OHCI1394_CARDS);
+		return 1;
+	}
+
+	ohci = &cards[num_of_cards++];
+
+	ohci->id = num_of_cards-1;
+	ohci->dev = dev;
+	
+	ohci->state = 0;
+
+	if (!request_irq(dev->irq, ohci_irq_handler, SA_SHIRQ,
+			 OHCI1394_DRIVER_NAME, ohci)) {
+		PRINT(KERN_INFO, ohci->id, "allocated interrupt %d", dev->irq);
+	} else {
+		FAIL("failed to allocate shared interrupt %d", dev->irq);
+	}
+
+	/* csr_config rom allocation */
+	ohci->csr_config_rom = kmalloc(1024, GFP_KERNEL);
+	if (ohci->csr_config_rom == NULL) {
+		FAIL("failed to allocate buffer config rom");
+	}
+	memcpy(ohci->csr_config_rom, ohci_csr_rom, sizeof(ohci_csr_rom));
+
+	/* self-id dma buffer allocation */
+	ohci->self_id_buffer = kmalloc(2048, GFP_KERNEL);
+	if (ohci->self_id_buffer == NULL) {
+		FAIL("failed to allocate DMA buffer for self-id packets");
+	}
+
+	/* AR dma buffer allocation */
+	ohci->AR_resp_buf = kmalloc(AR_RESP_BUF_SIZE, GFP_KERNEL);
+	if (ohci->AR_resp_buf != NULL) {
+		memset(ohci->AR_resp_buf, 0, AR_RESP_BUF_SIZE);
+	} else {
+		FAIL("failed to allocate AR response DMA buffer");
+	}
+
+	/* AR dma program allocation */
+	ohci->AR_resp_prg = (struct dma_cmd *) kmalloc(AR_RESP_PRG_SIZE, 
+						       GFP_KERNEL);
+	if (ohci->AR_resp_prg != NULL) {
+		memset(ohci->AR_resp_prg, 0, AR_RESP_PRG_SIZE);
+	} else {
+		FAIL("failed to allocate AR response DMA program");
+	}
+
+	/* AT dma program allocation */
+	ohci->AT_req_prg = (struct dma_cmd *) kmalloc(AT_REQ_PRG_SIZE, 
+						      GFP_KERNEL);
+	if (ohci->AT_req_prg != NULL) {
+		memset(ohci->AT_req_prg, 0, AT_REQ_PRG_SIZE);
+	} else {
+		FAIL("failed to allocate AT request DMA program");
+	}
+
+	/* IR dma buffer and program allocation */
+	ohci->IR_recv_buf=
+		kmalloc(IR_NUM_DESC * sizeof(quadlet_t*),
+			GFP_KERNEL);
+
+	if (ohci->IR_recv_buf == NULL) {
+		FAIL("failed to allocate IR receive DMA buffer");
+	}
+
+	ohci->IR_recv_prg=
+		kmalloc(IR_NUM_DESC * sizeof(struct dma_cmd*),
+			GFP_KERNEL);
+
+	if (ohci->IR_recv_prg == NULL) {
+		FAIL("failed to allocate IR receive DMA program");
+	}
+
+	ohci->IR_spb= kmalloc(IR_SPLIT_PACKET_BUF_SIZE, GFP_KERNEL);
+
+	if (ohci->IR_spb == NULL) {
+		FAIL("failed to allocate IR split packet buffer");
+	}
+
+	for (i= 0; i < IR_NUM_DESC; i++) {
+                ohci->IR_recv_buf[i]= kmalloc(IR_RECV_BUF_SIZE, GFP_KERNEL);
+
+                if (ohci->IR_recv_buf[i] != NULL) {
+                        memset(ohci->IR_recv_buf[i], 0, IR_RECV_BUF_SIZE);
+                } else {
+                        FAIL("failed to allocate IR DMA buffer");
+                }
+
+                ohci->IR_recv_prg[i]= kmalloc(sizeof(struct dma_cmd),
+                                              GFP_KERNEL);
+
+                if (ohci->IR_recv_prg[i] != NULL) {
+                        memset(ohci->IR_recv_prg[i], 0,
+                               sizeof(struct dma_cmd));
+                } else {
+                        FAIL("failed to allocate IR DMA buffer");
+                }
+
+	}
+
+        ohci->IR_buf_used= 0;
+        ohci->IR_buf_last_ind= 0;
+        ohci->IR_buf_next_ind= 0;
+        spin_lock_init(&ohci->IR_recv_lock);
+        spin_lock_init(&ohci->IR_channel_lock);
+        ohci->IR_channel_usage= 0x0000000000000000;
+
+        /* initialize iso receive task */
+        ohci->IR_pdl_task.routine= ohci_ir_proc_desc;
+        ohci->IR_pdl_task.data= (void*)ohci;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
+	ohci->registers = ioremap_nocache(dev->base_address[0],
+					  OHCI1394_REGISTER_SIZE);
+#else
+	ohci->registers = ioremap_nocache(dev->resource[0].start,
+					  OHCI1394_REGISTER_SIZE);
+#endif
+
+	if (ohci->registers == NULL) {
+		FAIL("failed to remap registers - card not accessible");
+	}
+
+	PRINT(KERN_INFO, ohci->id, "remapped memory spaces reg 0x%p",
+	      ohci->registers);
+
+	return 0;
+#undef FAIL
+}
+
+#ifdef CONFIG_PROC_FS
+
+#define SR(fmt, reg0, reg1, reg2)\
+p += sprintf(p,fmt,reg_read(ohci, reg0),\
+	       reg_read(ohci, reg1),reg_read(ohci, reg2));
+
+int ohci_get_info(char *buf, char **start, off_t fpos, 
+		  int length, int dummy)
+{
+	struct ti_ohci *ohci=&cards[0];
+	struct hpsb_host *host=ohci->host;
+	char *p=buf;
+	//unsigned char phyreg;
+	//int i, nports;
+	int i;
+
+	p += sprintf(p,"IEEE-1394 OHCI Driver status report:\n");
+	p += sprintf(p,"  bus number: 0x%x Node ID: 0x%x\n", 
+		     (reg_read(ohci, OHCI1394_NodeID) & 0xFFC0) >> 6, 
+		     reg_read(ohci, OHCI1394_NodeID)&0x3f);
+#if 0
+	p += sprintf(p,"  hardware version %d.%d GUID_ROM is %s\n\n", 
+		     (reg_read(ohci, OHCI1394_Version) & 0xFF0000) >>16, 
+		     reg_read(ohci, OHCI1394_Version) & 0xFF,
+		     (reg_read(ohci, OHCI1394_Version) & 0x01000000) 
+		     ? "set" : "clear");
+#endif
+	p += sprintf(p,"\n### Host data ###\n");
+	p += sprintf(p,"node_count: %8d  ",host->node_count);
+	p += sprintf(p,"node_id   : %08X\n",host->node_id);
+	p += sprintf(p,"irm_id    : %08X  ",host->irm_id);
+	p += sprintf(p,"busmgr_id : %08X\n",host->busmgr_id);
+	p += sprintf(p,"%s %s %s\n",
+		     host->initialized ? "initialized" : "",
+		     host->in_bus_reset ? "in_bus_reset" : "",
+		     host->attempt_root ? "attempt_root" : "");
+	p += sprintf(p,"%s %s %s %s\n",
+		     host->is_root ? "root" : "",
+		     host->is_cycmst ? "cycle_master" : "",
+		     host->is_irm ? "iso_res_mgr" : "",
+		     host->is_busmgr ? "bus_mgr" : "");
+  
+	p += sprintf(p,"\n### ohci data ###\n");
+	p += sprintf(p,"AR_resp_buf : %p  AR_resp_prg: %p\n",
+		     ohci->AR_resp_buf, ohci->AR_resp_prg);
+
+        for (i= 0; i < IR_NUM_DESC; i++) {
+                p += sprintf(p, "IR_recv_buf[%d] : %p  IR_recv_prg[%d]: %p\n",
+                             i, ohci->IR_recv_buf[i], i, ohci->IR_recv_prg[i]);
+	}
+
+	/* ----- Register Dump ----- */
+	p += sprintf(p,"\n### HC Register dump ###\n");
+	SR("Version     : %08x  GUID_ROM    : %08x  ATRetries   : %08x\n",
+	   OHCI1394_Version, OHCI1394_GUID_ROM, OHCI1394_ATRetries);
+	SR("CSRReadData : %08x  CSRCompData : %08x  CSRControl  : %08x\n",
+	   OHCI1394_CSRReadData, OHCI1394_CSRCompareData, OHCI1394_CSRControl);
+	SR("ConfigROMhdr: %08x  BusID       : %08x  BusOptions  : %08x\n",
+	   OHCI1394_ConfigROMhdr, OHCI1394_BusID, OHCI1394_BusOptions);
+	SR("GUIDHi      : %08x  GUIDLo      : %08x  ConfigROMmap: %08x\n",
+	   OHCI1394_GUIDHi, OHCI1394_GUIDLo, OHCI1394_ConfigROMmap);
+	SR("PtdWrAddrLo : %08x  PtdWrAddrHi : %08x  VendorID    : %08x\n",
+	   OHCI1394_PostedWriteAddressLo, OHCI1394_PostedWriteAddressHi, 
+	   OHCI1394_VendorID);
+	SR("HCControl   : %08x  SelfIDBuffer: %08x  SelfIDCount : %08x\n",
+	   OHCI1394_HCControlSet, OHCI1394_SelfIDBuffer, OHCI1394_SelfIDCount);
+	SR("IRMuChMaskHi: %08x  IRMuChMaskLo: %08x  IntEvent    : %08x\n",
+	   OHCI1394_IRMultiChanMaskHiSet, OHCI1394_IRMultiChanMaskLoSet, 
+	   OHCI1394_IntEventSet);
+	SR("IntMask     : %08x  IsoXmIntEvnt: %08x  IsoXmIntMask: %08x\n",
+	   OHCI1394_IntMaskSet, OHCI1394_IsoXmitIntEventSet, 
+	   OHCI1394_IsoXmitIntMaskSet);
+	SR("IsoRcvIntEvt: %08x  IsoRcvIntMsk: %08x  FairnessCtrl: %08x\n",
+	   OHCI1394_IsoRecvIntEventSet, OHCI1394_IsoRecvIntMaskSet, 
+	   OHCI1394_FairnessControl);
+	SR("LinkControl : %08x  NodeID      : %08x  PhyControl  : %08x\n",
+	   OHCI1394_LinkControlSet, OHCI1394_NodeID, OHCI1394_PhyControl);
+	SR("IsoCyclTimer: %08x  AsRqFilterHi: %08x  AsRqFilterLo: %08x\n",
+	   OHCI1394_IsochronousCycleTimer, 
+	   OHCI1394_AsReqFilterHiSet, OHCI1394_AsReqFilterLoSet);
+	SR("PhyReqFiltHi: %08x  PhyReqFiltLo: %08x  PhyUpperBnd : %08x\n",
+	   OHCI1394_PhyReqFilterHiSet, OHCI1394_PhyReqFilterLoSet, 
+	   OHCI1394_PhyUpperBound);
+	SR("AsRqTrCxtCtl: %08x  AsRqTrCmdPtr: %08x  AsRsTrCtxCtl: %08x\n",
+	   OHCI1394_AsReqTrContextControlSet, OHCI1394_AsReqTrCommandPtr, 
+	   OHCI1394_AsRspTrContextControlSet);
+	SR("AsRsTrCmdPtr: %08x  AsRqRvCtxCtl: %08x  AsRqRvCmdPtr: %08x\n",
+	   OHCI1394_AsRspTrCommandPtr, OHCI1394_AsReqRcvContextControlSet,
+	   OHCI1394_AsReqRcvCommandPtr);
+	SR("AsRsRvCtxCtl: %08x  AsRsRvCmdPtr: %08x  IntEvent    : %08x\n",
+	   OHCI1394_AsRspRcvContextControlSet, OHCI1394_AsRspRcvCommandPtr, 
+	   OHCI1394_IntEventSet);
+	
+#if 0
+	p += sprintf(p,"\n### Phy Register dump ###\n");
+	phyreg=get_phy_reg(ohci,1);
+	p += sprintf(p,"offset: %d val: 0x%02x -> RHB: %d IBR: %d Gap_count: %d\n",
+		     1,phyreg,(phyreg&0x80) != 0, (phyreg&0x40) !=0, phyreg&0x3f);
+	phyreg=get_phy_reg(ohci,2);
+	nports=phyreg&0x1f;
+	p += sprintf(p,"offset: %d val: 0x%02x -> SPD: %d E  : %d Ports    : %2d\n",
+		     2,phyreg,
+		     (phyreg&0xC0)>>6, (phyreg&0x20) !=0, nports);
+	for (i=0;i<nports;i++) {
+		phyreg=get_phy_reg(ohci,3+i);
+		p += sprintf(p,"offset: %d val: 0x%02x -> [port %d] TPA: %d TPB: %d | %s %s\n",
+			     3+i,phyreg,
+			     i, (phyreg&0xC0)>>6, (phyreg&0x30)>>4,
+			     (phyreg&0x08) ? "child" : "parent",
+			     (phyreg&0x04) ? "connected" : "disconnected");
+	}
+	phyreg=get_phy_reg(ohci,3+i);
+	p += sprintf(p,"offset: %d val: 0x%02x -> ENV: %s Reg_count: %d\n",
+		     3+i,phyreg,
+		     (((phyreg&0xC0)>>6)==0) ? "backplane" :
+		     (((phyreg&0xC0)>>6)==1) ? "cable" : "reserved",
+		     phyreg&0x3f);
+#endif
+
+	p += sprintf(p,"AR_resp_prg ctrl: %08x\n",ohci->AR_resp_prg->control);
+	p += sprintf(p,"AR_resp_prg status: %08x\n",ohci->AR_resp_prg->status);
+
+	return  p - buf;
+}
+
+struct proc_dir_entry ohci_proc_entry = 
+{
+	0,			/* Inode number - dynamic */
+	8,			/* Length of the file name */
+	"ohci1394",		/* The file name */
+	S_IFREG | S_IRUGO,	/* File mode */
+	1,			/* Number of links */
+	0, 0,			/* The uid and gid for the file */
+	0,			/* The size of the file reported by ls. */
+	NULL,			/* functions which can be done on the inode */
+	ohci_get_info,		/* The read function for this file */
+	NULL
+}; 
+#endif
+
+static void remove_card(struct ti_ohci *ohci)
+{
+	if (ohci->registers) 
+	  iounmap(ohci->registers);
+	if (ohci->AR_resp_buf) 
+	  kfree(ohci->AR_resp_buf);
+	if (ohci->AR_resp_prg) 
+	  kfree(ohci->AR_resp_prg);
+	if (ohci->AT_req_prg) 
+	  kfree(ohci->AT_req_prg);
+	if (ohci->IR_recv_buf) {
+		int i;
+                for (i= 0; i < IR_NUM_DESC; i++) {
+			kfree(ohci->IR_recv_buf[i]);
+		}
+		kfree(ohci->IR_recv_buf);
+	}
+	if (ohci->IR_recv_prg) {
+		int i;
+		for (i= 0; i < IR_NUM_DESC; i++) {
+			kfree(ohci->IR_recv_prg[i]);
+		}
+		kfree(ohci->IR_recv_prg);
+	}
+	kfree(ohci->IR_spb);
+	if (ohci->self_id_buffer)
+	  kfree(ohci->self_id_buffer);
+	if (ohci->csr_config_rom)
+	  kfree(ohci->csr_config_rom);
+
+	free_irq(ohci->dev->irq, ohci);
+
+	ohci->state = 0;
+}
+
+static int init_driver()
+{
+	struct pci_dev *dev = NULL;
+	int success = 0;
+	int i;
+
+	if (num_of_cards) {
+		PRINT_G(KERN_DEBUG, __PRETTY_FUNCTION__ " called again");
+		return 0;
+	}
+
+	PRINT_G(KERN_INFO, "looking for Ohci1394 cards");
+
+	for (i = 0; supported_chips[i][0] != -1; i++) {
+	    while ((dev = pci_find_device(supported_chips[i][0],
+					  supported_chips[i][1], dev)) 
+		   != NULL) {
+		if (add_card(dev) == 0) {
+		    success = 1;
+		}
+	    }
+	}
+
+	if (success == 0) {
+		PRINT_G(KERN_WARNING, "no operable Ohci1394 cards found");
+		return -ENXIO;
+	}
+
+#ifdef CONFIG_PROC_FS
+	if (proc_register(&proc_root, &ohci_proc_entry)) {
+		PRINT_G(KERN_ERR, "unable to register proc file\n");
+		return -EIO;
+	}
+#endif
+	return 0;
+}
+
+static size_t get_ohci_rom(struct hpsb_host *host, const quadlet_t **ptr)
+{
+	struct ti_ohci *ohci=host->hostdata;
+
+#if 0
+	PRINT(KERN_INFO, ohci->id, "request csr_rom address: %08X",
+	      (u32)ohci->csr_config_rom);
+#endif
+
+	*ptr = ohci->csr_config_rom;
+	return sizeof(ohci_csr_rom);
+}
+
+struct hpsb_host_template *get_ohci_template(void)
+{
+	static struct hpsb_host_template tmpl;
+	static int initialized = 0;
+
+	if (!initialized) {
+		/* Initialize by field names so that a template structure
+		 * reorganization does not influence this code. */
+		tmpl.name = "ohci1394";
+                
+		tmpl.detect_hosts = ohci_detect;
+		tmpl.initialize_host = ohci_initialize;
+		tmpl.release_host = ohci_remove;
+		tmpl.get_rom = get_ohci_rom;
+		tmpl.transmit_packet = ohci_transmit;
+		tmpl.devctl = ohci_devctl;
+
+		initialized = 1;
+	}
+
+	return &tmpl;
+}
+
+
+#ifdef MODULE
+
+/* EXPORT_NO_SYMBOLS; */
+
+MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>");
+MODULE_DESCRIPTION("driver for PCI Ohci IEEE-1394 controller");
+MODULE_SUPPORTED_DEVICE("ohci1394");
+
+void cleanup_module(void)
+{
+	hpsb_unregister_lowlevel(get_ohci_template());
+#ifdef CONFIG_PROC_FS
+	proc_unregister(&proc_root, ohci_proc_entry.low_ino);
+#endif
+	PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module\n");
+}
+
+int init_module(void)
+{
+
+	if (hpsb_register_lowlevel(get_ohci_template())) {
+		PRINT_G(KERN_ERR, "registering failed\n");
+		return -ENXIO;
+	} else {
+		return 0;
+	}
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/ohci1394.h linux/drivers/ieee1394/ohci1394.h
--- v2.3.39/linux/drivers/ieee1394/ohci1394.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/ohci1394.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,290 @@
+
+#ifndef _OHCI1394_H
+#define _OHCI1394_H
+
+#include "ieee1394_types.h"
+
+#define OHCI1394_DRIVER_NAME      "ohci1394"
+
+#ifndef PCI_DEVICE_ID_TI_OHCI1394
+#define PCI_DEVICE_ID_TI_OHCI1394 0x8009
+#endif 
+
+#ifndef PCI_DEVICE_ID_TI_OHCI1394_2
+#define PCI_DEVICE_ID_TI_OHCI1394_2 0x8019
+#endif
+
+#ifndef PCI_DEVICE_ID_VIA_OHCI1394
+#define PCI_DEVICE_ID_VIA_OHCI1394 0x3044
+#endif
+
+#define MAX_OHCI1394_CARDS        4
+
+#define AR_RESP_BUF_SIZE          4096
+#define AR_RESP_PRG_SIZE          256
+#define AT_REQ_PRG_SIZE           256
+
+#define IR_RECV_BUF_SIZE          4096 /* 4096 bytes/buffer */
+#define IR_SPLIT_PACKET_BUF_SIZE  8192 /* size of buffer for split packets */
+#define IR_NUM_DESC               16   /* number of ISO recv descriptors */
+
+struct dma_cmd {
+        u32 control;
+        u32 address;
+        u32 branchAddress;
+        u32 status;
+};
+
+struct ti_ohci {
+        int id; /* sequential card number */
+
+        struct pci_dev *dev;
+
+        u32 state;
+        
+        /* remapped memory spaces */
+        void *registers; 
+
+        quadlet_t *self_id_buffer; /* dma buffer for self-id packets */
+        quadlet_t *csr_config_rom; /* buffer for csr config rom */
+
+        /* asynchronous receive */
+        struct dma_cmd *AR_resp_prg;
+        quadlet_t *AR_resp_buf;
+
+        /* asynchronous transmit */
+        struct dma_cmd *AT_req_prg;
+
+        /* isochronous receive */
+        struct dma_cmd **IR_recv_prg;
+        quadlet_t **IR_recv_buf;
+        unsigned int IR_buf_used;
+        unsigned int IR_buf_last_ind;
+        unsigned int IR_buf_next_ind;
+        spinlock_t IR_recv_lock;
+
+        /* iso recv split packet handling */
+        quadlet_t *IR_spb;
+        unsigned int IR_sp_bytes_left;
+        unsigned int IR_spb_bytes_used;
+
+        /* iso receive channel usage */
+        spinlock_t IR_channel_lock;
+        u64 IR_channel_usage;
+
+        /* iso receive task */
+        struct tq_struct IR_pdl_task;
+
+        /* IEEE-1394 part follows */
+        struct hpsb_host *host;
+
+        int phyid, isroot;
+
+        spinlock_t phy_reg_lock;
+
+        struct hpsb_packet *async_queue;
+        spinlock_t async_queue_lock;
+
+        int AR_resp_active;
+        int NumBusResets;
+        int TxRdy;
+        int NumInterrupts;
+};
+
+
+/*
+ * Register read and write helper functions.
+ */
+inline static void reg_write(const struct ti_ohci *ohci, int offset, u32 data)
+{
+        writel(data, ohci->registers + offset);
+}
+
+inline static u32 reg_read(const struct ti_ohci *ohci, int offset)
+{
+        return readl(ohci->registers + offset);
+}
+
+/* This structure is not properly initialized ... it is taken from
+   the lynx_csr_rom written by Andreas ... Some fields in the root
+   directory and the module dependent info needs to be modified
+   I do not have the proper doc */
+quadlet_t ohci_csr_rom[] = {
+        /* bus info block */
+        0x04040000, /* info/CRC length, CRC */
+        0x31333934, /* 1394 magic number */
+        0xf064a000, /* misc. settings - FIXME */
+        0x08002856, /* vendor ID, chip ID high */
+        0x0000083E, /* chip ID low */
+        /* root directory - FIXME */
+        0x00090000, /* CRC length, CRC */
+        0x03080028, /* vendor ID (Texas Instr.) */
+        0x81000009, /* offset to textual ID */
+        0x0c000200, /* node capabilities */
+        0x8d00000e, /* offset to unique ID */
+        0xc7000010, /* offset to module independent info */
+        0x04000000, /* module hardware version */
+        0x81000026, /* offset to textual ID */
+        0x09000000, /* node hardware version */
+        0x81000026, /* offset to textual ID */
+        /* module vendor ID textual */
+        0x00080000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54455841, /* "Texas Instruments" */
+        0x5320494e,
+        0x53545255,
+        0x4d454e54,
+        0x53000000,
+        /* node unique ID leaf */
+        0x00020000, /* CRC length, CRC */
+        0x08002856, /* vendor ID, chip ID high */
+        0x0000083E, /* chip ID low */
+        /* module dependent info - FIXME */
+        0x00060000, /* CRC length, CRC */
+        0xb8000006, /* ??? offset to module textual ID */
+        0x81000004, /* ??? textual descriptor */
+        0x00000000, /* SRAM size */
+        0x00000000, /* AUXRAM size */
+        0x00000000, /* AUX device */
+        /* module textual ID */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54534231, /* "TSB12LV22" */
+        0x324c5632,
+        0x32000000,
+        /* part number */
+        0x00060000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x39383036, /* "9806000-0001" */
+        0x3030342d,
+        0x30303431,
+        0x20000001,
+        /* module hardware version textual */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x5453424b, /* "TSBKOHCI403" */
+        0x4f484349,
+        0x34303300,
+        /* node hardware version textual */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54534234, /* "TSB41LV03" */
+        0x314c5630,
+        0x33000000
+};
+
+
+/* 2 KiloBytes of register space */
+#define OHCI1394_REGISTER_SIZE                0x800       
+
+/* register map */
+#define OHCI1394_Version                      0x000
+#define OHCI1394_GUID_ROM                     0x004
+#define OHCI1394_ATRetries                    0x008
+#define OHCI1394_CSRReadData                  0x00C
+#define OHCI1394_CSRCompareData               0x010
+#define OHCI1394_CSRControl                   0x014
+#define OHCI1394_ConfigROMhdr                 0x018
+#define OHCI1394_BusID                        0x01C
+#define OHCI1394_BusOptions                   0x020
+#define OHCI1394_GUIDHi                       0x024
+#define OHCI1394_GUIDLo                       0x028
+#define OHCI1394_ConfigROMmap                 0x034
+#define OHCI1394_PostedWriteAddressLo         0x038
+#define OHCI1394_PostedWriteAddressHi         0x03C
+#define OHCI1394_VendorID                     0x040
+#define OHCI1394_HCControlSet                 0x050
+#define OHCI1394_HCControlClear               0x054
+#define OHCI1394_SelfIDBuffer                 0x064
+#define OHCI1394_SelfIDCount                  0x068
+#define OHCI1394_IRMultiChanMaskHiSet         0x070
+#define OHCI1394_IRMultiChanMaskHiClear       0x074
+#define OHCI1394_IRMultiChanMaskLoSet         0x078
+#define OHCI1394_IRMultiChanMaskLoClear       0x07C
+#define OHCI1394_IntEventSet                  0x080
+#define OHCI1394_IntEventClear                0x084
+#define OHCI1394_IntMaskSet                   0x088
+#define OHCI1394_IntMaskClear                 0x08C
+#define OHCI1394_IsoXmitIntEventSet           0x090
+#define OHCI1394_IsoXmitIntEventClear         0x094
+#define OHCI1394_IsoXmitIntMaskSet            0x098
+#define OHCI1394_IsoXmitIntMaskClear          0x09C
+#define OHCI1394_IsoRecvIntEventSet           0x0A0
+#define OHCI1394_IsoRecvIntEventClear         0x0A4
+#define OHCI1394_IsoRecvIntMaskSet            0x0A8
+#define OHCI1394_IsoRecvIntMaskClear          0x0AC
+#define OHCI1394_FairnessControl              0x0DC
+#define OHCI1394_LinkControlSet               0x0E0
+#define OHCI1394_LinkControlClear             0x0E4
+#define OHCI1394_NodeID                       0x0E8
+#define OHCI1394_PhyControl                   0x0EC
+#define OHCI1394_IsochronousCycleTimer        0x0F0
+#define OHCI1394_AsReqFilterHiSet             0x100
+#define OHCI1394_AsReqFilterHiClear           0x104
+#define OHCI1394_AsReqFilterLoSet             0x108
+#define OHCI1394_AsReqFilterLoClear           0x10C
+#define OHCI1394_PhyReqFilterHiSet            0x110
+#define OHCI1394_PhyReqFilterHiClear          0x114
+#define OHCI1394_PhyReqFilterLoSet            0x118
+#define OHCI1394_PhyReqFilterLoClear          0x11C
+#define OHCI1394_PhyUpperBound                0x120
+#define OHCI1394_AsReqTrContextControlSet     0x180
+#define OHCI1394_AsReqTrContextControlClear   0x184
+#define OHCI1394_AsReqTrCommandPtr            0x18C
+#define OHCI1394_AsRspTrContextControlSet     0x1A0
+#define OHCI1394_AsRspTrContextControlClear   0x1A4
+#define OHCI1394_AsRspTrCommandPtr            0x1AC
+#define OHCI1394_AsReqRcvContextControlSet    0x1C0
+#define OHCI1394_AsReqRcvContextControlClear  0x1C4
+#define OHCI1394_AsReqRcvCommandPtr           0x1CC
+#define OHCI1394_AsRspRcvContextControlSet    0x1E0
+#define OHCI1394_AsRspRcvContextControlClear  0x1E4
+#define OHCI1394_AsRspRcvCommandPtr           0x1EC
+
+/* Isochronous receive registers */
+/* Add (32 * n) for context n */
+#define OHCI1394_IrRcvContextControlSet       0x400
+#define OHCI1394_IrRcvContextControlClear     0x404
+#define OHCI1394_IrRcvCommandPtr              0x40C
+#define OHCI1394_IrRcvContextMatch            0x410
+
+/* Interrupts Mask/Events */
+
+#define OHCI1394_reqTxComplete           0x00000001
+#define OHCI1394_respTxComplete          0x00000002
+#define OHCI1394_ARRQ                    0x00000004
+#define OHCI1394_ARRS                    0x00000008
+#define OHCI1394_RQPkt                   0x00000010
+#define OHCI1394_RSPkt                   0x00000020
+#define OHCI1394_isochTx                 0x00000040
+#define OHCI1394_isochRx                 0x00000080
+#define OHCI1394_postedWriteErr          0x00001000
+#define OHCI1394_lockRespErr             0x00002000
+#define OHCI1394_selfIDComplete          0x00010000
+#define OHCI1394_busReset                0x00020000
+#define OHCI1394_phy                     0x00080000
+#define OHCI1394_cycleSynch              0x00100000
+#define OHCI1394_cycle64Seconds          0x00200000
+#define OHCI1394_cycleLost               0x00400000
+#define OHCI1394_cycleInconsistent       0x00800000
+#define OHCI1394_unrecoverableError      0x01000000
+#define OHCI1394_cycleTooLong            0x02000000
+#define OHCI1394_phyRegRcvd              0x04000000
+#define OHCI1394_masterIntEnable         0x80000000
+
+#define OUTPUT_MORE                      0x00000000
+#define OUTPUT_MORE_IMMEDIATE            0x02000000
+#define OUTPUT_LAST                      0x103c0000
+#define OUTPUT_LAST_IMMEDIATE            0x123c0000
+
+#define DMA_SPEED_100                    0x0
+#define DMA_SPEED_200                    0x1
+#define DMA_SPEED_400                    0x2
+
+#endif
+
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/pcilynx.c linux/drivers/ieee1394/pcilynx.c
--- v2.3.39/linux/drivers/ieee1394/pcilynx.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/pcilynx.c	Mon Jan 17 22:22:52 2000
@@ -0,0 +1,1469 @@
+/*
+ * ti_pcilynx.c - Texas Instruments PCILynx driver
+ * Copyright (C) 1999,2000 Andreas Bombe <andreas.bombe@munich.netsurf.de>,
+ *                         Stephan Linz <linz@mazet.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 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.
+ */
+
+/*
+ * Lynx DMA usage:
+ *
+ * 0 is used for Lynx local bus transfers
+ * 1 is async/selfid receive
+ * 2 is iso receive
+ * 3 is async transmit
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <asm/byteorder.h>
+#include <asm/atomic.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "ieee1394.h"
+#include "ieee1394_types.h"
+#include "hosts.h"
+#include "ieee1394_core.h"
+#include "pcilynx.h"
+
+
+#if MAX_PCILYNX_CARDS > PCILYNX_MINOR_ROM_START
+#error Max number of cards is bigger than PCILYNX_MINOR_ROM_START - this does not work.
+#endif
+
+/* print general (card independent) information */
+#define PRINT_G(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args)
+/* print card specific information */
+#define PRINT(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args)
+
+
+static struct ti_lynx cards[MAX_PCILYNX_CARDS];
+static int num_of_cards = 0;
+
+
+/*
+ * PCL handling functions.
+ */
+
+static pcl_t alloc_pcl(struct ti_lynx *lynx)
+{
+        u8 m;
+        int i, j;
+
+        spin_lock(&lynx->lock);
+        /* FIXME - use ffz() to make this readable */
+        for (i = 0; i < LOCALRAM_SIZE; i++) {
+                m = lynx->pcl_bmap[i];
+                for (j = 0; j < 8; j++) {
+                        if (m & 1<<j) {
+                                continue;
+                        }
+                        m |= 1<<j;
+                        lynx->pcl_bmap[i] = m;
+                        spin_unlock(&lynx->lock);
+                        return 8 * i + j;
+                }
+        }
+        spin_unlock(&lynx->lock);
+
+        return -1;
+}
+
+static void free_pcl(struct ti_lynx *lynx, pcl_t pclid)
+{
+        int off, bit;
+
+        off = pclid / 8;
+        bit = pclid % 8;
+
+        if (pclid < 0) {
+                return;
+        }
+
+        spin_lock(&lynx->lock);
+        if (lynx->pcl_bmap[off] & 1<<bit) {
+                lynx->pcl_bmap[off] &= ~(1<<bit);
+        } else {
+                PRINT(KERN_ERR, lynx->id, 
+                      "attempted to free unallocated PCL %d", pclid);
+        }
+        spin_unlock(&lynx->lock);
+}
+
+/* functions useful for debugging */        
+static void pretty_print_pcl(const struct ti_pcl *pcl)
+{
+        int i;
+
+        printk("PCL next %08x, userdata %08x, status %08x, remtrans %08x, nextbuf %08x\n",
+               pcl->next, pcl->user_data, pcl->pcl_status, 
+               pcl->remaining_transfer_count, pcl->next_data_buffer);
+
+        printk("PCL");
+        for (i=0; i<13; i++) {
+                printk(" c%x:%08x d%x:%08x",
+                       i, pcl->buffer[i].control, i, pcl->buffer[i].pointer);
+                if (!(i & 0x3) && (i != 12)) printk("\nPCL");
+        }
+        printk("\n");
+}
+        
+static void print_pcl(const struct ti_lynx *lynx, pcl_t pclid)
+{
+        struct ti_pcl pcl;
+
+        get_pcl(lynx, pclid, &pcl);
+        pretty_print_pcl(&pcl);
+}
+
+
+static int add_card(struct pci_dev *dev);
+static void remove_card(struct ti_lynx *lynx);
+static int init_driver(void);
+
+
+
+
+/***********************************
+ * IEEE-1394 functionality section *
+ ***********************************/
+
+
+static int get_phy_reg(struct ti_lynx *lynx, int addr)
+{
+        int retval;
+        int i = 0;
+
+        unsigned long flags;
+
+        if (addr > 15) {
+                PRINT(KERN_ERR, lynx->id, __FUNCTION__
+                      ": PHY register address %d out of range", addr);
+                return -1;
+        }
+
+        spin_lock_irqsave(&lynx->phy_reg_lock, flags);
+
+        do {
+                reg_write(lynx, LINK_PHY, LINK_PHY_READ | LINK_PHY_ADDR(addr));
+                retval = reg_read(lynx, LINK_PHY);
+
+                if (i > 10000) {
+                        PRINT(KERN_ERR, lynx->id, __FUNCTION__ 
+                              ": runaway loop, aborting");
+                        retval = -1;
+                        break;
+                }
+                i++;
+        } while ((retval & 0xf00) != LINK_PHY_RADDR(addr));
+
+        reg_write(lynx, LINK_INT_STATUS, LINK_INT_PHY_REG_RCVD);
+        spin_unlock_irqrestore(&lynx->phy_reg_lock, flags);
+
+        if (retval != -1) {
+                return retval & 0xff;
+        } else {
+                return -1;
+        }
+}
+
+static int set_phy_reg(struct ti_lynx *lynx, int addr, int val)
+{
+        unsigned long flags;
+
+        if (addr > 15) {
+                PRINT(KERN_ERR, lynx->id, __FUNCTION__
+                      ": PHY register address %d out of range", addr);
+                return -1;
+        }
+
+        if (val > 0xff) {
+                PRINT(KERN_ERR, lynx->id, __FUNCTION__
+                      ": PHY register value %d out of range", val);
+                return -1;
+        }
+
+        spin_lock_irqsave(&lynx->phy_reg_lock, flags);
+
+        reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | LINK_PHY_ADDR(addr)
+                  | LINK_PHY_WDATA(val));
+
+        spin_unlock_irqrestore(&lynx->phy_reg_lock, flags);
+
+        return 0;
+}
+
+static int sel_phy_reg_page(struct ti_lynx *lynx, int page)
+{
+        int reg;
+
+        if (page > 7) {
+                PRINT(KERN_ERR, lynx->id, __FUNCTION__
+                      ": PHY page %d out of range", page);
+                return -1;
+        }
+
+        reg = get_phy_reg(lynx, 7);
+        if (reg != -1) {
+                reg &= 0x1f;
+                reg |= (page << 5);
+                set_phy_reg(lynx, 7, reg);
+                return 0;
+        } else {
+                return -1;
+        }
+}
+
+#if 0 /* not needed at this time */
+static int sel_phy_reg_port(struct ti_lynx *lynx, int port)
+{
+        int reg;
+
+        if (port > 15) {
+                PRINT(KERN_ERR, lynx->id, __FUNCTION__
+                      ": PHY port %d out of range", port);
+                return -1;
+        }
+
+        reg = get_phy_reg(lynx, 7);
+        if (reg != -1) {
+                reg &= 0xf0;
+                reg |= port;
+                set_phy_reg(lynx, 7, reg);
+                return 0;
+        } else {
+                return -1;
+        }
+}
+#endif
+
+static u32 get_phy_vendorid(struct ti_lynx *lynx)
+{
+        u32 pvid = 0;
+        sel_phy_reg_page(lynx, 1);
+        pvid |= (get_phy_reg(lynx, 10) << 16);
+        pvid |= (get_phy_reg(lynx, 11) << 8);
+        pvid |= get_phy_reg(lynx, 12);
+        PRINT(KERN_INFO, lynx->id, "PHY vendor id 0x%06x", pvid);
+        return pvid;
+}
+
+static u32 get_phy_productid(struct ti_lynx *lynx)
+{
+        u32 id = 0;
+        sel_phy_reg_page(lynx, 1);
+        id |= (get_phy_reg(lynx, 13) << 16);
+        id |= (get_phy_reg(lynx, 14) << 8);
+        id |= get_phy_reg(lynx, 15);
+        PRINT(KERN_INFO, lynx->id, "PHY product id 0x%06x", id);
+        return id;
+}
+
+static quadlet_t generate_own_selfid(struct ti_lynx *lynx,
+                                     struct hpsb_host *host)
+{
+        quadlet_t lsid;
+        char phyreg[7];
+        int i;
+
+        for (i = 0; i < 7; i++) {
+                phyreg[i] = get_phy_reg(lynx, i);
+        }
+
+        /* FIXME? We assume a TSB21LV03A phy here.  This code doesn't support
+           more than 3 ports on the PHY anyway. */
+
+        lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22);
+        lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */
+        lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */
+        /* lsid |= (phyreg[6] & 0x01) << 11; *//* contender (phy dependent) */
+        lsid |= 1 << 11; /* set contender (hack) */
+        lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */
+
+        //for (i = 0; i < (phyreg[2] & 0xf); i++) { /* ports */
+        for (i = 0; i < (phyreg[2] & 0x1f); i++) { /* ports */
+                if (phyreg[3 + i] & 0x4) {
+                        lsid |= (((phyreg[3 + i] & 0x8) | 0x10) >> 3)
+                                << (6 - i*2);
+                } else {
+                        lsid |= 1 << (6 - i*2);
+                }
+        }
+
+        printk("-%d- generated own selfid 0x%x\n", lynx->id, lsid);
+        return lsid;
+}
+
+static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host, size_t size)
+{
+        quadlet_t *q = lynx->rcv_page;
+        int phyid, isroot;
+        quadlet_t lsid = 0;
+
+        if (!lynx->phyic.reg_1394a) {
+                lsid = generate_own_selfid(lynx, host);
+        }
+
+        phyid = get_phy_reg(lynx, 0);
+        isroot = (phyid & 2) != 0;
+        phyid >>= 2;
+        PRINT(KERN_INFO, lynx->id, "SelfID process finished (phyid %d, %s)",
+              phyid, (isroot ? "root" : "not root"));
+        reg_write(lynx, LINK_ID, (0xffc0 | phyid) << 16);
+
+        if (!lynx->phyic.reg_1394a && !size) {
+                hpsb_selfid_received(host, lsid);
+        }
+
+        while (size > 0) {
+                if (!lynx->phyic.reg_1394a 
+                    && (q[0] & 0x3f800000) == ((phyid + 1) << 24)) {
+                        hpsb_selfid_received(host, lsid);
+                }
+
+                if (q[0] == ~q[1]) {
+                        printk("-%d- selfid packet 0x%x rcvd\n", lynx->id, q[0]);
+                        hpsb_selfid_received(host, q[0]);
+                } else {
+                        printk("-%d- inconsistent selfid 0x%x/0x%x\n", lynx->id,
+                               q[0], q[1]);
+                }
+                q += 2;
+                size -= 8;
+        }
+
+        if (!lynx->phyic.reg_1394a && isroot && phyid != 0) {
+                hpsb_selfid_received(host, lsid);
+        }
+
+        hpsb_selfid_complete(host, phyid, isroot);
+}
+
+
+
+/* This must be called with the async_queue_lock held. */
+static void send_next_async(struct ti_lynx *lynx)
+{
+        struct ti_pcl pcl;
+        struct hpsb_packet *packet = lynx->async_queue;
+
+        pcl.next = PCL_NEXT_INVALID;
+        pcl.async_error_next = PCL_NEXT_INVALID;
+#ifdef __BIG_ENDIAN
+        pcl.buffer[0].control = PCL_CMD_XMT | packet->speed_code << 14
+                | packet->header_size;
+#else
+        pcl.buffer[0].control = PCL_CMD_XMT | packet->speed_code << 14
+                | packet->header_size | PCL_BIGENDIAN;
+#endif
+        pcl.buffer[0].pointer = virt_to_bus(packet->header);
+        pcl.buffer[1].control = PCL_LAST_BUFF | packet->data_size;
+        pcl.buffer[1].pointer = virt_to_bus(packet->data);
+
+        if (!packet->data_be) {
+                pcl.buffer[1].control |= PCL_BIGENDIAN;
+        }
+
+        put_pcl(lynx, lynx->async_pcl, &pcl);
+        run_pcl(lynx, lynx->async_pcl_start, 3);
+}
+
+
+static int lynx_detect(struct hpsb_host_template *tmpl)
+{
+        struct hpsb_host *host;
+        int i;
+
+        init_driver();
+
+        for (i = 0; i < num_of_cards; i++) {
+                host = hpsb_get_host(tmpl, 0);
+                if (host == NULL) {
+                        /* simply don't init more after out of mem */
+                        return i;
+                }
+                host->hostdata = &cards[i];
+                cards[i].host = host;
+        }
+
+        return num_of_cards;
+}
+
+static int lynx_initialize(struct hpsb_host *host)
+{
+        struct ti_lynx *lynx = host->hostdata;
+        struct ti_pcl pcl;
+        int i;
+        u32 *pcli;
+
+        lynx->async_queue = NULL;
+        spin_lock_init(&lynx->async_queue_lock);
+        spin_lock_init(&lynx->phy_reg_lock);
+        
+        pcl.next = pcl_bus(lynx, lynx->rcv_pcl);
+        put_pcl(lynx, lynx->rcv_pcl_start, &pcl);
+        
+        pcl.next = PCL_NEXT_INVALID;
+        pcl.async_error_next = PCL_NEXT_INVALID;
+#ifdef __BIG_ENDIAN
+        pcl.buffer[0].control = PCL_CMD_RCV | 2048;
+        pcl.buffer[1].control = PCL_LAST_BUFF | 2048;
+#else
+        pcl.buffer[0].control = PCL_CMD_RCV | PCL_BIGENDIAN | 2048;
+        pcl.buffer[1].control = PCL_LAST_BUFF | PCL_BIGENDIAN | 2048;
+#endif
+        pcl.buffer[0].pointer = virt_to_bus(lynx->rcv_page);
+        pcl.buffer[1].pointer = virt_to_bus(lynx->rcv_page) + 2048;
+        put_pcl(lynx, lynx->rcv_pcl, &pcl);
+        
+        pcl.next = pcl_bus(lynx, lynx->async_pcl);
+        pcl.async_error_next = pcl_bus(lynx, lynx->async_pcl);
+        put_pcl(lynx, lynx->async_pcl_start, &pcl);
+
+        pcl.next = PCL_NEXT_INVALID;
+        pcl.async_error_next = PCL_NEXT_INVALID;
+        pcl.buffer[0].control = PCL_CMD_RCV | PCL_LAST_BUFF | 2048;
+#ifndef __BIG_ENDIAN
+        pcl.buffer[0].control |= PCL_BIGENDIAN;
+#endif
+
+        for (i = 0; i < NUM_ISORCV_PCL; i++) {
+                int page = i / ISORCV_PER_PAGE;
+                int sec = i % ISORCV_PER_PAGE;
+
+                pcl.buffer[0].pointer = virt_to_bus(lynx->iso_rcv.page[page])
+                        + sec * MAX_ISORCV_SIZE;
+                put_pcl(lynx, lynx->iso_rcv.pcl[i], &pcl);
+        }
+
+        pcli = (u32 *)&pcl;
+        for (i = 0; i < NUM_ISORCV_PCL; i++) {
+                pcli[i] = pcl_bus(lynx, lynx->iso_rcv.pcl[i]);
+        }
+        put_pcl(lynx, lynx->iso_rcv.pcl_start, &pcl);
+
+        /* 85 bytes for each FIFO - FIXME - optimize or make configurable */
+        reg_write(lynx, FIFO_SIZES, 0x00555555);
+        /* 20 byte threshold before triggering PCI transfer */
+        reg_write(lynx, DMA_GLOBAL_REGISTER, 0x2<<24);
+        /* 69 byte threshold on both send FIFOs before transmitting */
+        reg_write(lynx, FIFO_XMIT_THRESHOLD, 0x4545);
+        
+        reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_1394);
+        reg_write(lynx, LINK_INT_ENABLE, LINK_INT_PHY_TIMEOUT
+                  | LINK_INT_PHY_REG_RCVD  | LINK_INT_PHY_BUSRESET
+                  | LINK_INT_ISO_STUCK     | LINK_INT_ASYNC_STUCK 
+                  | LINK_INT_SENT_REJECT   | LINK_INT_TX_INVALID_TC
+                  | LINK_INT_GRF_OVERFLOW  | LINK_INT_ITF_UNDERFLOW
+                  | LINK_INT_ATF_UNDERFLOW);
+        
+        reg_write(lynx, DMA1_WORD0_CMP_VALUE, 0);
+        reg_write(lynx, DMA1_WORD0_CMP_ENABLE, 0xa<<4);
+        reg_write(lynx, DMA1_WORD1_CMP_VALUE, 0);
+        reg_write(lynx, DMA1_WORD1_CMP_ENABLE, DMA_WORD1_CMP_MATCH_NODE_BCAST
+                  | DMA_WORD1_CMP_MATCH_BROADCAST | DMA_WORD1_CMP_MATCH_LOCAL
+                  | DMA_WORD1_CMP_MATCH_BUS_BCAST | DMA_WORD1_CMP_ENABLE_SELF_ID
+                  | DMA_WORD1_CMP_ENABLE_MASTER);
+
+        run_pcl(lynx, lynx->rcv_pcl_start, 1);
+
+        reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ISO_RCV), 0);
+        reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ISO_RCV), 0x9<<4);
+        reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ISO_RCV), 0);
+        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0);
+
+        run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, 0, CHANNEL_ISO_RCV);
+
+        reg_write(lynx, LINK_CONTROL, LINK_CONTROL_RCV_CMP_VALID
+                  | LINK_CONTROL_TX_ISO_EN   | LINK_CONTROL_RX_ISO_EN
+                  | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN
+                  | LINK_CONTROL_RESET_TX    | LINK_CONTROL_RESET_RX
+                  | LINK_CONTROL_CYCSOURCE   | LINK_CONTROL_CYCTIMEREN);
+        
+        /* attempt to enable contender bit -FIXME- would this work elsewhere? */
+        reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
+        reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1); 
+
+        return 1;
+}
+
+static void lynx_release(struct hpsb_host *host)
+{
+        struct ti_lynx *lynx;
+        
+        if (host != NULL) {
+                lynx = host->hostdata;
+                remove_card(lynx);
+        } else {
+                unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME);
+        }
+}
+
+
+/*
+ * FIXME - does not support iso/raw transmits yet and will choke on them.
+ */
+static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
+{
+        struct ti_lynx *lynx = host->hostdata;
+        struct hpsb_packet *p;
+        unsigned long flags;
+
+        if (packet->data_size >= 4096) {
+                PRINT(KERN_ERR, lynx->id, "transmit packet data too big (%d)",
+                      packet->data_size);
+                return 0;
+        }
+
+        packet->xnext = NULL;
+
+        spin_lock_irqsave(&lynx->async_queue_lock, flags);
+
+        if (lynx->async_queue == NULL) {
+                lynx->async_queue = packet;
+                send_next_async(lynx);
+        } else {
+                p = lynx->async_queue;
+                while (p->xnext != NULL) {
+                        p = p->xnext;
+                }
+
+                p->xnext = packet;
+        }
+
+        spin_unlock_irqrestore(&lynx->async_queue_lock, flags);
+
+        return 1;
+}
+
+static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
+{
+        struct ti_lynx *lynx = host->hostdata;
+        int retval = 0;
+        struct hpsb_packet *packet, *lastpacket;
+        unsigned long flags;
+
+        switch (cmd) {
+        case RESET_BUS:
+                if (arg) {
+                        arg = 3 << 6;
+                } else {
+                        arg = 1 << 6;
+                }
+                
+                PRINT(KERN_INFO, lynx->id, "resetting bus on request%s",
+                      (host->attempt_root ? " and attempting to become root"
+                       : ""));
+
+                spin_lock_irqsave(&lynx->phy_reg_lock, flags);
+                reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | LINK_PHY_ADDR(1) 
+                          | LINK_PHY_WDATA(arg));
+                spin_unlock_irqrestore(&lynx->phy_reg_lock, flags);
+                break;
+
+        case GET_CYCLE_COUNTER:
+                retval = reg_read(lynx, CYCLE_TIMER);
+                break;
+                
+        case SET_CYCLE_COUNTER:
+                reg_write(lynx, CYCLE_TIMER, arg);
+                break;
+
+        case SET_BUS_ID:
+                reg_write(lynx, LINK_ID, 
+                          (arg << 22) | (reg_read(lynx, LINK_ID) & 0x003f0000));
+                break;
+                
+        case ACT_CYCLE_MASTER:
+                if (arg) {
+                        reg_set_bits(lynx, LINK_CONTROL,
+                                     LINK_CONTROL_CYCMASTER);
+                } else {
+                        reg_clear_bits(lynx, LINK_CONTROL,
+                                       LINK_CONTROL_CYCMASTER);
+                }
+                break;
+
+        case CANCEL_REQUESTS:
+                spin_lock_irqsave(&lynx->async_queue_lock, flags);
+
+                reg_write(lynx, DMA3_CHAN_CTRL, 0);
+                packet = lynx->async_queue;
+                lynx->async_queue = NULL;
+
+                spin_unlock_irqrestore(&lynx->async_queue_lock, flags);
+
+                while (packet != NULL) {
+                        lastpacket = packet;
+                        packet = packet->xnext;
+                        hpsb_packet_sent(host, lastpacket, ACKX_ABORTED);
+                }
+
+                break;
+
+        case MODIFY_USAGE:
+                if (arg) {
+                        MOD_INC_USE_COUNT;
+                } else {
+                        MOD_DEC_USE_COUNT;
+                }
+                break;
+
+        case ISO_LISTEN_CHANNEL:
+                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
+                
+                if (lynx->iso_rcv.chan_count++ == 0) {
+                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
+                                  DMA_WORD1_CMP_ENABLE_MASTER);
+                }
+
+                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
+                break;
+
+        case ISO_UNLISTEN_CHANNEL:
+                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
+
+                if (--lynx->iso_rcv.chan_count == 0) {
+                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
+                                  0);
+                }
+
+                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
+                break;
+
+        default:
+                PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
+                retval = -1;
+        }
+
+        return retval;
+}
+
+
+/***************************************
+ * IEEE-1394 functionality section END *
+ ***************************************/
+
+
+/* VFS functions for local bus / aux device access.  Access to those
+ * is implemented as a character device instead of block devices
+ * because buffers are not wanted for this.  Therefore llseek (from
+ * VFS) can be used for these char devices with obvious effects.
+ */
+static int mem_open(struct inode*, struct file*);
+static int mem_release(struct inode*, struct file*);
+static unsigned int aux_poll(struct file*, struct poll_table_struct*);
+static ssize_t mem_read (struct file*, char*, size_t, loff_t*);
+static ssize_t mem_write(struct file*, const char*, size_t, loff_t*);
+
+
+static struct file_operations aux_ops = {
+        /* FIXME: should have custom llseek with bounds checking*/
+        read:     mem_read,
+        write:    mem_write,
+        poll:     aux_poll,
+        open:     mem_open,
+        release:  mem_release
+};
+
+
+static void aux_setup_pcls(struct ti_lynx *lynx)
+{
+        struct ti_pcl pcl;
+        unsigned long membufbus = virt_to_bus(lynx->mem_dma_buffer);
+        int i;
+
+        /* This pcl is used to start any aux transfers, the pointer to next
+           points to itself to avoid a dummy pcl (the PCL engine only executes
+           the next pcl on startup.  The real chain is done by branch */
+        pcl.next = pcl_bus(lynx, lynx->mem_pcl.start);
+        pcl.buffer[0].control = PCL_CMD_BRANCH | PCL_COND_DMARDY_SET;
+        pcl.buffer[0].pointer = pcl_bus(lynx, lynx->mem_pcl.max);
+        pcl.buffer[1].control = PCL_CMD_BRANCH | PCL_COND_DMARDY_CLEAR;
+        pcl.buffer[1].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd);
+        put_pcl(lynx, lynx->mem_pcl.start, &pcl);
+
+        /* let maxpcl transfer exactly 32kB */
+        pcl.next = PCL_NEXT_INVALID;
+        for (i=0; i<8; i++) {
+                pcl.buffer[i].control = 4000;
+                pcl.buffer[i].pointer = membufbus + i * 4000;
+        }
+        pcl.buffer[0].control |= PCL_CMD_LBUS_TO_PCI /*| PCL_GEN_INTR*/;
+        pcl.buffer[8].control = 768 | PCL_LAST_BUFF;
+        pcl.buffer[8].pointer = membufbus + 8 * 4000;
+        put_pcl(lynx, lynx->mem_pcl.max, &pcl);
+
+
+        /* magic stuff - self and modpcl modifying pcl */
+        pcl.next = pcl_bus(lynx, lynx->mem_pcl.mod);
+        pcl.user_data = 4000;
+        pcl.buffer[0].control = PCL_CMD_LOAD;
+        pcl.buffer[0].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) 
+                                + pcloffs(user_data);
+        pcl.buffer[1].control = PCL_CMD_STOREQ;
+        pcl.buffer[1].pointer = pcl_bus(lynx, lynx->mem_pcl.mod) 
+                                + pcloffs(buffer[1].control);
+        pcl.buffer[2].control = PCL_CMD_LOAD;
+        pcl.buffer[2].pointer = membufbus;
+        pcl.buffer[3].control = PCL_CMD_STOREQ;
+        pcl.buffer[3].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) 
+                                + pcloffs(buffer[1].pointer);
+        pcl.buffer[4].control = PCL_CMD_STOREQ;
+        pcl.buffer[4].pointer = pcl_bus(lynx, lynx->mem_pcl.cmd) 
+                                + pcloffs(buffer[6].pointer);
+        pcl.buffer[5].control = PCL_CMD_LOAD;
+        pcl.buffer[5].pointer = membufbus + 4;
+        pcl.buffer[6].control = PCL_CMD_STOREQ | PCL_LAST_CMD;
+        put_pcl(lynx, lynx->mem_pcl.cmd, &pcl);
+
+        /* modified by cmdpcl when actual transfer occurs */
+        pcl.next = PCL_NEXT_INVALID;
+        pcl.buffer[0].control = PCL_CMD_LBUS_TO_PCI; /* null transfer */
+        for (i=1; i<13; i++) {
+                pcl.buffer[i].control = 4000;
+                pcl.buffer[i].pointer = membufbus + (i-1) * 4000;
+        }
+        put_pcl(lynx, lynx->mem_pcl.mod, &pcl);
+}
+
+static int mem_open(struct inode *inode, struct file *file)
+{
+        int cid = MINOR(inode->i_rdev);
+        enum { rom, aux, ram } type;
+        struct memdata *md;
+
+        MOD_INC_USE_COUNT;
+        
+        if (cid < PCILYNX_MINOR_AUX_START) {
+                /* just for completeness */
+                MOD_DEC_USE_COUNT;
+                return -ENXIO;
+        } else if (cid < PCILYNX_MINOR_ROM_START) {
+                cid -= PCILYNX_MINOR_AUX_START;
+                if (cid >= num_of_cards || !cards[cid].aux_port) {
+                        MOD_DEC_USE_COUNT;
+                        return -ENXIO;
+                }
+                type = aux;
+        } else if (cid < PCILYNX_MINOR_RAM_START) {
+                cid -= PCILYNX_MINOR_ROM_START;
+                if (cid >= num_of_cards || !cards[cid].local_rom) {
+                        MOD_DEC_USE_COUNT;
+                        return -ENXIO;
+                }
+                type = rom;
+        } else {
+                /* WARNING: Know what you are doing when opening RAM.
+                 * It is currently used inside the driver! */
+                cid -= PCILYNX_MINOR_RAM_START;
+                if (cid >= num_of_cards || !cards[cid].local_ram) {
+                        MOD_DEC_USE_COUNT;
+                        return -ENXIO;
+                }
+                type = ram;
+        }
+
+        md = (struct memdata *)vmalloc(sizeof(struct memdata));
+        if (md == NULL) {
+                MOD_DEC_USE_COUNT;
+                return -ENOMEM;
+        }
+
+        md->lynx = &cards[cid];
+        md->cid = cid;
+
+        switch (type) {
+        case rom:
+                md->type = rom;
+                break;
+        case ram:
+                md->type = ram;
+                break;
+        case aux:
+                md->aux_intr_last_seen = atomic_read(&cards[cid].aux_intr_seen);
+                md->type = aux;
+                break;
+        }
+
+        file->private_data = md;
+
+        return 0;
+}
+
+static int mem_release(struct inode *inode, struct file *file)
+{
+        struct memdata *md = (struct memdata *)file->private_data;
+
+        vfree(md);
+
+        MOD_DEC_USE_COUNT;
+        return 0;
+}
+
+static unsigned int aux_poll(struct file *file, poll_table *pt)
+{
+        struct memdata *md = (struct memdata *)file->private_data;
+        int cid = md->cid;
+        unsigned int mask;
+        int intr_seen;
+
+        /* reading and writing is always allowed */
+        mask = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
+
+        if (md->type == aux) {
+                poll_wait(file, &cards[cid].aux_intr_wait, pt);
+                intr_seen = atomic_read(&cards[cid].aux_intr_seen);
+
+                if (md->aux_intr_last_seen != intr_seen) {
+                        mask |= POLLPRI;
+                        /* md->aux_intr_last_seen = intr_seen; */
+                        md->aux_intr_last_seen++; /* don't miss interrupts */
+                        /* FIXME - make ioctl for configuring this */
+                }
+        }
+
+        return mask;
+}
+
+
+/* 
+ * do not DMA if count is too small because this will have a serious impact 
+ * on performance - the value 2400 was found by experiment and may not work
+ * everywhere as good as here - use mem_mindma option for modules to change 
+ */
+short mem_mindma = 2400;
+MODULE_PARM(mem_mindma, "h");
+
+static ssize_t mem_read(struct file *file, char *buffer, size_t count,
+                        loff_t *offset)
+{
+        struct memdata *md = (struct memdata *)file->private_data;
+        size_t bcount;
+        size_t alignfix;
+        int off = (int)*offset; /* avoid useless 64bit-arithmetic */
+        void *membase;
+
+        DECLARE_WAITQUEUE(wait, current);
+
+        if ((off + count) > PCILYNX_MAX_MEMORY+1) {
+                count = PCILYNX_MAX_MEMORY+1 - off;
+        }
+        if (count <= 0) {
+                return 0;
+        }
+
+
+        down(&md->lynx->mem_dma_mutex);
+
+        switch (md->type) {
+        case rom:
+                reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_ROM | off);
+                membase = md->lynx->local_rom;
+                break;
+        case ram:
+                reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_RAM | off);
+                membase = md->lynx->local_ram;
+                break;
+        case aux:
+                reg_write(md->lynx, LBUS_ADDR, LBUS_ADDR_SEL_AUX | off);
+                membase = md->lynx->aux_port;
+                break;
+        default:
+                panic("pcilynx%d: unsupported md->type %d in " __FUNCTION__,
+                      md->lynx->id, md->type);
+        }
+
+        if (count < mem_mindma) {
+                memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, count);
+                copy_to_user(buffer, md->lynx->mem_dma_buffer, count);
+                bcount = 0;
+                goto done;
+        }
+        
+        bcount = count;
+        alignfix = 4 - (off % 4);
+        if (alignfix != 4) {
+                if (bcount < alignfix) {
+                        alignfix = bcount;
+                }
+                memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, alignfix);
+                copy_to_user(buffer, md->lynx->mem_dma_buffer, alignfix);
+                if (bcount == alignfix) {
+                        goto done;
+                }
+                bcount -= alignfix;
+                buffer += alignfix;
+                off += alignfix;
+        }
+
+        if (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) {
+                PRINT(KERN_WARNING, md->lynx->id, "DMA ALREADY ACTIVE!");
+        }
+
+        add_wait_queue(&md->lynx->mem_dma_intr_wait, &wait);
+
+        if (bcount > 32768) {
+                current->state = TASK_INTERRUPTIBLE;
+
+                reg_write(md->lynx, DMA0_READY, 1); /* select maxpcl */
+                run_pcl(md->lynx, md->lynx->mem_pcl.start, 0);
+
+                while (reg_read(md->lynx, DMA0_CHAN_CTRL)
+                       & DMA_CHAN_CTRL_BUSY) {
+                        if (signal_pending(current)) {
+                                reg_write(md->lynx, DMA0_CHAN_CTRL, 0);
+                                goto rmwait_done;
+                        }
+                        schedule();
+                }
+
+                copy_to_user(buffer, md->lynx->mem_dma_buffer, 32768);
+                buffer += 32768;
+                bcount -= 32768;
+        }
+
+        *(u32 *)(md->lynx->mem_dma_buffer) = 
+                pcl_bus(md->lynx, md->lynx->mem_pcl.mod) 
+                + pcloffs(buffer[bcount/4000+1].control);
+        *(u32 *)(md->lynx->mem_dma_buffer+4) = PCL_LAST_BUFF | (bcount % 4000);
+
+        current->state = TASK_INTERRUPTIBLE;
+
+        reg_write(md->lynx, DMA0_READY, 0);
+        run_pcl(md->lynx, md->lynx->mem_pcl.start, 0);
+
+        while (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) {
+                if (signal_pending(current)) {
+                        reg_write(md->lynx, DMA0_CHAN_CTRL, 0);
+                        goto rmwait_done;
+                }
+                schedule();
+        }
+
+        copy_to_user(buffer, md->lynx->mem_dma_buffer, bcount);
+        bcount = 0;
+
+        if (reg_read(md->lynx, DMA0_CHAN_CTRL) & DMA_CHAN_CTRL_BUSY) {
+                PRINT(KERN_ERR, md->lynx->id, "DMA STILL ACTIVE!");
+        }
+
+ rmwait_done:
+        reg_write(md->lynx, DMA0_CHAN_CTRL, 0);
+        remove_wait_queue(&md->lynx->mem_dma_intr_wait, &wait);
+ done:
+        up(&md->lynx->mem_dma_mutex);
+
+        count -= bcount;
+        *offset += count;
+        return (count ? count : -EINTR);
+}
+
+
+static ssize_t mem_write(struct file *file, const char *buffer, size_t count, 
+                         loff_t *offset)
+{
+        struct memdata *md = (struct memdata *)file->private_data;
+
+        if (((*offset) + count) > PCILYNX_MAX_MEMORY+1) {
+                count = PCILYNX_MAX_MEMORY+1 - *offset;
+        }
+        if (count == 0 || *offset > PCILYNX_MAX_MEMORY) {
+                return -ENOSPC;
+        }
+
+        /* FIXME: dereferencing pointers to PCI mem doesn't work everywhere */
+        switch (md->type) {
+        case aux:
+                copy_from_user(md->lynx->aux_port+(*offset), buffer, count);
+                break;
+        case ram:
+                copy_from_user(md->lynx->local_ram+(*offset), buffer, count);
+                break;
+        case rom:
+                /* the ROM may be writeable */
+                copy_from_user(md->lynx->local_rom+(*offset), buffer, count);
+                break;
+        }
+
+        file->f_pos += count;
+        return count;
+}
+
+
+
+/********************************************************
+ * Global stuff (interrupt handler, init/shutdown code) *
+ ********************************************************/
+
+
+static void lynx_irq_handler(int irq, void *dev_id,
+                             struct pt_regs *regs_are_unused)
+{
+        struct ti_lynx *lynx = (struct ti_lynx *)dev_id;
+        struct hpsb_host *host = lynx->host;
+        u32 intmask = reg_read(lynx, PCI_INT_STATUS);
+        u32 linkint = reg_read(lynx, LINK_INT_STATUS);
+
+        reg_write(lynx, PCI_INT_STATUS, intmask);
+        reg_write(lynx, LINK_INT_STATUS, linkint);
+        //printk("-%d- one interrupt: 0x%08x / 0x%08x\n", lynx->id, intmask, linkint);
+
+        if (intmask & PCI_INT_AUX_INT) {
+                atomic_inc(&lynx->aux_intr_seen);
+                wake_up_interruptible(&lynx->aux_intr_wait);
+        }
+
+        if (intmask & PCI_INT_DMA0_HLT) {
+                wake_up_interruptible(&lynx->mem_dma_intr_wait);
+        }
+
+
+        if (intmask & PCI_INT_1394) {
+                if (linkint & LINK_INT_PHY_TIMEOUT) {
+                        PRINT(KERN_INFO, lynx->id, "PHY timeout occured");
+                }
+                if (linkint & LINK_INT_PHY_BUSRESET) {
+                        PRINT(KERN_INFO, lynx->id, "bus reset interrupt");
+                        if (!host->in_bus_reset) {
+                                hpsb_bus_reset(host);
+                        }
+                }
+                if (linkint & LINK_INT_PHY_REG_RCVD) {
+                        if (!host->in_bus_reset) {
+                                printk("-%d- phy reg received without reset\n",
+                                       lynx->id);
+                        }
+                }
+                if (linkint & LINK_INT_ISO_STUCK) {
+                        PRINT(KERN_INFO, lynx->id, "isochronous transmitter stuck");
+                }
+                if (linkint & LINK_INT_ASYNC_STUCK) {
+                        PRINT(KERN_INFO, lynx->id, "asynchronous transmitter stuck");
+                }
+                if (linkint & LINK_INT_SENT_REJECT) {
+                        PRINT(KERN_INFO, lynx->id, "sent reject");
+                }
+                if (linkint & LINK_INT_TX_INVALID_TC) {
+                        PRINT(KERN_INFO, lynx->id, "invalid transaction code");
+                }
+                if (linkint & LINK_INT_GRF_OVERFLOW) {
+                        PRINT(KERN_INFO, lynx->id, "GRF overflow");
+                }
+                if (linkint & LINK_INT_ITF_UNDERFLOW) {
+                        PRINT(KERN_INFO, lynx->id, "ITF underflow");
+                }
+                if (linkint & LINK_INT_ATF_UNDERFLOW) {
+                        PRINT(KERN_INFO, lynx->id, "ATF underflow");
+                }
+        }
+
+        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_RCV)) {
+                PRINT(KERN_INFO, lynx->id, "iso receive");
+
+                spin_lock(&lynx->iso_rcv.lock);
+
+                lynx->iso_rcv.stat[lynx->iso_rcv.next] =
+                        reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ISO_RCV));
+
+                lynx->iso_rcv.used++;
+                lynx->iso_rcv.next = (lynx->iso_rcv.next + 1) % NUM_ISORCV_PCL;
+
+                if ((lynx->iso_rcv.next == lynx->iso_rcv.last)
+                    || !lynx->iso_rcv.chan_count) {
+                        printk("stopped\n");
+                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0);
+                }
+
+                run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, lynx->iso_rcv.next,
+                            CHANNEL_ISO_RCV);
+
+                spin_unlock(&lynx->iso_rcv.lock);
+
+                queue_task(&lynx->iso_rcv.tq, &tq_immediate);
+                mark_bh(IMMEDIATE_BH);
+        }
+
+        if (intmask & PCI_INT_DMA3_HLT) {
+                /* async send DMA completed */
+                u32 ack;
+                struct hpsb_packet *packet;
+                
+                spin_lock(&lynx->async_queue_lock);
+
+                ack = reg_read(lynx, DMA3_CHAN_STAT);
+                packet = lynx->async_queue;
+                lynx->async_queue = packet->xnext;
+
+                if (lynx->async_queue != NULL) {
+                        send_next_async(lynx);
+                }
+
+                spin_unlock(&lynx->async_queue_lock);
+
+                if (ack & DMA_CHAN_STAT_SPECIALACK) {
+                        printk("-%d- special ack %d\n", lynx->id,
+                               (ack >> 15) & 0xf);
+                        ack = ACKX_SEND_ERROR;
+                } else {
+                        ack = (ack >> 15) & 0xf;
+                }
+                
+                hpsb_packet_sent(host, packet, ack);
+        }
+
+        if (intmask & (PCI_INT_DMA1_HLT | PCI_INT_DMA1_PCL)) {
+                /* general receive DMA completed */
+                int stat = reg_read(lynx, DMA1_CHAN_STAT);
+
+                printk("-%d- received packet size %d\n", lynx->id, 
+                       stat & 0x1fff); 
+
+                if (stat & DMA_CHAN_STAT_SELFID) {
+                        handle_selfid(lynx, host, stat & 0x1fff);
+                        reg_set_bits(lynx, LINK_CONTROL,
+                                     LINK_CONTROL_RCV_CMP_VALID
+                                     | LINK_CONTROL_TX_ASYNC_EN
+                                     | LINK_CONTROL_RX_ASYNC_EN);
+                } else {
+                        hpsb_packet_received(host, lynx->rcv_page,
+                                             stat & 0x1fff);
+                }
+
+                run_pcl(lynx, lynx->rcv_pcl_start, 1);
+        }
+}
+
+static void iso_rcv_bh(struct ti_lynx *lynx)
+{
+        unsigned int idx;
+        quadlet_t *data;
+        unsigned long flags;
+
+        spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
+
+        while (lynx->iso_rcv.used) {
+                idx = lynx->iso_rcv.last;
+                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
+
+                data = lynx->iso_rcv.page[idx / ISORCV_PER_PAGE]
+                        + (idx % ISORCV_PER_PAGE) * MAX_ISORCV_SIZE;
+
+                if (lynx->iso_rcv.stat[idx] 
+                    & (DMA_CHAN_STAT_PCIERR | DMA_CHAN_STAT_PKTERR)) {
+                        PRINT(KERN_INFO, lynx->id,
+                              "iso receive error on %d to 0x%p", idx, data);
+                } else {
+                        hpsb_packet_received(lynx->host, data,
+                                             lynx->iso_rcv.stat[idx] & 0x1fff);
+                }
+
+                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
+                lynx->iso_rcv.last = (idx + 1) % NUM_ISORCV_PCL;
+                lynx->iso_rcv.used--;
+        }
+
+        if (lynx->iso_rcv.chan_count) {
+                reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
+                          DMA_WORD1_CMP_ENABLE_MASTER);
+        }
+        spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
+}
+
+
+static int add_card(struct pci_dev *dev)
+{
+#define FAIL(fmt, args...) \
+        PRINT_G(KERN_ERR, fmt , ## args); \
+        num_of_cards--; \
+        remove_card(lynx); \
+        return 1
+
+        struct ti_lynx *lynx; /* shortcut to currently handled device */
+        unsigned long page;
+        unsigned int i;
+
+        if (num_of_cards == MAX_PCILYNX_CARDS) {
+                PRINT_G(KERN_WARNING, "cannot handle more than %d cards.  "
+                        "Adjust MAX_PCILYNX_CARDS in ti_pcilynx.h.",
+                        MAX_PCILYNX_CARDS);
+                return 1;
+        }
+
+        lynx = &cards[num_of_cards++];
+
+        lynx->id = num_of_cards-1;
+        lynx->dev = dev;
+
+        pci_set_master(dev);
+
+        if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ,
+                         PCILYNX_DRIVER_NAME, lynx)) {
+                PRINT(KERN_INFO, lynx->id, "allocated interrupt %d", dev->irq);
+                lynx->state = have_intr;
+        } else {
+                FAIL("failed to allocate shared interrupt %d", dev->irq);
+        }
+
+#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
+	lynx->pcl_mem = kmalloc(8 * sizeof(lynx->pcl_bmap) 
+                                * sizeof(struct ti_pcl), GFP_KERNEL);
+
+        if (lynx->pcl_mem != NULL) {
+                lynx->state = have_pcl_mem;
+                PRINT(KERN_INFO, lynx->id, 
+                      "allocated PCL memory %d Bytes @ 0x%p",
+                      8 * sizeof(lynx->pcl_bmap) * sizeof(struct ti_pcl),
+                      lynx->pcl_mem);
+        } else {
+                FAIL("failed to allocate PCL memory area");
+        }
+#endif
+
+        lynx->mem_dma_buffer = kmalloc(32768, GFP_KERNEL);
+        if (lynx->mem_dma_buffer != NULL) {
+                lynx->state = have_aux_buf;
+        } else {
+                FAIL("failed to allocate DMA buffer for aux");
+        }
+
+        page = get_free_page(GFP_KERNEL);
+        if (page != 0) {
+                lynx->rcv_page = (void *)page;
+                lynx->state = have_1394_buffers;
+        } else {
+                FAIL("failed to allocate receive buffer");
+        }
+
+        for (i = 0; i < ISORCV_PAGES; i++) {
+                page = get_free_page(GFP_KERNEL);
+                if (page != 0) {
+                        lynx->iso_rcv.page[i] = (void *)page;
+                } else {
+                        FAIL("failed to allocate iso receive buffers");
+                }
+        }
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13)
+        lynx->registers = ioremap_nocache(dev->base_address[0],
+                                          PCILYNX_MAX_REGISTER);
+        lynx->local_ram = ioremap(dev->base_address[1], PCILYNX_MAX_MEMORY);
+        lynx->aux_port = ioremap(dev->base_address[2], PCILYNX_MAX_MEMORY);
+#else
+        lynx->registers = ioremap_nocache(dev->resource[0].start,
+                                          PCILYNX_MAX_REGISTER);
+        lynx->local_ram = ioremap(dev->resource[1].start, PCILYNX_MAX_MEMORY);
+        lynx->aux_port = ioremap(dev->resource[2].start, PCILYNX_MAX_MEMORY);
+#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,15)
+        lynx->local_rom = ioremap(dev->rom_address, PCILYNX_MAX_MEMORY);
+#else
+        lynx->local_rom = ioremap(dev->resource[PCI_ROM_RESOURCE].start,
+                                  PCILYNX_MAX_MEMORY);
+#endif
+        lynx->state = have_iomappings;
+
+        if (lynx->registers == NULL) {
+                FAIL("failed to remap registers - card not accessible");
+        }
+
+#ifdef CONFIG_IEEE1394_PCILYNX_LOCALRAM
+        if (lynx->local_ram == NULL) {
+                FAIL("failed to remap local RAM which is required for "
+                     "operation");
+        }
+#endif
+
+        /* alloc_pcl return values are not checked, it is expected that the
+         * provided PCL space is sufficient for the initial allocations */
+        if (lynx->aux_port != NULL) {
+                lynx->mem_pcl.start = alloc_pcl(lynx);
+                lynx->mem_pcl.cmd = alloc_pcl(lynx);
+                lynx->mem_pcl.mod = alloc_pcl(lynx);
+                lynx->mem_pcl.max = alloc_pcl(lynx);
+                aux_setup_pcls(lynx);
+        
+                sema_init(&lynx->mem_dma_mutex, 1);
+        }
+        lynx->rcv_pcl = alloc_pcl(lynx);
+        lynx->rcv_pcl_start = alloc_pcl(lynx);
+        lynx->async_pcl = alloc_pcl(lynx);
+        lynx->async_pcl_start = alloc_pcl(lynx);
+
+        for (i = 0; i < NUM_ISORCV_PCL; i++) {
+                lynx->iso_rcv.pcl[i] = alloc_pcl(lynx);
+        }
+        lynx->iso_rcv.pcl_start = alloc_pcl(lynx);
+
+        /* all allocations successful - simple init stuff follows */
+
+        lynx->lock = SPIN_LOCK_UNLOCKED;
+
+        reg_write(lynx, PCI_INT_ENABLE, PCI_INT_AUX_INT | PCI_INT_DMA_ALL);
+
+        init_waitqueue_head(&lynx->mem_dma_intr_wait);
+        init_waitqueue_head(&lynx->aux_intr_wait);
+
+        lynx->iso_rcv.tq.routine = (void (*)(void*))iso_rcv_bh;
+        lynx->iso_rcv.tq.data = lynx;
+        lynx->iso_rcv.lock = SPIN_LOCK_UNLOCKED;
+        
+        PRINT(KERN_INFO, lynx->id, "remapped memory spaces reg 0x%p, rom 0x%p, "
+              "ram 0x%p, aux 0x%p", lynx->registers, lynx->local_rom,
+              lynx->local_ram, lynx->aux_port);
+
+        /* now, looking for PHY register set */
+        if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) {
+                lynx->phyic.reg_1394a = 1;
+                PRINT(KERN_INFO, lynx->id,
+                      "found 1394a conform PHY (using extended register set)");
+                lynx->phyic.vendor = get_phy_vendorid(lynx);
+                lynx->phyic.product = get_phy_productid(lynx);
+        } else {
+                lynx->phyic.reg_1394a = 0;
+                PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");
+        }
+
+        return 0;
+#undef FAIL
+}
+
+static void remove_card(struct ti_lynx *lynx)
+{
+        int i;
+
+        switch (lynx->state) {
+        case have_iomappings:
+                reg_write(lynx, PCI_INT_ENABLE, 0);
+                reg_write(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
+                iounmap(lynx->registers);
+                iounmap(lynx->local_rom);
+                iounmap(lynx->local_ram);
+                iounmap(lynx->aux_port);
+        case have_1394_buffers:
+                for (i = 0; i < ISORCV_PAGES; i++) {
+                        if (lynx->iso_rcv.page[i]) {
+                                free_page((unsigned long)lynx->iso_rcv.page[i]);
+                        }
+                }
+                free_page((unsigned long)lynx->rcv_page);
+        case have_aux_buf:
+                kfree(lynx->mem_dma_buffer);
+	case have_pcl_mem:
+#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
+		kfree(lynx->pcl_mem);
+#endif
+        case have_intr:
+                free_irq(lynx->dev->irq, lynx);
+        case clear:
+                /* do nothing - already freed */
+        }
+
+        lynx->state = clear;
+}
+
+static int init_driver()
+{
+        struct pci_dev *dev = NULL;
+        int success = 0;
+
+        if (num_of_cards) {
+                PRINT_G(KERN_DEBUG, __PRETTY_FUNCTION__ " called again");
+                return 0;
+        }
+
+        PRINT_G(KERN_INFO, "looking for PCILynx cards");
+
+        while ((dev = pci_find_device(PCI_VENDOR_ID_TI,
+                                      PCI_DEVICE_ID_TI_PCILYNX, dev)) 
+               != NULL) {
+                if (add_card(dev) == 0) {
+                        success = 1;
+                }
+        }
+
+        if (success == 0) {
+                PRINT_G(KERN_WARNING, "no operable PCILynx cards found");
+                return -ENXIO;
+        }
+
+        if (register_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME, &aux_ops)) {
+                PRINT_G(KERN_ERR, "allocation of char major number %d failed\n",
+                        PCILYNX_MAJOR);
+                return -EBUSY;
+        }
+
+        return 0;
+}
+
+
+static size_t get_lynx_rom(struct hpsb_host *host, const quadlet_t **ptr)
+{
+        *ptr = lynx_csr_rom;
+        return sizeof(lynx_csr_rom);
+}
+
+struct hpsb_host_template *get_lynx_template(void)
+{
+        static struct hpsb_host_template tmpl = {
+                name:             "pcilynx",
+                detect_hosts:     lynx_detect,
+                initialize_host:  lynx_initialize,
+                release_host:     lynx_release,
+                get_rom:          get_lynx_rom,
+                transmit_packet:  lynx_transmit,
+                devctl:           lynx_devctl
+        };
+
+        return &tmpl;
+}
+
+
+#ifdef MODULE
+
+/* EXPORT_NO_SYMBOLS; */
+
+MODULE_AUTHOR("Andreas E. Bombe <andreas.bombe@munich.netsurf.de>");
+MODULE_DESCRIPTION("driver for Texas Instruments PCI Lynx IEEE-1394 controller");
+MODULE_SUPPORTED_DEVICE("pcilynx");
+
+void cleanup_module(void)
+{
+        hpsb_unregister_lowlevel(get_lynx_template());
+        PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module\n");
+}
+
+int init_module(void)
+{
+        if (hpsb_register_lowlevel(get_lynx_template())) {
+                PRINT_G(KERN_ERR, "registering failed\n");
+                return -ENXIO;
+        } else {
+                return 0;
+        }
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/pcilynx.h linux/drivers/ieee1394/pcilynx.h
--- v2.3.39/linux/drivers/ieee1394/pcilynx.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/pcilynx.h	Thu Jan 20 10:44:46 2000
@@ -0,0 +1,528 @@
+#include <linux/config.h>
+
+#define PCILYNX_DRIVER_NAME      "pcilynx"
+#define PCILYNX_MAJOR            177
+
+#define PCILYNX_MINOR_AUX_START  0
+#define PCILYNX_MINOR_ROM_START  16
+#define PCILYNX_MINOR_RAM_START  32
+
+#define PCILYNX_MAX_REGISTER     0xfff
+#define PCILYNX_MAX_MEMORY       0xffff
+
+#define PCI_DEVICE_ID_TI_PCILYNX 0x8000
+#define MAX_PCILYNX_CARDS        4
+#define LOCALRAM_SIZE            64
+
+#define NUM_ISORCV_PCL           4
+#define MAX_ISORCV_SIZE          2048
+#define ISORCV_PER_PAGE          (PAGE_SIZE / MAX_ISORCV_SIZE)
+#define ISORCV_PAGES             (NUM_ISORCV_PCL / ISORCV_PER_PAGE)
+
+/* only iso rcv uses these definitions so far */
+#define CHANNEL_LOCALBUS         0
+#define CHANNEL_ASYNC_RCV        1
+#define CHANNEL_ISO_RCV          2
+#define CHANNEL_ASYNC_SEND       3
+
+typedef int pcl_t;
+
+struct ti_lynx {
+        int id; /* sequential card number */
+
+        spinlock_t lock;
+
+        struct pci_dev *dev;
+
+        struct {
+                unsigned reg_1394a:1;
+                u32 vendor;
+                u32 product;
+        } phyic;
+
+        enum { clear, have_intr, have_aux_buf, have_pcl_mem,
+               have_1394_buffers, have_iomappings } state;
+        
+        /* remapped memory spaces */
+        void *registers;
+        void *local_rom;
+        void *local_ram;
+        void *aux_port;
+
+
+        atomic_t aux_intr_seen;
+        wait_queue_head_t aux_intr_wait;
+
+        void *mem_dma_buffer;
+        struct semaphore mem_dma_mutex;
+        wait_queue_head_t mem_dma_intr_wait;
+
+        /*
+         * use local RAM of LOCALRAM_SIZE (in kB) for PCLs, which allows for 
+         * LOCALRAM_SIZE * 8 PCLs (each sized 128 bytes);
+         * the following is an allocation bitmap 
+         */
+        u8 pcl_bmap[LOCALRAM_SIZE];
+
+#ifndef CONFIG_IEEE1394_LYNXRAM
+	/* point to PCLs memory area if needed */
+	void *pcl_mem;
+#endif
+
+        /* PCLs for local mem / aux transfers */
+        struct {
+                pcl_t start, cmd, mod, max;
+        } mem_pcl;
+
+        /* IEEE-1394 part follows */
+        struct hpsb_host *host;
+
+        int phyid, isroot;
+
+        spinlock_t phy_reg_lock;
+
+        pcl_t rcv_pcl_start, rcv_pcl;
+        void *rcv_page;
+        int rcv_active;
+
+        pcl_t async_pcl_start, async_pcl;
+        struct hpsb_packet *async_queue;
+        spinlock_t async_queue_lock;
+
+        struct {
+                pcl_t pcl[NUM_ISORCV_PCL];
+                u32 stat[NUM_ISORCV_PCL];
+                void *page[ISORCV_PAGES];
+                pcl_t pcl_start;
+                int chan_count;
+                int next, last, used, running;
+                struct tq_struct tq;
+                spinlock_t lock;
+        } iso_rcv;
+};
+
+/* the per-file data structure for mem space access */
+struct memdata {
+        struct ti_lynx *lynx;
+        int cid;
+        int aux_intr_last_seen;
+        enum { rom, aux, ram } type;
+};
+
+
+
+/*
+ * Register read and write helper functions.
+ */
+inline static void reg_write(const struct ti_lynx *lynx, int offset, u32 data)
+{
+        writel(data, lynx->registers + offset);
+}
+
+inline static u32 reg_read(const struct ti_lynx *lynx, int offset)
+{
+        return readl(lynx->registers + offset);
+}
+
+inline static void reg_set_bits(const struct ti_lynx *lynx, int offset,
+                                u32 mask)
+{
+        reg_write(lynx, offset, (reg_read(lynx, offset) | mask));
+}
+
+inline static void reg_clear_bits(const struct ti_lynx *lynx, int offset,
+                                  u32 mask)
+{
+        reg_write(lynx, offset, (reg_read(lynx, offset) & ~mask));
+}
+
+
+
+/* chip register definitions follow */
+
+#define MISC_CONTROL                      0x40
+#define MISC_CONTROL_SWRESET              (1<<0)
+
+#define PCI_INT_STATUS                    0x48
+#define PCI_INT_ENABLE                    0x4c               
+/* status and enable have identical bit numbers */
+#define PCI_INT_INT_PEND                  (1<<31)
+#define PCI_INT_FORCED_INT                (1<<30)
+#define PCI_INT_SLV_ADR_PERR              (1<<28)
+#define PCI_INT_SLV_DAT_PERR              (1<<27)
+#define PCI_INT_MST_DAT_PERR              (1<<26)
+#define PCI_INT_MST_DEV_TIMEOUT           (1<<25)
+#define PCI_INT_INTERNAL_SLV_TIMEOUT      (1<<23)
+#define PCI_INT_AUX_TIMEOUT               (1<<18)
+#define PCI_INT_AUX_INT                   (1<<17)
+#define PCI_INT_1394                      (1<<16)
+#define PCI_INT_DMA4_PCL                  (1<<9)
+#define PCI_INT_DMA4_HLT                  (1<<8)
+#define PCI_INT_DMA3_PCL                  (1<<7)
+#define PCI_INT_DMA3_HLT                  (1<<6)
+#define PCI_INT_DMA2_PCL                  (1<<5)
+#define PCI_INT_DMA2_HLT                  (1<<4)
+#define PCI_INT_DMA1_PCL                  (1<<3)
+#define PCI_INT_DMA1_HLT                  (1<<2)
+#define PCI_INT_DMA0_PCL                  (1<<1)
+#define PCI_INT_DMA0_HLT                  (1<<0)
+/* all DMA interrupts combined: */
+#define PCI_INT_DMA_ALL                   0x3ff
+
+#define PCI_INT_DMA_HLT(chan)             (1 << (chan * 2))
+#define PCI_INT_DMA_PCL(chan)             (1 << (chan * 2 + 1))
+
+#define LBUS_ADDR                         0xb4
+#define LBUS_ADDR_SEL_RAM                 (0x0<<16)
+#define LBUS_ADDR_SEL_ROM                 (0x1<<16)
+#define LBUS_ADDR_SEL_AUX                 (0x2<<16)
+#define LBUS_ADDR_SEL_ZV                  (0x3<<16)       
+
+#define GPIO_CTRL_A                       0xb8
+#define GPIO_CTRL_B                       0xbc
+#define GPIO_DATA_BASE                    0xc0
+
+#define DMA_BREG(base, chan)              (base + chan * 0x20)
+#define DMA_SREG(base, chan)              (base + chan * 0x10)
+
+#define DMA0_PREV_PCL                     0x100               
+#define DMA1_PREV_PCL                     0x120
+#define DMA2_PREV_PCL                     0x140
+#define DMA3_PREV_PCL                     0x160
+#define DMA4_PREV_PCL                     0x180
+#define DMA_PREV_PCL(chan)                (DMA_BREG(DMA0_PREV_PCL, chan))
+
+#define DMA0_CURRENT_PCL                  0x104            
+#define DMA1_CURRENT_PCL                  0x124
+#define DMA2_CURRENT_PCL                  0x144
+#define DMA3_CURRENT_PCL                  0x164
+#define DMA4_CURRENT_PCL                  0x184
+#define DMA_CURRENT_PCL(chan)             (DMA_BREG(DMA0_CURRENT_PCL, chan))
+
+#define DMA0_CHAN_STAT                    0x10c
+#define DMA1_CHAN_STAT                    0x12c
+#define DMA2_CHAN_STAT                    0x14c
+#define DMA3_CHAN_STAT                    0x16c
+#define DMA4_CHAN_STAT                    0x18c
+#define DMA_CHAN_STAT(chan)               (DMA_BREG(DMA0_CHAN_STAT, chan))
+/* CHAN_STATUS registers share bits */
+#define DMA_CHAN_STAT_SELFID              (1<<31)
+#define DMA_CHAN_STAT_ISOPKT              (1<<30)
+#define DMA_CHAN_STAT_PCIERR              (1<<29)
+#define DMA_CHAN_STAT_PKTERR              (1<<28)
+#define DMA_CHAN_STAT_PKTCMPL             (1<<27)
+#define DMA_CHAN_STAT_SPECIALACK          (1<<14)
+
+
+#define DMA0_CHAN_CTRL                    0x110              
+#define DMA1_CHAN_CTRL                    0x130
+#define DMA2_CHAN_CTRL                    0x150
+#define DMA3_CHAN_CTRL                    0x170
+#define DMA4_CHAN_CTRL                    0x190
+#define DMA_CHAN_CTRL(chan)               (DMA_BREG(DMA0_CHAN_CTRL, chan))
+/* CHAN_CTRL registers share bits */
+#define DMA_CHAN_CTRL_ENABLE              (1<<31)      
+#define DMA_CHAN_CTRL_BUSY                (1<<30)
+#define DMA_CHAN_CTRL_LINK                (1<<29)
+
+#define DMA0_READY                        0x114
+#define DMA1_READY                        0x134
+#define DMA2_READY                        0x154
+#define DMA3_READY                        0x174
+#define DMA4_READY                        0x194
+#define DMA_READY(chan)                   (DMA_BREG(DMA0_READY, chan))
+
+#define DMA_GLOBAL_REGISTER               0x908
+
+#define FIFO_SIZES                        0xa00
+
+#define FIFO_CONTROL                      0xa10
+#define GRF_FLUSH                         (1<<4)
+#define ITF_FLUSH                         (1<<3)
+#define ATF_FLUSH                         (1<<2)
+
+#define FIFO_XMIT_THRESHOLD               0xa14
+
+#define DMA0_WORD0_CMP_VALUE              0xb00
+#define DMA1_WORD0_CMP_VALUE              0xb10
+#define DMA2_WORD0_CMP_VALUE              0xb20
+#define DMA3_WORD0_CMP_VALUE              0xb30
+#define DMA4_WORD0_CMP_VALUE              0xb40
+#define DMA_WORD0_CMP_VALUE(chan)         (DMA_SREG(DMA0_WORD0_CMP_VALUE, chan))
+
+#define DMA0_WORD0_CMP_ENABLE             0xb04
+#define DMA1_WORD0_CMP_ENABLE             0xb14
+#define DMA2_WORD0_CMP_ENABLE             0xb24
+#define DMA3_WORD0_CMP_ENABLE             0xb34
+#define DMA4_WORD0_CMP_ENABLE             0xb44
+#define DMA_WORD0_CMP_ENABLE(chan)        (DMA_SREG(DMA0_WORD0_CMP_ENABLE,chan))
+
+#define DMA0_WORD1_CMP_VALUE              0xb08
+#define DMA1_WORD1_CMP_VALUE              0xb18
+#define DMA2_WORD1_CMP_VALUE              0xb28
+#define DMA3_WORD1_CMP_VALUE              0xb38
+#define DMA4_WORD1_CMP_VALUE              0xb48
+#define DMA_WORD1_CMP_VALUE(chan)         (DMA_SREG(DMA0_WORD1_CMP_VALUE, chan))
+
+#define DMA0_WORD1_CMP_ENABLE             0xb0c
+#define DMA1_WORD1_CMP_ENABLE             0xb1c
+#define DMA2_WORD1_CMP_ENABLE             0xb2c
+#define DMA3_WORD1_CMP_ENABLE             0xb3c
+#define DMA4_WORD1_CMP_ENABLE             0xb4c
+#define DMA_WORD1_CMP_ENABLE(chan)        (DMA_SREG(DMA0_WORD1_CMP_ENABLE,chan))
+/* word 1 compare enable flags */
+#define DMA_WORD1_CMP_MATCH_OTHERBUS      (1<<15)
+#define DMA_WORD1_CMP_MATCH_BROADCAST     (1<<14)
+#define DMA_WORD1_CMP_MATCH_BUS_BCAST     (1<<13)
+#define DMA_WORD1_CMP_MATCH_NODE_BCAST    (1<<12)
+#define DMA_WORD1_CMP_MATCH_LOCAL         (1<<11)
+#define DMA_WORD1_CMP_ENABLE_SELF_ID      (1<<10)
+#define DMA_WORD1_CMP_ENABLE_MASTER       (1<<8)
+
+#define LINK_ID                           0xf00
+#define LINK_ID_BUS(id)                   (id<<22)
+#define LINK_ID_NODE(id)                  (id<<16)
+
+#define LINK_CONTROL                      0xf04
+#define LINK_CONTROL_BUSY                 (1<<29)
+#define LINK_CONTROL_TX_ISO_EN            (1<<26)
+#define LINK_CONTROL_RX_ISO_EN            (1<<25)
+#define LINK_CONTROL_TX_ASYNC_EN          (1<<24)
+#define LINK_CONTROL_RX_ASYNC_EN          (1<<23)
+#define LINK_CONTROL_RESET_TX             (1<<21)
+#define LINK_CONTROL_RESET_RX             (1<<20)
+#define LINK_CONTROL_CYCMASTER            (1<<11)
+#define LINK_CONTROL_CYCSOURCE            (1<<10)
+#define LINK_CONTROL_CYCTIMEREN           (1<<9)
+#define LINK_CONTROL_RCV_CMP_VALID        (1<<7)
+#define LINK_CONTROL_SNOOP_ENABLE         (1<<6)
+
+#define CYCLE_TIMER                       0xf08
+
+#define LINK_PHY                          0xf0c
+#define LINK_PHY_READ                     (1<<31)
+#define LINK_PHY_WRITE                    (1<<30)
+#define LINK_PHY_ADDR(addr)               (addr<<24)
+#define LINK_PHY_WDATA(data)              (data<<16)
+#define LINK_PHY_RADDR(addr)              (addr<<8)
+
+
+#define LINK_INT_STATUS                   0xf14
+#define LINK_INT_ENABLE                   0xf18
+/* status and enable have identical bit numbers */
+#define LINK_INT_LINK_INT                 (1<<31)
+#define LINK_INT_PHY_TIMEOUT              (1<<30)
+#define LINK_INT_PHY_REG_RCVD             (1<<29)
+#define LINK_INT_PHY_BUSRESET             (1<<28)
+#define LINK_INT_TX_RDY                   (1<<26)
+#define LINK_INT_RX_DATA_RDY              (1<<25)
+#define LINK_INT_ISO_STUCK                (1<<20)
+#define LINK_INT_ASYNC_STUCK              (1<<19)
+#define LINK_INT_SENT_REJECT              (1<<17)
+#define LINK_INT_HDR_ERR                  (1<<16)
+#define LINK_INT_TX_INVALID_TC            (1<<15)
+#define LINK_INT_CYC_SECOND               (1<<11)
+#define LINK_INT_CYC_START                (1<<10)
+#define LINK_INT_CYC_DONE                 (1<<9)
+#define LINK_INT_CYC_PENDING              (1<<8)
+#define LINK_INT_CYC_LOST                 (1<<7)
+#define LINK_INT_CYC_ARB_FAILED           (1<<6)
+#define LINK_INT_GRF_OVERFLOW             (1<<5)
+#define LINK_INT_ITF_UNDERFLOW            (1<<4)
+#define LINK_INT_ATF_UNDERFLOW            (1<<3)
+#define LINK_INT_ISOARB_FAILED            (1<<0) 
+
+/* PHY specifics */
+#define PHY_VENDORID_TI                 0x800028
+#define PHY_PRODUCTID_TSB41LV03         0x000000
+
+
+/* this is the physical layout of a PCL, its size is 128 bytes */
+struct ti_pcl {
+        u32 next;
+        u32 async_error_next;
+        u32 user_data;
+        u32 pcl_status;
+        u32 remaining_transfer_count;
+        u32 next_data_buffer;
+        struct {
+                u32 control;
+                u32 pointer;
+        } buffer[13];
+};
+
+#include <linux/stddef.h>
+#define pcloffs(MEMBER) (offsetof(struct ti_pcl, MEMBER))
+
+
+#ifdef CONFIG_IEEE1394_PCILYNX_LOCALRAM
+
+inline static void put_pcl(const struct ti_lynx *lynx, pcl_t pclid,
+                           const struct ti_pcl *pcl)
+{
+        int i;
+        u32 *in = (u32 *)pcl;
+        u32 *out = (u32 *)(lynx->local_ram + pclid * sizeof(struct ti_pcl));
+
+        for (i = 0; i < 32; i++, out++, in++) {
+                writel(cpu_to_le32(*in), out);
+        }
+}
+
+inline static void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
+                           struct ti_pcl *pcl)
+{
+        int i;
+        u32 *out = (u32 *)pcl;
+        u32 *in = (u32 *)(lynx->local_ram + pclid * sizeof(struct ti_pcl));
+
+        for (i = 0; i < 32; i++, out++, in++) {
+                *out = le32_to_cpu(readl(in));
+        }
+}
+
+inline static u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
+{
+        return lynx->dev->resource[1].start + pclid * sizeof(struct ti_pcl);
+}
+
+#else /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
+
+inline static void put_pcl(const struct ti_lynx *lynx, pcl_t pclid,
+                           const struct ti_pcl *pcl)
+{
+        memcpy_le32((u32 *)(lynx->pcl_mem + pclid * sizeof(struct ti_pcl)),
+                    (u32 *)pcl, sizeof(struct ti_pcl));
+}
+
+inline static void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
+                           struct ti_pcl *pcl)
+{
+        memcpy_le32((u32 *)pcl,
+                    (u32 *)(lynx->pcl_mem + pclid * sizeof(struct ti_pcl)),
+                    sizeof(struct ti_pcl));
+}
+
+inline static u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
+{
+        return virt_to_bus(lynx->pcl_mem) + pclid * sizeof(struct ti_pcl);
+}
+
+#endif /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
+
+
+inline static void run_sub_pcl(const struct ti_lynx *lynx, pcl_t pclid, int idx,
+                               int dmachan)
+{
+        reg_write(lynx, DMA0_CURRENT_PCL + dmachan * 0x20,
+                  pcl_bus(lynx, pclid) + idx * 4);
+        reg_write(lynx, DMA0_CHAN_CTRL + dmachan * 0x20,
+                  DMA_CHAN_CTRL_ENABLE | DMA_CHAN_CTRL_LINK);
+}
+
+inline static void run_pcl(const struct ti_lynx *lynx, pcl_t pclid, int dmachan)
+{
+        run_sub_pcl(lynx, pclid, 0, dmachan);
+}
+
+#define PCL_NEXT_INVALID (1<<0)
+
+/* transfer commands */
+#define PCL_CMD_RCV            (0x1<<24)
+#define PCL_CMD_RCV_AND_UPDATE (0xa<<24)
+#define PCL_CMD_XMT            (0x2<<24)
+#define PCL_CMD_UNFXMT         (0xc<<24)
+#define PCL_CMD_PCI_TO_LBUS    (0x8<<24)
+#define PCL_CMD_LBUS_TO_PCI    (0x9<<24)
+
+/* aux commands */
+#define PCL_CMD_NOP            (0x0<<24)
+#define PCL_CMD_LOAD           (0x3<<24)
+#define PCL_CMD_STOREQ         (0x4<<24)
+#define PCL_CMD_STORED         (0xb<<24)
+#define PCL_CMD_STORE0         (0x5<<24)
+#define PCL_CMD_STORE1         (0x6<<24)
+#define PCL_CMD_COMPARE        (0xe<<24)
+#define PCL_CMD_SWAP_COMPARE   (0xf<<24)
+#define PCL_CMD_ADD            (0xd<<24)
+#define PCL_CMD_BRANCH         (0x7<<24)
+
+/* BRANCH condition codes */
+#define PCL_COND_DMARDY_SET    (0x1<<20)
+#define PCL_COND_DMARDY_CLEAR  (0x2<<20)
+
+#define PCL_GEN_INTR           (1<<19)
+#define PCL_LAST_BUFF          (1<<18)
+#define PCL_LAST_CMD           (PCL_LAST_BUFF)
+#define PCL_WAITSTAT           (1<<17)
+#define PCL_BIGENDIAN          (1<<16)
+
+
+quadlet_t lynx_csr_rom[] = {
+        /* bus info block */
+        0x04040000, /* info/CRC length, CRC */
+        0x31333934, /* 1394 magic number */
+        0xf064a000, /* misc. settings */
+        0x08002850, /* vendor ID, chip ID high */
+        0x0000ffff, /* chip ID low */
+        /* root directory */
+        0x00090000, /* CRC length, CRC */
+        0x03080028, /* vendor ID (Texas Instr.) */
+        0x81000009, /* offset to textual ID */
+        0x0c000200, /* node capabilities */
+        0x8d00000e, /* offset to unique ID */
+        0xc7000010, /* offset to module independent info */
+        0x04000000, /* module hardware version */
+        0x81000026, /* offset to textual ID */
+        0x09000000, /* node hardware version */
+        0x81000026, /* offset to textual ID */
+        /* module vendor ID textual */
+        0x00080000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54455841, /* "Texas Instruments" */
+        0x5320494e,
+        0x53545255,
+        0x4d454e54,
+        0x53000000,
+        /* node unique ID leaf */
+        0x00020000, /* CRC length, CRC */
+        0x08002850, /* vendor ID, chip ID high */
+        0x0000ffff, /* chip ID low */
+        /* module dependent info */
+        0x00060000, /* CRC length, CRC */
+        0xb8000006, /* offset to module textual ID */
+        0x81000004, /* ??? textual descriptor */
+        0x39010000, /* SRAM size */
+        0x3a010000, /* AUXRAM size */
+        0x3b000000, /* AUX device */
+        /* module textual ID */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54534231, /* "TSB12LV21" */
+        0x324c5632,
+        0x31000000,
+        /* part number */
+        0x00060000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x39383036, /* "9806000-0001" */
+        0x3030342d,
+        0x30303431,
+        0x20000001,
+        /* module hardware version textual */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x5453424b, /* "TSBKPCITST" */
+        0x50434954,
+        0x53540000,
+        /* node hardware version textual */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54534232, /* "TSB21LV03" */
+        0x313c5630,
+        0x33000000
+};
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/raw1394.c linux/drivers/ieee1394/raw1394.c
--- v2.3.39/linux/drivers/ieee1394/raw1394.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/raw1394.c	Fri Jan 14 19:18:53 2000
@@ -0,0 +1,823 @@
+/*
+ * IEEE 1394 for Linux
+ *
+ * Raw interface to the bus
+ *
+ * Copyright (C) 1999 Andreas E. Bombe
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+#include "ieee1394.h"
+#include "ieee1394_types.h"
+#include "ieee1394_core.h"
+#include "hosts.h"
+#include "highlevel.h"
+#include "ieee1394_transactions.h"
+#include "raw1394.h"
+
+
+LIST_HEAD(host_info_list);
+static int host_count = 0;
+spinlock_t host_info_lock = SPIN_LOCK_UNLOCKED;
+
+static struct hpsb_highlevel *hl_handle = NULL;
+
+static void queue_complete_cb(struct pending_request *req);
+
+static struct pending_request *__alloc_pending_request(int flags)
+{
+        struct pending_request *req;
+
+        req = (struct pending_request *)kmalloc(sizeof(struct pending_request),
+                                                flags);
+        if (req != NULL) {
+                memset(req, 0, sizeof(struct pending_request));
+                INIT_LIST_HEAD(&req->list);
+                req->tq.routine = (void(*)(void*))queue_complete_cb;
+        }
+
+        return req;
+}
+
+inline static struct pending_request *alloc_pending_request(void)
+{
+        return __alloc_pending_request(SLAB_KERNEL);
+}
+
+static void free_pending_request(struct pending_request *req)
+{
+        if (req->ibs) {
+                if (atomic_dec_and_test(&req->ibs->refcount)) {
+                        kfree(req->ibs);
+                }
+        } else if (req->free_data) {
+                kfree(req->data);
+        }
+        free_hpsb_packet(req->packet);
+        kfree(req);
+}
+
+static void queue_complete_req(struct pending_request *req)
+{
+        unsigned long flags;
+        struct file_info *fi = req->file_info;
+
+        spin_lock_irqsave(&fi->reqlists_lock, flags);
+        list_del(&req->list);
+        list_add_tail(&req->list, &fi->req_complete);
+        spin_unlock_irqrestore(&fi->reqlists_lock, flags);
+
+        up(&fi->complete_sem);
+        wake_up_interruptible(&fi->poll_wait_complete);
+}
+
+static void queue_complete_cb(struct pending_request *req)
+{
+        struct hpsb_packet *packet = req->packet;
+        int rcode = (packet->header[1] >> 12) & 0xf;
+
+        switch (packet->ack_code) {
+        case ACKX_NONE:
+        case ACKX_SEND_ERROR:
+                req->req.error = RAW1394_ERROR_SEND_ERROR;
+                break;
+        case ACKX_ABORTED:
+                req->req.error = RAW1394_ERROR_ABORTED;
+                break;
+        case ACKX_TIMEOUT:
+                req->req.error = RAW1394_ERROR_TIMEOUT;
+                break;
+        default:
+                req->req.error = (packet->ack_code << 16) | rcode;
+                break;
+        }
+
+        if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {
+                req->req.length = 0;
+        }
+
+        free_tlabel(packet->host, packet->node_id, packet->tlabel);
+        queue_complete_req(req);
+}
+
+
+static void add_host(struct hpsb_host *host)
+{
+        struct host_info *hi;
+
+        hi = (struct host_info *)kmalloc(sizeof(struct host_info), SLAB_KERNEL);
+        if (hi != NULL) {
+                INIT_LIST_HEAD(&hi->list);
+                hi->host = host;
+                INIT_LIST_HEAD(&hi->file_info_list);
+
+                spin_lock_irq(&host_info_lock);
+                list_add_tail(&hi->list, &host_info_list);
+                host_count++;
+                spin_unlock_irq(&host_info_lock);
+        }
+}
+
+
+static struct host_info *find_host_info(struct hpsb_host *host)
+{
+        struct list_head *lh;
+        struct host_info *hi;
+
+        lh = host_info_list.next;
+        while (lh != &host_info_list) {
+                hi = list_entry(lh, struct host_info, list);
+                if (hi->host == host) {
+                        return hi;
+                }
+                lh = lh->next;
+        }
+
+        return NULL;
+}
+
+static void remove_host(struct hpsb_host *host)
+{
+        struct host_info *hi;
+
+        spin_lock_irq(&host_info_lock);
+        hi = find_host_info(host);
+
+        if (hi != NULL) {
+                list_del(&hi->list);
+                host_count--;
+        }
+        spin_unlock_irq(&host_info_lock);
+
+        if (hi == NULL) {
+                printk(KERN_ERR "raw1394: attempt to remove unknown host "
+                       "0x%p\n", host);
+                return;
+        }
+
+        kfree(hi);
+}
+
+static void host_reset(struct hpsb_host *host)
+{
+        unsigned long flags;
+        struct list_head *lh;
+        struct host_info *hi;
+        struct file_info *fi;
+        struct pending_request *req;
+
+        spin_lock_irqsave(&host_info_lock, flags);
+        hi = find_host_info(host);
+
+        if (hi != NULL) {
+                lh = hi->file_info_list.next;
+
+                while (lh != &hi->file_info_list) {
+                        fi = list_entry(lh, struct file_info, list);
+                        req = __alloc_pending_request(SLAB_ATOMIC);
+
+                        if (req != NULL) {
+                                req->file_info = fi;
+                                req->req.type = RAW1394_REQ_BUS_RESET;
+                                req->req.generation = get_hpsb_generation();
+                                req->req.misc = (host->node_id << 16) 
+                                        | host->node_count;
+                                queue_complete_req(req);
+                        }
+                                
+                        lh = lh->next;
+                }
+        }
+        spin_unlock_irqrestore(&host_info_lock, flags);
+}
+
+static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
+                        unsigned int length)
+{
+        unsigned long flags;
+        struct list_head *lh;
+        struct host_info *hi;
+        struct file_info *fi;
+        struct pending_request *req;
+        struct iso_block_store *ibs = NULL;
+        LIST_HEAD(reqs);
+
+        spin_lock_irqsave(&host_info_lock, flags);
+        hi = find_host_info(host);
+
+        if (hi != NULL) {
+                for (lh = hi->file_info_list.next; lh != &hi->file_info_list;
+                     lh = lh->next) {
+                        fi = list_entry(lh, struct file_info, list);
+
+                        if (!(fi->listen_channels & (1ULL << channel))) {
+                                continue;
+                        }
+
+                        if (!ibs) {
+                                ibs = kmalloc(sizeof(struct iso_block_store)
+                                              + length, SLAB_ATOMIC);
+                                if (!ibs) break;
+
+                                atomic_set(&ibs->refcount, 0);
+                                memcpy(ibs->data, data, length);
+                        }
+
+                        req = __alloc_pending_request(SLAB_ATOMIC);
+                        if (!req) {
+                                kfree(ibs);
+                                break;
+                        }
+
+                        atomic_inc(&ibs->refcount);
+
+                        req->file_info = fi;
+                        req->ibs = ibs;
+                        req->data = ibs->data;
+                        req->req.type = RAW1394_REQ_ISO_RECEIVE;
+                        req->req.generation = get_hpsb_generation();
+                        req->req.misc = 0;
+                        req->req.recvb = fi->iso_buffer;
+                        req->req.length = MIN(length, fi->iso_buffer_length);
+                        
+                        list_add_tail(&req->list, &reqs);
+                }
+        }
+        spin_unlock_irqrestore(&host_info_lock, flags);
+
+        lh = reqs.next;
+        while (lh != &reqs) {
+                req = list_entry(lh, struct pending_request, list);
+                lh = lh->next;
+                queue_complete_req(req);
+        }
+}
+
+
+static int dev_read(struct file *file, char *buffer, size_t count,
+                    loff_t *offset_is_ignored)
+{
+        struct file_info *fi = (struct file_info *)file->private_data;
+        struct list_head *lh;
+        struct pending_request *req;
+
+        if (count != sizeof(struct raw1394_request)) {
+                return -EINVAL;
+        }
+
+        if (!access_ok(VERIFY_WRITE, buffer, count)) {
+                return -EFAULT;
+        }
+
+        if (file->f_flags & O_NONBLOCK) {
+                if (down_trylock(&fi->complete_sem)) {
+                        return -EAGAIN;
+                }
+        } else {
+                if (down_interruptible(&fi->complete_sem)) {
+                        return -ERESTARTSYS;
+                }
+        }
+
+        spin_lock_irq(&fi->reqlists_lock);
+        lh = fi->req_complete.next;
+        list_del(lh);
+        spin_unlock_irq(&fi->reqlists_lock);
+
+        req = list_entry(lh, struct pending_request, list);
+
+        if (req->req.length) {
+                if (copy_to_user(req->req.recvb, req->data, req->req.length)) {
+                        req->req.error = RAW1394_ERROR_MEMFAULT;
+                }
+        }
+        __copy_to_user(buffer, &req->req, sizeof(req->req));
+
+        free_pending_request(req);
+        return sizeof(struct raw1394_request);
+}
+
+
+static int state_opened(struct file_info *fi, struct pending_request *req)
+{
+        if (req->req.type == RAW1394_REQ_INITIALIZE) {
+                if (req->req.misc == RAW1394_KERNELAPI_VERSION) {
+                        fi->state = initialized;
+                        req->req.error = RAW1394_ERROR_NONE;
+                        req->req.generation = get_hpsb_generation();
+                } else {
+                        req->req.error = RAW1394_ERROR_COMPAT;
+                        req->req.misc = RAW1394_KERNELAPI_VERSION;
+                }
+        } else {
+                req->req.error = RAW1394_ERROR_STATE_ORDER;
+        }
+
+        req->req.length = 0;
+        queue_complete_req(req);
+        return sizeof(struct raw1394_request);
+}
+
+static int state_initialized(struct file_info *fi, struct pending_request *req)
+{
+        struct list_head *lh;
+        struct host_info *hi;
+        struct raw1394_khost_list *khl;
+
+        if (req->req.generation != get_hpsb_generation()) {
+                req->req.error = RAW1394_ERROR_GENERATION;
+                req->req.generation = get_hpsb_generation();
+                req->req.length = 0;
+                queue_complete_req(req);
+                return sizeof(struct raw1394_request);
+        }
+
+        switch (req->req.type) {
+        case RAW1394_REQ_LIST_CARDS:
+                spin_lock_irq(&host_info_lock);
+                khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
+                              SLAB_ATOMIC);
+
+                if (khl != NULL) {
+                        req->req.misc = host_count;
+                        req->data = (quadlet_t *)khl;
+                        
+                        lh = host_info_list.next;
+                        while (lh != &host_info_list) {
+                                hi = list_entry(lh, struct host_info, list);
+
+                                khl->nodes = hi->host->node_count;
+                                strcpy(khl->name, hi->host->template->name);
+
+                                khl++;
+                                lh = lh->next;
+                        }
+                }
+                spin_unlock_irq(&host_info_lock);
+
+                if (khl != NULL) {
+                        req->req.error = RAW1394_ERROR_NONE;
+                        req->req.length = MIN(req->req.length,
+                                              sizeof(struct raw1394_khost_list)
+                                              * req->req.misc);
+                        req->free_data = 1;
+                } else {
+                        return -ENOMEM;
+                }
+                break;
+
+        case RAW1394_REQ_SET_CARD:
+                lh = NULL;
+
+                spin_lock_irq(&host_info_lock);
+                if (req->req.misc < host_count) {
+                        lh = host_info_list.next;
+                        while (req->req.misc--) {
+                                lh = lh->next;
+                        }
+                        hi = list_entry(lh, struct host_info, list);
+                        hpsb_inc_host_usage(hi->host);
+                        list_add_tail(&fi->list, &hi->file_info_list);
+                        fi->host = hi->host;
+                        fi->state = connected;
+                }
+                spin_unlock_irq(&host_info_lock);
+
+                if (lh != NULL) {
+                        req->req.error = RAW1394_ERROR_NONE;
+                        req->req.misc = (fi->host->node_id << 16) 
+                                | fi->host->node_count;
+                } else {
+                        req->req.error = RAW1394_ERROR_INVALID_ARG;
+                }
+
+                req->req.length = 0;
+                break;
+
+        default:
+                req->req.error = RAW1394_ERROR_STATE_ORDER;
+                req->req.length = 0;
+                break;
+        }
+
+        queue_complete_req(req);
+        return sizeof(struct raw1394_request);
+}
+
+static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
+{
+        int channel = req->req.misc;
+
+        spin_lock(&host_info_lock);
+        if ((channel > 63) || (channel < -64)) {
+                req->req.error = RAW1394_ERROR_INVALID_ARG;
+        } else if (channel >= 0) {
+                /* allocate channel req.misc */
+                if (fi->listen_channels & (1ULL << channel)) {
+                        req->req.error = RAW1394_ERROR_ALREADY;
+                } else {
+                        fi->listen_channels |= 1ULL << channel;
+                        hpsb_listen_channel(hl_handle, fi->host, channel);
+                        fi->iso_buffer = req->req.recvb;
+                        fi->iso_buffer_length = req->req.length;
+                }
+        } else {
+                /* deallocate channel (one's complement neg) req.misc */
+                channel = ~channel;
+
+                if (fi->listen_channels & (1ULL << channel)) {
+                        hpsb_unlisten_channel(hl_handle, fi->host, channel);
+                        fi->listen_channels &= ~(1ULL << channel);
+                } else {
+                        req->req.error = RAW1394_ERROR_INVALID_ARG;
+                }
+        }
+
+        req->req.length = 0;
+        queue_complete_req(req);
+        spin_unlock(&host_info_lock);
+}
+
+static int handle_local_request(struct file_info *fi,
+                                struct pending_request *req)
+{
+        u64 addr = req->req.address & 0xffffffffffffULL;
+
+        req->data = kmalloc(req->req.length, SLAB_KERNEL);
+        if (!req->data) return -ENOMEM;
+        req->free_data = 1;
+
+        switch (req->req.type) {
+        case RAW1394_REQ_ASYNC_READ:
+                req->req.error = highlevel_read(fi->host, req->data, addr,
+                                                req->req.length);
+                break;
+
+        case RAW1394_REQ_ASYNC_WRITE:
+                if (copy_from_user(req->data, req->req.sendb, 
+                                   req->req.length)) {
+                        req->req.error = RAW1394_ERROR_MEMFAULT;
+                        break;
+                }
+
+                req->req.error = highlevel_write(fi->host, req->data, addr,
+                                                 req->req.length);
+                req->req.length = 0;
+                break;
+
+        case RAW1394_REQ_LOCK:
+                if ((req->req.misc != EXTCODE_FETCH_ADD)
+                    && (req->req.misc != EXTCODE_LITTLE_ADD)) {
+                        if (req->req.length != 4) {
+                                req->req.error = RAW1394_ERROR_INVALID_ARG;
+                                break;
+                        }
+                } else {
+                        if (req->req.length != 8) {
+                                req->req.error = RAW1394_ERROR_INVALID_ARG;
+                                break;
+                        }
+                }
+
+                if (copy_from_user(req->data, req->req.sendb,
+                                   req->req.length)) {
+                        req->req.error = RAW1394_ERROR_MEMFAULT;
+                        break;
+                }
+
+                if (req->req.length == 8) {
+                        req->req.error = highlevel_lock(fi->host, req->data,
+                                                        addr, req->data[0],
+                                                        req->data[1],
+                                                        req->req.misc);
+                        req->req.length = 4;
+                } else {
+                        req->req.error = highlevel_lock(fi->host, req->data,
+                                                        addr, req->data[0], 0,
+                                                        req->req.misc);
+                }
+                break;
+
+        case RAW1394_REQ_LOCK64:
+        default:
+                req->req.error = RAW1394_ERROR_STATE_ORDER;
+        }
+
+        if (req->req.error) req->req.length = 0;
+        req->req.error |= 0x00100000;
+        queue_complete_req(req);
+        return sizeof(struct raw1394_request);
+}
+
+static int handle_remote_request(struct file_info *fi,
+                                 struct pending_request *req, int node)
+{
+        struct hpsb_packet *packet = NULL;
+        u64 addr = req->req.address & 0xffffffffffffULL;
+
+        switch (req->req.type) {
+        case RAW1394_REQ_ASYNC_READ:
+                if (req->req.length == 4) {
+                        packet = hpsb_make_readqpacket(fi->host, node, addr);
+                        if (!packet) return -ENOMEM;
+
+                        req->data = &packet->header[3];
+                } else if ((req->req.length % 4) == 0) {
+                        packet = hpsb_make_readbpacket(fi->host, node, addr,
+                                                       req->req.length);
+                        if (!packet) return -ENOMEM;
+
+                        req->data = packet->data;
+                } else {
+                        req->req.error = RAW1394_ERROR_UNTIDY_LEN;
+                }
+                break;
+
+        case RAW1394_REQ_ASYNC_WRITE:
+                if (req->req.length == 4) {
+                        packet = hpsb_make_writeqpacket(fi->host, node, addr,
+                                                        0);
+                        if (!packet) return -ENOMEM;
+
+                        if (copy_from_user(&packet->header[3], req->req.sendb,
+                                           4)) {
+                                req->req.error = RAW1394_ERROR_MEMFAULT;
+                        }
+                } else if ((req->req.length % 4) == 0) {
+                        packet = hpsb_make_writebpacket(fi->host, node, addr,
+                                                        req->req.length);
+                        if (!packet) return -ENOMEM;
+
+                        if (copy_from_user(packet->data, req->req.sendb,
+                                           req->req.length)) {
+                                req->req.error = RAW1394_ERROR_MEMFAULT;
+                        }
+                } else {
+                        req->req.error = RAW1394_ERROR_UNTIDY_LEN;
+                }
+                req->req.length = 0;
+                break;
+
+        case RAW1394_REQ_LOCK:
+        case RAW1394_REQ_LOCK64:
+        default:
+                req->req.error = RAW1394_ERROR_STATE_ORDER;
+        }
+
+        req->packet = packet;
+
+        if (req->req.error) {
+                req->req.length = 0;
+                queue_complete_req(req);
+                return sizeof(struct raw1394_request);
+        }
+
+        req->tq.data = req;
+        queue_task(&req->tq, &packet->complete_tq);
+
+        spin_lock_irq(&fi->reqlists_lock);
+        list_add_tail(&req->list, &fi->req_pending);
+        spin_unlock_irq(&fi->reqlists_lock);
+
+        if (!hpsb_send_packet(packet)) {
+                req->req.error = RAW1394_ERROR_SEND_ERROR;
+                req->req.length = 0;
+                queue_complete_req(req);
+        }
+        return sizeof(struct raw1394_request);
+}
+
+static int state_connected(struct file_info *fi, struct pending_request *req)
+{
+        int node = req->req.address >> 48;
+
+        req->req.error = RAW1394_ERROR_NONE;
+
+        if (req->req.generation != get_hpsb_generation()) {
+                req->req.error = RAW1394_ERROR_GENERATION;
+                req->req.generation = get_hpsb_generation();
+                req->req.length = 0;
+                queue_complete_req(req);
+                return sizeof(struct raw1394_request);
+        }
+
+        if (req->req.type == RAW1394_REQ_ISO_LISTEN) {
+                handle_iso_listen(fi, req);
+                return sizeof(struct raw1394_request);
+        }
+
+        if (req->req.length == 0) {
+                req->req.error = RAW1394_ERROR_INVALID_ARG;
+                queue_complete_req(req);
+                return sizeof(struct raw1394_request);
+        }
+
+        if (fi->host->node_id == node) {
+                return handle_local_request(fi, req);
+        }
+
+        return handle_remote_request(fi, req, node);
+}
+
+
+static int dev_write(struct file *file, const char *buffer, size_t count,
+                     loff_t *offset_is_ignored)
+{
+        struct file_info *fi = (struct file_info *)file->private_data;
+        struct pending_request *req;
+        int retval = 0;
+
+        if (count != sizeof(struct raw1394_request)) {
+                return -EINVAL;
+        }
+
+        req = alloc_pending_request();
+        if (req == NULL) {
+                return -ENOMEM;
+        }
+        req->file_info = fi;
+
+        if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {
+                free_pending_request(req);
+                return -EFAULT;
+        }
+
+        switch (fi->state) {
+        case opened:
+                retval = state_opened(fi, req);
+                break;
+
+        case initialized:
+                retval = state_initialized(fi, req);
+                break;
+
+        case connected:
+                retval = state_connected(fi, req);
+                break;
+        }
+
+        if (retval < 0) {
+                free_pending_request(req);
+        }
+
+        return retval;
+}
+
+static unsigned int dev_poll(struct file *file, poll_table *pt)
+{
+        struct file_info *fi = file->private_data;
+        unsigned int mask = POLLOUT | POLLWRNORM;
+
+        poll_wait(file, &fi->poll_wait_complete, pt);
+
+        spin_lock_irq(&fi->reqlists_lock);
+        if (!list_empty(&fi->req_complete)) {
+                mask |= POLLIN | POLLRDNORM;
+        }
+        spin_unlock_irq(&fi->reqlists_lock);
+
+        return mask;
+}
+
+static int dev_open(struct inode *inode, struct file *file)
+{
+        struct file_info *fi;
+
+        if (MINOR(inode->i_rdev)) {
+                return -ENXIO;
+        }
+
+        fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
+        if (fi == NULL) {
+                return -ENOMEM;
+        }
+        
+        memset(fi, 0, sizeof(struct file_info));
+
+        INIT_LIST_HEAD(&fi->list);
+        fi->state = opened;
+        INIT_LIST_HEAD(&fi->req_pending);
+        INIT_LIST_HEAD(&fi->req_complete);
+        sema_init(&fi->complete_sem, 0);
+        spin_lock_init(&fi->reqlists_lock);
+        init_waitqueue_head(&fi->poll_wait_complete);
+
+        file->private_data = fi;
+
+        MOD_INC_USE_COUNT;
+        return 0;
+}
+
+static int dev_release(struct inode *inode, struct file *file)
+{
+        struct file_info *fi = file->private_data;
+        struct list_head *lh;
+        struct pending_request *req;
+        int done = 0, i;
+
+        for (i = 0; i < 64; i++) {
+                if (fi->listen_channels & (1ULL << i)) {
+                        hpsb_unlisten_channel(hl_handle, fi->host, i);
+                }
+        }
+
+        spin_lock(&host_info_lock);
+        fi->listen_channels = 0;
+        spin_unlock(&host_info_lock);
+
+        while (!done) {
+                spin_lock_irq(&fi->reqlists_lock);
+
+                while (!list_empty(&fi->req_complete)) {
+                        lh = fi->req_complete.next;
+                        list_del(lh);
+
+                        req = list_entry(lh, struct pending_request, list);
+
+                        free_pending_request(req);
+                }
+
+                if (list_empty(&fi->req_pending)) {
+                        done = 1;
+                }
+
+                spin_unlock_irq(&fi->reqlists_lock);
+
+                if (!done) {
+                        down_interruptible(&fi->complete_sem);
+                }
+        }
+
+        if (fi->state == connected) {
+                spin_lock_irq(&host_info_lock);
+                list_del(&fi->list);
+                spin_unlock_irq(&host_info_lock);
+
+                hpsb_dec_host_usage(fi->host);
+        }
+
+        kfree(fi);
+
+        MOD_DEC_USE_COUNT;
+        return 0;
+}
+
+static struct hpsb_highlevel_ops hl_ops = {
+        add_host,
+        remove_host,
+        host_reset,
+        iso_receive
+};
+
+static struct file_operations file_ops = {
+        read:     dev_read, 
+        write:    dev_write, 
+        poll:     dev_poll, 
+        open:     dev_open, 
+        release:  dev_release, 
+};
+
+int init_raw1394(void)
+{
+        hl_handle = hpsb_register_highlevel(RAW1394_DEVICE_NAME, &hl_ops);
+        if (hl_handle == NULL) {
+                HPSB_ERR("raw1394 failed to register with ieee1394 highlevel");
+                return -ENOMEM;
+        }
+
+        if (register_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME, 
+                            &file_ops)) {
+                HPSB_ERR("raw1394 failed to allocate device major");
+                return -EBUSY;
+        }
+
+        return 0;
+}
+
+void cleanup_raw1394(void)
+{
+        unregister_chrdev(RAW1394_DEVICE_MAJOR, RAW1394_DEVICE_NAME);
+        hpsb_unregister_highlevel(hl_handle);
+}
+
+#ifdef MODULE
+
+int init_module(void)
+{
+        return init_raw1394();
+}
+
+void cleanup_module(void)
+{
+        return cleanup_raw1394();
+}
+
+#endif
diff -u --recursive --new-file v2.3.39/linux/drivers/ieee1394/raw1394.h linux/drivers/ieee1394/raw1394.h
--- v2.3.39/linux/drivers/ieee1394/raw1394.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ieee1394/raw1394.h	Thu Jan 13 16:49:22 2000
@@ -0,0 +1,110 @@
+
+#ifndef IEEE1394_RAW1394_H
+#define IEEE1394_RAW1394_H
+
+#define RAW1394_DEVICE_MAJOR      171
+#define RAW1394_DEVICE_NAME       "raw1394"
+
+#define RAW1394_KERNELAPI_VERSION 1
+
+/* state: opened */
+#define RAW1394_REQ_INITIALIZE    1
+
+/* state: initialized */
+#define RAW1394_REQ_LIST_CARDS    2
+#define RAW1394_REQ_SET_CARD      3
+
+/* state: connected */
+#define RAW1394_REQ_ASYNC_READ    100
+#define RAW1394_REQ_ASYNC_WRITE   101
+#define RAW1394_REQ_LOCK          102
+#define RAW1394_REQ_LOCK64        103
+
+#define RAW1394_REQ_ISO_LISTEN    200
+
+/* kernel to user */
+#define RAW1394_REQ_BUS_RESET     10000
+#define RAW1394_REQ_ISO_RECEIVE   10001
+
+/* error codes */
+#define RAW1394_ERROR_NONE        0
+#define RAW1394_ERROR_COMPAT      (-1001)
+#define RAW1394_ERROR_STATE_ORDER (-1002)
+#define RAW1394_ERROR_GENERATION  (-1003)
+#define RAW1394_ERROR_INVALID_ARG (-1004)
+#define RAW1394_ERROR_MEMFAULT    (-1005)
+#define RAW1394_ERROR_ALREADY     (-1006)
+
+#define RAW1394_ERROR_EXCESSIVE   (-1020)
+#define RAW1394_ERROR_UNTIDY_LEN  (-1021)
+
+#define RAW1394_ERROR_SEND_ERROR  (-1100)
+#define RAW1394_ERROR_ABORTED     (-1101)
+#define RAW1394_ERROR_TIMEOUT     (-1102)
+
+
+struct raw1394_request {
+        int type;
+        int error;
+        int misc;
+
+        unsigned int generation;
+        octlet_t address;
+
+        unsigned long tag;
+
+        size_t length;
+        quadlet_t *sendb;
+        quadlet_t *recvb;
+};
+
+struct raw1394_khost_list {
+        int nodes;
+        char name[32];
+};
+
+#ifdef __KERNEL__
+
+struct iso_block_store {
+        atomic_t refcount;
+        quadlet_t data[0];
+};
+
+struct file_info {
+        struct list_head list;
+
+        enum { opened, initialized, connected } state;
+
+        struct hpsb_host *host;
+
+        struct list_head req_pending;
+        struct list_head req_complete;
+        struct semaphore complete_sem;
+        spinlock_t reqlists_lock;
+        wait_queue_head_t poll_wait_complete;
+
+        u64 listen_channels;
+        quadlet_t *iso_buffer;
+        size_t iso_buffer_length;
+};
+
+struct pending_request {
+        struct list_head list;
+        struct file_info *file_info;
+        struct hpsb_packet *packet;
+        struct tq_struct tq;
+        struct iso_block_store *ibs;
+        quadlet_t *data;
+        int free_data;
+        struct raw1394_request req;
+};
+
+struct host_info {
+        struct list_head list;
+        struct hpsb_host *host;
+        struct list_head file_info_list;
+};
+
+#endif /* __KERNEL__ */
+
+#endif /* IEEE1394_RAW1394_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.3.39/linux/drivers/net/3c509.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/net/3c509.c	Mon Jan 17 16:26:43 2000
@@ -251,6 +251,7 @@
 				if (el3_debug > 2) {
 					printk("3c529: irq %d  ioaddr 0x%x  ifport %d\n", irq, ioaddr, if_port);
 				}
+				EL3WINDOW(0);
 				for (i = 0; i < 3; i++) {
 					phys_addr[i] = htons(read_eeprom(ioaddr, i));
 				}
diff -u --recursive --new-file v2.3.39/linux/drivers/net/3c527.c linux/drivers/net/3c527.c
--- v2.3.39/linux/drivers/net/3c527.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/net/3c527.c	Thu Jan 20 10:44:46 2000
@@ -16,7 +16,7 @@
  */
 
 static const char *version =
-	"3c527.c:v0.05 1999/09/06 Alan Cox (alan@redhat.com)\n";
+	"3c527.c:v0.07 2000/01/18 Alan Cox (alan@redhat.com)\n";
 
 /*
  *	Things you need
@@ -447,10 +447,22 @@
 
 
 /*
- *	Send exec commands
+ *	Send exec commands. This requires a bit of explaining.
+ *
+ *	You feed the card a command, you wait, it interrupts you get a 
+ *	reply. All well and good. The complication arises because you use
+ *	commands for filter list changes which come in at bh level from things
+ *	like IPV6 group stuff.
+ *
+ *	We have a simple state machine
+ *
+ *	0	- nothing issued
+ *	1	- command issued, wait reply
+ *	2	- reply waiting - reader then goes to state 0
+ *	3	- command issued, trash reply. In which case the irq
+ *		  takes it back to state 0
  */
 
-
 /*
  *	Send command from interrupt state
  */
@@ -463,7 +475,7 @@
 	if(lp->exec_pending)
 		return -1;
 		
-	lp->exec_pending=1;
+	lp->exec_pending=3;
 	lp->exec_box->mbox=0;
 	lp->exec_box->mbox=cmd;
 	memcpy((void *)lp->exec_box->data, data, len);
@@ -492,6 +504,9 @@
 	 *	Wait for a command
 	 */
 	 
+	save_flags(flags);
+	cli();
+	 
 	while(lp->exec_pending)
 		sleep_on(&lp->event);
 		
@@ -500,6 +515,9 @@
 	 */
 
 	lp->exec_pending=1;
+	
+	restore_flags(flags);
+	
 	lp->exec_box->mbox=0;
 	lp->exec_box->mbox=cmd;
 	memcpy((void *)lp->exec_box->data, data, len);
@@ -826,6 +844,10 @@
 		wmb();
 		
 		np->length	= skb->len;
+		
+		if(np->length < 60)
+			np->length = 60;
+			
 		np->data	= virt_to_bus(skb->data);
 		np->status	= 0;
 		np->control	= (1<<7)|(1<<6);	/* EOP EOL */
@@ -1015,8 +1037,11 @@
 		status>>=3;
 		if(status&1)
 		{
-			/* 0=no 1=yes 2=reply clearing */
-			lp->exec_pending=2;
+			/* 0=no 1=yes 2=replied, get cmd, 3 = wait reply & dump it */
+			if(lp->exec_pending!=3)
+				lp->exec_pending=2;
+			else
+				lp->exec_pending=0;
 			wake_up(&lp->event);
 		}
 		if(status&2)
diff -u --recursive --new-file v2.3.39/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.3.39/linux/drivers/net/Config.in	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/Config.in	Thu Jan 13 18:03:58 2000
@@ -34,6 +34,7 @@
       tristate '  MACE (Power Mac ethernet) support' CONFIG_MACE
       tristate '  BMAC (G3 ethernet) support' CONFIG_BMAC
       tristate '  Symbios 53c885 (Synergy ethernet) support' CONFIG_NCR885E
+      tristate '  National DP83902AV (Oak ethernet) support' CONFIG_OAKNET
    fi
    if [ "$CONFIG_ZORRO" = "y" ]; then
       tristate '  Ariadne support' CONFIG_ARIADNE
@@ -261,6 +262,6 @@
 
 source drivers/net/wan/Config.in
 
-if [ "$CONFIG_PCMCIA" != "n" ]; then
+if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
    source drivers/net/pcmcia/Config.in
 fi
diff -u --recursive --new-file v2.3.39/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.3.39/linux/drivers/net/Makefile	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/Makefile	Thu Jan 13 18:03:58 2000
@@ -250,6 +250,7 @@
 obj-$(CONFIG_BMAC) += bmac.o
 obj-$(CONFIG_NCR885E) += ncr885e.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
+obj-$(CONFIG_OAKNET) += oaknet.o 8390.o
 
 #
 # HIPPI adapters
diff -u --recursive --new-file v2.3.39/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v2.3.39/linux/drivers/net/lance.c	Wed Dec  8 14:11:26 1999
+++ linux/drivers/net/lance.c	Thu Jan 20 10:44:46 2000
@@ -40,12 +40,16 @@
     8/20/96 Fixed 7990 autoIRQ failure and reversed unneeded alignment -djb
     v1.12 10/27/97 Module support -djb
     v1.14  2/3/98 Module support modified, made PCI support optional -djb
+    v1.15 5/27/99 Fixed bug in the cleanup_module(). dev->priv was freed
+                  before unregister_netdev() which caused NULL pointer
+                  reference later in the chain (in rtnetlink_fill_ifinfo())
+                  -- Mika Kuoppala <miku@iki.fi>
     
     Forward ported v1.14 to 2.1.129, merged the PCI and misc changes from
     the 2.1 version of the old driver - Alan Cox
 */
 
-static const char *version = "lance.c:v1.14ac 1998/11/20 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
+static const char *version = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -349,11 +353,11 @@
 	for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
 		struct net_device *dev = &dev_lance[this_dev];
 		if (dev->priv != NULL) {
-			kfree(dev->priv);
-			dev->priv = NULL;
+			unregister_netdev(dev);	
 			free_dma(dev->dma);
 			release_region(dev->base_addr, LANCE_TOTAL_SIZE);
-			unregister_netdev(dev);
+			kfree(dev->priv);
+			dev->priv = NULL;
 		}
 	}
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/net/oaknet.c linux/drivers/net/oaknet.c
--- v2.3.39/linux/drivers/net/oaknet.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/net/oaknet.c	Tue Jan 11 21:49:26 2000
@@ -12,8 +12,6 @@
  */
 
 #include <linux/module.h>
-
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/3c574_cs.c linux/drivers/net/pcmcia/3c574_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/3c574_cs.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/pcmcia/3c574_cs.c	Tue Jan 18 22:29:17 2000
@@ -119,7 +119,7 @@
 #define TX_TIMEOUT  ((800*HZ)/1000)
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 64;
+static int max_interrupt_work = 32;
 
 /* Force full duplex modes? */
 static int full_duplex = 0;
@@ -207,6 +207,8 @@
 #define MEDIA_TP	0x00C0	/* Enable link beat and jabber for 10baseT. */
 
 struct el3_private {
+	dev_link_t link;
+	struct net_device dev;
 	dev_node_t node;
 	struct net_device_stats stats;
 	u16 advertising, partner;			/* NWay media advertisement */
@@ -253,13 +255,11 @@
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void update_stats(ioaddr_t addr, struct net_device *dev);
+static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev, int worklimit);
 static int el3_close(struct net_device *dev);
-#ifdef HAVE_PRIVATE_IOCTL
-static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#endif
+static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static void set_rx_mode(struct net_device *dev);
 
 static dev_info_t dev_info = "3c574_cs";
@@ -307,6 +307,7 @@
 
 static dev_link_t *tc574_attach(void)
 {
+	struct el3_private *lp;
 	client_reg_t client_reg;
 	dev_link_t *link;
 	struct net_device *dev;
@@ -316,8 +317,12 @@
 	flush_stale_links();
 
 	/* Create the PC card device object. */
-	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-	memset(link, 0, sizeof(struct dev_link_t));
+	lp = kmalloc(sizeof(*lp), GFP_KERNEL);
+	if (!lp) return NULL;
+	memset(lp, 0, sizeof(*lp));
+	link = &lp->link; dev = &lp->dev;
+	link->priv = dev->priv = link->irq.Instance = lp;
+	
 	link->release.function = &tc574_release;
 	link->release.data = (u_long)link;
 	link->io.NumPorts1 = 32;
@@ -336,33 +341,18 @@
 	link->conf.ConfigIndex = 1;
 	link->conf.Present = PRESENT_OPTION;
 
-	/* Create the network device object. */
-	dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-	memset(dev, 0, sizeof(struct net_device));
-
-	/* Make up a Odie-specific data structure. */
-	dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
-	memset(dev->priv, 0, sizeof(struct el3_private));
-
 	/* The EL3-specific entries in the device structure. */
 	dev->hard_start_xmit = &el3_start_xmit;
 	dev->get_stats = &el3_get_stats;
-#ifdef HAVE_PRIVATE_IOCTL
-	dev->do_ioctl = &private_ioctl;
-#endif
+	dev->do_ioctl = &el3_ioctl;
 	dev->set_multicast_list = &set_rx_mode;
 	ether_setup(dev);
-	dev->name = ((struct el3_private *)dev->priv)->node.dev_name;
+	dev->name = lp->node.dev_name;
 	dev->init = &tc574_init;
 	dev->open = &el3_open;
 	dev->stop = &el3_close;
 	dev->tbusy = 1;
 
-	link->priv = dev;
-#if CS_RELEASE_CODE > 0x2911
-	link->irq.Instance = dev;
-#endif
-
 	/* Register with Card Services */
 	link->next = dev_list;
 	dev_list = link;
@@ -396,6 +386,7 @@
 
 static void tc574_detach(dev_link_t *link)
 {
+	struct el3_private *lp = link->priv;
 	dev_link_t **linkp;
 	long flags;
 
@@ -428,15 +419,9 @@
 
 	/* Unlink device structure, free bits */
 	*linkp = link->next;
-	if (link->priv) {
-		struct net_device *dev = link->priv;
-		if (link->dev != NULL)
-			unregister_netdev(dev);
-		if (dev->priv)
-			kfree(dev->priv);
-		kfree(link->priv);
-	}
-	kfree(link);
+	if (link->dev)
+		unregister_netdev(&lp->dev);
+	kfree(lp);
 
 } /* tc574_detach */
 
@@ -451,9 +436,9 @@
 
 static void tc574_config(dev_link_t *link)
 {
-	client_handle_t handle;
-	struct net_device *dev;
-	struct el3_private *lp;
+	client_handle_t handle = link->handle;
+	struct el3_private *lp = link->priv;
+	struct net_device *dev = &lp->dev;
 	tuple_t tuple;
 	cisparse_t parse;
 	u_short buf[32];
@@ -462,8 +447,6 @@
 	u16 *phys_addr;
 	char *cardname;
 
-	handle = link->handle;
-	dev = link->priv;
 	phys_addr = (u16 *)dev->dev_addr;
 
 	DEBUG(0, "3c574_config(0x%p)\n", link);
@@ -528,7 +511,6 @@
 	link->state &= ~DEV_CONFIG_PENDING;
 
 	ioaddr = dev->base_addr;
-	lp = (struct el3_private *)dev->priv;
 	link->dev = &lp->node;
 
 	/* The 3c574 normally uses an EEPROM for configuration info, including
@@ -641,7 +623,8 @@
 static void tc574_release(u_long arg)
 {
 	dev_link_t *link = (dev_link_t *)arg;
-	struct net_device *dev = link->priv;
+	struct el3_private *lp = link->priv;
+	struct net_device *dev = &lp->dev;
 
 	DEBUG(0, "3c574_release(0x%p)\n", link);
 
@@ -675,7 +658,8 @@
 					   event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
-	struct net_device *dev = link->priv;
+	struct el3_private *lp = link->priv;
+	struct net_device *dev = &lp->dev;
 
 	DEBUG(1, "3c574_event(0x%06x)\n", event);
 
@@ -922,10 +906,8 @@
 static int el3_open(struct net_device *dev)
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
-	dev_link_t *link;
+	dev_link_t *link = &lp->link;
 
-	for (link = dev_list; link; link = link->next)
-		if (link->priv == dev) break;
 	if (!DEV_OK(link))
 		return -ENODEV;
 	
@@ -935,14 +917,14 @@
 	
 	tc574_reset(dev);
 	lp->media.function = &media_check;
-	lp->media.data = (u_long)dev;
+	lp->media.data = (u_long)lp;
 	lp->media.expires = jiffies + HZ;
 	add_timer(&lp->media);
 	
 	DEBUG(2, "%s: opened, status %4.4x.\n",
 		  dev->name, inw(dev->base_addr + EL3_STATUS));
 	
-	return 0;					/* Always succeed */
+	return 0;
 }
 
 static void el3_tx_timeout(struct net_device *dev)
@@ -1054,14 +1036,13 @@
 /* The EL3 interrupt handler. */
 static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	struct net_device *dev = (struct net_device *)dev_id;
-	struct el3_private *lp;
+	struct el3_private *lp = dev_id;
+	struct net_device *dev = &lp->dev;
 	ioaddr_t ioaddr, status;
 	int work_budget = max_interrupt_work;
 
-	if ((dev == NULL) || !dev->start)
+	if ((lp == NULL) || !dev->start)
 		return;
-	lp = (struct el3_private *)dev->priv;
 	ioaddr = dev->base_addr;
 
 #ifdef PCMCIA_DEBUG
@@ -1098,7 +1079,7 @@
 		if (status & (AdapterFailure | RxEarly | StatsFull)) {
 			/* Handle all uncommon interrupts. */
 			if (status & StatsFull)
-				update_stats(ioaddr, dev);
+				update_stats(dev);
 			if (status & RxEarly) {
 				work_budget = el3_rx(dev, work_budget);
 				outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
@@ -1151,8 +1132,8 @@
 */
 static void media_check(u_long arg)
 {
-    struct net_device *dev = (struct net_device *)(arg);
-    struct el3_private *lp = (struct el3_private *)dev->priv;
+    struct el3_private *lp = (struct el3_private *)arg;
+    struct net_device *dev = &lp->dev;
     ioaddr_t ioaddr = dev->base_addr;
     u_long flags;
 	u_short /* cable, */ media, partner;
@@ -1165,7 +1146,7 @@
 		(inb(ioaddr + Timer) == 0xff)) {
 		if (!lp->fast_poll)
 			printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-		el3_interrupt(dev->irq, dev, NULL);
+		el3_interrupt(dev->irq, lp, NULL);
 		lp->fast_poll = HZ;
     }
     if (lp->fast_poll) {
@@ -1228,7 +1209,7 @@
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 
 	if (dev->start)
-		update_stats(dev->base_addr, dev);
+		update_stats(dev);
 	return &lp->stats;
 }
 
@@ -1236,9 +1217,10 @@
 	Suprisingly this need not be run single-threaded, but it effectively is.
 	The counters clear when read, so the adds must merely be atomic.
  */
-static void update_stats(ioaddr_t ioaddr, struct net_device *dev)
+static void update_stats(struct net_device *dev)
 {
 	struct el3_private *lp = (struct el3_private *)dev->priv;
+	ioaddr_t ioaddr = dev->base_addr;
 	u8 upper_cnt;
 
 	DEBUG(2, "%s: updating the statistics.\n", dev->name);
@@ -1252,16 +1234,16 @@
 	lp->stats.tx_carrier_errors 	+= inb(ioaddr + 0);
 	lp->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
 	/* Multiple collisions. */	   	inb(ioaddr + 2);
-	lp->stats.collisions		+= inb(ioaddr + 3);
-	lp->stats.tx_window_errors	+= inb(ioaddr + 4);
-	lp->stats.rx_fifo_errors	+= inb(ioaddr + 5);
-	lp->stats.tx_packets		+= inb(ioaddr + 6);
-	upper_cnt = inb(ioaddr + 9);
-	lp->stats.tx_packets		+= (upper_cnt&0x30) << 4;
-	/* Rx packets   */			inb(ioaddr + 7);
-	/* Tx deferrals */			inb(ioaddr + 8);
-	lp->stats.rx_bytes += inw(ioaddr + 10);
-	lp->stats.tx_bytes += inw(ioaddr + 12);
+	lp->stats.collisions			+= inb(ioaddr + 3);
+	lp->stats.tx_window_errors		+= inb(ioaddr + 4);
+	lp->stats.rx_fifo_errors		+= inb(ioaddr + 5);
+	lp->stats.tx_packets			+= inb(ioaddr + 6);
+	upper_cnt 						 = inb(ioaddr + 9);
+	lp->stats.tx_packets			+= (upper_cnt&0x30) << 4;
+	/* Rx packets   */				inb(ioaddr + 7);
+	/* Tx deferrals */				inb(ioaddr + 8);
+	lp->stats.rx_bytes 				+= inw(ioaddr + 10);
+	lp->stats.tx_bytes				+= inw(ioaddr + 12);
 
 	/* With Vortex and later we must also clear the BadSSD counter. */
 	EL3WINDOW(4);
@@ -1284,12 +1266,12 @@
 			short error = rx_status & 0x3800;
 			lp->stats.rx_errors++;
 			switch (error) {
-			case 0x0000:		lp->stats.rx_over_errors++; break;
-			case 0x0800:		lp->stats.rx_length_errors++; break;
-			case 0x1000:		lp->stats.rx_frame_errors++; break;
-			case 0x1800:		lp->stats.rx_length_errors++; break;
-			case 0x2000:		lp->stats.rx_frame_errors++; break;
-			case 0x2800:		lp->stats.rx_crc_errors++; break;
+			case 0x0000:	lp->stats.rx_over_errors++; break;
+			case 0x0800:	lp->stats.rx_length_errors++; break;
+			case 0x1000:	lp->stats.rx_frame_errors++; break;
+			case 0x1800:	lp->stats.rx_length_errors++; break;
+			case 0x2000:	lp->stats.rx_frame_errors++; break;
+			case 0x2800:	lp->stats.rx_crc_errors++; break;
 			}
 		} else {
 			short pkt_len = rx_status & 0x7ff;
@@ -1343,14 +1325,13 @@
 	return worklimit;
 }
 
-#ifdef HAVE_PRIVATE_IOCTL
 /* Provide ioctl() calls to examine the MII xcvr state. */
-static int private_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct el3_private *vp = (struct el3_private *)dev->priv;
+	struct el3_private *lp = (struct el3_private *)dev->priv;
 	ioaddr_t ioaddr = dev->base_addr;
 	u16 *data = (u16 *)&rq->ifr_data;
-	int phy = vp->phys[0] & 0x1f;
+	int phy = lp->phys[0] & 0x1f;
 
 	DEBUG(2, "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",
 		  dev->name, rq->ifr_ifrn.ifrn_name, cmd,
@@ -1378,7 +1359,7 @@
 			int saved_window;
 			long flags;
 
-			if (!suser())
+			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
 			save_flags(flags);
 			cli();
@@ -1393,7 +1374,6 @@
 		return -EOPNOTSUPP;
 	}
 }
-#endif  /* HAVE_PRIVATE_IOCTL */
 
 /* The Odie chip has a 64 bin multicast filter, but the bit layout is not
    documented.  Until it is we revert to receiving all multicast frames when
@@ -1419,12 +1399,8 @@
 static int el3_close(struct net_device *dev)
 {
 	ioaddr_t ioaddr = dev->base_addr;
-	dev_link_t *link;
-
-	for (link = dev_list; link; link = link->next)
-		if (link->priv == dev) break;
-	if (link == NULL)
-		return -ENODEV;
+	struct el3_private *lp = dev->priv;
+	dev_link_t *link = &lp->link;
 
 	DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
 	
@@ -1439,12 +1415,12 @@
 		/* Note: Switching to window 0 may disable the IRQ. */
 		EL3WINDOW(0);
 		
-		update_stats(ioaddr, dev);
+		update_stats(dev);
 	}
 
 	link->open--;
 	dev->start = 0;
-	del_timer(&((struct el3_private *)dev->priv)->media);
+	del_timer(&lp->media);
 	if (link->state & DEV_STALE_CONFIG) {
 		link->release.expires = jiffies + HZ/20;
 		link->state |= DEV_RELEASE_PENDING;
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/3c575_cb.c linux/drivers/net/pcmcia/3c575_cb.c
--- v2.3.39/linux/drivers/net/pcmcia/3c575_cb.c	Tue Nov 23 22:42:20 1999
+++ linux/drivers/net/pcmcia/3c575_cb.c	Tue Jan 18 22:29:17 2000
@@ -24,7 +24,7 @@
 /* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */
 static const int mtu = 1500;
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
+static int max_interrupt_work = 32;
 
 /* Put out somewhat more debugging messages. (0: no msg, 1 minimal .. 6). */
 #define vortex_debug debug
@@ -40,7 +40,7 @@
 
 /* A few values that may be tweaked. */
 /* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (2*HZ)
+#define TX_TIMEOUT  ((400*HZ)/1000)
 
 /* Keep the ring sizes a power of two for efficiency. */
 #define TX_RING_SIZE	16
@@ -442,13 +442,15 @@
 		full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang  */
 		hw_csums:1,				/* Has hardware checksums. */
 		tx_full:1,
-		open:1;
+		open:1,
+		reap:1;
 	u16 status_enable;
 	u16 intr_enable;
 	u16 available_media;				/* From Wn3_Options. */
 	u16 capabilities, info1, info2;		/* Various, from EEPROM. */
 	u16 advertising;					/* NWay media advertisement */
 	unsigned char phys[2];				/* MII device addresses. */
+	u16 deferred;
 };
 
 /* The action to take with a media selection timer tick.
@@ -520,6 +522,22 @@
 
 #include <pcmcia/driver_ops.h>
 
+static void vortex_reap(void)
+{
+	struct net_device **devp, **next;
+	printk(KERN_DEBUG "vortex_reap()\n");
+	for (devp = &root_vortex_dev; *devp; devp = next) {
+		struct vortex_private *vp = (*devp)->priv;
+		next = &vp->next_module;
+		if (vp->open || !vp->reap) continue;
+		unregister_netdev(*devp);
+		if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
+		kfree(*devp);
+		kfree(vp->priv_addr);
+		*devp = *next; next = devp;
+	}
+}
+
 static dev_node_t *vortex_attach(dev_locator_t *loc)
 {
 	u16 dev_id, vendor_id;
@@ -528,6 +546,7 @@
 	struct net_device *dev;
 	int chip_idx;
 
+	vortex_reap();
 	if (loc->bus != LOC_PCI) return NULL;
 	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
 	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
@@ -567,23 +586,16 @@
 
 static void vortex_detach(dev_node_t *node)
 {
-	struct net_device **devp, **next;
-	printk(KERN_INFO "vortex_detach(%s)\n", node->dev_name);
-	for (devp = &root_vortex_dev; *devp; devp = next) {
-		next = &((struct vortex_private *)(*devp)->priv)->next_module;
-		if (strcmp((*devp)->name, node->dev_name) == 0) break;
+	struct net_device *dev, *next;
+	printk(KERN_DEBUG "vortex_detach(%s)\n", node->dev_name);
+	for (dev = root_vortex_dev; dev; dev = next) {
+		next = ((struct vortex_private *)dev->priv)->next_module;
+		if (strcmp(dev->name, node->dev_name) == 0) break;
 	}
-	if (*devp) {
-		struct net_device *dev = *devp;
+	if (dev && dev->priv) {
 		struct vortex_private *vp = dev->priv;
-		if (dev->flags & IFF_UP)
-			vortex_close(dev);
-		dev->flags &= ~(IFF_UP|IFF_RUNNING);
-		unregister_netdev(dev);
-		if (vp->cb_fn_base) iounmap(vp->cb_fn_base);
-		kfree(dev);
-		*devp = *next;
-		kfree(vp->priv_addr);
+		if (vp->open) vortex_down(dev);
+		vp->reap = 1;
 		kfree(node);
 		MOD_DEC_USE_COUNT;
 	}
@@ -592,7 +604,7 @@
 static void vortex_suspend(dev_node_t *node)
 {
 	struct net_device *dev, *next;
-	printk(KERN_INFO "vortex_suspend(%s)\n", node->dev_name);
+	printk(KERN_DEBUG "vortex_suspend(%s)\n", node->dev_name);
 	for (dev = root_vortex_dev; dev; dev = next) {
 		next = ((struct vortex_private *)dev->priv)->next_module;
 		if (strcmp(dev->name, node->dev_name) == 0) break;
@@ -606,7 +618,7 @@
 static void vortex_resume(dev_node_t *node)
 {
 	struct net_device *dev, *next;
-	printk(KERN_INFO "vortex_resume(%s)\n", node->dev_name);
+	printk(KERN_DEBUG "vortex_resume(%s)\n", node->dev_name);
 	for (dev = root_vortex_dev; dev; dev = next) {
 		next = ((struct vortex_private *)dev->priv)->next_module;
 		if (strcmp(dev->name, node->dev_name) == 0) break;
@@ -797,9 +809,9 @@
 	{
 		void *mem = kmalloc(sizeof(*vp) + 15, GFP_KERNEL);
 		vp =  (void *)(((long)mem + 15) & ~15);
+		memset(vp, 0, sizeof(*vp));
 		vp->priv_addr = mem;
 	}
-	memset(vp, 0, sizeof(*vp));
 	dev->priv = vp;
 
 	vp->next_module = root_vortex_dev;
@@ -1133,7 +1145,9 @@
 		dev->hard_start_xmit = &boomerang_start_xmit;
 		vp->cur_tx = vp->dirty_tx = 0;
 		outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */
-		/* Clear the Tx ring. */
+		/* Clear the Rx, Tx rings. */
+		for (i = 0; i < RX_RING_SIZE; i++)
+			vp->rx_ring[i].status = 0;
 		for (i = 0; i < TX_RING_SIZE; i++)
 			vp->tx_skbuff[i] = 0;
 		outl(0, ioaddr + DownListPtr);
@@ -1172,6 +1186,10 @@
 	struct vortex_private *vp = (struct vortex_private *)dev->priv;
 	int i;
 
+#ifdef CARDBUS
+	if (vp->reap)
+		return -ENODEV;
+#endif
 	/* Use the now-standard shared IRQ implementation. */
 	if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) {
 		return -EAGAIN;
@@ -1306,6 +1324,8 @@
 
 	vp->timer.expires = RUN_AT(next_tick);
 	add_timer(&vp->timer);
+	if (vp->deferred)
+		outw(FakeIntr, ioaddr + EL3_CMD);
 	return;
 }
 
@@ -1431,10 +1451,10 @@
 			   dev->name, fifo_diag);
 		/* Adapter failure requires Tx/Rx reset and reinit. */
 		if (vp->full_bus_master_tx) {
+			/* In this case, blow the card away */
+			vortex_down(dev);
 			wait_for_completion(dev, TotalReset | 0xff);
-			/* Re-enable the receiver. */
-			outw(RxEnable, ioaddr + EL3_CMD);
-			outw(TxEnable, ioaddr + EL3_CMD);
+			vortex_up(dev);
 		} else if (fifo_diag & 0x0400)
 			do_tx_reset = 1;
 		if (fifo_diag & 0x3000) {
@@ -1597,6 +1617,10 @@
 	ioaddr = dev->base_addr;
 	latency = inb(ioaddr + Timer);
 	status = inw(ioaddr + EL3_STATUS);
+	if (status & IntReq) {
+		status |= vp->deferred;
+		vp->deferred = 0;
+	}
 
 	if (status == 0xffff)
 		goto handler_exit;
@@ -1665,19 +1689,20 @@
 		}
 
 		if (--work_done < 0) {
-			if ((status & (0x7fe - (UpComplete | DownComplete))) == 0) {
-				/* Just ack these and return. */
-				outw(AckIntr | UpComplete | DownComplete, ioaddr + EL3_CMD);
-			} else {
-				printk(KERN_WARNING "%s: Too much work in interrupt, status "
-					   "%4.4x.  Temporarily disabling functions (%4.4x).\n",
-					   dev->name, status, SetStatusEnb | ((~status) & 0x7FE));
-				/* Disable all pending interrupts. */
-				outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD);
-				outw(AckIntr | 0x7FF, ioaddr + EL3_CMD);
-				/* The timer will reenable interrupts. */
-				break;
-			}
+			printk(KERN_WARNING "%s: Too much work in interrupt, status "
+				   "%4.4x.\n", dev->name, status);
+			/* Disable all pending interrupts. */
+			do {
+				vp->deferred |= status;
+				outw(SetStatusEnb | (~vp->deferred & vp->status_enable),
+					 ioaddr + EL3_CMD);
+				outw(AckIntr | (vp->deferred & 0x7ff), ioaddr + EL3_CMD);
+			} while ((status = inw(ioaddr + EL3_CMD)) & IntLatch);
+			/* The timer will reenable interrupts. */
+			del_timer(&vp->timer);
+			vp->timer.expires = RUN_AT(1);
+			add_timer(&vp->timer);
+			break;
 		}
 		/* Acknowledge the IRQ. */
 		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
@@ -1758,12 +1783,8 @@
 				printk(KERN_NOTICE "%s: No memory to allocate a sk_buff of "
 					   "size %d.\n", dev->name, pkt_len);
 		}
-		outw(RxDiscard, ioaddr + EL3_CMD);
 		vp->stats.rx_dropped++;
-		/* Wait a limited time to skip this packet. */
-		for (i = 200; i >= 0; i--)
-			if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress))
-				break;
+		wait_for_completion(dev, RxDiscard);
 	}
 
 	return 0;
@@ -2185,6 +2206,7 @@
 
 #ifdef CARDBUS
 	unregister_driver(&vortex_ops);
+	vortex_reap();
 #endif
 
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/3c589_cs.c linux/drivers/net/pcmcia/3c589_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/3c589_cs.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/pcmcia/3c589_cs.c	Tue Jan 18 22:29:17 2000
@@ -4,7 +4,7 @@
     
     Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
 
-    3c589_cs.c 1.137 1999/11/08 20:46:17
+    3c589_cs.c 1.143 1999/12/30 21:28:10
 
     The network driver code is based on Donald Becker's 3c589 code:
     
@@ -99,13 +99,15 @@
 #define TX_TIMEOUT	((400*HZ)/1000)
 
 struct el3_private {
-    dev_node_t node;
+    dev_link_t		link;
+    struct net_device	dev;
+    dev_node_t 		node;
     struct net_device_stats stats;
     /* For transceiver monitoring */
-    struct timer_list media;
-    u_short	media_status;
-    u_short	fast_poll;
-    u_long	last_irq;
+    struct timer_list	media;
+    u_short		media_status;
+    u_short		fast_poll;
+    u_long		last_irq;
 };
 
 static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
@@ -115,7 +117,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"3c589_cs.c 1.137 1999/11/08 20:46:17 (David Hinds)";
+"3c589_cs.c 1.143 1999/12/30 21:28:10 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -149,7 +151,7 @@
 static int el3_open(struct net_device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void update_stats(ioaddr_t addr, struct net_device *dev);
+static void update_stats(struct net_device *dev);
 static struct net_device_stats *el3_get_stats(struct net_device *dev);
 static int el3_rx(struct net_device *dev);
 static int el3_close(struct net_device *dev);
@@ -211,6 +213,7 @@
 
 static dev_link_t *tc589_attach(void)
 {
+    struct el3_private *lp;
     client_reg_t client_reg;
     dev_link_t *link;
     struct net_device *dev;
@@ -220,8 +223,12 @@
     flush_stale_links();
     
     /* Create new ethernet device */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    memset(link, 0, sizeof(struct dev_link_t));
+    lp = kmalloc(sizeof(*lp), GFP_KERNEL);
+    if (!lp) return NULL;
+    memset(lp, 0, sizeof(*lp));
+    link = &lp->link; dev = &lp->dev;
+    link->priv = dev->priv = link->irq.Instance = lp;
+    
     link->release.function = &tc589_release;
     link->release.data = (u_long)link;
     link->io.NumPorts1 = 16;
@@ -240,25 +247,17 @@
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
     
-    dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-    memset(dev, 0, sizeof(struct net_device));
-    
-    /* Make up a EL3-specific-data structure. */
-    dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
-    memset(dev->priv, 0, sizeof(struct el3_private));
-    
     /* The EL3-specific entries in the device structure. */
     dev->hard_start_xmit = &el3_start_xmit;
     dev->set_config = &el3_config;
     dev->get_stats = &el3_get_stats;
     dev->set_multicast_list = &set_multicast_list;
     ether_setup(dev);
-    dev->name = ((struct el3_private *)dev->priv)->node.dev_name;
+    dev->name = lp->node.dev_name;
     dev->init = &tc589_init;
     dev->open = &el3_open;
     dev->stop = &el3_close;
     dev->tbusy = 1;
-    link->priv = link->irq.Instance = dev;
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -293,6 +292,7 @@
 
 static void tc589_detach(dev_link_t *link)
 {
+    struct el3_private *lp = link->priv;
     dev_link_t **linkp;
     long flags;
     
@@ -325,15 +325,9 @@
     
     /* Unlink device structure, free bits */
     *linkp = link->next;
-    if (link->priv) {
-	struct net_device *dev = link->priv;
-	if (link->dev != NULL)
-	    unregister_netdev(dev);
-	if (dev->priv)
-	    kfree(dev->priv);
-	kfree(link->priv);
-    }
-    kfree(link);
+    if (link->dev)
+	unregister_netdev(&lp->dev);
+    kfree(lp);
     
 } /* tc589_detach */
 
@@ -350,8 +344,9 @@
 
 static void tc589_config(dev_link_t *link)
 {
-    client_handle_t handle;
-    struct net_device *dev;
+    client_handle_t handle = link->handle;
+    struct el3_private *lp = link->priv;
+    struct net_device *dev = &lp->dev;
     tuple_t tuple;
     cisparse_t parse;
     u_short buf[32], *phys_addr;
@@ -359,12 +354,9 @@
     ioaddr_t ioaddr;
     char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
     
-    handle = link->handle;
-    dev = link->priv;
-    phys_addr = (u_short *)dev->dev_addr;
-
     DEBUG(0, "3c589_config(0x%p)\n", link);
 
+    phys_addr = (u_short *)dev->dev_addr;
     tuple.Attributes = 0;
     tuple.DesiredTuple = CISTPL_CONFIG;
     CS_CHECK(GetFirstTuple, handle, &tuple);
@@ -434,7 +426,7 @@
 	}
     }
     
-    link->dev = &((struct el3_private *)dev->priv)->node;
+    link->dev = &lp->node;
     
     /* The address and resource configuration register aren't loaded from
        the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
@@ -507,7 +499,8 @@
 		       event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
+    struct el3_private *lp = link->priv;
+    struct net_device *dev = &lp->dev;
     
     DEBUG(1, "3c589_event(0x%06x)\n", event);
     
@@ -683,10 +676,8 @@
 static int el3_open(struct net_device *dev)
 {
     struct el3_private *lp = (struct el3_private *)dev->priv;
-    dev_link_t *link;
+    dev_link_t *link = &lp->link;
     
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
     if (!DEV_OK(link))
 	return -ENODEV;
 
@@ -696,14 +687,14 @@
     
     tc589_reset(dev);
     lp->media.function = &media_check;
-    lp->media.data = (u_long)dev;
+    lp->media.data = (u_long)lp;
     lp->media.expires = jiffies + HZ;
     add_timer(&lp->media);
 
     DEBUG(1, "%s: opened, status %4.4x.\n",
 	  dev->name, inw(dev->base_addr + EL3_STATUS));
     
-    return 0;					/* Always succeed */
+    return 0;
 }
 
 static void el3_tx_timeout(struct net_device *dev)
@@ -746,7 +737,6 @@
 
 static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-    struct el3_private *lp = (struct el3_private *)dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
 
     /* Transmitter timeout, serious problems. */
@@ -765,6 +755,7 @@
 	printk(KERN_NOTICE "%s: transmitter access conflict.\n",
 	       dev->name);
     else {
+	struct el3_private *lp = (struct el3_private *)dev->priv;
 	lp->stats.tx_bytes += skb->len;
 	/* Put out the doubleword header... */
 	outw(skb->len, ioaddr + TX_FIFO);
@@ -789,14 +780,13 @@
 /* The EL3 interrupt handler. */
 static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct net_device *dev = (struct net_device *)dev_id;
-    struct el3_private *lp;
+    struct el3_private *lp = dev_id;
+    struct net_device *dev = &lp->dev;
     ioaddr_t ioaddr, status;
     int i = 0;
     
-    if ((dev == NULL) || !dev->start)
+    if ((lp == NULL) || !dev->start)
 	return;
-    lp = (struct el3_private *)dev->priv;
     ioaddr = dev->base_addr;
 
 #ifdef PCMCIA_DEBUG
@@ -834,7 +824,7 @@
 	if (status & (AdapterFailure | RxEarly | StatsFull)) {
 	    /* Handle all uncommon interrupts. */
 	    if (status & StatsFull)		/* Empty statistics. */
-		update_stats(ioaddr, dev);
+		update_stats(dev);
 	    if (status & RxEarly) {		/* Rx early is unused. */
 		el3_rx(dev);
 		outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
@@ -883,14 +873,14 @@
 
 static void media_check(u_long arg)
 {
-    struct net_device *dev = (struct net_device *)(arg);
-    struct el3_private *lp = (struct el3_private *)dev->priv;
+    struct el3_private *lp = (struct el3_private *)(arg);
+    struct net_device *dev = &lp->dev;
     ioaddr_t ioaddr = dev->base_addr;
     u_short media, errs;
     u_long flags;
 
     if (dev->start == 0) goto reschedule;
-    
+
     EL3WINDOW(1);
     /* Check for pending interrupt with expired latency timer: with
        this, we can limp along even if the interrupt is blocked */
@@ -898,7 +888,7 @@
 	(inb(ioaddr + EL3_TIMER) == 0xff)) {
 	if (!lp->fast_poll)
 	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-	el3_interrupt(dev->irq, dev, NULL);
+	el3_interrupt(dev->irq, lp, NULL);
 	lp->fast_poll = HZ;
     }
     if (lp->fast_poll) {
@@ -965,14 +955,12 @@
 {
     struct el3_private *lp = (struct el3_private *)dev->priv;
     unsigned long flags;
-    dev_link_t *link;
+    dev_link_t *link = &lp->link;
 
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
     if (DEV_OK(link)) {
 	save_flags(flags);
 	cli();
-	update_stats(dev->base_addr, dev);
+	update_stats(dev);
 	restore_flags(flags);
     }
     return &lp->stats;
@@ -984,10 +972,11 @@
   operation, and it's simpler for the rest of the driver to assume that
   window 1 is always valid rather than use a special window-state variable.
 */
-static void update_stats(ioaddr_t ioaddr, struct net_device *dev)
+static void update_stats(struct net_device *dev)
 {
     struct el3_private *lp = (struct el3_private *)dev->priv;
-    
+    ioaddr_t ioaddr = dev->base_addr;
+
     DEBUG(2, "%s: updating the statistics.\n", dev->name);
     /* Turn off statistics updates while reading. */
     outw(StatsDisable, ioaddr + EL3_CMD);
@@ -1002,8 +991,8 @@
     lp->stats.tx_packets		+= inb(ioaddr + 6);
     /* Rx packets   */			inb(ioaddr + 7);
     /* Tx deferrals */			inb(ioaddr + 8);
-    inw(ioaddr + 10);	/* Total Rx and Tx octets. */
-    inw(ioaddr + 12);
+    /* Rx octets */			inw(ioaddr + 10);
+    /* Tx octets */			inw(ioaddr + 12);
     
     /* Back to window 1, and turn statistics back on. */
     EL3WINDOW(1);
@@ -1025,12 +1014,12 @@
 	    short error = rx_status & 0x3800;
 	    lp->stats.rx_errors++;
 	    switch (error) {
-	    case 0x0000:		lp->stats.rx_over_errors++; break;
-	    case 0x0800:		lp->stats.rx_length_errors++; break;
-	    case 0x1000:		lp->stats.rx_frame_errors++; break;
-	    case 0x1800:		lp->stats.rx_length_errors++; break;
-	    case 0x2000:		lp->stats.rx_frame_errors++; break;
-	    case 0x2800:		lp->stats.rx_crc_errors++; break;
+	    case 0x0000:	lp->stats.rx_over_errors++; break;
+	    case 0x0800:	lp->stats.rx_length_errors++; break;
+	    case 0x1000:	lp->stats.rx_frame_errors++; break;
+	    case 0x1800:	lp->stats.rx_length_errors++; break;
+	    case 0x2000:	lp->stats.rx_frame_errors++; break;
+	    case 0x2800:	lp->stats.rx_crc_errors++; break;
 	    }
 	} else {
 	    short pkt_len = rx_status & 0x7ff;
@@ -1073,10 +1062,10 @@
  */
 static void set_multicast_list(struct net_device *dev)
 {
+    struct el3_private *lp = dev->priv;
+    dev_link_t *link = &lp->link;
     ioaddr_t ioaddr = dev->base_addr;
-    dev_link_t *link;
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
+
     if (!(DEV_OK(link))) return;
 #ifdef PCMCIA_DEBUG
     if (pc_debug > 2) {
@@ -1099,13 +1088,9 @@
 
 static int el3_close(struct net_device *dev)
 {
+    struct el3_private *lp = dev->priv;
+    dev_link_t *link = &lp->link;
     ioaddr_t ioaddr = dev->base_addr;
-    dev_link_t *link;
-
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
-    if (link == NULL)
-	return -ENODEV;
     
     DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
 
@@ -1133,12 +1118,12 @@
         
 	/* Check if the card still exists */
 	if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000)
-	    update_stats(ioaddr, dev);
+	    update_stats(dev);
     }
 
     link->open--;
     dev->start = 0;
-    del_timer(&((struct el3_private *)dev->priv)->media);
+    del_timer(&lp->media);
     if (link->state & DEV_STALE_CONFIG) {
 	link->release.expires = jiffies + HZ/20;
 	link->state |= DEV_RELEASE_PENDING;
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in
--- v2.3.39/linux/drivers/net/pcmcia/Config.in	Tue Jan  4 13:57:17 2000
+++ linux/drivers/net/pcmcia/Config.in	Mon Jan 17 22:22:52 2000
@@ -31,6 +31,8 @@
    fi
 fi
 
+endmenu
+
 if [ "$CONFIG_PCMCIA_3C589" = "y" -o "$CONFIG_PCMCIA_3C574" = "y" -o \
      "$CONFIG_PCMCIA_FMVJ18X" = "y" -o "$CONFIG_PCMCIA_PCNET" = "y" -o \
      "$CONFIG_PCMCIA_NMCLAN" = "y" -o "$CONFIG_PCMCIA_SMC91C92" = "y" -o \
@@ -38,5 +40,3 @@
      "$CONFIG_PCMCIA_NETWAVE" = "y" -o "$CONFIG_PCMCIA_WAVELAN" = "y" ]; then
    define_bool CONFIG_PCMCIA_NETCARD y
 fi
-
-endmenu
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/fmvj18x_cs.c linux/drivers/net/pcmcia/fmvj18x_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/fmvj18x_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/fmvj18x_cs.c	Tue Jan 18 22:29:17 2000
@@ -69,16 +69,6 @@
 #define DEBUG(n, args...)
 #endif
 
-/*
-   For debugging this driver you may need more information.
-   To enable printing registers or status, set 'fmvj18x_debug=#' option .
- */
-#ifdef FMVJ18X_DEBUG
-static int fmvj18x_debug = FMVJ18X_DEBUG;
-#else
-static int fmvj18x_debug = 2;
-#endif /* FMVJ18X_DEBUG */
-
 /* Bit map of interrupts to choose from */
 /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
 static u_int irq_mask = 0xdeb8;
@@ -138,6 +128,8 @@
     driver specific data structure
 */
 typedef struct local_info_t {
+    dev_link_t link;
+    struct net_device dev;
     dev_node_t node;
     struct net_device_stats stats;
     long open_time;
@@ -273,17 +265,21 @@
 
 static dev_link_t *fmvj18x_attach(void)
 {
-    client_reg_t client_reg;
+    local_info_t *lp;
     dev_link_t *link;
     struct net_device *dev;
+    client_reg_t client_reg;
     int i, ret;
     
     DEBUG(0, "fmvj18x_attach()\n");
     flush_stale_links();
 
-    /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    memset(link, 0, sizeof(struct dev_link_t));
+    /* Make up a FMVJ18x specific data structure */
+    lp = kmalloc(sizeof(*lp), GFP_KERNEL);
+    if (!lp) return NULL;
+    memset(lp, 0, sizeof(*lp));
+    link = &lp->link; dev = &lp->dev;
+    link->priv = dev->priv = link->irq.Instance = lp;
 
     link->release.function = &fmvj18x_release;
     link->release.data = (u_long)link;
@@ -308,24 +304,17 @@
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    /* Make up a FMVJ18x specific data structure */
-    dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-    memset(dev, 0, sizeof(struct net_device));
-    dev->priv = kmalloc(sizeof(local_info_t), GFP_KERNEL);
-    memset(dev->priv, 0, sizeof(local_info_t));
-
     /* The FMVJ18x specific entries in the device structure. */
     dev->hard_start_xmit = &fjn_start_xmit;
     dev->set_config = &fjn_config;
     dev->get_stats = &fjn_get_stats;
     dev->set_multicast_list = &set_rx_mode;
     ether_setup(dev);
-    dev->name = ((local_info_t *)dev->priv)->node.dev_name;
+    dev->name = lp->node.dev_name;
     dev->init = &fmvj18x_init;
     dev->open = &fjn_open;
     dev->stop = &fjn_close;
     dev->tbusy = 0xFF;
-    link->priv = link->irq.Instance = dev;
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -353,6 +342,7 @@
 
 static void fmvj18x_detach(dev_link_t *link)
 {
+    local_info_t *lp = link->priv;
     dev_link_t **linkp;
     long flags;
     
@@ -386,15 +376,9 @@
     
     /* Unlink device structure, free pieces */
     *linkp = link->next;
-    if (link->priv) {
-	struct net_device *dev = link->priv;
-	if (link->dev != NULL)
-	    unregister_netdev(dev);
-	if (dev->priv) 
-	    kfree(dev->priv);
-	kfree(dev);
-    }
-    kfree(link);
+    if (link->dev)
+	unregister_netdev(&lp->dev);
+    kfree(lp);
     
 } /* fmvj18x_detach */
 
@@ -405,10 +389,11 @@
 
 static void fmvj18x_config(dev_link_t *link)
 {
-    client_handle_t handle;
+    client_handle_t handle = link->handle;
+    local_info_t *lp = link->priv;
+    struct net_device *dev = &lp->dev;
     tuple_t tuple;
     cisparse_t parse;
-    struct net_device *dev;
     u_short buf[32];
     int i, last_fn, last_ret;
     ioaddr_t ioaddr;
@@ -416,9 +401,6 @@
     char *card_name = "unknown";
     u_char *node_id;
     
-    handle = link->handle;
-    dev =link->priv;
-
     DEBUG(0, "fmvj18x_config(0x%p)\n", link);
 
     /*
@@ -538,10 +520,10 @@
 	break;
     }
 
-    link->dev = &((local_info_t *)dev->priv)->node;
+    link->dev = &lp->node;
     link->state &= ~DEV_CONFIG_PENDING;
 
-    ((struct local_info_t *)dev->priv)->cardtype = cardtype ;
+    lp->cardtype = cardtype;
     /* print current configuration */
     printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ", 
 	   dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", 
@@ -594,7 +576,8 @@
 			  event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
+    local_info_t *lp = link->priv;
+    struct net_device *dev = &lp->dev;
 
     DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
     
@@ -677,12 +660,12 @@
 
 static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct net_device *dev = (struct net_device *)dev_id;
+    local_info_t *lp = dev_id;
+    struct net_device *dev = &lp->dev;
     ioaddr_t ioaddr;
-    local_info_t *lp;
     unsigned short tx_stat, rx_stat;
 
-    if (dev == NULL) {
+    if (lp == NULL) {
         printk(KERN_NOTICE "fjn_interrupt(): irq %d for "
 	       "unknown device.\n", irq);
         return;
@@ -693,7 +676,6 @@
         return;
     }
     dev->interrupt = 1;
-    lp = (struct local_info_t *)dev->priv;
     ioaddr = dev->base_addr;
 
     /* avoid multiple interrupts */
@@ -710,12 +692,8 @@
     outb(tx_stat, ioaddr + TX_STATUS);
     outb(rx_stat, ioaddr + RX_STATUS);
     
-    if (fmvj18x_debug > 4) {
-        printk(KERN_DEBUG "%s: interrupt, rx_status %02x.\n",
-	       dev->name, rx_stat);
-        printk(KERN_DEBUG "               tx_status %02x.\n",
-	       tx_stat);
-    }
+    DEBUG(4, "%s: interrupt, rx_status %02x.\n", dev->name, rx_stat);
+    DEBUG(4, "               tx_status %02x.\n", tx_stat);
     
     if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
 	/* there is packet(s) in rx buffer */
@@ -738,11 +716,8 @@
 	    mark_bh(NET_BH);	/* Inform upper layers. */
 	}
     }
-    if (fmvj18x_debug > 4) {
-        printk(KERN_DEBUG "%s: exiting interrupt,\n", dev->name);
-        printk(KERN_DEBUG "    tx_status %02x, rx_status %02x.\n",
-	       tx_stat, rx_stat);
-    }
+    DEBUG(4, "%s: exiting interrupt,\n", dev->name);
+    DEBUG(4, "    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
 
     dev->interrupt = 0;
     outb(D_TX_INTR, ioaddr + TX_INTR);
@@ -802,15 +777,13 @@
 	unsigned char *buf = skb->data;
 
 	if (length > ETH_FRAME_LEN) {
-	    if (fmvj18x_debug)
-		printk(KERN_NOTICE "%s: Attempting to send a large packet"
-		       " (%d bytes).\n", dev->name, length);
+	    printk(KERN_NOTICE "%s: Attempting to send a large packet"
+		   " (%d bytes).\n", dev->name, length);
 	    return 1;
 	}
 
-	if (fmvj18x_debug > 4)
-	    printk(KERN_DEBUG "%s: Transmitting a packet of length %lu.\n",
-		   dev->name, (unsigned long)skb->len);
+	DEBUG(4, "%s: Transmitting a packet of length %lu.\n",
+	      dev->name, (unsigned long)skb->len);
 	lp->stats.tx_bytes += skb->len;
 
 	/* Disable both interrupts. */
@@ -864,9 +837,7 @@
     ioaddr_t ioaddr = dev->base_addr;
     int i;
 
-    if (fmvj18x_debug > 4) {
-	printk(KERN_DEBUG "fjn_reset(%s) called.\n",dev->name);
-    }
+    DEBUG(4, "fjn_reset(%s) called.\n",dev->name);
 
     /* Power On chip and select bank 0 */
     outb(BANK_0, ioaddr + CONFIG_1);
@@ -885,12 +856,6 @@
     for (i = 0; i < 6; i++) 
         outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
 
-    if (fmvj18x_debug > 4) {
-	printk(KERN_DEBUG "node id: ");
-	for (i = 0; i < 6; i++) 
-	    printk("%02X ",inb(ioaddr + NODE_ID + i));
-	printk("\n");
-    }
     /* Switch to bank 1 */
     outb(BANK_1, ioaddr + CONFIG_1);
 
@@ -948,16 +913,14 @@
     ioaddr_t ioaddr = dev->base_addr;
     int boguscount = 10;	/* 5 -> 10: by agy 19940922 */
 
-    if (fmvj18x_debug > 4)
-        printk(KERN_DEBUG "%s: in rx_packet(), rx_status %02x.\n",
-               dev->name, inb(ioaddr + RX_STATUS));
+    DEBUG(4, "%s: in rx_packet(), rx_status %02x.\n",
+	  dev->name, inb(ioaddr + RX_STATUS));
 
     while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
 	u_short status = inw(ioaddr + DATAPORT);
 
-	if (fmvj18x_debug > 4)
-	    printk(KERN_DEBUG "%s: Rxing packet mode %02x status %04x.\n",
-		   dev->name, inb(ioaddr + RX_MODE), status);
+	DEBUG(4, "%s: Rxing packet mode %02x status %04x.\n",
+	      dev->name, inb(ioaddr + RX_MODE), status);
 #ifndef final_version
 	if (status == 0) {
 	    outb(F_SKP_PKT, ioaddr + RX_SKIP);
@@ -997,7 +960,8 @@
 		    (pkt_len + 1) >> 1);
 	    skb->protocol = eth_type_trans(skb, dev);
 
-	    if (fmvj18x_debug > 5) {
+#ifdef PCMCIA_DEBUG
+	    if (pc_debug > 5) {
 		int i;
 		printk(KERN_DEBUG "%s: Rxed packet of length %d: ",
 		       dev->name, pkt_len);
@@ -1005,6 +969,7 @@
 		    printk(" %02x", skb->data[i]);
 		printk(".\n");
 	    }
+#endif
 
 	    netif_rx(skb);
 	    lp->stats.rx_packets++;
@@ -1027,9 +992,9 @@
 	    outb(F_SKP_PKT, ioaddr + RX_SKIP);
 	}
 
-	if (fmvj18x_debug > 5 && i > 0)
-	    printk(KERN_DEBUG "%s: Exint Rx packet with mode %02x after"
-		   " %d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
+	if (i > 0)
+	    DEBUG(5, "%s: Exint Rx packet with mode %02x after "
+		  "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
     }
 */
 
@@ -1040,18 +1005,15 @@
 
 static int fjn_config(struct net_device *dev, struct ifmap *map){
     return 0;
-} /* fjn_config */
+}
 
 static int fjn_open(struct net_device *dev)
 {
     struct local_info_t *lp = (struct local_info_t *)dev->priv;
-    dev_link_t *link;
+    dev_link_t *link = &lp->link;
 
-    if (fmvj18x_debug > 4)
-        printk(KERN_DEBUG "fjn_open('%s').\n", dev->name);
+    DEBUG(4, "fjn_open('%s').\n", dev->name);
 
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
     if (!DEV_OK(link))
 	return -ENODEV;
     
@@ -1076,23 +1038,13 @@
 
 static int fjn_close(struct net_device *dev)
 {
-    ioaddr_t ioaddr = dev->base_addr;
     struct local_info_t *lp = (struct local_info_t *)dev->priv;
-    dev_link_t *link;
-
-    if (fmvj18x_debug > 4)
-        printk(KERN_DEBUG "fjn_open('%s').\n", dev->name);
-
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
-    if (link == NULL)
-	return -ENODEV;
-    
-    if (fmvj18x_debug > 2)
-	printk(KERN_DEBUG "%s: shutting down ethercard.\n", dev->name);
+    dev_link_t *link = &lp->link;
+    ioaddr_t ioaddr = dev->base_addr;
 
-    ((struct local_info_t *)dev->priv)->open_time = 0;
+    DEBUG(4, "fjn_close('%s').\n", dev->name);
 
+    lp->open_time = 0;
     dev->tbusy = 1;
     dev->start = 0;
 
@@ -1109,7 +1061,7 @@
 
     /* Set the ethernet adaptor disable IRQ */
     if( lp->cardtype != TDK ) 
-    		outb(INTR_OFF, ioaddr + LAN_CTRL);
+	outb(INTR_OFF, ioaddr + LAN_CTRL);
 
     link->open--;
     dev->start = 0;
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/netwave_cs.c linux/drivers/net/pcmcia/netwave_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/netwave_cs.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/net/pcmcia/netwave_cs.c	Tue Jan 18 22:29:17 2000
@@ -302,6 +302,8 @@
 };	
    
 typedef struct netwave_private {
+    dev_link_t link;
+    struct net_device      dev;
     dev_node_t node;
     u_char     *ramBase;
     int        timeoutCounter;
@@ -440,7 +442,7 @@
     client_reg_t client_reg;
     dev_link_t *link;
     struct net_device *dev;
-    netwave_private *priv; 
+    netwave_private *priv;
     int i, ret;
     
     DEBUG(0, "netwave_attach()\n");
@@ -449,8 +451,11 @@
     netwave_flush_stale_links();
 
     /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    memset(link, 0, sizeof(struct dev_link_t));
+    priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+    if (!priv) return NULL;
+    memset(priv, 0, sizeof(*priv));
+    link = &priv->link; dev = &priv->dev;
+    link->priv = dev->priv = priv;
     link->release.function = &netwave_release;
     link->release.data = (u_long)link;
 	
@@ -478,15 +483,7 @@
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
 
-    /* Allocate space for private device-specific data */
-    dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-    memset(dev, 0, sizeof(struct net_device));
-
-    dev->priv = kmalloc(sizeof(netwave_private), GFP_KERNEL);
-    memset(dev->priv, 0, sizeof(netwave_private));
-
     /* Set the watchdog timer */
-    priv = (netwave_private *) dev->priv;
     priv->watchdog.function = &netwave_watchdog;
     priv->watchdog.data = (unsigned long) dev;
 
@@ -502,12 +499,12 @@
     dev->do_ioctl = &netwave_ioctl;
 
     ether_setup(dev);
-    dev->name = ((struct netwave_private *)dev->priv)->node.dev_name;
+    dev->name = priv->node.dev_name;
     dev->init = &netwave_init;
     dev->open = &netwave_open;
     dev->stop = &netwave_close;
     dev->tbusy = 1;
-    link->priv = link->irq.Instance = dev;
+    link->irq.Instance = dev;
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -541,6 +538,7 @@
  */
 static void netwave_detach(dev_link_t *link)
 {
+    netwave_private *priv = link->priv;
     dev_link_t **linkp;
     long flags;
 
@@ -587,16 +585,9 @@
 
     /* Unlink device structure, free pieces */
     *linkp = link->next;
-    if (link->priv) {
-	struct net_device *dev = link->priv;
-	if (link->dev != NULL)
-	  unregister_netdev(dev);
-	link->dev = NULL;
-	if (dev->priv)
-	    kfree(dev->priv);
-	kfree(link->priv);
-    }
-    kfree(link);
+    if (link->dev)
+	unregister_netdev(&priv->dev);
+    kfree(priv);
     
 } /* netwave_detach */
 
@@ -633,8 +624,8 @@
  *
  */
 static int netwave_ioctl(struct net_device *dev, /* ioctl device */
-						 struct ifreq *rq,	 /* Data passed */
-						 int	cmd)	     /* Ioctl number */
+			 struct ifreq *rq,	 /* Data passed */
+			 int	cmd)	     /* Ioctl number */
 {
     unsigned long flags;
     int			ret = 0;
@@ -839,20 +830,16 @@
 while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
 
 static void netwave_pcmcia_config(dev_link_t *link) {
-    client_handle_t handle;
+    client_handle_t handle = link->handle;
+    netwave_private *priv = link->priv;
+    struct net_device *dev = &priv->dev;
     tuple_t tuple;
     cisparse_t parse;
-    struct net_device *dev;
     int i, j, last_ret, last_fn;
     u_char buf[64];
     win_req_t req;
     memreq_t mem;
     u_char *ramBase = NULL;
-    /*    modwin_t mod;
-	  short iobase, *phys_addr;
-	  */  
-    handle = link->handle;
-    dev = link->priv;
 
     DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link);
 
@@ -969,7 +956,7 @@
  */
 static void netwave_release(u_long arg) {
     dev_link_t *link = (dev_link_t *)arg;
-    struct net_device *dev = link->priv;
+    netwave_private *priv = link->priv;
 
     DEBUG(0, "netwave_release(0x%p)\n", link);
 
@@ -986,7 +973,7 @@
 	
     /* Don't bother checking to see if these succeed or not */
     if (link->win) {
-	iounmap(((netwave_private *)dev->priv)->ramBase);
+	iounmap(priv->ramBase);
 	CardServices(ReleaseWindow, link->win);
     }
     CardServices(ReleaseConfiguration, link->handle);
@@ -1014,7 +1001,8 @@
 static int netwave_event(event_t event, int priority,
 			 event_callback_args_t *args) {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
+    netwave_private *priv = link->priv;
+    struct net_device *dev = &priv->dev;
 	
     DEBUG(1, "netwave_event(0x%06x)\n", event);
   
@@ -1027,7 +1015,6 @@
 	link->state &= ~DEV_PRESENT;
 	if (link->state & DEV_CONFIG) {
 	    dev->tbusy = 1; dev->start = 0;
-	    /* ((netwave_private *)link->priv)->block = 1; */
 	    link->release.expires = jiffies + 5;
 	    add_timer(&link->release);
 	}
@@ -1312,24 +1299,18 @@
     ioaddr_t iobase;
     u_char *ramBase;
     struct net_device *dev = (struct net_device *)dev_id;
-    struct netwave_private *priv;
+    struct netwave_private *priv = dev->priv;
+    dev_link_t *link = &priv->link;
     int i;
-    dev_link_t *link;
-    
-	if ((dev == NULL) | (!dev->start))
-		return;
     
-    priv = (netwave_private *)dev->priv;
+    if ((dev == NULL) | (!dev->start))
+	return;
     
     if (dev->interrupt) {
 	printk("%s: re-entering the interrupt handler.\n", dev->name);
 	return;
     }
     dev->interrupt = 1;
-	
-    /* Find the correct dev_link_t */
-    for (link = dev_list; NULL != link; link = link->next)
-	if (dev == link->priv) break;
     
     iobase = dev->base_addr;
     ramBase = priv->ramBase;
@@ -1592,12 +1573,10 @@
 }
 
 static int netwave_open(struct net_device *dev) {
-    dev_link_t *link;
+    netwave_private *priv = dev->priv;
+    dev_link_t *link = &priv->link;
 
     DEBUG(1, "netwave_open: starting.\n");
-
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
     
     if (!DEV_OK(link))
 	return -ENODEV;
@@ -1612,16 +1591,11 @@
 }
 
 static int netwave_close(struct net_device *dev) {
-    dev_link_t *link;
-    netwave_private *priv = (netwave_private *) dev->priv;
+    netwave_private *priv = (netwave_private *)dev->priv;
+    dev_link_t *link = &priv->link;
 
     DEBUG(1, "netwave_close: finishing.\n");
 
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
-    if (link == NULL)
-	return -ENODEV;
-	
     /* If watchdog was activated, kill it ! */
     del_timer(&priv->watchdog);
 	
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/nmclan_cs.c linux/drivers/net/pcmcia/nmclan_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/nmclan_cs.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/pcmcia/nmclan_cs.c	Tue Jan 18 22:29:17 2000
@@ -312,61 +312,63 @@
 ---------------------------------------------------------------------------- */
 
 typedef struct _mace_statistics {
-  /* MACE_XMTFS */
-  int xmtsv;
-  int uflo;
-  int lcol;
-  int more;
-  int one;
-  int defer;
-  int lcar;
-  int rtry;
+    /* MACE_XMTFS */
+    int xmtsv;
+    int uflo;
+    int lcol;
+    int more;
+    int one;
+    int defer;
+    int lcar;
+    int rtry;
+
+    /* MACE_XMTRC */
+    int exdef;
+    int xmtrc;
+
+    /* RFS1--Receive Status (RCVSTS) */
+    int oflo;
+    int clsn;
+    int fram;
+    int fcs;
+
+    /* RFS2--Runt Packet Count (RNTPC) */
+    int rfs_rntpc;
+
+    /* RFS3--Receive Collision Count (RCVCC) */
+    int rfs_rcvcc;
+
+    /* MACE_IR */
+    int jab;
+    int babl;
+    int cerr;
+    int rcvcco;
+    int rntpco;
+    int mpco;
 
-  /* MACE_XMTRC */
-  int exdef;
-  int xmtrc;
-
-  /* RFS1--Receive Status (RCVSTS) */
-  int oflo;
-  int clsn;
-  int fram;
-  int fcs;
-
-  /* RFS2--Runt Packet Count (RNTPC) */
-  int rfs_rntpc;
-
-  /* RFS3--Receive Collision Count (RCVCC) */
-  int rfs_rcvcc;
+    /* MACE_MPC */
+    int mpc;
 
-  /* MACE_IR */
-  int jab;
-  int babl;
-  int cerr;
-  int rcvcco;
-  int rntpco;
-  int mpco;
-
-  /* MACE_MPC */
-  int mpc;
+    /* MACE_RNTPC */
+    int rntpc;
 
-  /* MACE_RNTPC */
-  int rntpc;
-
-  /* MACE_RCVCC */
-  int rcvcc;
+    /* MACE_RCVCC */
+    int rcvcc;
 } mace_statistics;
 
 typedef struct _mace_private {
-  dev_node_t node;
-  struct net_device_stats linux_stats; /* Linux statistics counters */
-  mace_statistics mace_stats; /* MACE chip statistics counters */
-
-  /* restore_multicast_list() state variables */
-  int multicast_ladrf[MACE_LADRF_LEN]; /* Logical address filter */
-  int multicast_num_addrs;
+    dev_link_t link;
+    struct net_device dev;
+    dev_node_t node;
+    struct net_device_stats linux_stats; /* Linux statistics counters */
+    mace_statistics mace_stats; /* MACE chip statistics counters */
+
+    /* restore_multicast_list() state variables */
+    int multicast_ladrf[MACE_LADRF_LEN]; /* Logical address filter */
+    int multicast_num_addrs;
 
-  char tx_free_frames; /* Number of free transmit frame buffers */
-  char tx_irq_disabled; /* MACE TX interrupt disabled */
+    char tx_free_frames; /* Number of free transmit frame buffers */
+    char tx_irq_disabled; /* MACE TX interrupt disabled */
 } mace_private;
 
 /* ----------------------------------------------------------------------------
@@ -384,9 +386,7 @@
 static dev_link_t *dev_list=NULL;
 
 static char *if_names[]={
-  "Auto",
-  "10baseT",
-  "BNC",
+    "Auto", "10baseT", "BNC",
 };
 
 #ifdef PCMCIA_DEBUG
@@ -403,12 +403,8 @@
 	'insmod'.
 ---------------------------------------------------------------------------- */
 
-static int if_port=0; /* default=auto */
-  /*
-   * 0=auto
-   * 1=10base-T (twisted pair)
-   * 2=10base-2 (BNC)
-   */
+/* 0=auto, 1=10baseT, 2 = 10base2, default=auto */
+static int if_port=0;
 
 /* Bit map of interrupts to choose from */
 static u_int irq_mask = 0xdeb8;
@@ -425,7 +421,7 @@
 static void nmclan_config(dev_link_t *link);
 static void nmclan_release(u_long arg);
 static int nmclan_event(event_t event, int priority,
-		       event_callback_args_t *args);
+			event_callback_args_t *args);
 
 static void nmclan_reset(struct net_device *dev);
 static int mace_config(struct net_device *dev, struct ifmap *map);
@@ -473,10 +469,11 @@
 	We never need to do anything when a nmclan device is "initialized"
 	by the net software, because we only register already-found cards.
 ---------------------------------------------------------------------------- */
+
 static int nmclan_init(struct net_device *dev)
 {
-  return 0;
-} /* nmclan_init */
+    return 0;
+}
 
 /* ----------------------------------------------------------------------------
 nmclan_attach
@@ -484,79 +481,78 @@
 	structures for one device.  The device is registered with Card
 	Services.
 ---------------------------------------------------------------------------- */
+
 static dev_link_t *nmclan_attach(void)
 {
-  client_reg_t client_reg;
-  dev_link_t *link;
-  struct net_device *dev;
-  int i, ret;
-
-  DEBUG(0, "nmclan_attach()\n");
-  DEBUG(1, "%s\n", rcsid);
-  flush_stale_links();
-
-  /* Create new ethernet device */
-  link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-  memset(link, 0, sizeof(struct dev_link_t));
-  link->release.function = &nmclan_release;
-  link->release.data = (u_long)link;
-  link->io.NumPorts1 = 32;
-  link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
-  link->io.IOAddrLines = 5;
-  link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-  link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
-  if (irq_list[0] == -1)
-    link->irq.IRQInfo2 = irq_mask;
-  else
-    for (i = 0; i < 4; i++)
-      link->irq.IRQInfo2 |= 1 << irq_list[i];
-  link->irq.Handler = &mace_interrupt;
-  link->conf.Attributes = CONF_ENABLE_IRQ;
-  link->conf.Vcc = 50;
-  link->conf.IntType = INT_MEMORY_AND_IO;
-  link->conf.ConfigIndex = 1;
-  link->conf.Present = PRESENT_OPTION;
-
-  dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-  memset(dev, 0, sizeof(struct net_device));
-
-  /* Allocate private data area for this device. */
-  dev->priv = kmalloc(sizeof(mace_private), GFP_KERNEL);
-  memset(dev->priv, 0, sizeof(mace_private));
-  ((mace_private *)dev->priv)->tx_free_frames=AM2150_MAX_TX_FRAMES;
-
-  dev->hard_start_xmit = &mace_start_xmit;
-  dev->set_config = &mace_config;
-  dev->get_stats = &mace_get_stats;
-  dev->set_multicast_list = &set_multicast_list;
-  ether_setup(dev);
-  dev->name = ((mace_private *)dev->priv)->node.dev_name;
-  dev->init = &nmclan_init;
-  dev->open = &mace_open;
-  dev->stop = &mace_close;
-  dev->tbusy = 0xFF;
-  link->priv = link->irq.Instance = dev;
-
-  /* Register with Card Services */
-  link->next = dev_list;
-  dev_list = link;
-  client_reg.dev_info = &dev_info;
-  client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
-  client_reg.EventMask =
-    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-  client_reg.event_handler = &nmclan_event;
-  client_reg.Version = 0x0210;
-  client_reg.event_callback_args.client_data = link;
-  ret = CardServices(RegisterClient, &link->handle, &client_reg);
-  if (ret != 0) {
-    cs_error(link->handle, RegisterClient, ret);
-    nmclan_detach(link);
-    return NULL;
-  }
+    mace_private *lp;
+    dev_link_t *link;
+    struct net_device *dev;
+    client_reg_t client_reg;
+    int i, ret;
+
+    DEBUG(0, "nmclan_attach()\n");
+    DEBUG(1, "%s\n", rcsid);
+    flush_stale_links();
+
+    /* Create new ethernet device */
+    lp = kmalloc(sizeof(*lp), GFP_KERNEL);
+    if (!lp) return NULL;
+    memset(lp, 0, sizeof(*lp));
+    link = &lp->link; dev = &lp->dev;
+    link->priv = dev->priv = link->irq.Instance = lp;
+
+    link->release.function = &nmclan_release;
+    link->release.data = (u_long)link;
+    link->io.NumPorts1 = 32;
+    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
+    link->io.IOAddrLines = 5;
+    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+    link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
+    if (irq_list[0] == -1)
+	link->irq.IRQInfo2 = irq_mask;
+    else
+	for (i = 0; i < 4; i++)
+	    link->irq.IRQInfo2 |= 1 << irq_list[i];
+    link->irq.Handler = &mace_interrupt;
+    link->conf.Attributes = CONF_ENABLE_IRQ;
+    link->conf.Vcc = 50;
+    link->conf.IntType = INT_MEMORY_AND_IO;
+    link->conf.ConfigIndex = 1;
+    link->conf.Present = PRESENT_OPTION;
+
+    lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
+
+    dev->hard_start_xmit = &mace_start_xmit;
+    dev->set_config = &mace_config;
+    dev->get_stats = &mace_get_stats;
+    dev->set_multicast_list = &set_multicast_list;
+    ether_setup(dev);
+    dev->name = lp->node.dev_name;
+    dev->init = &nmclan_init;
+    dev->open = &mace_open;
+    dev->stop = &mace_close;
+    dev->tbusy = 0xFF;
+
+    /* Register with Card Services */
+    link->next = dev_list;
+    dev_list = link;
+    client_reg.dev_info = &dev_info;
+    client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+    client_reg.EventMask =
+	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+	CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+	CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+    client_reg.event_handler = &nmclan_event;
+    client_reg.Version = 0x0210;
+    client_reg.event_callback_args.client_data = link;
+    ret = CardServices(RegisterClient, &link->handle, &client_reg);
+    if (ret != 0) {
+	cs_error(link->handle, RegisterClient, ret);
+	nmclan_detach(link);
+	return NULL;
+    }
 
-  return link;
+    return link;
 } /* nmclan_attach */
 
 /* ----------------------------------------------------------------------------
@@ -566,40 +562,36 @@
 	structures are freed.  Otherwise, the structures will be freed
 	when the device is released.
 ---------------------------------------------------------------------------- */
+
 static void nmclan_detach(dev_link_t *link)
 {
-  dev_link_t **linkp;
-
-  DEBUG(0, "nmclan_detach(0x%p)\n", link);
+    mace_private *lp = link->priv;
+    dev_link_t **linkp;
 
-  /* Locate device structure */
-  for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-    if (*linkp == link) break;
-  if (*linkp == NULL)
-    return;
+    DEBUG(0, "nmclan_detach(0x%p)\n", link);
 
-  if (link->state & DEV_CONFIG) {
-    nmclan_release((u_long)link);
-    if (link->state & DEV_STALE_CONFIG) {
-      link->state |= DEV_STALE_LINK;
-      return;
+    /* Locate device structure */
+    for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+	if (*linkp == link) break;
+    if (*linkp == NULL)
+	return;
+
+    if (link->state & DEV_CONFIG) {
+	nmclan_release((u_long)link);
+	if (link->state & DEV_STALE_CONFIG) {
+	    link->state |= DEV_STALE_LINK;
+	    return;
+	}
     }
-  }
 
-  if (link->handle)
-    CardServices(DeregisterClient, link->handle);
+    if (link->handle)
+	CardServices(DeregisterClient, link->handle);
 
-  /* Unlink device structure, free bits */
-  *linkp = link->next;
-  if (link->priv) {
-    struct net_device *dev = link->priv;
-    if (link->dev != NULL)
-      unregister_netdev(dev);
-    if (dev->priv)
-      kfree(dev->priv);
-    kfree(link->priv);
-  }
-  kfree(link);
+    /* Unlink device structure, free bits */
+    *linkp = link->next;
+    if (link->dev)
+	unregister_netdev(&lp->dev);
+    kfree(lp);
 
 } /* nmclan_detach */
 
@@ -731,18 +723,14 @@
 
 static void nmclan_config(dev_link_t *link)
 {
-  client_handle_t handle;
-  struct net_device *dev;
+  client_handle_t handle = link->handle;
+  mace_private *lp = link->priv;
+  struct net_device *dev = &lp->dev;
   tuple_t tuple;
   cisparse_t parse;
   u_char buf[64];
   int i, last_ret, last_fn;
   ioaddr_t ioaddr;
-  u_short *phys_addr;
-
-  handle = link->handle;
-  dev = link->priv;
-  phys_addr = (u_short *)dev->dev_addr;
 
   DEBUG(0, "nmclan_config(0x%p)\n", link);
 
@@ -770,7 +758,7 @@
     printk(KERN_NOTICE "nmclan_cs: register_netdev() failed\n");
     goto failed;
   }
-  
+
   ioaddr = dev->base_addr;
 
   /* Read the ethernet address from the CIS. */
@@ -807,9 +795,9 @@
   else
     printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");
 
-  link->dev = &((mace_private *)dev->priv)->node;
+  link->dev = &lp->node;
   link->state &= ~DEV_CONFIG_PENDING;
-  
+
   printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port, hw_addr ",
 	 dev->name, dev->base_addr, dev->irq, if_names[dev->if_port]);
   for (i = 0; i < 6; i++)
@@ -821,7 +809,7 @@
 failed:
     nmclan_release((u_long)link);
     return;
-    
+
 } /* nmclan_config */
 
 /* ----------------------------------------------------------------------------
@@ -862,10 +850,11 @@
 		       event_callback_args_t *args)
 {
   dev_link_t *link = args->client_data;
-  struct net_device *dev = link->priv;
+  mace_private *lp = link->priv;
+  struct net_device *dev = &lp->dev;
 
   DEBUG(1, "nmclan_event(0x%06x)\n", event);
-    
+
   switch (event) {
     case CS_EVENT_CARD_REMOVAL:
       link->state &= ~DEV_PRESENT;
@@ -918,20 +907,13 @@
 ---------------------------------------------------------------------------- */
 static void nmclan_reset(struct net_device *dev)
 {
+  mace_private *lp = dev->priv;
 
 #if RESET_XILINX
-  dev_link_t *link;
+  dev_link_t *link = &lp->link;
   conf_reg_t reg;
   u_long OrigCorValue; 
 
-  /* Find our client handle. */
-  for (link = dev_list; link; link = link->next)
-    if (link->priv == dev) break;
-  if (link == NULL) {
-    printk(KERN_NOTICE "nmclan_cs: bad device pointer!\n");
-    return;
-  }
-
   /* Save original COR value */
   reg.Function = 0;
   reg.Action = CS_READ;
@@ -953,13 +935,13 @@
   reg.Value = COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK);
   CardServices(AccessConfigurationRegister, link->handle, &reg);
   /* Xilinx is now completely reset along with the MACE chip. */
-  ((mace_private *)dev->priv)->tx_free_frames=AM2150_MAX_TX_FRAMES;
+  lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
 
 #endif /* #if RESET_XILINX */
 
   /* Xilinx is now completely reset along with the MACE chip. */
-  ((mace_private *)dev->priv)->tx_free_frames=AM2150_MAX_TX_FRAMES;
-  
+  lp->tx_free_frames=AM2150_MAX_TX_FRAMES;
+
   /* Reinitialize the MACE chip for operation. */
   mace_init(dev->base_addr, dev->dev_addr);
   mace_write(dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT);
@@ -981,9 +963,8 @@
       dev->if_port = map->port;
       printk(KERN_INFO "%s: switched to %s port\n", dev->name,
 	     if_names[dev->if_port]);
-    }
-  else
-    return -EINVAL;
+    } else
+      return -EINVAL;
   }
   return 0;
 } /* mace_config */
@@ -995,10 +976,9 @@
 static int mace_open(struct net_device *dev)
 {
   ioaddr_t ioaddr = dev->base_addr;
-  dev_link_t *link;
+  mace_private *lp = dev->priv;
+  dev_link_t *link = &lp->link;
 
-  for (link = dev_list; link; link = link->next)
-    if (link->priv == dev) break;
   if (!DEV_OK(link))
     return -ENODEV;
 
@@ -1023,15 +1003,11 @@
 static int mace_close(struct net_device *dev)
 {
   ioaddr_t ioaddr = dev->base_addr;
-  dev_link_t *link;
-
-  for (link = dev_list; link; link = link->next)
-    if (link->priv == dev) break;
-  if (link == NULL)
-    return -ENODEV;
+  mace_private *lp = dev->priv;
+  dev_link_t *link = &lp->link;
 
   DEBUG(2, "%s: shutting down ethercard.\n", dev->name);
-  
+
   /* Mask off all interrupts from the MACE chip. */
   outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR);
 
@@ -1062,7 +1038,7 @@
 {
   mace_private *lp = (mace_private *)dev->priv;
   ioaddr_t ioaddr = dev->base_addr;
-  dev_link_t *link;
+  dev_link_t *link = &lp->link;
 
 #if TIMEOUT_TX
   /* Transmitter timeout. */
@@ -1074,10 +1050,7 @@
     printk(KERN_NOTICE "%s: transmit timed out -- ", dev->name);
 #if RESET_ON_TIMEOUT
     printk("resetting card\n");
-    for (link = dev_list; link; link = link->next)
-      if (link->priv == dev) break;
-    if (link)
-      CardServices(ResetCard, link->handle);
+    CardServices(ResetCard, link->handle);
 #else /* #if RESET_ON_TIMEOUT */
     printk("NOT resetting card\n");
 #endif /* #if RESET_ON_TIMEOUT */
@@ -1091,7 +1064,7 @@
 
   DEBUG(3, "%s: mace_start_xmit(length = %ld) called.\n",
 	dev->name, (long)skb->len);
-  
+
   /* Avoid timer-based retransmission conflicts. */
   if (test_and_set_bit(TBUSY_UNSPECIFIED, (void*)&dev->tbusy) != 0) {
     printk(KERN_NOTICE "%s: transmitter access conflict.\n",
@@ -1146,7 +1119,7 @@
 #endif /* #if (!TX_INTERRUPTABLE) */
 
   dev_kfree_skb(skb);
-    
+
   return 0;
 } /* mace_start_xmit */
 
@@ -1156,8 +1129,8 @@
 ---------------------------------------------------------------------------- */
 static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-  struct net_device *dev = (struct net_device *)dev_id;
-  mace_private *lp = (mace_private *)dev->priv;
+  mace_private *lp = (mace_private *)dev_id;
+  struct net_device *dev = &lp->dev;
   ioaddr_t ioaddr = dev->base_addr;
   int status;
   int IntrCnt = MACE_MAX_IR_ITERATIONS;
@@ -1169,7 +1142,6 @@
   }
 
   if (dev->interrupt || lp->tx_irq_disabled) {
-    sti();
     printk(
       (lp->tx_irq_disabled?
        KERN_NOTICE "%s: Interrupt with tx_irq_disabled "
@@ -1184,7 +1156,6 @@
     return;
   }
   dev->interrupt = 1;
-  sti();
 
   if (dev->start == 0) {
     DEBUG(2, "%s: interrupt from dead card\n", dev->name);
@@ -1194,7 +1165,7 @@
   do {
     /* WARNING: MACE_IR is a READ/CLEAR port! */
     status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR);
- 
+
     DEBUG(3, "mace_interrupt: irq 0x%X status 0x%X.\n", irq, status);
 
     if (status & MACE_IR_RCVINT) {
@@ -1346,9 +1317,9 @@
 
       DEBUG(3, "    receiving packet size 0x%X rx_status"
 	    " 0x%X.\n", pkt_len, rx_status);
-      
+
       skb = dev_alloc_skb(pkt_len+2);
-      
+
       if (skb != NULL) {
 	skb->dev = dev;
 
@@ -1425,7 +1396,7 @@
   /* MACE_XMTRC */
   DEBUG(2, " exdef=%-7d             xmtrc=%d\n",
 	pstats->exdef, pstats->xmtrc);
-  
+
   /* RFS1--Receive Status (RCVSTS) */
   DEBUG(2, " oflo=%-7d              clsn=%d\n",
 	pstats->oflo, pstats->clsn);
@@ -1472,7 +1443,7 @@
 static void update_stats(ioaddr_t ioaddr, struct net_device *dev)
 {
   mace_private *lp = (mace_private *)dev->priv;
-    
+
   lp->mace_stats.rcvcc += mace_read(ioaddr, MACE_RCVCC);
   lp->mace_stats.rntpc += mace_read(ioaddr, MACE_RNTPC);
   lp->mace_stats.mpc += mace_read(ioaddr, MACE_MPC);
@@ -1711,7 +1682,7 @@
 
   DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", dev->name,
 	((mace_private *)(dev->priv))->multicast_num_addrs);
-  
+
   if (dev->flags & IFF_PROMISC) {
     /* Promiscuous mode: receive all packets */
     mace_write(ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL);
@@ -1768,10 +1739,10 @@
 
 static void __exit exit_nmclan_cs(void)
 {
-  DEBUG(0, "nmclan_cs: unloading\n");
-  unregister_pccard_driver(&dev_info);
-  while (dev_list != NULL)
-    nmclan_detach(dev_list);
+    DEBUG(0, "nmclan_cs: unloading\n");
+    unregister_pccard_driver(&dev_info);
+    while (dev_list != NULL)
+	nmclan_detach(dev_list);
 }
 
 module_init(init_nmclan_cs);
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/pcnet_cs.c linux/drivers/net/pcmcia/pcnet_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/pcnet_cs.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/pcmcia/pcnet_cs.c	Tue Jan 18 22:29:17 2000
@@ -11,7 +11,7 @@
 
     Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
 
-    pcnet_cs.c 1.106 1999/11/09 21:53:13
+    pcnet_cs.c 1.110 1999/12/06 21:39:18
     
     The network driver code is based on Donald Becker's NE2000 code:
 
@@ -72,7 +72,7 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"pcnet_cs.c 1.106 1999/11/09 21:53:13 (David Hinds)";
+"pcnet_cs.c 1.110 1999/12/06 21:39:18 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
@@ -122,26 +122,21 @@
 static void pcnet_release(u_long arg);
 static int pcnet_event(event_t event, int priority,
 		       event_callback_args_t *args);
-
 static int pcnet_open(struct net_device *dev);
 static int pcnet_close(struct net_device *dev);
 static void ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs);
 static void ei_watchdog(u_long arg);
-
 static void pcnet_reset_8390(struct net_device *dev);
-
 static int set_config(struct net_device *dev, struct ifmap *map);
-
 static int setup_shmem_window(dev_link_t *link, int start_pg,
 			      int stop_pg, int cm_offset);
 static int setup_dma_config(dev_link_t *link, int start_pg,
 			    int stop_pg);
 
-static dev_info_t dev_info = "pcnet_cs";
-
 static dev_link_t *pcnet_attach(void);
 static void pcnet_detach(dev_link_t *);
 
+static dev_info_t dev_info = "pcnet_cs";
 static dev_link_t *dev_list;
 
 /*====================================================================*/
@@ -215,7 +210,8 @@
     { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b,
       DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF },
     { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
-    { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 }
+    { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
+    { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 }
 };
 
 #define NR_INFO		(sizeof(hw_info)/sizeof(hw_info_t))
@@ -226,12 +222,13 @@
 { /* D-Link EtherFast */ 0x00, 0x00, 0x00, 0x00, IS_DL10019A };
 
 typedef struct pcnet_dev_t {
-    struct net_device	dev;
+    struct net_device	dev; /* so &dev == &pcnet_dev_t */
+    dev_link_t		link;
     dev_node_t		node;
     u_long		flags;
     caddr_t		base;
     struct timer_list	watchdog;
-    int			stale, link;
+    int			stale, state;
     u_short		fast_poll;
 } pcnet_dev_t;
 
@@ -283,18 +280,22 @@
 
 static dev_link_t *pcnet_attach(void)
 {
-    client_reg_t client_reg;
-    dev_link_t *link;
     pcnet_dev_t *info;
+    dev_link_t *link;
     struct net_device *dev;
+    client_reg_t client_reg;
     int i, ret;
 
     DEBUG(0, "pcnet_attach()\n");
     flush_stale_links();
 
     /* Create new ethernet device */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    memset(link, 0, sizeof(struct dev_link_t));
+    info = kmalloc(sizeof(*info), GFP_KERNEL);
+    if (!info) return NULL;
+    memset(info, 0, sizeof(*info));
+    link = &info->link; dev = &info->dev;
+    link->priv = info;
+    
     link->release.function = &pcnet_release;
     link->release.data = (u_long)link;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
@@ -308,9 +309,6 @@
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    info = kmalloc(sizeof(struct pcnet_dev_t), GFP_KERNEL);
-    memset(info, 0, sizeof(struct pcnet_dev_t));
-    dev = &info->dev;
     ethdev_init(dev);
     dev->name = info->node.dev_name;
     dev->init = &pcnet_init;
@@ -318,7 +316,6 @@
     dev->stop = &pcnet_close;
     dev->set_config = &set_config;
     dev->tbusy = 1;
-    link->priv = info;
 
     /* Register with Card Services */
     link->next = dev_list;
@@ -353,6 +350,7 @@
 
 static void pcnet_detach(dev_link_t *link)
 {
+    pcnet_dev_t *info = link->priv;
     dev_link_t **linkp;
     long flags;
 
@@ -385,15 +383,9 @@
 
     /* Unlink device structure, free bits */
     *linkp = link->next;
-    if (link->priv) {
-	struct net_device *dev = link->priv;
-	if (link->dev != NULL)
-	    unregister_netdev(dev);
-	if (dev->priv)
-	    kfree_s(dev->priv, sizeof(struct ei_device));
-	kfree_s(dev, sizeof(struct pcnet_dev_t));
-    }
-    kfree_s(link, sizeof(struct dev_link_t));
+    if (link->dev)
+	unregister_netdev(&info->dev);
+    kfree(info);
 
 } /* pcnet_detach */
 
@@ -595,20 +587,16 @@
 
 static void pcnet_config(dev_link_t *link)
 {
-    client_handle_t handle;
+    client_handle_t handle = link->handle;
+    pcnet_dev_t *info = link->priv;
+    struct net_device *dev = &info->dev;
     tuple_t tuple;
     cisparse_t parse;
-    pcnet_dev_t *info;
-    struct net_device *dev;
     int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
     int manfid = 0, prodid = 0, has_shmem = 0;
     u_short buf[64];
     hw_info_t *hw_info;
 
-    handle = link->handle;
-    info = link->priv;
-    dev = &info->dev;
-
     DEBUG(0, "pcnet_config(0x%p)\n", link);
 
     tuple.Attributes = 0;
@@ -881,12 +869,10 @@
 static int pcnet_open(struct net_device *dev)
 {
     pcnet_dev_t *info = (pcnet_dev_t *)dev;
-    dev_link_t *link;
+    dev_link_t *link = &info->link;
     
     DEBUG(2, "pcnet_open('%s')\n", dev->name);
 
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
     if (!DEV_OK(link))
 	return -ENODEV;
 
@@ -897,7 +883,7 @@
     request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev);
 
     /* Start by assuming the link is bad */
-    info->link = 1;
+    info->state = 1;
     info->watchdog.function = &ei_watchdog;
     info->watchdog.data = (u_long)info;
     info->watchdog.expires = jiffies + HZ;
@@ -910,18 +896,15 @@
 
 static int pcnet_close(struct net_device *dev)
 {
-    dev_link_t *link;
+    pcnet_dev_t *info = (pcnet_dev_t *)dev;
+    dev_link_t *link = &info->link;
 
     DEBUG(2, "pcnet_close('%s')\n", dev->name);
 
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
-    if (link == NULL)
-	return -ENODEV;
     free_irq(dev->irq, dev);
     
     link->open--; dev->start = 0;
-    del_timer(&((pcnet_dev_t *)dev)->watchdog);
+    del_timer(&info->watchdog);
     if (link->state & DEV_STALE_CONFIG) {
 	link->release.expires = jiffies + HZ/20;
 	link->state |= DEV_RELEASE_PENDING;
@@ -1016,12 +999,12 @@
 
     if (info->flags & IS_DL10019A) {
 	int state = inb(dev->base_addr+0x1c) & 0x01;
-	if (state != info->link) {
+	if (state != info->state) {
 	    printk(KERN_INFO "%s: %s link beat\n", dev->name,
 		   (state) ? "lost" : "found");
 	    if (!state)
 		NS8390_init(dev, 1);
-	    info->link = state;
+	    info->state = state;
 	}
     }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/smc91c92_cs.c linux/drivers/net/pcmcia/smc91c92_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/smc91c92_cs.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/pcmcia/smc91c92_cs.c	Tue Jan 18 22:29:17 2000
@@ -8,7 +8,7 @@
 
     Copyright (C) 1999 David A. Hinds -- dhinds@pcmcia.sourceforge.org
 
-    smc91c92_cs.c 1.82 1999/11/08 20:46:17
+    smc91c92_cs.c 1.85 2000/01/15 02:03:14
     
     This driver contains code written by Donald Becker
     (becker@cesdis.gsfc.nasa.gov), Rowan Hughes (x-csrdh@jcu.edu.au),
@@ -110,6 +110,8 @@
 static dev_link_t *dev_list = NULL;
 
 struct smc_private {
+    dev_link_t			link;
+    struct net_device		dev;
     u_short			manfid;
     u_short			cardid;
     struct net_device_stats	stats;
@@ -336,6 +338,7 @@
 static dev_link_t *smc91c92_attach(void)
 {
     client_reg_t client_reg;
+    struct smc_private *smc;
     dev_link_t *link;
     struct net_device *dev;
     int i, ret;
@@ -344,8 +347,11 @@
     flush_stale_links();
     
     /* Create new ethernet device */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    memset(link, 0, sizeof(struct dev_link_t));
+    smc = kmalloc(sizeof(struct smc_private), GFP_KERNEL);
+    if (!smc) return NULL;
+    memset(smc, 0, sizeof(struct smc_private));
+    link = &smc->link; dev = &smc->dev;
+
     link->release.function = &smc91c92_release;
     link->release.data = (u_long)link;
     link->io.NumPorts1 = 16;
@@ -362,26 +368,19 @@
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.Vcc = 50;
     link->conf.IntType = INT_MEMORY_AND_IO;
-    
-    dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-    memset(dev, 0, sizeof(struct net_device));
-    
-    /* Make up a SMC91-specific-data structure. */
-    dev->priv = kmalloc(sizeof(struct smc_private), GFP_KERNEL);
-    memset(dev->priv, 0, sizeof(struct smc_private));
-    
+
     /* The SMC91c92-specific entries in the device structure. */
     dev->hard_start_xmit = &smc_start_xmit;
     dev->get_stats = &smc91c92_get_stats;
     dev->set_config = &s9k_config;
     dev->set_multicast_list = &set_rx_mode;
     ether_setup(dev);
-    dev->name = ((struct smc_private *)dev->priv)->node.dev_name;
+    dev->name = smc->node.dev_name;
     dev->init = &smc91c92_init;
     dev->open = &smc91c92_open;
     dev->stop = &smc91c92_close;
     dev->tbusy = 1;
-    link->priv = link->irq.Instance = dev;
+    dev->priv = link->priv = link->irq.Instance = smc;
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -415,6 +414,7 @@
 
 static void smc91c92_detach(dev_link_t *link)
 {
+    struct smc_private *smc = link->priv;
     dev_link_t **linkp;
     long flags;
 
@@ -447,15 +447,9 @@
     
     /* Unlink device structure, free bits */
     *linkp = link->next;
-    if (link->priv) {
-	struct net_device *dev = link->priv;
-	if (link->dev != NULL)
-	    unregister_netdev(dev);
-	if (dev->priv)
-	    kfree(dev->priv);
-	kfree(link->priv);
-    }
-    kfree(link);
+    if (link->dev)
+	unregister_netdev(&smc->dev);
+    kfree(smc);
     
 } /* smc91c92_detach */
 
@@ -509,30 +503,29 @@
 
 static int mhz_3288_power(dev_link_t *link)
 {
-    struct net_device *dev = link->priv;
-    struct smc_private *lp = dev->priv;
+    struct smc_private *smc = link->priv;
     u_char tmp;
     
     /* Read the ISR twice... */
-    readb(lp->base+MEGAHERTZ_ISR);
+    readb(smc->base+MEGAHERTZ_ISR);
     udelay(5);
-    readb(lp->base+MEGAHERTZ_ISR);
+    readb(smc->base+MEGAHERTZ_ISR);
 
     /* Pause 200ms... */
     mdelay(200);
     
     /* Now read and write the COR... */
-    tmp = readb(lp->base + link->conf.ConfigBase + CISREG_COR);
+    tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);
     udelay(5);
-    writeb(tmp, lp->base + link->conf.ConfigBase + CISREG_COR);
+    writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR);
 
     return 0;
 }
 
 static int mhz_mfc_config(dev_link_t *link)
 {
-    struct net_device *dev = link->priv;
-    struct smc_private *lp = dev->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     tuple_t tuple;
     cisparse_t parse;
     u_char buf[255];
@@ -545,6 +538,7 @@
     link->conf.Status = CCSR_AUDIO_ENA;
     link->irq.Attributes =
 	IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
+    link->io.IOAddrLines = 16;
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
     link->io.NumPorts2 = 8;
 
@@ -581,15 +575,15 @@
     i = CardServices(RequestWindow, &link->win, &req);
     if (i != CS_SUCCESS)
 	return i;
-    lp->base = ioremap(req.Base, 0x1000);
+    smc->base = ioremap(req.Base, 0x1000);
     mem.CardOffset = mem.Page = 0;
-    if (lp->manfid == MANFID_MOTOROLA)
+    if (smc->manfid == MANFID_MOTOROLA)
 	mem.CardOffset = link->conf.ConfigBase;
     i = CardServices(MapMemPage, link->win, &mem);
     
     if ((i == CS_SUCCESS)
-	&& (lp->manfid == MANFID_MEGAHERTZ)
-	&& (lp->cardid == PRODID_MEGAHERTZ_EM3288))
+	&& (smc->manfid == MANFID_MEGAHERTZ)
+	&& (smc->cardid == PRODID_MEGAHERTZ_EM3288))
 	mhz_3288_power(link);
     
     return i;
@@ -598,7 +592,8 @@
 static int mhz_setup(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     tuple_t tuple;
     cisparse_t parse;
     u_char buf[255], *station_addr;
@@ -645,27 +640,28 @@
 
 static void mot_config(dev_link_t *link)
 {
-    struct net_device *dev = link->priv;
-    struct smc_private *lp = dev->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     ioaddr_t ioaddr = dev->base_addr;
     ioaddr_t iouart = link->io.BasePort2;
     
     /* Set UART base address and force map with COR bit 1 */
-    writeb(iouart & 0xff,        lp->base + MOT_UART + CISREG_IOBASE_0);
-    writeb((iouart >> 8) & 0xff, lp->base + MOT_UART + CISREG_IOBASE_1);
-    writeb(MOT_NORMAL,           lp->base + MOT_UART + CISREG_COR);
+    writeb(iouart & 0xff,        smc->base + MOT_UART + CISREG_IOBASE_0);
+    writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1);
+    writeb(MOT_NORMAL,           smc->base + MOT_UART + CISREG_COR);
     
     /* Set SMC base address and force map with COR bit 1 */
-    writeb(ioaddr & 0xff,        lp->base + MOT_LAN + CISREG_IOBASE_0);
-    writeb((ioaddr >> 8) & 0xff, lp->base + MOT_LAN + CISREG_IOBASE_1);
-    writeb(MOT_NORMAL,           lp->base + MOT_LAN + CISREG_COR);
+    writeb(ioaddr & 0xff,        smc->base + MOT_LAN + CISREG_IOBASE_0);
+    writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1);
+    writeb(MOT_NORMAL,           smc->base + MOT_LAN + CISREG_COR);
 
     /* Wait for things to settle down */
     mdelay(100);
 }
 
 static int mot_setup(dev_link_t *link) {
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     ioaddr_t ioaddr = dev->base_addr;
     int i, wait, loop;
     unsigned int addr;
@@ -699,7 +695,8 @@
 
 static int smc_config(dev_link_t *link)
 {
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     tuple_t tuple;
     cisparse_t parse;
     u_char buf[255];
@@ -731,7 +728,8 @@
 static int smc_setup(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     tuple_t tuple;
     cisparse_t parse;
     cistpl_lan_node_id_t *node_id;
@@ -774,7 +772,8 @@
 
 static int osi_config(dev_link_t *link)
 {
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
     int i, j;
     
@@ -808,7 +807,8 @@
 static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
 {
     client_handle_t handle = link->handle;
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     tuple_t tuple;
     u_char buf[255];
     int i;
@@ -862,7 +862,8 @@
 
 static int check_sig(dev_link_t *link)
 {
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     ioaddr_t ioaddr = dev->base_addr;
     int width;
     u_short s;
@@ -920,8 +921,8 @@
 static void smc91c92_config(dev_link_t *link)
 {
     client_handle_t handle = link->handle;
-    struct net_device *dev = link->priv;
-    struct smc_private *lp = dev->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     tuple_t tuple;
     cisparse_t parse;
     u_short buf[32];
@@ -943,19 +944,19 @@
     tuple.DesiredTuple = CISTPL_MANFID;
     tuple.Attributes = TUPLE_RETURN_COMMON;
     if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
-	lp->manfid = parse.manfid.manf;
-	lp->cardid = parse.manfid.card;
+	smc->manfid = parse.manfid.manf;
+	smc->cardid = parse.manfid.card;
     }
     
     /* Configure card */
     link->state |= DEV_CONFIG;
 
-    if (lp->manfid == MANFID_OSITECH) {
+    if (smc->manfid == MANFID_OSITECH) {
 	i = osi_config(link);
-    } else if (lp->manfid == MANFID_MOTOROLA
-	     || ((lp->manfid == MANFID_MEGAHERTZ)
-		 && ((lp->cardid == PRODID_MEGAHERTZ_VARIOUS)
-		     || (lp->cardid == PRODID_MEGAHERTZ_EM3288)))) {
+    } else if (smc->manfid == MANFID_MOTOROLA
+	     || ((smc->manfid == MANFID_MEGAHERTZ)
+		 && ((smc->cardid == PRODID_MEGAHERTZ_VARIOUS)
+		     || (smc->cardid == PRODID_MEGAHERTZ_EM3288)))) {
 	i = mhz_mfc_config(link);
     } else {
 	i = smc_config(link);
@@ -967,7 +968,7 @@
     i = CardServices(RequestConfiguration, link->handle, &link->conf);
     CS_EXIT_TEST(i, RequestConfiguration, config_failed);
     
-    if (lp->manfid == MANFID_MOTOROLA)
+    if (smc->manfid == MANFID_MOTOROLA)
 	mot_config(link);
 
     dev->irq = link->irq.AssignedIRQ;
@@ -983,10 +984,10 @@
 	goto config_undo;
     }
 
-    switch (lp->manfid) {
+    switch (smc->manfid) {
     case MANFID_OSITECH:
     case MANFID_PSION:
-	i = osi_setup(link, lp->manfid, lp->cardid); break;
+	i = osi_setup(link, smc->manfid, smc->cardid); break;
     case MANFID_SMC:
     case MANFID_NEW_MEDIA:
 	i = smc_setup(link); break;
@@ -1004,7 +1005,7 @@
 	goto config_undo;
     }
 
-    link->dev = &lp->node;
+    link->dev = &smc->node;
     link->state &= ~DEV_CONFIG_PENDING;
 
     rev = check_sig(link);
@@ -1060,13 +1061,13 @@
 static void smc91c92_release(u_long arg)
 {
     dev_link_t *link = (dev_link_t *)arg;
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
 
     DEBUG(0, "smc91c92_release(0x%p)\n", link);
     
     if (link->open) {
 	DEBUG(1, "smc91c92_cs: release postponed, '%s' still open\n",
-	      dev->name);
+	      link->dev->dev_name);
 	link->state |= DEV_STALE_CONFIG;
 	return;
     }
@@ -1075,8 +1076,7 @@
     CardServices(ReleaseIO, link->handle, &link->io);
     CardServices(ReleaseIRQ, link->handle, &link->irq);
     if (link->win) {
-	struct smc_private *lp = dev->priv;
-	iounmap(lp->base);
+	iounmap(smc->base);
 	CardServices(ReleaseWindow, link->win);
     }
     
@@ -1097,7 +1097,8 @@
 			  event_callback_args_t *args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
+    struct smc_private *smc = link->priv;
+    struct net_device *dev = &smc->dev;
     
     DEBUG(1, "smc91c92_event(0x%06x)\n", event);
 
@@ -1132,15 +1133,14 @@
 	/* Fall through... */
     case CS_EVENT_CARD_RESET:
 	if (link->state & DEV_CONFIG) {
-	    struct smc_private *lp = dev->priv;
-	    if ((lp->manfid == MANFID_MEGAHERTZ) &&
-		(lp->cardid == PRODID_MEGAHERTZ_EM3288))
+	    if ((smc->manfid == MANFID_MEGAHERTZ) &&
+		(smc->cardid == PRODID_MEGAHERTZ_EM3288))
 		mhz_3288_power(link);
 	    CardServices(RequestConfiguration, link->handle, &link->conf);
-	    if (lp->manfid == MANFID_MOTOROLA)
+	    if (smc->manfid == MANFID_MOTOROLA)
 		mot_config(link);
-	    if ((lp->manfid == MANFID_OSITECH) &&
-		(lp->cardid != PRODID_OSITECH_SEVEN)) {
+	    if ((smc->manfid == MANFID_OSITECH) &&
+		(smc->cardid != PRODID_OSITECH_SEVEN)) {
 		/* Power up the card and enable interrupts */
 		set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
 		set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
@@ -1181,8 +1181,8 @@
 
 static int smc91c92_open(struct net_device *dev)
 {
-    struct smc_private *lp = (struct smc_private *)dev->priv;
-    dev_link_t *link;
+    struct smc_private *smc = dev->priv;
+    dev_link_t *link = &smc->link;
 
 #ifdef PCMCIA_DEBUG
     DEBUG(0, "%s: smc91c92_open(%p), ID/Window %4.4x.\n",
@@ -1191,11 +1191,9 @@
 #endif
     
     /* Check that the PCMCIA card is still here. */
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
-    /* Physical device present signature. */
     if (!DEV_OK(link))
 	return -ENODEV;
+    /* Physical device present signature. */
     if (check_sig(link) < 0) {
 	printk("smc91c92_cs: Yikes!  Bad chip signature!\n");
 	return -ENODEV;
@@ -1204,14 +1202,14 @@
     MOD_INC_USE_COUNT;
     
     dev->interrupt = 0; dev->tbusy = 0; dev->start = 1;
-    lp->saved_skb = 0;
-    lp->packets_waiting = 0;
+    smc->saved_skb = 0;
+    smc->packets_waiting = 0;
     
     smc_reset(dev);
-    lp->media.function = &media_check;
-    lp->media.data = (u_long)dev;
-    lp->media.expires = jiffies + HZ;
-    add_timer(&lp->media);
+    smc->media.function = &media_check;
+    smc->media.data = (u_long)smc;
+    smc->media.expires = jiffies + HZ;
+    add_timer(&smc->media);
     
     return 0;
 } /* smc91c92_open */
@@ -1220,8 +1218,9 @@
 
 static int smc91c92_close(struct net_device *dev)
 {
+    struct smc_private *smc = dev->priv;
+    dev_link_t *link = &smc->link;
     ioaddr_t ioaddr = dev->base_addr;
-    dev_link_t *link;
 
     DEBUG(0, "%s: smc91c92_close(), status %4.4x.\n",
 	  dev->name, inw(ioaddr + BANK_SELECT));
@@ -1241,13 +1240,8 @@
     SMC_SELECT_BANK( 1 );
     outw(CTL_POWERDOWN, ioaddr + CONTROL  );
     
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev) break;
-    if (link == NULL)
-	return -ENODEV;
-    
     link->open--; dev->start = 0;
-    del_timer(&((struct smc_private *)dev->priv)->media);
+    del_timer(&smc->media);
     if (link->state & DEV_STALE_CONFIG) {
 	link->release.expires = jiffies + HZ/20;
 	link->state |= DEV_RELEASE_PENDING;
@@ -1269,8 +1263,8 @@
 
 static void smc_hardware_send_packet( struct net_device * dev )
 {
-    struct smc_private *lp = (struct smc_private *)dev->priv;
-    struct sk_buff *skb = lp->saved_skb;
+    struct smc_private *smc = dev->priv;
+    struct sk_buff *skb = smc->saved_skb;
     ioaddr_t ioaddr = dev->base_addr;
     unsigned char packet_no;
     
@@ -1286,12 +1280,12 @@
 	printk(KERN_WARNING "%s: 91c92 hardware Tx buffer allocation"
 	       " failed, status %#2.2x.\n", dev->name, packet_no);
 	dev_kfree_skb (skb);
-	lp->saved_skb = NULL;
+	smc->saved_skb = NULL;
 	dev->tbusy = 0;
 	return;
     }
     
-    lp->stats.tx_bytes += skb->len;
+    smc->stats.tx_bytes += skb->len;
     /* The card should use the just-allocated buffer. */
     outw( packet_no, ioaddr + PNR_ARR );
     /* point to the beginning of the packet */
@@ -1332,7 +1326,7 @@
     /* The chip does the rest of the work. */
     outw( MC_ENQUEUE , ioaddr + MMU_CMD );
     
-    lp->saved_skb = NULL;
+    smc->saved_skb = NULL;
     dev_kfree_skb (skb);
     dev->trans_start = jiffies;
     dev->tbusy = 0;
@@ -1343,7 +1337,7 @@
 
 static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-    struct smc_private *lp = (struct smc_private *)dev->priv;
+    struct smc_private *smc = dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
     unsigned short num_pages;
     short time_out, ir;
@@ -1356,11 +1350,11 @@
 	printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
 	       "Tx_status %2.2x status %4.4x.\n",
 	       dev->name, inw(ioaddr)&0xff, inw(ioaddr + 2));
-	lp->stats.tx_errors++;
+	smc->stats.tx_errors++;
 	smc_reset(dev);
 	dev->trans_start = jiffies;
 	dev->tbusy = 0;
-	lp->saved_skb = NULL;
+	smc->saved_skb = NULL;
     }
 
     DEBUG(2, "%s: smc91c92_start_xmit(length = %d) called,"
@@ -1372,26 +1366,26 @@
 	return 1;
     }
     
-    if ( lp->saved_skb) {
+    if ( smc->saved_skb) {
 	/* THIS SHOULD NEVER HAPPEN. */
-	lp->stats.tx_aborted_errors++;
+	smc->stats.tx_aborted_errors++;
 	printk(KERN_DEBUG "%s: Internal error -- sent packet while busy.\n",
 	       dev->name);
 	return 1;
     }
-    lp->saved_skb = skb;
+    smc->saved_skb = skb;
     
     num_pages = skb->len >> 8;
     
     if (num_pages > 7) {
 	printk(KERN_ERR "%s: Far too big packet error.\n", dev->name);
 	dev_kfree_skb (skb);
-	lp->saved_skb = NULL;
-	lp->stats.tx_dropped++;
+	smc->saved_skb = NULL;
+	smc->stats.tx_dropped++;
 	return 0;		/* Do not re-queue this packet. */
     }
     /* A packet is now waiting. */
-    lp->packets_waiting++;
+    smc->packets_waiting++;
     
     SMC_SELECT_BANK( 2 );	/* Paranoia, we should always be in window 2 */
     
@@ -1422,7 +1416,7 @@
 
 static void smc_tx_err( struct net_device * dev )
 {
-    struct smc_private *lp = (struct smc_private *)dev->priv;
+    struct smc_private *smc = (struct smc_private *)dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
     int saved_packet = inw(ioaddr + PNR_ARR) & 0xff;
     int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f;
@@ -1436,12 +1430,12 @@
     
     tx_status = inw(ioaddr + DATA_1);
 
-    lp->stats.tx_errors++;
-    if (tx_status & TS_LOSTCAR) lp->stats.tx_carrier_errors++;
-    if (tx_status & TS_LATCOL)  lp->stats.tx_window_errors++;
+    smc->stats.tx_errors++;
+    if (tx_status & TS_LOSTCAR) smc->stats.tx_carrier_errors++;
+    if (tx_status & TS_LATCOL)  smc->stats.tx_window_errors++;
     if (tx_status & TS_16COL) {
-	lp->stats.tx_aborted_errors++;
-	lp->tx_err++;
+	smc->stats.tx_aborted_errors++;
+	smc->tx_err++;
     }
     
     if ( tx_status & TS_SUCCESS ) {
@@ -1456,7 +1450,7 @@
     outw( MC_FREEPKT, ioaddr + MMU_CMD ); 	/* Free the packet memory. */
     
     /* one less packet waiting for me */
-    lp->packets_waiting--;
+    smc->packets_waiting--;
     
     outw( saved_packet, ioaddr + PNR_ARR );
     return;
@@ -1466,7 +1460,7 @@
 
 static void smc_eph_irq(struct net_device *dev)
 {
-    struct smc_private *lp = dev->priv;
+    struct smc_private *smc = dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
     unsigned short card_stats, ephs;
     
@@ -1477,10 +1471,10 @@
     /* Could be a counter roll-over warning: update stats. */
     card_stats = inw( ioaddr + COUNTER );
     /* single collisions */
-    lp->stats.collisions += card_stats & 0xF;
+    smc->stats.collisions += card_stats & 0xF;
     card_stats >>= 4;
     /* multiple collisions */
-    lp->stats.collisions += card_stats & 0xF;
+    smc->stats.collisions += card_stats & 0xF;
 #if 0 		/* These are for when linux supports these statistics */
     card_stats >>= 4;			/* deferred */
     card_stats >>= 4;			/* excess deferred */
@@ -1500,13 +1494,13 @@
     
 static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    struct net_device *dev = dev_id;
-    struct smc_private *lp;
+    struct smc_private *smc = dev_id;
+    struct net_device *dev = &smc->dev;
     ioaddr_t ioaddr;
     u_short saved_bank, saved_pointer, mask, status;
     char bogus_cnt = INTR_WORK;		/* Work we are willing to do. */
 
-    if ((dev == NULL) || !dev->start)
+    if ((smc == NULL) || !dev->start)
 	return;
     ioaddr = dev->base_addr;
     
@@ -1522,8 +1516,7 @@
 	  irq, ioaddr);
 #endif
     
-    lp = (struct smc_private *)dev->priv;
-    lp->watchdog = 0;
+    smc->watchdog = 0;
     saved_bank = inw(ioaddr + BANK_SELECT);
     if ((saved_bank & 0xff00) != 0x3300) {
 	/* The device does not exist -- the card could be off-line, or
@@ -1553,7 +1546,7 @@
 	if (status & IM_RCV_INT) {
 	    /* Got a packet(s). */
 	    smc_rx(dev);
-	    lp->last_rx = jiffies;
+	    smc->last_rx = jiffies;
 	}
 	if (status & IM_TX_INT) {
 	    smc_tx_err(dev);
@@ -1563,8 +1556,8 @@
 	if (status & IM_TX_EMPTY_INT) {
 	    outw(IM_TX_EMPTY_INT, ioaddr + INTERRUPT);
 	    mask &= ~IM_TX_EMPTY_INT;
-	    lp->stats.tx_packets += lp->packets_waiting;
-	    lp->packets_waiting = 0;
+	    smc->stats.tx_packets += smc->packets_waiting;
+	    smc->packets_waiting = 0;
 	}
 	if (status & IM_ALLOC_INT) {
 	    /* Clear this interrupt so it doesn't happen again */
@@ -1579,8 +1572,8 @@
 	    mark_bh( NET_BH );
 	}
 	if (status & IM_RX_OVRN_INT) {
-	    lp->stats.rx_errors++;
-	    lp->stats.rx_fifo_errors++;		
+	    smc->stats.rx_errors++;
+	    smc->stats.rx_fifo_errors++;		
 	    outw(IM_RX_OVRN_INT, ioaddr + INTERRUPT);
 	}
 	if (status & IM_EPH_INT)
@@ -1602,25 +1595,25 @@
 
 irq_done:
     
-    if ((lp->manfid == MANFID_OSITECH) &&
-	(lp->cardid != PRODID_OSITECH_SEVEN)) {
+    if ((smc->manfid == MANFID_OSITECH) &&
+	(smc->cardid != PRODID_OSITECH_SEVEN)) {
 	/* Retrigger interrupt if needed */
 	mask_bits(0x00ff, ioaddr-0x10+OSITECH_RESET_ISR);
 	set_bits(0x0300, ioaddr-0x10+OSITECH_RESET_ISR);
     }
-    if (lp->manfid == MANFID_MOTOROLA) {
+    if (smc->manfid == MANFID_MOTOROLA) {
 	u_char cor;
-	cor = readb(lp->base + MOT_UART + CISREG_COR);
-	writeb(cor & ~COR_IREQ_ENA, lp->base + MOT_UART + CISREG_COR);
-	writeb(cor, lp->base + MOT_UART + CISREG_COR);
-	cor = readb(lp->base + MOT_LAN + CISREG_COR);
-	writeb(cor & ~COR_IREQ_ENA, lp->base + MOT_LAN + CISREG_COR);
-	writeb(cor, lp->base + MOT_LAN + CISREG_COR);
+	cor = readb(smc->base + MOT_UART + CISREG_COR);
+	writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_UART + CISREG_COR);
+	writeb(cor, smc->base + MOT_UART + CISREG_COR);
+	cor = readb(smc->base + MOT_LAN + CISREG_COR);
+	writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR);
+	writeb(cor, smc->base + MOT_LAN + CISREG_COR);
     }
 #ifdef DOES_NOT_WORK
-    if (lp->base != NULL) { /* Megahertz MFC's */
-	readb(lp->base+MEGAHERTZ_ISR);
-	readb(lp->base+MEGAHERTZ_ISR);
+    if (smc->base != NULL) { /* Megahertz MFC's */
+	readb(smc->base+MEGAHERTZ_ISR);
+	readb(smc->base+MEGAHERTZ_ISR);
     }
 #endif
 }
@@ -1629,7 +1622,7 @@
 
 static void smc_rx(struct net_device *dev)
 {
-    struct smc_private *lp = (struct smc_private *)dev->priv;
+    struct smc_private *smc = (struct smc_private *)dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
     int rx_status;
     int packet_length;	/* Caution: not frame length, rather words
@@ -1660,7 +1653,7 @@
 	
 	if ( skb == NULL ) {
 	    DEBUG(1, "%s: Low memory, packet dropped.\n", dev->name);
-	    lp->stats.rx_dropped++;
+	    smc->stats.rx_dropped++;
 	    outw( MC_RELEASE, ioaddr + MMU_CMD );
 	    return;
 	}
@@ -1673,18 +1666,18 @@
 	
 	skb->dev = dev;
 	netif_rx(skb);
-	lp->stats.rx_packets++;
-	lp->stats.rx_bytes += skb->len;
+	smc->stats.rx_packets++;
+	smc->stats.rx_bytes += skb->len;
 	if (rx_status & RS_MULTICAST)
-	    lp->stats.multicast++;
+	    smc->stats.multicast++;
     } else {
 	/* error ... */
-	lp->stats.rx_errors++;
+	smc->stats.rx_errors++;
 	
-	if (rx_status & RS_ALGNERR)  lp->stats.rx_frame_errors++;
+	if (rx_status & RS_ALGNERR)  smc->stats.rx_frame_errors++;
 	if (rx_status & (RS_TOOSHORT | RS_TOOLONG))
-	    lp->stats.rx_length_errors++;
-	if (rx_status & RS_BADCRC)	lp->stats.rx_crc_errors++;
+	    smc->stats.rx_length_errors++;
+	if (rx_status & RS_BADCRC)	smc->stats.rx_crc_errors++;
     }
     /* Let the MMU free the memory of this packet. */
     outw(MC_RELEASE, ioaddr + MMU_CMD);
@@ -1696,9 +1689,9 @@
 
 static struct net_device_stats *smc91c92_get_stats(struct net_device *dev)
 {
-    struct smc_private *lp = (struct smc_private *)dev->priv;
+    struct smc_private *smc = (struct smc_private *)dev->priv;
     /* Nothing to update - the 91c92 is a pretty primative chip. */
-    return &lp->stats;
+    return &smc->stats;
 }
 
 /*======================================================================
@@ -1801,9 +1794,9 @@
 
 static int s9k_config(struct net_device *dev, struct ifmap *map)
 {
-    struct smc_private *lp = dev->priv;
+    struct smc_private *smc = dev->priv;
     if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
-	if (lp->cfg & CFG_MII_SELECT)
+	if (smc->cfg & CFG_MII_SELECT)
 	    return -EOPNOTSUPP;
 	else if (map->port > 2)
 	    return -EINVAL;
@@ -1827,24 +1820,24 @@
 */
 static void smc_set_xcvr(struct net_device *dev, int if_port)
 {
-    struct smc_private *lp = (struct smc_private *)dev->priv;
+    struct smc_private *smc = (struct smc_private *)dev->priv;
     ioaddr_t ioaddr = dev->base_addr;
     u_short saved_bank;
 
     saved_bank = inw(ioaddr + BANK_SELECT);
     SMC_SELECT_BANK(1);
     if (if_port == 2) {
-	outw(lp->cfg | CFG_AUI_SELECT, ioaddr + CONFIG);
-	if ((lp->manfid == MANFID_OSITECH) &&
-	    (lp->cardid != PRODID_OSITECH_SEVEN))
+	outw(smc->cfg | CFG_AUI_SELECT, ioaddr + CONFIG);
+	if ((smc->manfid == MANFID_OSITECH) &&
+	    (smc->cardid != PRODID_OSITECH_SEVEN))
 	    set_bits(OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR);
-	lp->media_status = ((dev->if_port == 0) ? 0x0001 : 0x0002);
+	smc->media_status = ((dev->if_port == 0) ? 0x0001 : 0x0002);
     } else {
-	outw(lp->cfg, ioaddr + CONFIG);
-	if ((lp->manfid == MANFID_OSITECH) &&
-	    (lp->cardid != PRODID_OSITECH_SEVEN))
+	outw(smc->cfg, ioaddr + CONFIG);
+	if ((smc->manfid == MANFID_OSITECH) &&
+	    (smc->cardid != PRODID_OSITECH_SEVEN))
 	    mask_bits(~OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR);
-	lp->media_status = ((dev->if_port == 0) ? 0x0012 : 0x4001);
+	smc->media_status = ((dev->if_port == 0) ? 0x0012 : 0x4001);
     }
     SMC_SELECT_BANK(saved_bank);
 }
@@ -1852,7 +1845,7 @@
 static void smc_reset(struct net_device *dev)
 {
     ioaddr_t ioaddr = dev->base_addr;
-    struct smc_private *lp = dev->priv;
+    struct smc_private *smc = dev->priv;
     int i;
 
     DEBUG(0, "%s: smc91c92 reset called.\n", dev->name);
@@ -1875,12 +1868,12 @@
        Accept link errors, counter and Tx error interrupts. */
     outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE,
 	 ioaddr + CONTROL);
-    lp->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;
-    lp->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC |
-	(lp->manfid == MANFID_OSITECH ? (CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0) : 0);
+    smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;
+    smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC |
+	(smc->manfid == MANFID_OSITECH ? (CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0) : 0);
     smc_set_xcvr(dev, dev->if_port);
-    if ((lp->manfid == MANFID_OSITECH) &&
-	(lp->cardid != PRODID_OSITECH_SEVEN))
+    if ((smc->manfid == MANFID_OSITECH) &&
+	(smc->cardid != PRODID_OSITECH_SEVEN))
 	outw((dev->if_port == 2 ? OSI_AUI_PWR : 0) |
 	     (inw(ioaddr-0x10+OSITECH_AUI_PWR) & 0xff00),
 	     ioaddr - 0x10 + OSITECH_AUI_PWR);
@@ -1897,7 +1890,7 @@
     
     /* Re-enable the chip. */
     SMC_SELECT_BANK(0);
-    outw(((lp->cfg & CFG_MII_SELECT) ? 0 : TCR_MONCSN) |
+    outw(((smc->cfg & CFG_MII_SELECT) ? 0 : TCR_MONCSN) |
 	 TCR_ENABLE | TCR_PAD_EN, ioaddr + TCR);
     set_rx_mode(dev);
 
@@ -1915,14 +1908,13 @@
 
 static void media_check(u_long arg)
 {
-    struct net_device *dev = (struct net_device *)(arg);
-    struct smc_private *lp = (struct smc_private *)dev->priv;
+    struct smc_private *smc = (struct smc_private *)(arg);
+    struct net_device *dev = &smc->dev;
     ioaddr_t ioaddr = dev->base_addr;
     u_short i, media, saved_bank;
 
     if (dev->start == 0) goto reschedule;
     
-    lp = (struct smc_private *)dev->priv;
     saved_bank = inw(ioaddr + BANK_SELECT);
     SMC_SELECT_BANK(2);
     i = inw(ioaddr + INTERRUPT);
@@ -1934,36 +1926,36 @@
     
     /* Check for pending interrupt with watchdog flag set: with
        this, we can limp along even if the interrupt is blocked */
-    if (lp->watchdog++ && ((i>>8) & i)) {
-	if (!lp->fast_poll)
+    if (smc->watchdog++ && ((i>>8) & i)) {
+	if (!smc->fast_poll)
 	    printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
-	smc_interrupt(dev->irq, dev, NULL);
-	lp->fast_poll = HZ;
+	smc_interrupt(dev->irq, smc, NULL);
+	smc->fast_poll = HZ;
     }
-    if (lp->fast_poll) {
-	lp->fast_poll--;
-	lp->media.expires = jiffies + 1;
-	add_timer(&lp->media);
+    if (smc->fast_poll) {
+	smc->fast_poll--;
+	smc->media.expires = jiffies + 1;
+	add_timer(&smc->media);
 	return;
     }
 
-    if (lp->cfg & CFG_MII_SELECT)
+    if (smc->cfg & CFG_MII_SELECT)
 	goto reschedule;
 
     /* Ignore collisions unless we've had no rx's recently */
-    if (jiffies - lp->last_rx > HZ) {
-	if (lp->tx_err || (lp->media_status & EPH_16COL))
+    if (jiffies - smc->last_rx > HZ) {
+	if (smc->tx_err || (smc->media_status & EPH_16COL))
 	    media |= EPH_16COL;
     }
-    lp->tx_err = 0;
+    smc->tx_err = 0;
 
-    if (media != lp->media_status) {
-	if ((media & lp->media_status & 1) &&
-	    ((lp->media_status ^ media) & EPH_LINK_OK))
+    if (media != smc->media_status) {
+	if ((media & smc->media_status & 1) &&
+	    ((smc->media_status ^ media) & EPH_LINK_OK))
 	    printk(KERN_INFO "%s: %s link beat\n", dev->name,
-		   (lp->media_status & EPH_LINK_OK ? "lost" : "found"));
-	else if ((media & lp->media_status & 2) &&
-		 ((lp->media_status ^ media) & EPH_16COL))
+		   (smc->media_status & EPH_LINK_OK ? "lost" : "found"));
+	else if ((media & smc->media_status & 2) &&
+		 ((smc->media_status ^ media) & EPH_16COL))
 	    printk(KERN_INFO "%s: coax cable %s\n", dev->name,
 		   (media & EPH_16COL ? "problem" : "ok"));
 	if (dev->if_port == 0) {
@@ -1981,12 +1973,12 @@
 			   dev->name);
 	    }
 	}
-	lp->media_status = media;
+	smc->media_status = media;
     }
     
 reschedule:
-    lp->media.expires = jiffies + HZ;
-    add_timer(&lp->media);
+    smc->media.expires = jiffies + HZ;
+    add_timer(&smc->media);
 }
 
 /*====================================================================*/
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/tulip_cb.c linux/drivers/net/pcmcia/tulip_cb.c
--- v2.3.39/linux/drivers/net/pcmcia/tulip_cb.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/net/pcmcia/tulip_cb.c	Thu Jan 20 09:57:06 2000
@@ -256,58 +256,6 @@
 
 */
 
-static struct net_device *
-tulip_probe1(int pci_bus, int pci_devfn, struct net_device *dev, long ioaddr,
-			 int irq, int chip_idx, int board_idx);
-
-/* This table drives the PCI probe routines.  It's mostly boilerplate in all
-   of the drivers, and will likely be provided by some future kernel.
-   Note the matching code -- the first table entry matchs all 56** cards but
-   second only the 1234 card.
-*/
-enum pci_flags_bit {
-	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
-	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
-};
-#define PCI_ADDR0_IO (PCI_USES_IO|PCI_ADDR0)
-
-struct pci_id_info {
-	const char *name;
-	u16	vendor_id, device_id, device_id_mask, flags;
-	int io_size, min_latency;
-	struct net_device *(*probe1)(int pci_bus, int pci_devfn, struct net_device *dev,
-							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
-};
-static struct pci_id_info pci_tbl[] = {
-  { "Digital DC21040 Tulip",
-	0x1011, 0x0002, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
-  { "Digital DC21041 Tulip",
-	0x1011, 0x0014, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
-  { "Digital DS21140 Tulip",
-	0x1011, 0x0009, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
-  { "Digital DS21143 Tulip",
-	0x1011, 0x0019, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
-  { "Lite-On 82c168 PNIC",
-	0x11AD, 0x0002, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
-  { "Macronix 98713 PMAC",
-	0x10d9, 0x0512, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
-  { "Macronix 98715 PMAC",
-	0x10d9, 0x0531, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
-  { "Macronix 98725 PMAC",
-	0x10d9, 0x0531, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
-  { "ASIX AX88140",
-	0x125B, 0x1400, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
-  { "Lite-On LC82C115 PNIC-II",
-	0x11AD, 0xc115, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
-  { "ADMtek AN981 Comet",
-	0x1317, 0x0981, 0xffff, PCI_ADDR0_IO, 256, 32, tulip_probe1 },
-  { "Compex RL100-TX",
-	0x11F6, 0x9881, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
-  { "Xircom Cardbus Adapter (DEC 21143 compatible mode)",
-	0x115D, 0x0003, 0xffff, PCI_ADDR0_IO, 128, 32, tulip_probe1 },
-  {0},
-};
-
 /* This table use during operation for capabilities and media timer. */
 
 static void tulip_timer(unsigned long data);
@@ -2530,7 +2478,7 @@
 	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
 		printk(KERN_ERR "%s: Duplicate entry of the interrupt handler by "
 			   "processor %d.\n",
-			   dev->name, hard_smp_processor_id());
+			   dev->name, smp_processor_id());
 		dev->interrupt = 0;
 		return;
 	}
@@ -3140,32 +3088,41 @@
 	outl_CSR6(csr6 | 0x0000, ioaddr, tp->chip_id);
 }
 
-static int tulip_probe(struct pci_dev *pdev)
+static const struct pci_device_id tulip_pci_table[] __devinitdata = {
+  { 0x1011, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21040 },
+  { 0x1011, 0x0014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21041 },
+  { 0x1011, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 },
+  { 0x1011, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21142 },
+  { 0x11AD, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, LC82C168 },
+  { 0x10d9, 0x0512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98713 },
+  { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
+  { 0x10d9, 0x0531, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98725 },
+  { 0x125B, 0x1400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AX88140 },
+  { 0x11AD, 0xc115, PCI_ANY_ID, PCI_ANY_ID, 0, 0, PNIC2 },
+  { 0x1317, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+  { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
+  { 0x115D, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, X3201_3 },
+  {0},
+};
+
+MODULE_DEVICE_TABLE(pci, tulip_pci_table);
+
+static int __devinit tulip_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct net_device *dev;
-	int chip_idx;
 	static int board_idx = 0;
 
 	printk(KERN_INFO "tulip_attach(%s)\n", pdev->slot_name);
 
-	for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++)
-		if (pdev->vendor == pci_tbl[chip_idx].vendor_id
-		    && (pdev->device & pci_tbl[chip_idx].device_id_mask) ==
-		    pci_tbl[chip_idx].device_id)
-			break;
-	if (pci_tbl[chip_idx].vendor_id == 0)
-		return 0;
-
 	pci_set_master(pdev);
-	dev = pci_tbl[chip_idx].probe1(pdev->bus->number, pdev->devfn, NULL,
+	dev = tulip_probe1(pdev->bus->number, pdev->devfn, NULL,
 				       pdev->resource[0].start, pdev->irq,
-				       chip_idx, board_idx++);
+				       id->driver_data, board_idx++);
 	if (dev) {
 		pdev->driver_data = dev;
-		MOD_INC_USE_COUNT;
-		return 1;
+		return 0;
 	}
-	return 0;
+	return -ENODEV;
 }
 
 static void tulip_suspend(struct pci_dev *pdev)
@@ -3184,7 +3141,7 @@
 	if (tp->open) tulip_up(dev);
 }
 
-static void tulip_remove(struct pci_dev *pdev)
+static void __devexit tulip_remove(struct pci_dev *pdev)
 {
 	struct net_device *dev = pdev->driver_data;
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -3195,27 +3152,29 @@
 	kfree(tp);
 }
 
-struct pci_driver tulip_ops = {
+static struct pci_driver tulip_ops = {
 	name:		"tulip_cb",
-	probe:		tulip_probe,
+	id_table:	tulip_pci_table,
+	probe:		tulip_pci_probe,
 	remove:		tulip_remove,
 	suspend:	tulip_suspend,
 	resume:		tulip_resume
 };
 
-int __init tulip_init(void)
+static int __init tulip_init(void)
 {
 	pci_register_driver(&tulip_ops);
 	return 0;
 }
 
-void __exit tulip_cleanup(void)
+static __exit void tulip_exit(void)
 {
 	pci_unregister_driver(&tulip_ops);
 }
 
-module_init(tulip_init);
-module_exit(tulip_cleanup);
+module_init(tulip_init)
+module_exit(tulip_exit)
+
 
 /*
  * Local variables:
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/wavelan_cs.c linux/drivers/net/pcmcia/wavelan_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/wavelan_cs.c	Fri Oct 22 13:21:49 1999
+++ linux/drivers/net/pcmcia/wavelan_cs.c	Tue Jan 18 22:29:17 2000
@@ -2105,7 +2105,7 @@
 	}
 
       /* only super-user can see encryption key */
-      if(!suser())
+      if(!capable(CAP_NET_ADMIN))
 	{
 	  ret = -EPERM;
 	  break;
@@ -2437,7 +2437,7 @@
       /* ------------------ PRIVATE IOCTL ------------------ */
 
     case SIOCSIPQTHR:
-      if(!suser())
+      if(!capable(CAP_NET_ADMIN))
 	{
 	  ret = -EPERM;
 	  break;
@@ -2476,7 +2476,7 @@
 #ifdef HISTOGRAM
     case SIOCSIPHISTO:
       /* Verif if the user is root */
-      if(!suser())
+      if(!capable(CAP_NET_ADMIN))
 	{
 	  ret = -EPERM;
 	}
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcmcia/xirc2ps_cs.c linux/drivers/net/pcmcia/xirc2ps_cs.c
--- v2.3.39/linux/drivers/net/pcmcia/xirc2ps_cs.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/pcmcia/xirc2ps_cs.c	Tue Jan 18 22:29:17 2000
@@ -1,37 +1,44 @@
-/* [xirc2ps_cs.c wk 14.04.97] (1.31 1998/12/09 19:32:55)
- * Xircom Creditcard Ethernet Adapter IIps driver
- *
- * This driver works for the CE2, CEM28, CEM33, CE3 and CEM56 cards.
- * The CEM56 has some problems, but it works.
- * The CEII card with the 14k4 modem and other old cards do not work.
- *
- * Written by Werner Koch (werner.koch@guug.de),
- * based on David Hinds skeleton driver.
- *
- * You can get the latest driver revision from
- *	"http://www.d.shuttle.de/isil/xircom/xirc2ps.html"
- *
- * Please report bugs to: "xircom-bugs@isil.d.shuttle.de"
- *
- * A bug fix for the CEM56 to use modem and ethernet simultaneously
- * was provided by Koen Van Herck (Koen.Van.Herck@xircom.com).
- *
- * If your card locks up you should use the option "lockup_hack=1";
- * this may solve the problem but violates a kernel timing convention
- * (Thanks to David Luyer).
- *
- * Thanks to David Hinds for the PCMCIA package, Donald Becker for some
- * advice, Xircom for providing specs and help, 4PC GmbH Duesseldorf for
- * providing some hardware and last not least to all folks who helped to
- * develop this driver.
- *
- * For those, who are willing to do alpha testing of drivers, I have setup
- * the mailing list "xircom-devel@isil.d.shuttle.de" (To subscribe send a
- * message containing the word "subscribe" in the subject or somewhere at
- * the beginning of a line to "xircom-devel-request@isil.d.shuttle.de").
+/* [xirc2ps_cs.c wk 03.11.99] (1.40 1999/11/18 00:06:03)
+ * Xircom CreditCard Ethernet Adapter IIps driver
+ * Xircom Realport 10/100 (RE-100) driver 
+ *
+ * This driver originally was made by Werner Koch. Since the driver was left
+ * unmaintained for some time, there have been some improvements and changes
+ * since. These include supporting some of the "Realport" cards and develop-
+ * ing enhancements to support the new ones.
+ * It is made for CE2, CEM28, CEM33, CE33 and 
+ * CEM56 cards. The CEM56 cards work both with their modem and ethernet
+ * interface. The RealPort 10/100 Modem and similar cards are supported but
+ * with some bugs which are being corrected as they are detected. 
+ * 
+ * Code revised and maintained by Allan Baker Ortegon
+ * al527261@prodigy.net.mx
+ * Written originally by Werner Koch based on David Hinds' skeleton of the
+ * PCMCIA driver. The code has been modified as to make the newer cards
+ * available.
+ *
+ * The latest code for the driver, information on the development project
+ * for the Xircom RealPort and CE cards for the PCMCIA driver, and other
+ * related material, can be found at the following URL, which is underway:
+ * 
+ * "http://xirc2ps.linuxbox.com/index.html"
+ *
+ * Any bugs regarding this driver, please send them to:
+ * alanyuu@linuxbox.com
+ *
+ * The driver is still evolving and there are many cards which will benefit
+ * from having alpha testers. If you have a particular card and would like
+ * to be involved in this ongoing effort, please send mail to the maintainer.
+ * 
+ * Special thanks to David Hinds, to Xircom for the specifications and their
+ * software development kit, and all others who may have colaborated in the
+ * development of the driver: Koen Van Herck (Koen.Van.Herck@xircom.com),
+ * 4PC GmbH Duesseldorf, David Luger, et al.
+ * 
  *
  ************************************************************************
  * Copyright (c) 1997,1998 Werner Koch (dd9jn)
+ * Copyright (c) 1999 Allan Baker Ortegon 
  *
  * This driver is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -70,7 +77,7 @@
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED.	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
@@ -388,6 +395,8 @@
  */
 
 typedef struct local_info_t {
+    dev_link_t link;
+    struct net_device dev;
     dev_node_t node;
     struct enet_statistics stats;
     int card_type;
@@ -472,14 +481,18 @@
 static void
 busy_loop(u_long len)
 {
-    u_long timeout = jiffies + len;
-    u_long flags;
-
-    save_flags(flags);
-    sti();
-    while (timeout >= jiffies)
-	;
-    restore_flags(flags);
+    if (in_interrupt()) {
+	u_long timeout = jiffies + len;
+	u_long flags;
+	save_flags(flags);
+	sti();
+	while (timeout >= jiffies)
+	    ;
+	restore_flags(flags);
+    } else {
+	__set_current_state(TASK_UNINTERRUPTIBLE);
+	schedule_timeout(len);
+    }
 }
 
 /*====== Functions used for debugging =================================*/
@@ -674,9 +687,13 @@
     DEBUG(0, "attach()\n");
     flush_stale_links();
 
-    /* Initialize the dev_link_t structure */
-    link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    memset(link, 0, sizeof(struct dev_link_t));
+    /* Allocate the device structure */
+    local = kmalloc(sizeof(*local), GFP_KERNEL);
+    if (!local) return NULL;
+    memset(local, 0, sizeof(*local));
+    link = &local->link; dev = &local->dev;
+    link->priv = dev->priv = local;
+
     link->release.function = &xirc2ps_release;
     link->release.data = (u_long) link;
 
@@ -686,13 +703,8 @@
     link->conf.IntType = INT_MEMORY_AND_IO;
     link->conf.ConfigIndex = 1;
     link->conf.Present = PRESENT_OPTION;
-
-    /* Allocate space for a device structure */
-    dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
-    memset(dev, 0, sizeof(struct net_device));
-    local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
-    memset(local, 0, sizeof(local_info_t));
-    dev->priv = local;
+    link->irq.Handler = xirc2ps_interrupt;
+    link->irq.Instance = dev;
 
     /* Fill in card specific entries */
     dev->hard_start_xmit = &do_start_xmit;
@@ -706,7 +718,6 @@
     dev->open = &do_open;
     dev->stop = &do_stop;
     dev->tbusy = 1;
-    link->priv = dev;
 
     /* Register with Card Services */
     link->next = dev_list;
@@ -739,6 +750,7 @@
 static void
 xirc2ps_detach(dev_link_t * link)
 {
+    local_info_t *local = link->priv;
     dev_link_t **linkp;
     long flags;
 
@@ -778,17 +790,11 @@
     if (link->handle)
 	CardServices(DeregisterClient, link->handle);
 
-    /* Unlink device structure, free pieces */
+    /* Unlink device structure, free it */
     *linkp = link->next;
-    if (link->priv) {
-	struct net_device *dev = link->priv;
-	if (link->dev != NULL)
-	    unregister_netdev(dev);
-	if (dev->priv)
-	    kfree(dev->priv);
-	kfree(link->priv);
-    }
-    kfree(link);
+    if (link->dev)
+	unregister_netdev(&local->dev);
+    kfree(local);
 
 } /* xirc2ps_detach */
 
@@ -813,8 +819,7 @@
 static int
 set_card_type(dev_link_t *link, const void *s)
 {
-    struct net_device *dev = link->priv;
-    local_info_t *local = dev->priv;
+    local_info_t *local = link->priv;
   #ifdef PCMCIA_DEBUG
     unsigned cisrev = ((const unsigned char *)s)[2];
   #endif
@@ -907,20 +912,17 @@
 static void
 xirc2ps_config(dev_link_t * link)
 {
-    client_handle_t handle;
+    client_handle_t handle = link->handle;
+    local_info_t *local = link->priv;
+    struct net_device *dev = &local->dev;
     tuple_t tuple;
     cisparse_t parse;
-    struct net_device *dev;
-    local_info_t *local;
     ioaddr_t ioaddr;
     int err, i;
     u_char buf[64];
     cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
 
-    handle = link->handle;
-    dev = link->priv;
-    local = dev->priv;
     local->dingo_ccr = 0;
 
     DEBUG(0, "config(0x%p)\n", link);
@@ -1034,8 +1036,6 @@
 	for (i = 0; i < 4; i++)
 	    link->irq.IRQInfo2 |= 1 << irq_list[i];
     }
-    link->irq.Handler = xirc2ps_interrupt;
-    link->irq.Instance = dev;
     if (local->modem) {
 	int pass;
 
@@ -1124,7 +1124,7 @@
      * the I/O windows and the interrupt mapping.
      */
     if ((err=CardServices(RequestConfiguration,
-					link->handle, &link->conf))) {
+			  link->handle, &link->conf))) {
 	cs_error(link->handle, RequestConfiguration, err);
 	goto config_error;
     }
@@ -1146,7 +1146,7 @@
 	reg.Offset = CISREG_IOBASE_0;
 	reg.Value = link->io.BasePort2 & 0xff;
 	if ((err = CardServices(AccessConfigurationRegister, link->handle,
-							     &reg))) {
+				&reg))) {
 	    cs_error(link->handle, AccessConfigurationRegister, err);
 	    goto config_error;
 	}
@@ -1154,7 +1154,7 @@
 	reg.Offset = CISREG_IOBASE_1;
 	reg.Value = (link->io.BasePort2 >> 8) & 0xff;
 	if ((err = CardServices(AccessConfigurationRegister, link->handle,
-							      &reg))) {
+				&reg))) {
 	    cs_error(link->handle, AccessConfigurationRegister, err);
 	    goto config_error;
 	}
@@ -1213,20 +1213,19 @@
 	}
       #endif
 
-	writeb(0x01		  , local->dingo_ccr + 0x20);
-	writeb(0x0c		  , local->dingo_ccr + 0x22);
-	writeb(0x00		  , local->dingo_ccr + 0x24);
-	writeb(0x00		  , local->dingo_ccr + 0x26);
-	writeb(0x00		  , local->dingo_ccr + 0x28);
+	writeb(0x01, local->dingo_ccr + 0x20);
+	writeb(0x0c, local->dingo_ccr + 0x22);
+	writeb(0x00, local->dingo_ccr + 0x24);
+	writeb(0x00, local->dingo_ccr + 0x26);
+	writeb(0x00, local->dingo_ccr + 0x28);
     }
 
     /* The if_port symbol can be set when the module is loaded */
     local->probe_port=0;
     if (!if_port) {
-	local->probe_port=1;
-	dev->if_port = 1;
-    }
-    else if ((if_port >= 1 && if_port <= 2) || (local->mohawk && if_port==4))
+	local->probe_port = dev->if_port = 1;
+    } else if ((if_port >= 1 && if_port <= 2) ||
+	       (local->mohawk && if_port==4))
 	dev->if_port = if_port;
     else
 	printk(KNOT_XIRC "invalid if_port requested\n");
@@ -1275,7 +1274,8 @@
 xirc2ps_release(u_long arg)
 {
     dev_link_t *link = (dev_link_t *) arg;
-    struct net_device *dev = link->priv;
+    local_info_t *local = link->priv;
+    struct net_device *dev = &local->dev;
 
     DEBUG(0, "release(0x%p)\n", link);
 
@@ -1322,8 +1322,8 @@
 	      event_callback_args_t * args)
 {
     dev_link_t *link = args->client_data;
-    struct net_device *dev = link->priv;
-    local_info_t *lp = dev? dev->priv : NULL;
+    local_info_t *lp = link->priv;
+    struct net_device *dev = &lp->dev;
 
     DEBUG(0, "event(%d)\n", (int)event);
 
@@ -1382,7 +1382,7 @@
 xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct net_device *dev = (struct net_device *)dev_id;
-    local_info_t *lp;
+    local_info_t *lp = dev->priv;
     ioaddr_t ioaddr;
     u_char saved_page;
     unsigned bytes_rcvd;
@@ -1401,7 +1401,6 @@
 	return;
     }
     dev->interrupt = 1;
-    lp = dev->priv;
     ioaddr = dev->base_addr;
     if (lp->mohawk) { /* must disable the interrupt */
 	PutByte(XIRCREG_CR, 0);
@@ -1441,7 +1440,7 @@
 	    /* too many bytes received during this int, drop the rest of the
 	     * packets */
 	    lp->stats.rx_dropped++;
-	    printk(KINF_XIRC "%s: RX drop, too much done\n", dev->name);
+	    DEBUG(2, "%s: RX drop, too much done\n", dev->name);
 	    PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */
 	} else if (rsr & PktRxOk) {
 	    struct sk_buff *skb;
@@ -1782,8 +1781,6 @@
 
     DEBUG(0, "do_config(%p)\n", dev);
     if (map->port != 255 && map->port != dev->if_port) {
-	if (local->new_mii)
-	    return -EOPNOTSUPP;
 	if (map->port > 4)
 	    return -EINVAL;
 	if (!map->port) {
@@ -1813,14 +1810,11 @@
 do_open(struct net_device *dev)
 {
     local_info_t *lp = dev->priv;
-    dev_link_t *link;
+    dev_link_t *link = &lp->link;
 
     DEBUG(0, "do_open(%p)\n", dev);
 
     /* Check that the PCMCIA card is still here. */
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev)
-	    break;
     /* Physical device present signature. */
     if (!DEV_OK(link))
 	return -ENODEV;
@@ -1858,7 +1852,7 @@
 	data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
 	break;
       case SIOCDEVPRIVATE+2:	/* Write the specified MII register */
-	if (!suser())
+	if (!capable(CAP_NET_ADMIN))
 	    return -EPERM;
 	mii_wr(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2], 16);
 	break;
@@ -2064,7 +2058,7 @@
 
     local->new_mii = (mii_rd(ioaddr, 0, 2) != 0xffff);
     
-    if (local->new_mii || local->probe_port)
+    if (local->probe_port)
 	control = 0x1000; /* auto neg */
     else if (dev->if_port == 4)
 	control = 0x2000; /* no auto neg, 100mbs mode */
@@ -2081,8 +2075,8 @@
 	return 0;
     }
 
-    if (local->new_mii || local->probe_port) {
-	/* according to the DP83840A specs the auto negotation process
+    if (local->probe_port) {
+	/* according to the DP83840A specs the auto negotiation process
 	 * may take up to 3.5 sec, so we use this also for our ML6692
 	 * Fixme: Better to use a timer here!
 	 */
@@ -2094,7 +2088,7 @@
 	}
 
 	if (!(status & 0x0020)) {
-	    printk(KERN_INFO "%s: auto negotation failed;"
+	    printk(KERN_INFO "%s: autonegotiation failed;"
 		   " using 10mbs\n", dev->name);
 	    if (!local->new_mii) {
 		control = 0x0000;
@@ -2112,7 +2106,6 @@
 	    } else
 		dev->if_port = 1;
 	}
-	local->probe_port = 0;
     }
 
   #ifdef PCMCIA_DEBUG
@@ -2140,13 +2133,11 @@
 do_stop(struct net_device *dev)
 {
     ioaddr_t ioaddr = dev->base_addr;
-    dev_link_t *link;
+    local_info_t *lp = dev->priv;
+    dev_link_t *link = &lp->link;
 
     DEBUG(0, "do_stop(%p)\n", dev);
 
-    for (link = dev_list; link; link = link->next)
-	if (link->priv == dev)
-	    break;
     if (!link)
 	return -ENODEV;
 
diff -u --recursive --new-file v2.3.39/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.3.39/linux/drivers/net/pcnet32.c	Thu Nov 11 20:11:41 1999
+++ linux/drivers/net/pcnet32.c	Thu Jan 20 10:44:46 2000
@@ -584,6 +584,7 @@
      case 0x2627:
 	chipname = "PCnet/FAST III 79C975";
 	fdx = 1; mii = 1;
+	break;
      default:
 	printk("pcnet32: PCnet version %#x, no PCnet32 chip.\n",chip_version);
 	return ENODEV;
diff -u --recursive --new-file v2.3.39/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v2.3.39/linux/drivers/net/plip.c	Fri Sep 10 23:57:30 1999
+++ linux/drivers/net/plip.c	Thu Jan 20 15:19:27 2000
@@ -318,7 +318,6 @@
 	dev->open		 = plip_open;
 	dev->stop		 = plip_close;
 	dev->get_stats 		 = plip_get_stats;
-	dev->set_config		 = plip_config;
 	dev->do_ioctl		 = plip_ioctl;
 	dev->header_cache_update = NULL;
 	dev->tx_queue_len 	 = 10;
@@ -1229,27 +1228,6 @@
 }
 
 static int
-plip_config(struct net_device *dev, struct ifmap *map)
-{
-	struct net_local *nl = (struct net_local *) dev->priv;
-	struct pardevice *pardev = nl->pardev;
-
-	if (dev->flags & IFF_UP)
-		return -EBUSY;
-
-	printk(KERN_WARNING "plip: Warning, changing irq with ifconfig will be obsoleted.\n");
-	printk(KERN_WARNING "plip: Next time, please set with /proc/parport/*/irq instead.\n");
-
-	if (map->irq != (unsigned char)-1) {
-		pardev->port->irq = dev->irq = map->irq;
-		/* Dummy request */
-		request_irq(dev->irq, plip_interrupt, SA_INTERRUPT,
-			    pardev->name, NULL);
-	}
-	return 0;
-}
-
-static int
 plip_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct net_local *nl = (struct net_local *) dev->priv;
@@ -1375,6 +1353,7 @@
 			if (!dev_plip[i]->name) {
 				printk(KERN_ERR "plip: memory squeeze.\n");
 				kfree(dev_plip[i]);
+				dev_plip[i] = NULL;
 				break;
 			}
 			sprintf(dev_plip[i]->name, "plip%d", i);
@@ -1382,6 +1361,7 @@
 			if (plip_init_dev(dev_plip[i],pb) || register_netdev(dev_plip[i])) {
 				kfree(dev_plip[i]->name);
 				kfree(dev_plip[i]);
+				dev_plip[i] = NULL;
 			} else {
 				i++;
 			}
diff -u --recursive --new-file v2.3.39/linux/drivers/net/setup.c linux/drivers/net/setup.c
--- v2.3.39/linux/drivers/net/setup.c	Wed Dec  8 14:11:26 1999
+++ linux/drivers/net/setup.c	Thu Jan 13 18:03:58 2000
@@ -30,6 +30,7 @@
 extern int bigmac_probe(void); 
 extern int bmac_probe(void); 
 extern int cpm_enet_init(void); 
+extern int oaknet_init(void);
 extern int dlci_setup(void); 
 extern int dgrs_probe(void); 
 extern int dmfe_reg_board(void); 
@@ -162,6 +163,13 @@
 #endif
 #ifdef CONFIG_NCR885E
 	{ncr885e_probe, 0},
+#endif
+
+/*
+ *	IBM "Oak" Evaluation board
+ */
+#ifdef	CONFIG_OAKNET
+	{oaknet_init, 0},
 #endif
 
 /*
diff -u --recursive --new-file v2.3.39/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
--- v2.3.39/linux/drivers/net/shaper.c	Thu Aug 26 13:05:38 1999
+++ linux/drivers/net/shaper.c	Thu Jan 20 10:44:46 2000
@@ -557,6 +557,13 @@
 {
 	struct shaperconf *ss= (struct shaperconf *)&ifr->ifr_data;
 	struct shaper *sh=dev->priv;
+	
+	if(ss->ss_cmd == SHAPER_SET_DEV || ss->ss_cmd == SHAPER_SET_SPEED)
+	{
+		if(!capable(CAP_NET_ADMIN))
+			return -EPERM;
+	}
+	
 	switch(ss->ss_cmd)
 	{
 		case SHAPER_SET_DEV:
diff -u --recursive --new-file v2.3.39/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.3.39/linux/drivers/net/smc-ultra.c	Mon Nov  1 13:56:26 1999
+++ linux/drivers/net/smc-ultra.c	Thu Jan 20 10:44:46 2000
@@ -480,14 +480,14 @@
 	for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) {
 		struct net_device *dev = &dev_ultra[this_dev];
 		if (dev->priv != NULL) {
-			/* NB: ultra_close_card() does free_irq + irq2dev */
+			/* NB: ultra_close_card() does free_irq */
 			int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
-			kfree(dev->priv);
-			release_region(ioaddr, ULTRA_IO_EXTENT);
 			unregister_netdev(dev);
-			dev->priv = NULL;
+			release_region(ioaddr, ULTRA_IO_EXTENT);
+			kfree(dev->priv);
 		}
 	}
+	unlock_8390_module();
 }
 #endif /* MODULE */
 
diff -u --recursive --new-file v2.3.39/linux/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c
--- v2.3.39/linux/drivers/net/tokenring/ibmtr.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/net/tokenring/ibmtr.c	Fri Jan 14 11:25:21 2000
@@ -1651,7 +1651,7 @@
        	ti->tr_stats.rx_packets++;
 
 	skb->protocol = tr_type_trans(skb,dev);
- 	if (IPv4_p){ 
+ 	if (IPv4_p && (skb->protocol == ETH_P_IP)) { 
 		skb->csum      = chksum;
 		skb->ip_summed = 1;
 	}
diff -u --recursive --new-file v2.3.39/linux/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c
--- v2.3.39/linux/drivers/net/tokenring/olympic.c	Tue Dec  7 09:32:44 1999
+++ linux/drivers/net/tokenring/olympic.c	Fri Jan 14 11:25:21 2000
@@ -25,10 +25,11 @@
  *  8/18/99 - Updated driver for 2.3.13 kernel to use new pci
  *	      resource. Driver also reports the card name returned by
  *            the pci resource.
+ *  1/11/00 - Added spinlocks for smp
  *  
  *  To Do:
  *
- *  Sanitize for smp
+ *  IPv6 Multicast
  *
  *  If Problems do Occur
  *  Most problems can be rectified by either closing and opening the interface
@@ -69,6 +70,7 @@
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/spinlock.h>
 #include <net/checksum.h>
 
 #include <asm/io.h>
@@ -86,7 +88,7 @@
  */
 
 static char *version = 
-"Olympic.c v0.3.0 8/18/99 - Peter De Schrijver & Mike Phillips" ; 
+"Olympic.c v0.3.1 1/11/00 - Peter De Schrijver & Mike Phillips" ; 
 
 static char *open_maj_error[]  = {"No error", "Lobe Media Test", "Physical Insertion",
 				   "Address Verification", "Neighbor Notification (Ring Poll)",
@@ -202,7 +204,6 @@
 
 			olympic_priv->olympic_ring_speed = ringspeed[card_no] ; 
 			olympic_priv->olympic_message_level = message_level[card_no] ; 
-			olympic_priv->olympic_multicast_set  = 0 ; 
 	
 			if(olympic_init(dev)==-1) {
 				unregister_netdevice(dev);
@@ -251,6 +252,8 @@
 		}
 	}
 
+	spin_lock_init(&olympic_priv->olympic_lock) ; 
+
 #if OLYMPIC_DEBUG
 	printk("BCTL: %x\n",readl(olympic_mmio+BCTL));
 	printk("GPR: %x\n",readw(olympic_mmio+GPR));
@@ -757,6 +760,8 @@
 	if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ 
 		return ;
 
+	spin_lock(&olympic_priv->olympic_lock);
+
 	if (dev->interrupt) 
 		printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ; 
 
@@ -835,15 +840,20 @@
 	dev->interrupt = 0 ;  
 
 	writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
-
+	
+	spin_unlock(&olympic_priv->olympic_lock) ; 
 }	
 
 static int olympic_xmit(struct sk_buff *skb, struct net_device *dev) 
 {
 	struct olympic_private *olympic_priv=(struct olympic_private *)dev->priv;
-    __u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
+	unsigned long flags ; 
+
+	spin_lock_irqsave(&olympic_priv->olympic_lock, flags);
 
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
 		return 1;
 	}
 
@@ -860,10 +870,12 @@
 		writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
 
 		dev->tbusy=0;		
-
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
 		return 0;
-	} else 
+	} else {
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags);
 		return 1;
+	} 
 
 }
 	
@@ -936,9 +948,11 @@
 {
 	struct olympic_private *olympic_priv = (struct olympic_private *) dev->priv ; 
    	__u8 *olympic_mmio = olympic_priv->olympic_mmio ; 
-	__u8 options = 0, set_mc_list = 0 ; 
-	__u8 *srb, *ata ;
+	__u8 options = 0; 
+	__u8 *srb;
 	struct dev_mc_list *dmi ; 
+	unsigned char dev_mc_address[4] ; 
+	int i ; 
 
 	writel(olympic_priv->srb,olympic_mmio+LAPA);
 	srb=olympic_priv->olympic_lap + (olympic_priv->srb & (~0xf800));
@@ -949,10 +963,6 @@
 	else
 		options &= ~(3<<5) ; 
 
-	if (dev->mc_count) {  
-		set_mc_list = 1 ; 
-	}
-
 	/* Only issue the srb if there is a change in options */
 
 	if ((options ^ olympic_priv->olympic_copy_all_options)) { 
@@ -975,60 +985,30 @@
 		return ;  
 	} 
 
-	if (set_mc_list ^ olympic_priv->olympic_multicast_set) { /* Multicast options have changed */ 
-
-		dmi = dev->mc_list ; 
+	/* Set the functional addresses we need for multicast */
 
-		if (set_mc_list) { /* Turn multicast on */
-
-			/* RFC 1469 Says we must support using the functional address C0 00 00 04 00 00
-                         * We do this with a set functional address mask.
-			 */
-						
-			ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ;
-			if (!(readb(ata+11) & 0x04)) { /* Hmmm, need to set the functional mask */ 
-				writeb(SRB_SET_FUNC_ADDRESS,srb+0);
-				writeb(0,srb+1);
-				writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
-				writeb(0,srb+3);
-				writeb(0,srb+4);
-				writeb(0,srb+5);
-				writeb(readb(ata+10),srb+6);
-				writeb(readb(ata+11)|4,srb+7);
-				writeb(readb(ata+12),srb+8);
-				writeb(readb(ata+13),srb+9);
-			
-				olympic_priv->srb_queued = 2 ; 
-				writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
-
-				olympic_priv->olympic_multicast_set = 1 ;  
-			}    
-
-
-		} else { /* Turn multicast off */
-	
-			ata=olympic_priv->olympic_lap + (olympic_priv->olympic_addr_table_addr) ;
-			if ((readb(ata+11) & 0x04)) { /* Hmmm, need to reset the functional mask */ 
-				writeb(SRB_SET_FUNC_ADDRESS,srb+0);
-				writeb(0,srb+1);
-				writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
-				writeb(0,srb+3);
-				writeb(0,srb+4);
-				writeb(0,srb+5);
-				writeb(readb(ata+10),srb+6);
-				writeb(readb(ata+11) & ~4,srb+7);
-				writeb(readb(ata+12),srb+8);
-				writeb(readb(ata+13),srb+9);
-			
-				olympic_priv->srb_queued = 2 ; 
-				writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);	
-
-				olympic_priv->olympic_multicast_set = 0 ; 
-			}
-		} 		
+	dev_mc_address[0] = dev_mc_address[1] = dev_mc_address[2] = dev_mc_address[3] = 0 ; 
 
+	for (i=0,dmi=dev->mc_list;i < dev->mc_count; i++,dmi = dmi->next) { 
+		dev_mc_address[0] |= dmi->dmi_addr[2] ; 
+		dev_mc_address[1] |= dmi->dmi_addr[3] ; 
+		dev_mc_address[2] |= dmi->dmi_addr[4] ; 
+		dev_mc_address[3] |= dmi->dmi_addr[5] ; 
 	}
 
+	writeb(SRB_SET_FUNC_ADDRESS,srb+0);
+	writeb(0,srb+1);
+	writeb(OLYMPIC_CLEAR_RET_CODE,srb+2);
+	writeb(0,srb+3);
+	writeb(0,srb+4);
+	writeb(0,srb+5);
+	writeb(dev_mc_address[0],srb+6);
+	writeb(dev_mc_address[1],srb+7);
+	writeb(dev_mc_address[2],srb+8);
+	writeb(dev_mc_address[3],srb+9);
+
+	olympic_priv->srb_queued = 2 ;
+	writel(LISR_SRB_CMD,olympic_mmio+LISR_SUM);
 
 }
 
@@ -1069,7 +1049,6 @@
 		case SRB_SET_GROUP_ADDRESS:
 			switch (readb(srb+2)) { 
 				case 0x00:
-					olympic_priv->olympic_multicast_set = 1 ; 
 					break ; 
 				case 0x01:
 					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 
@@ -1097,7 +1076,6 @@
 		case SRB_RESET_GROUP_ADDRESS:
 			switch (readb(srb+2)) { 
 				case 0x00:
-					olympic_priv->olympic_multicast_set = 0 ; 
 					break ; 
 				case 0x01:
 					printk(KERN_WARNING "%s: Unrecognized srb command \n",dev->name) ; 
diff -u --recursive --new-file v2.3.39/linux/drivers/net/tokenring/olympic.h linux/drivers/net/tokenring/olympic.h
--- v2.3.39/linux/drivers/net/tokenring/olympic.h	Mon Oct 11 15:38:15 1999
+++ linux/drivers/net/tokenring/olympic.h	Fri Jan 14 11:25:21 2000
@@ -245,6 +245,8 @@
 	__u8 *olympic_lap;
 	char *olympic_card_name ; 
 
+	spinlock_t olympic_lock ; 
+
 	volatile int srb_queued;    /* True if an SRB is still posted */	
 	wait_queue_head_t srb_wait;
 
@@ -265,7 +267,6 @@
 	__u8 olympic_ring_speed ;
 	__u16 pkt_buf_sz ; 
 	__u8 olympic_receive_options, olympic_copy_all_options, olympic_message_level;  
-	__u8 olympic_multicast_set ; 
 	__u16 olympic_addr_table_addr, olympic_parms_addr ; 
 	__u8 olympic_laa[6] ; 
 };
diff -u --recursive --new-file v2.3.39/linux/drivers/net/tokenring/tms380tr.c linux/drivers/net/tokenring/tms380tr.c
--- v2.3.39/linux/drivers/net/tokenring/tms380tr.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/net/tokenring/tms380tr.c	Fri Jan 14 11:25:21 2000
@@ -2470,7 +2470,8 @@
 				tp->RplHead = SaveHead;
 				break;	/* Return to tms380tr_interrupt */
 			}
-
+#if 0	/* This might happen for multicast or broadcast packets.
+	   The upper layers are expected to handle this, not here */
 			/* Drop frames sent by myself */
 			if(tms380tr_chk_frame(dev, rpl->MData))
 			{
@@ -2480,6 +2481,7 @@
 					dev_kfree_skb(rpl->Skb);
 			}
 			else
+#endif
 			{
 			  tms380tr_update_rcv_stats(tp,ReceiveDataPtr,Length);
 			  
diff -u --recursive --new-file v2.3.39/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.3.39/linux/drivers/net/tulip.c	Tue Nov 23 22:42:21 1999
+++ linux/drivers/net/tulip.c	Thu Jan 20 09:51:42 2000
@@ -102,7 +102,6 @@
 #endif
 
 #if (LINUX_VERSION_CODE < 0x20123)
-#define hard_smp_processor_id() smp_processor_id()
 #define test_and_set_bit(val, addr) set_bit(val, addr)
 #endif
 
@@ -2164,7 +2163,7 @@
 #ifdef SMP_CHECK
 		printk(KERN_ERR "%s: Re-entering the interrupt handler with proc %d,"
 			   " proc %d already handling.\n", dev->name,
-			   tp->smp_proc_id, hard_smp_processor_id());
+			   tp->smp_proc_id, smp_processor_id());
 #else
 		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
 #endif
@@ -2172,7 +2171,7 @@
 	}
 	dev->interrupt = 1;
 #ifdef SMP_CHECK
-	tp->smp_proc_id = hard_smp_processor_id();
+	tp->smp_proc_id = smp_processor_id();
 #endif
 
 	do {
diff -u --recursive --new-file v2.3.39/linux/drivers/net/wan/syncppp.c linux/drivers/net/wan/syncppp.c
--- v2.3.39/linux/drivers/net/wan/syncppp.c	Mon Dec 20 18:48:21 1999
+++ linux/drivers/net/wan/syncppp.c	Thu Jan 20 10:44:46 2000
@@ -660,14 +660,14 @@
 	h = (struct cisco_packet *)skb->data;
 	skb_pull(skb, sizeof(struct cisco_packet*));
 	if (sp->pp_flags & PP_DEBUG)
-		printk (KERN_WARNING "%s: cisco input: %d bytes <%lxh %xh %xh %xh %xh-%xh>\n",
+		printk (KERN_WARNING "%s: cisco input: %d bytes <%xh %xh %xh %xh %xh-%xh>\n",
 			dev->name,  skb->len,
 			ntohl (h->type), h->par1, h->par2, h->rel,
 			h->time0, h->time1);
 	switch (ntohl (h->type)) {
 	default:
 		if (sp->pp_flags & PP_DEBUG)
-			printk (KERN_WARNING "%s: unknown cisco packet type: 0x%lx\n",
+			printk (KERN_WARNING "%s: unknown cisco packet type: 0x%x\n",
 				dev->name,  ntohl (h->type));
 		break;
 	case CISCO_ADDR_REPLY:
@@ -814,7 +814,7 @@
 	ch->time1 = htons ((u16) t);
 
 	if (sp->pp_flags & PP_DEBUG)
-		printk (KERN_WARNING "%s: cisco output: <%lxh %xh %xh %xh %xh-%xh>\n",
+		printk (KERN_WARNING "%s: cisco output: <%xh %xh %xh %xh %xh-%xh>\n",
 			dev->name,  ntohl (ch->type), ch->par1,
 			ch->par2, ch->rel, ch->time0, ch->time1);
 	sp->obytes += skb->len;
diff -u --recursive --new-file v2.3.39/linux/drivers/net/wan/z85230.c linux/drivers/net/wan/z85230.c
--- v2.3.39/linux/drivers/net/wan/z85230.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/net/wan/z85230.c	Thu Jan 20 10:44:46 2000
@@ -170,7 +170,7 @@
 /*
  *	As above but for enhanced chips.
  */
-
+ 
 u8 z8530_hdlc_kilostream_85230[]=
 {
 	4,	SYNC_ENAB|SDLC|X1CLK,
@@ -355,13 +355,15 @@
 		z8530_tx_done(chan);
 	}
 		
-	if(altered&DCD)
+	if(altered&chan->dcdcheck)
 	{
-		if(status&DCD)
+		if(status&chan->dcdcheck)
 		{
 			printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
 			write_zsreg(chan, R3, chan->regs[3]|RxENABLE);
-			if(chan->netdevice)
+			if(chan->netdevice &&
+			    ((chan->netdevice->type == ARPHRD_HDLC) ||
+			    (chan->netdevice->type == ARPHRD_PPP)))
 				sppp_reopen(chan->netdevice);
 		}
 		else
@@ -441,7 +443,6 @@
 		if(status&TxEOM)
 		{
 			flags=claim_dma_lock();
-			/* Transmit underrun */
 			disable_dma(chan->txdma);
 			clear_dma_ff(chan->txdma);	
 			chan->txdma_on=0;
@@ -449,13 +450,15 @@
 			z8530_tx_done(chan);
 		}
 	}
-	if(altered&DCD)
+	if(altered&chan->dcdcheck)
 	{
-		if(status&DCD)
+		if(status&chan->dcdcheck)
 		{
 			printk(KERN_INFO "%s: DCD raised\n", chan->dev->name);
 			write_zsreg(chan, R3, chan->regs[3]|RxENABLE);
-			if(chan->netdevice)
+			if(chan->netdevice &&
+			    ((chan->netdevice->type == ARPHRD_HDLC) ||
+			    (chan->netdevice->type == ARPHRD_PPP)))
 				sppp_reopen(chan->netdevice);
 		}
 		else
@@ -670,15 +673,15 @@
 	if(c->mtu  > PAGE_SIZE/2)
 		return -EMSGSIZE;
 	 
-	c->rx_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA);
+	c->rx_buf[0]=(void *)get_free_page(GFP_KERNEL|GFP_DMA);
 	if(c->rx_buf[0]==NULL)
 		return -ENOBUFS;
 	c->rx_buf[1]=c->rx_buf[0]+PAGE_SIZE/2;
 	
-	c->tx_dma_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA);
+	c->tx_dma_buf[0]=(void *)get_free_page(GFP_KERNEL|GFP_DMA);
 	if(c->tx_dma_buf[0]==NULL)
 	{
-		free_page(c->rx_buf[0]);
+		free_page((unsigned long)c->rx_buf[0]);
 		c->rx_buf[0]=NULL;
 		return -ENOBUFS;
 	}
@@ -795,12 +798,12 @@
 	
 	if(c->rx_buf[0])
 	{
-		free_page(c->rx_buf[0]);
+		free_page((unsigned long)c->rx_buf[0]);
 		c->rx_buf[0]=NULL;
 	}
 	if(c->tx_dma_buf[0])
 	{
-		free_page(c->tx_dma_buf[0]);
+		free_page((unsigned  long)c->tx_dma_buf[0]);
 		c->tx_dma_buf[0]=NULL;
 	}
 	chk=read_zsreg(c,R0);
@@ -845,7 +848,7 @@
 	if(c->mtu  > PAGE_SIZE/2)
 		return -EMSGSIZE;
 	 
-	c->tx_dma_buf[0]=get_free_page(GFP_KERNEL|GFP_DMA);
+	c->tx_dma_buf[0]=(void *)get_free_page(GFP_KERNEL|GFP_DMA);
 	if(c->tx_dma_buf[0]==NULL)
 		return -ENOBUFS;
 
@@ -935,7 +938,7 @@
 	
 	if(c->tx_dma_buf[0])
 	{
-		free_page(c->tx_dma_buf[0]);
+		free_page((unsigned long)c->tx_dma_buf[0]);
 		c->tx_dma_buf[0]=NULL;
 	}
 	chk=read_zsreg(c,R0);
@@ -982,6 +985,8 @@
 	   floating IRQ transition when we reset the chip */
 	dev->chanA.irqs=&z8530_nop;
 	dev->chanB.irqs=&z8530_nop;
+	dev->chanA.dcdcheck=DCD;
+	dev->chanB.dcdcheck=DCD;
 	/* Reset the chip */
 	write_zsreg(&dev->chanA, R9, 0xC0);
 	udelay(200);
@@ -1074,7 +1079,7 @@
 	c->mtu=1500;
 	c->max=0;
 	c->count=0;
-	c->status=0;	/* Fixme - check DCD now */
+	c->status=read_zsreg(c, R0);
 	c->sync=1;
 	write_zsreg(c, R3, c->regs[R3]|RxENABLE);
 	return 0;
@@ -1221,7 +1226,7 @@
 		 *	Save the ready state and the buffer currently
 		 *	being used as the DMA target
 		 */
-
+		 
 		int ready=c->dma_ready;
 		unsigned char *rxb=c->rx_buf[c->dma_num];
 		unsigned long flags;
diff -u --recursive --new-file v2.3.39/linux/drivers/net/wan/z85230.h linux/drivers/net/wan/z85230.h
--- v2.3.39/linux/drivers/net/wan/z85230.h	Mon Oct 11 15:38:15 1999
+++ linux/drivers/net/wan/z85230.h	Thu Jan 20 10:44:46 2000
@@ -270,6 +270,7 @@
 	struct sk_buff	*skb;		/* Buffer dptr points into */
 	struct sk_buff	*skb2;		/* Pending buffer */
 	u8		status;		/* Current DCD */
+	u8		dcdcheck;	/* which bit to check for line */
 	u8		sync;		/* Set if in sync mode */
 
 	u8		regs[32];	/* Register map for the chip */
@@ -413,7 +414,7 @@
  *	Standard interrupt vector sets
  */
  
-struct z8530_irqhandler z8530_sync, z8530_async, z8530_nop;
+extern struct z8530_irqhandler z8530_sync, z8530_async, z8530_nop;
 
 /*
  *	Asynchronous Interfacing
diff -u --recursive --new-file v2.3.39/linux/drivers/parport/Config.in linux/drivers/parport/Config.in
--- v2.3.39/linux/drivers/parport/Config.in	Tue Nov 23 22:42:21 1999
+++ linux/drivers/parport/Config.in	Thu Jan 13 11:54:37 2000
@@ -14,7 +14,7 @@
    if [ "$CONFIG_PARPORT_PC" = "y" ]; then
       # Don't bother with this if parport_pc is a module; it only affects
       # the presence or not of some __init's, which are no-ops for modules.
-      if [ "$CONFIG_PCMCIA" != "n" ]; then
+      if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
 	 bool '    Support for PCMCIA management for PC-style ports' CONFIG_PARPORT_PC_PCMCIA
       fi
    fi
diff -u --recursive --new-file v2.3.39/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c
--- v2.3.39/linux/drivers/parport/ieee1284_ops.c	Tue Nov 23 22:42:21 1999
+++ linux/drivers/parport/ieee1284_ops.c	Thu Jan 20 12:35:23 2000
@@ -56,6 +56,7 @@
 	}
 
 	port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
+	parport_write_control (port, ctl);
 	while (count < len) {
 		long expire = jiffies + dev->timeout;
 		long wait = (HZ + 99) / 100;
diff -u --recursive --new-file v2.3.39/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.3.39/linux/drivers/parport/parport_pc.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/parport/parport_pc.c	Thu Jan 13 12:03:00 2000
@@ -740,7 +740,7 @@
 		printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
 		/* Prevent further data transfer. */
-		frob_econtrol (port, 0xe0, ECR_TST);
+		frob_econtrol (port, 0xe0, ECR_TST << 5);
 
 		/* Adjust for the contents of the FIFO. */
 		for (written -= priv->fifo_depth; ; written++) {
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/Makefile linux/drivers/pci/Makefile
--- v2.3.39/linux/drivers/pci/Makefile	Wed Dec 29 13:13:16 1999
+++ linux/drivers/pci/Makefile	Wed Jan 12 09:21:23 2000
@@ -24,10 +24,10 @@
 O_OBJS   += proc.o
 endif
 
-L_OBJS   += compat.o names.o helper.o
+L_OBJS   += compat.o names.o setup-res.o setup-bus.o setup-irq.o
 
 ifndef CONFIG_X86
-L_OBJS   += syscall.o setup.o
+L_OBJS   += syscall.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/helper.c linux/drivers/pci/helper.c
--- v2.3.39/linux/drivers/pci/helper.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/pci/helper.c	Wed Dec 31 16:00:00 1969
@@ -1,69 +0,0 @@
-/*
- * $Id$
- *
- * drivers/pci/helper.c
- *
- * Copyright 1999 Jeff Garzik <jgarzik@mandrakesoft.com>
- * This software is free.  See the file COPYING for licensing details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-
-int pci_simple_probe (const struct pci_simple_probe_entry *list,
-		      size_t match_limit, pci_simple_probe_callback cb,
-		      void *drvr_data)
-{
-	struct pci_dev *dev;
-	const struct pci_simple_probe_entry *ent;
-	size_t matches = 0;
-	unsigned short vendor, device;
-	int rc;
-
-	if (!list || !cb)
-		return -1;
-
-	dev = pci_find_device (PCI_ANY_ID, PCI_ANY_ID, NULL);
-	while (dev) {
-		ent = list;
-		while (ent->vendor && ent->device) {
-			vendor = ent->vendor;
-			device = ent->device;
-
-			if (((vendor != 0xFFFF) &&
-			     (vendor != dev->vendor)) ||
-			    ((device != 0xFFFF) &&
-			     (device != dev->device))) {
-			     	ent++;
-				continue;
-			}
-			    
-			if (((ent->subsys_vendor) &&
-			     (ent->subsys_vendor != dev->subsystem_vendor)) ||
-			    ((ent->subsys_device) &&
-			     (ent->subsys_device != dev->subsystem_device))) {
-			     	ent++;
-				continue;
-			}
-			    
-			rc = (* cb) (dev, matches, ent, drvr_data);
-			if (rc < 0)
-				return rc;
-
-			matches++;
-
-			if (match_limit && match_limit == matches)
-				return matches;
-
-			break; /* stop list search on first match */
-		}
-
-		dev = pci_find_device (PCI_ANY_ID, PCI_ANY_ID, dev);
-	}
-
-	return matches;
-}
-
-
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.3.39/linux/drivers/pci/pci.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/pci/pci.c	Thu Jan 20 09:55:23 2000
@@ -202,16 +202,51 @@
 
 static LIST_HEAD(pci_drivers);
 
-void
+const struct pci_device_id *
+pci_match_device(const struct pci_device_id *ids, struct pci_dev *dev)
+{
+	while (ids->vendor || ids->subvendor || ids->class_mask) {
+		if ((ids->vendor == PCI_ANY_ID || ids->vendor == dev->vendor) &&
+		    (ids->device == PCI_ANY_ID || ids->device == dev->device) &&
+		    (ids->subvendor == PCI_ANY_ID || ids->subvendor == dev->subsystem_vendor) &&
+		    (ids->subdevice == PCI_ANY_ID || ids->subdevice == dev->subsystem_device) &&
+		    !((ids->class ^ dev->class) & ids->class_mask))
+			return ids;
+		ids++;
+	}
+	return NULL;
+}
+
+static int
+pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
+{
+	const struct pci_device_id *id;
+
+	if (drv->id_table) {
+		id = pci_match_device(drv->id_table, dev);
+		if (!id)
+			return 0;
+	} else
+		id = NULL;
+	if (drv->probe(dev, id) >= 0) {
+		dev->driver = drv;
+		return 1;
+	}
+	return 0;
+}
+
+int
 pci_register_driver(struct pci_driver *drv)
 {
 	struct pci_dev *dev;
+	int count = 0;
 
 	list_add_tail(&drv->node, &pci_drivers);
 	pci_for_each_dev(dev) {
-		if (!pci_dev_driver(dev) && drv->probe(dev))
-			dev->driver = drv;
+		if (!pci_dev_driver(dev))
+			count += pci_announce_device(drv, dev);
 	}
+	return count;
 }
 
 void
@@ -229,6 +264,8 @@
 	}
 }
 
+#ifdef CONFIG_HOTPLUG
+
 void
 pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
 {
@@ -241,10 +278,8 @@
 #endif
 	for(ln=pci_drivers.next; ln != &pci_drivers; ln=ln->next) {
 		struct pci_driver *drv = list_entry(ln, struct pci_driver, node);
-		if (drv->probe(dev)) {
-			dev->driver = drv;
+		if (drv->remove && pci_announce_device(drv, dev))
 			break;
-		}
 	}
 }
 
@@ -272,6 +307,8 @@
 	pci_proc_detach_device(dev);
 #endif
 }
+
+#endif
 
 static struct pci_driver pci_compat_driver = {
 	name: "compat"
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- v2.3.39/linux/drivers/pci/pci.ids	Thu Jan  6 12:57:47 2000
+++ linux/drivers/pci/pci.ids	Fri Jan 14 00:50:53 2000
@@ -356,6 +356,12 @@
 	2001  79c978 [HomePNA]
 	2020  53c974 [PCscsi]
 	2040  79c974
+	7006  IronGate Host
+	7403  Viper Power Management
+	7408  Viper ISA
+	7409  Viper IDE
+	740B  Viper ACPI
+	740C  Viper USB
 1023  Trident Microsystems
 	0194  82C194
 	2000  4DWave DX
@@ -931,8 +937,9 @@
 	0640  PCI0640
 	0643  PCI0643
 	0646  PCI0646
-	0650  PBC0650A
 	0647  PCI0647
+	0648  PCI0648
+	0650  PBC0650A
 	0670  USB0670
 	0673  USB0673
 1096  Alacron
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c
--- v2.3.39/linux/drivers/pci/pcisyms.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/pci/pcisyms.c	Wed Jan 12 09:21:23 2000
@@ -6,6 +6,7 @@
  *	Copyright 1998 Martin Mares
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
@@ -23,14 +24,16 @@
 EXPORT_SYMBOL(pci_find_device);
 EXPORT_SYMBOL(pci_find_slot);
 EXPORT_SYMBOL(pci_set_master);
-EXPORT_SYMBOL(pci_simple_probe);
 EXPORT_SYMBOL(pci_set_power_state);
 EXPORT_SYMBOL(pci_assign_resource);
+EXPORT_SYMBOL(pci_register_driver);
+EXPORT_SYMBOL(pci_unregister_driver);
+
+#ifdef CONFIG_HOTPLUG
 EXPORT_SYMBOL(pci_setup_device);
 EXPORT_SYMBOL(pci_insert_device);
 EXPORT_SYMBOL(pci_remove_device);
-EXPORT_SYMBOL(pci_register_driver);
-EXPORT_SYMBOL(pci_unregister_driver);
+#endif
 
 /* Obsolete functions */
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/setup-bus.c linux/drivers/pci/setup-bus.c
--- v2.3.39/linux/drivers/pci/setup-bus.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/setup-bus.c	Tue Jan 11 14:22:31 2000
@@ -0,0 +1,156 @@
+/*
+ *	drivers/pci/setup-bus.c
+ *
+ * Extruded from code written by
+ *      Dave Rusling (david.rusling@reo.mts.dec.com)
+ *      David Mosberger (davidm@cs.arizona.edu)
+ *	David Miller (davem@redhat.com)
+ *
+ * Support routines for initializing a PCI subsystem.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/cache.h>
+
+
+#define DEBUG_CONFIG 0
+#if DEBUG_CONFIG
+# define DBGC(args)     printk args
+#else
+# define DBGC(args)
+#endif
+
+
+#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
+#define ROUND_DOWN(x, a)	((x) & ~((a) - 1))
+
+static void __init
+pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
+{
+	struct pbus_set_ranges_data inner;
+	struct pci_dev *dev;
+	struct list_head *ln;
+
+	inner.found_vga = 0;
+	inner.mem_start = inner.io_start = ~0UL;
+	inner.mem_end = inner.io_end = 0;
+
+	/* Collect information about how our direct children are layed out. */
+	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+		int i;
+		dev = pci_dev_b(ln);
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *res = &dev->resource[i];
+			if (res->flags & IORESOURCE_IO) {
+				if (res->start < inner.io_start)
+					inner.io_start = res->start;
+				if (res->end > inner.io_end)
+					inner.io_end = res->end;
+			} else if (res->flags & IORESOURCE_MEM) {
+				if (res->start < inner.mem_start)
+					inner.mem_start = res->start;
+				if (res->end > inner.mem_end)
+					inner.mem_end = res->end;
+			}
+		}
+                if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
+                        inner.found_vga = 1;
+	}
+
+	/* And for all of the sub-busses.  */
+	for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
+		pbus_set_ranges(pci_bus_b(ln), &inner);
+
+	/* Align the values.  */
+	inner.io_start = ROUND_DOWN(inner.io_start, 4*1024);
+	inner.io_end = ROUND_UP(inner.io_end, 4*1024);
+
+	inner.mem_start = ROUND_DOWN(inner.mem_start, 1*1024*1024);
+	inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024);
+
+	pcibios_fixup_pbus_ranges(bus, &inner);
+
+	/* Configure the bridge, if possible.  */
+	if (bus->self) {
+		struct pci_dev *bridge = bus->self;
+		u32 l;
+
+                /* Set up the top and bottom of the PCI I/O segment
+                   for this bus.  */
+                pci_read_config_dword(bridge, PCI_IO_BASE, &l);
+                l &= 0xffff0000;
+                l |= (inner.io_start >> 8) & 0x00f0;
+		l |= (inner.io_end - 1) & 0xf000;
+                pci_write_config_dword(bridge, PCI_IO_BASE, l);
+
+                /*
+                 * Clear out the upper 16 bits of IO base/limit.
+                 * Clear out the upper 32 bits of PREF base/limit.
+                 */
+                pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0);
+                pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
+                pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
+
+                /* Set up the top and bottom of the PCI Memory segment
+                   for this bus.  */
+                l = (inner.mem_start & 0xfff00000) >> 16;
+		l |= (inner.mem_end - 1) & 0xfff00000;
+                pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
+
+                /*
+                 * Turn off downstream PF memory address range, unless
+                 * there is a VGA behind this bridge, in which case, we
+                 * enable the PREFETCH range to include BIOS ROM at C0000.
+                 *
+                 * NOTE: this is a bit of a hack, done with PREFETCH for
+                 * simplicity, rather than having to add it into the above
+                 * non-PREFETCH range, which could then be bigger than we want.
+                 * We might assume that we could relocate the BIOS ROM, but
+                 * that would depend on having it found by those who need it
+                 * (the DEC BIOS emulator would find it, but I do not know
+                 * about the Xservers). So, we do it this way for now... ;-)
+                 */
+                l = (inner.found_vga) ? 0 : 0x0000ffff;
+                pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
+
+                /*
+                 * Tell bridge that there is an ISA bus in the system,
+                 * and (possibly) a VGA as well.
+                 */
+                l = (inner.found_vga) ? 0x0c : 0x04;
+                pci_write_config_byte(bridge, PCI_BRIDGE_CONTROL, l);
+
+                /*
+                 * Clear status bits,
+                 * turn on I/O    enable (for downstream I/O),
+                 * turn on memory enable (for downstream memory),
+                 * turn on master enable (for upstream memory and I/O).
+                 */
+                pci_write_config_dword(bridge, PCI_COMMAND, 0xffff0007);
+	}
+
+	if (outer) {
+		outer->found_vga |= inner.found_vga;
+		if (inner.io_start < outer->io_start)
+			outer->io_start = inner.io_start;
+		if (inner.io_end > outer->io_end)
+			outer->io_end = inner.io_end;
+		if (inner.mem_start < outer->mem_start)
+			outer->mem_start = inner.mem_start;
+		if (inner.mem_end > outer->mem_end)
+			outer->mem_end = inner.mem_end;
+	}
+}
+
+void __init
+pci_set_bus_ranges(void)
+{
+	struct list_head *ln;
+
+	for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
+		pbus_set_ranges(pci_bus_b(ln), NULL);
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/setup-irq.c linux/drivers/pci/setup-irq.c
--- v2.3.39/linux/drivers/pci/setup-irq.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/setup-irq.c	Tue Jan 11 14:22:31 2000
@@ -0,0 +1,71 @@
+/*
+ *	drivers/pci/setup-irq.c
+ *
+ * Extruded from code written by
+ *      Dave Rusling (david.rusling@reo.mts.dec.com)
+ *      David Mosberger (davidm@cs.arizona.edu)
+ *	David Miller (davem@redhat.com)
+ *
+ * Support routines for initializing a PCI subsystem.
+ */
+
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/cache.h>
+
+
+#define DEBUG_CONFIG 0
+#if DEBUG_CONFIG
+# define DBGC(args)     printk args
+#else
+# define DBGC(args)
+#endif
+
+
+static void __init
+pdev_fixup_irq(struct pci_dev *dev,
+	       u8 (*swizzle)(struct pci_dev *, u8 *),
+	       int (*map_irq)(struct pci_dev *, u8, u8))
+{
+	u8 pin, slot;
+	int irq;
+
+	/* If this device is not on the primary bus, we need to figure out
+	   which interrupt pin it will come in on.   We know which slot it
+	   will come in on 'cos that slot is where the bridge is.   Each
+	   time the interrupt line passes through a PCI-PCI bridge we must
+	   apply the swizzle function.  */
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	/* Cope with 0 and illegal. */
+	if (pin == 0 || pin > 4)
+		pin = 1;
+
+	/* Follow the chain of bridges, swizzling as we go.  */
+	slot = (*swizzle)(dev, &pin);
+
+	irq = (*map_irq)(dev, slot, pin);
+	if (irq == -1)
+		irq = 0;
+	dev->irq = irq;
+
+	DBGC(("PCI fixup irq: (%s) got %d\n", dev->name, dev->irq));
+
+	/* Always tell the device, so the driver knows what is
+	   the real IRQ to use; the device does not use it. */
+	pcibios_update_irq(dev, irq);
+}
+
+void __init
+pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
+	       int (*map_irq)(struct pci_dev *, u8, u8))
+{
+	struct pci_dev *dev;
+	pci_for_each_dev(dev) {
+		pdev_fixup_irq(dev, swizzle, map_irq);
+	}
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c
--- v2.3.39/linux/drivers/pci/setup-res.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pci/setup-res.c	Wed Jan 12 11:15:16 2000
@@ -0,0 +1,164 @@
+/*
+ *	drivers/pci/setup-res.c
+ *
+ * Extruded from code written by
+ *      Dave Rusling (david.rusling@reo.mts.dec.com)
+ *      David Mosberger (davidm@cs.arizona.edu)
+ *	David Miller (davem@redhat.com)
+ *
+ * Support routines for initializing a PCI subsystem.
+ */
+
+/* fixed for multiple pci buses, 1999 Andrea Arcangeli <andrea@suse.de> */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/cache.h>
+
+
+#define DEBUG_CONFIG 0
+#if DEBUG_CONFIG
+# define DBGC(args)     printk args
+#else
+# define DBGC(args)
+#endif
+
+
+int __init
+pci_claim_resource(struct pci_dev *dev, int resource)
+{
+        struct resource *res = &dev->resource[resource];
+	struct resource *root = pci_find_parent_resource(dev, res);
+	int err;
+
+	err = -EINVAL;
+	if (root != NULL) {
+		err = request_resource(root, res);
+		if (err) {
+			printk(KERN_ERR "PCI: Address space collision on "
+			       "region %d of device %s [%lx:%lx]\n",
+			       resource, dev->name, res->start, res->end);
+		}
+	} else {
+		printk(KERN_ERR "PCI: No parent found for region %d "
+		       "of device %s\n", resource, dev->name);
+	}
+
+	return err;
+}
+
+int 
+pci_assign_resource(struct pci_dev *dev, int i)
+{
+	struct resource *root, *res;
+	unsigned long size, min;
+
+	res = &dev->resource[i];
+
+	/* Determine the root we allocate from.  */
+	res->end -= res->start;
+	res->start = 0;
+	root = pci_find_parent_resource(dev, res);
+	if (root == NULL) {
+		printk(KERN_ERR "PCI: Cannot find parent resource for "
+		       "device %s\n", dev->slot_name);
+		return -EINVAL;
+	}
+
+	min = (res->flags & IORESOURCE_IO ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM);
+	size = res->end + 1;
+	DBGC(("  for root[%lx:%lx] min[%lx] size[%lx]\n",
+	      root->start, root->end, min, size));
+
+	if (allocate_resource(root, res, size, min, -1, size,
+			      pcibios_align_resource, dev) < 0) {
+		printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n",
+		       i, dev->name);
+		return -EBUSY;
+	}
+
+	DBGC(("  got res[%lx:%lx] for resource %d\n",
+	      res->start, res->end, i));
+
+	/* Update PCI config space.  */
+	pcibios_update_resource(dev, root, res, i);
+
+	return 0;
+}
+
+static void
+pdev_assign_unassigned_resources(struct pci_dev *dev)
+{
+	u32 reg;
+	u16 cmd;
+	int i;
+
+	DBGC(("PCI assign unassigned: (%s)\n", dev->name));
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		struct resource *res = &dev->resource[i];
+
+		if (res->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		else if (res->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+
+		/* If it is already assigned or the resource does
+		   not exist, there is nothing to do.  */
+		if (res->parent != NULL || res->flags == 0)
+			continue;
+
+		pci_assign_resource(dev, i);
+	}
+
+	/* Special case, disable the ROM.  Several devices act funny
+	   (ie. do not respond to memory space writes) when it is left
+	   enabled.  A good example are QlogicISP adapters.  */
+
+	if (dev->rom_base_reg) {
+		pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+		reg &= ~PCI_ROM_ADDRESS_ENABLE;
+		pci_write_config_dword(dev, dev->rom_base_reg, reg);
+		dev->resource[PCI_ROM_RESOURCE].flags &= ~PCI_ROM_ADDRESS_ENABLE;
+	}
+
+	/* All of these (may) have I/O scattered all around and may not
+	   use I/O base address registers at all.  So we just have to
+	   always enable IO to these devices.  */
+	if ((dev->class >> 8) == PCI_CLASS_NOT_DEFINED
+	    || (dev->class >> 8) == PCI_CLASS_NOT_DEFINED_VGA
+	    || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE
+	    || (dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+		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;
+
+	/* Enable the appropriate bits in the PCI command register.  */
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+	DBGC(("  cmd reg 0x%x\n", cmd));
+
+	/* If this is a PCI bridge, set the cache line correctly.  */
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+				      (L1_CACHE_BYTES / sizeof(u32)));
+	}
+}
+
+void __init
+pci_assign_unassigned_resources(void)
+{
+	struct pci_dev *dev;
+
+	pci_for_each_dev(dev) {
+		pdev_assign_unassigned_resources(dev);
+	}
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/setup.c linux/drivers/pci/setup.c
--- v2.3.39/linux/drivers/pci/setup.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/pci/setup.c	Wed Dec 31 16:00:00 1969
@@ -1,331 +0,0 @@
-/*
- *	drivers/pci/setup.c
- *
- * Extruded from code written by
- *      Dave Rusling (david.rusling@reo.mts.dec.com)
- *      David Mosberger (davidm@cs.arizona.edu)
- *	David Miller (davem@redhat.com)
- *
- * Support routines for initializing a PCI subsystem.
- */
-
-/* fixed for multiple pci buses, 1999 Andrea Arcangeli <andrea@suse.de> */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/cache.h>
-
-
-#define DEBUG_CONFIG 0
-#if DEBUG_CONFIG
-# define DBGC(args)     printk args
-#else
-# define DBGC(args)
-#endif
-
-int __init
-pci_claim_resource(struct pci_dev *dev, int resource)
-{
-        struct resource *res = &dev->resource[resource];
-	struct resource *root = pci_find_parent_resource(dev, res);
-	int err;
-
-	err = -EINVAL;
-	if (root != NULL) {
-		err = request_resource(root, res);
-		if (err) {
-			printk(KERN_ERR "PCI: Address space collision on "
-			       "region %d of device %s [%lx:%lx]\n",
-			       resource, dev->name, res->start, res->end);
-		}
-	} else {
-		printk(KERN_ERR "PCI: No parent found for region %d "
-		       "of device %s\n", resource, dev->name);
-	}
-
-	return err;
-}
-
-static void
-pdev_assign_unassigned_resources(struct pci_dev *dev, u32 min_io, u32 min_mem)
-{
-	u32 reg;
-	u16 cmd;
-	int i;
-
-	DBGC(("PCI assign unassigned: (%s)\n", dev->name));
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-
-	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-		struct resource *root, *res;
-		unsigned long size, min;
-
-		res = &dev->resource[i];
-
-		if (res->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		else if (res->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-
-		/* If it is already assigned or the resource does
-		   not exist, there is nothing to do.  */
-		if (res->parent != NULL || res->flags == 0)
-			continue;
-
-		/* Determine the root we allocate from.  */
-		res->end -= res->start;
-		res->start = 0;
-		root = pci_find_parent_resource(dev, res);
-		if (root == NULL)
-			continue;
-
-		min = (res->flags & IORESOURCE_IO ? min_io : min_mem);
-		min += root->start;
-		size = res->end + 1;
-		DBGC(("  for root[%lx:%lx] min[%lx] size[%lx]\n",
-		      root->start, root->end, min, size));
-
-		if (allocate_resource(root, res, size, min, -1, size, pcibios_align_resource, dev) < 0) {
-			printk(KERN_ERR
-			       "PCI: Failed to allocate resource %d for %s\n",
-			       i, dev->name);
-			continue;
-		}
-
-		DBGC(("  got res[%lx:%lx] for resource %d\n",
-		      res->start, res->end, i));
-
-		/* Update PCI config space.  */
-		pcibios_update_resource(dev, root, res, i);
-	}
-
-	/* Special case, disable the ROM.  Several devices act funny
-	   (ie. do not respond to memory space writes) when it is left
-	   enabled.  A good example are QlogicISP adapters.  */
-
-	if (dev->rom_base_reg) {
-		pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-		reg &= ~PCI_ROM_ADDRESS_ENABLE;
-		pci_write_config_dword(dev, dev->rom_base_reg, reg);
-		dev->resource[PCI_ROM_RESOURCE].flags &= ~PCI_ROM_ADDRESS_ENABLE;
-	}
-
-	/* All of these (may) have I/O scattered all around and may not
-	   use I/O base address registers at all.  So we just have to
-	   always enable IO to these devices.  */
-	if ((dev->class >> 8) == PCI_CLASS_NOT_DEFINED
-	    || (dev->class >> 8) == PCI_CLASS_NOT_DEFINED_VGA
-	    || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE
-	    || (dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
-		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;
-
-	/* Enable the appropriate bits in the PCI command register.  */
-	pci_write_config_word(dev, PCI_COMMAND, cmd);
-
-	DBGC(("  cmd reg 0x%x\n", cmd));
-
-	/* If this is a PCI bridge, set the cache line correctly.  */
-	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
-				      (L1_CACHE_BYTES / sizeof(u32)));
-	}
-}
-
-void __init
-pci_assign_unassigned_resources(u32 min_io, u32 min_mem)
-{
-	struct pci_dev *dev;
-
-	pci_for_each_dev(dev) {
-		pdev_assign_unassigned_resources(dev, min_io, min_mem);
-	}
-}
-
-#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
-#define ROUND_DOWN(x, a)	((x) & ~((a) - 1))
-
-static void __init
-pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
-{
-	struct pbus_set_ranges_data inner;
-	struct pci_dev *dev;
-	struct list_head *ln;
-
-	inner.found_vga = 0;
-	inner.mem_start = inner.io_start = ~0UL;
-	inner.mem_end = inner.io_end = 0;
-
-	/* Collect information about how our direct children are layed out. */
-	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
-		int i;
-		dev = pci_dev_b(ln);
-		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-			struct resource *res = &dev->resource[i];
-			if (res->flags & IORESOURCE_IO) {
-				if (res->start < inner.io_start)
-					inner.io_start = res->start;
-				if (res->end > inner.io_end)
-					inner.io_end = res->end;
-			} else if (res->flags & IORESOURCE_MEM) {
-				if (res->start < inner.mem_start)
-					inner.mem_start = res->start;
-				if (res->end > inner.mem_end)
-					inner.mem_end = res->end;
-			}
-		}
-                if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
-                        inner.found_vga = 1;
-	}
-
-	/* And for all of the sub-busses.  */
-	for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
-		pbus_set_ranges(pci_bus_b(ln), &inner);
-
-	/* Align the values.  */
-	inner.io_start = ROUND_DOWN(inner.io_start, 4*1024);
-	inner.io_end = ROUND_UP(inner.io_end, 4*1024);
-
-	inner.mem_start = ROUND_DOWN(inner.mem_start, 1*1024*1024);
-	inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024);
-
-	pcibios_fixup_pbus_ranges(bus, &inner);
-
-	/* Configure the bridge, if possible.  */
-	if (bus->self) {
-		struct pci_dev *bridge = bus->self;
-		u32 l;
-
-                /* Set up the top and bottom of the PCI I/O segment
-                   for this bus.  */
-                pci_read_config_dword(bridge, PCI_IO_BASE, &l);
-                l &= 0xffff0000;
-                l |= (inner.io_start >> 8) & 0x00f0;
-		l |= (inner.io_end - 1) & 0xf000;
-                pci_write_config_dword(bridge, PCI_IO_BASE, l);
-
-                /*
-                 * Clear out the upper 16 bits of IO base/limit.
-                 * Clear out the upper 32 bits of PREF base/limit.
-                 */
-                pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0);
-                pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
-                pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
-
-                /* Set up the top and bottom of the PCI Memory segment
-                   for this bus.  */
-                l = (inner.mem_start & 0xfff00000) >> 16;
-		l |= (inner.mem_end - 1) & 0xfff00000;
-                pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
-
-                /*
-                 * Turn off downstream PF memory address range, unless
-                 * there is a VGA behind this bridge, in which case, we
-                 * enable the PREFETCH range to include BIOS ROM at C0000.
-                 *
-                 * NOTE: this is a bit of a hack, done with PREFETCH for
-                 * simplicity, rather than having to add it into the above
-                 * non-PREFETCH range, which could then be bigger than we want.
-                 * We might assume that we could relocate the BIOS ROM, but
-                 * that would depend on having it found by those who need it
-                 * (the DEC BIOS emulator would find it, but I do not know
-                 * about the Xservers). So, we do it this way for now... ;-)
-                 */
-                l = (inner.found_vga) ? 0 : 0x0000ffff;
-                pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
-
-                /*
-                 * Tell bridge that there is an ISA bus in the system,
-                 * and (possibly) a VGA as well.
-                 */
-                l = (inner.found_vga) ? 0x0c : 0x04;
-                pci_write_config_byte(bridge, PCI_BRIDGE_CONTROL, l);
-
-                /*
-                 * Clear status bits,
-                 * turn on I/O    enable (for downstream I/O),
-                 * turn on memory enable (for downstream memory),
-                 * turn on master enable (for upstream memory and I/O).
-                 */
-                pci_write_config_dword(bridge, PCI_COMMAND, 0xffff0007);
-	}
-
-	if (outer) {
-		outer->found_vga |= inner.found_vga;
-		if (inner.io_start < outer->io_start)
-			outer->io_start = inner.io_start;
-		if (inner.io_end > outer->io_end)
-			outer->io_end = inner.io_end;
-		if (inner.mem_start < outer->mem_start)
-			outer->mem_start = inner.mem_start;
-		if (inner.mem_end > outer->mem_end)
-			outer->mem_end = inner.mem_end;
-	}
-}
-
-void __init
-pci_set_bus_ranges(void)
-{
-	struct list_head *ln;
-
-	for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
-		pbus_set_ranges(pci_bus_b(ln), NULL);
-}
-
-static void __init
-pdev_fixup_irq(struct pci_dev *dev,
-	       u8 (*swizzle)(struct pci_dev *, u8 *),
-	       int (*map_irq)(struct pci_dev *, u8, u8))
-{
-	u8 pin, slot;
-	int irq;
-
-	/* If this device is not on the primary bus, we need to figure out
-	   which interrupt pin it will come in on.   We know which slot it
-	   will come in on 'cos that slot is where the bridge is.   Each
-	   time the interrupt line passes through a PCI-PCI bridge we must
-	   apply the swizzle function.  */
-
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-	/* Cope with 0 and illegal. */
-	if (pin == 0 || pin > 4)
-		pin = 1;
-
-	/* Follow the chain of bridges, swizzling as we go.  */
-	slot = (*swizzle)(dev, &pin);
-
-	irq = (*map_irq)(dev, slot, pin);
-	if (irq == -1)
-		irq = 0;
-	dev->irq = irq;
-
-	DBGC(("PCI fixup irq: (%s) got %d\n", dev->name, dev->irq));
-
-	/* Always tell the device, so the driver knows what is
-	   the real IRQ to use; the device does not use it. */
-	pcibios_update_irq(dev, irq);
-}
-
-void __init
-pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
-	       int (*map_irq)(struct pci_dev *, u8, u8))
-{
-	struct pci_dev *dev;
-	pci_for_each_dev(dev) {
-		pdev_fixup_irq(dev, swizzle, map_irq);
-	}
-}
-
-int
-pcibios_enable_device(struct pci_dev *dev)
-{
-	return 0;
-}
diff -u --recursive --new-file v2.3.39/linux/drivers/pci/syscall.c linux/drivers/pci/syscall.c
--- v2.3.39/linux/drivers/pci/syscall.c	Thu Nov 18 20:25:37 1999
+++ linux/drivers/pci/syscall.c	Wed Jan 12 11:51:49 2000
@@ -120,7 +120,7 @@
 		err = get_user(word, (u16 *)buf);
 		if (err)
 			break;
-		err = pci_write_config_byte(dev, off, word);
+		err = pci_write_config_word(dev, off, word);
 		if (err != PCIBIOS_SUCCESSFUL)
 			err = -EIO;
 		break;
@@ -129,7 +129,7 @@
 		err = get_user(dword, (u32 *)buf);
 		if (err)
 			break;
-		pci_write_config_byte(dev, off, dword);
+		err = pci_write_config_dword(dev, off, dword);
 		if (err != PCIBIOS_SUCCESSFUL)
 			err = -EIO;
 		break;
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c
--- v2.3.39/linux/drivers/pcmcia/bulkmem.c	Wed Dec 29 13:13:17 1999
+++ linux/drivers/pcmcia/bulkmem.c	Tue Jan 18 22:29:17 2000
@@ -2,7 +2,7 @@
 
     PCMCIA Bulk Memory Services
 
-    bulkmem.c 1.33 1999/10/25 20:03:33
+    bulkmem.c 1.34 1999/11/17 01:37:55
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -179,7 +179,7 @@
 	}
 	busy->client->event_callback_args.info = erase;
 	EVENT(busy->client, CS_EVENT_ERASE_COMPLETE, CS_EVENT_PRI_LOW);
-	kfree_s(busy, sizeof(*busy));
+	kfree(busy);
 	/* Resubmit anything waiting for a request to finish */
 	wake_up_interruptible(&mtd->mtd_req);
 	retry_erase_list(&mtd->erase_busy, 0);
@@ -484,6 +484,7 @@
     if ((handle == NULL) || CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
     queue = kmalloc(sizeof(*queue), GFP_KERNEL);
+    if (!queue) return CS_OUT_OF_RESOURCE;
     queue->eraseq_magic = ERASEQ_MAGIC;
     queue->handle = *handle;
     queue->count = header->QueueEntryCnt;
@@ -502,7 +503,7 @@
     if (i < eraseq->count)
 	return CS_BUSY;
     eraseq->eraseq_magic = 0;
-    kfree_s(eraseq, sizeof(*eraseq));
+    kfree(eraseq);
     return CS_SUCCESS;
 } /* deregister_erase_queue */
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c
--- v2.3.39/linux/drivers/pcmcia/cardbus.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/pcmcia/cardbus.c	Tue Jan 11 21:49:22 2000
@@ -106,39 +106,12 @@
 /*=====================================================================
 
     Expansion ROM's have a special layout, and pointers specify an
-    image number and an offset within that image.  check_rom()
-    verifies that the expansion ROM exists and has the standard
-    layout.  xlate_rom_addr() converts an image/offset address to an
-    absolute offset from the ROM's base address.
+    image number and an offset within that image.  xlate_rom_addr()
+    converts an image/offset address to an absolute offset from the
+    ROM's base address.
     
 =====================================================================*/
 
-static int check_rom(u_char * b, u_long len)
-{
-	u_int img = 0, ofs = 0, sz;
-	u_short data;
-	DEBUG(0, "ROM image dump:\n");
-	while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
-		data = readb(b + ROM_DATA_PTR) +
-		    (readb(b + ROM_DATA_PTR + 1) << 8);
-		sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
-			    (readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
-		DEBUG(0, "  image %d: 0x%06x-0x%06x, signature %c%c%c%c\n",
-		      img, ofs, ofs + sz - 1,
-		      readb(b + data + PCDATA_SIGNATURE),
-		      readb(b + data + PCDATA_SIGNATURE + 1),
-		      readb(b + data + PCDATA_SIGNATURE + 2),
-		      readb(b + data + PCDATA_SIGNATURE + 3));
-		ofs += sz;
-		img++;
-		if ((readb(b + data + PCDATA_INDICATOR) & 0x80) ||
-		    (sz == 0) || (ofs >= len))
-			break;
-		b += sz;
-	}
-	return img;
-}
-
 static u_int xlate_rom_addr(u_char * b, u_int addr)
 {
 	u_int img = 0, ofs = 0, sz;
@@ -326,12 +299,8 @@
 		/* FIXME: Do we need to enable the expansion ROM? */
 		for (r = 0; r < 7; r++) {
 			struct resource *res = dev->resource + r;
-			if (res->flags) {
-				/* Unset resource address, assign new one! */
-				res->end -= res->start;
-				res->start = 0;
+			if (res->flags)
 				pci_assign_resource(dev, r);
-			}
 		}
 		pci_enable_device(dev);
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/cb_enabler.c linux/drivers/pcmcia/cb_enabler.c
--- v2.3.39/linux/drivers/pcmcia/cb_enabler.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/pcmcia/cb_enabler.c	Tue Jan 18 22:29:17 2000
@@ -1,8 +1,8 @@
 /*======================================================================
 
-    Cardbus device enabler
+    CardBus device enabler
 
-    cb_enabler.c 1.25 1999/10/25 20:03:33
+    cb_enabler.c 1.28 1999/12/09 20:57:37
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -58,11 +58,14 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static char *version =
-"cb_enabler.c 1.25 1999/10/25 20:03:33 (David Hinds)";
+"cb_enabler.c 1.28 1999/12/09 20:57:37 (David Hinds)";
 #else
 #define DEBUG(n, args...) do { } while (0)
 #endif
 
+MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_DESCRIPTION("CardBus stub enabler module");
+
 /*====================================================================*/
 
 /* Parameters that can be set with 'insmod' */
@@ -126,10 +129,11 @@
     
     DEBUG(0, "cb_attach(%d)\n", n);
 
-    MOD_INC_USE_COUNT;
     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
-    memset(link, 0, sizeof(struct dev_link_t));
+    if (!link) return NULL;
 
+    MOD_INC_USE_COUNT;
+    memset(link, 0, sizeof(struct dev_link_t));
     link->conf.IntType = INT_CARDBUS;
     link->conf.Vcc = 33;
 
@@ -142,7 +146,7 @@
     client_reg.dev_info = &driver[n].dev_info;
     client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
     client_reg.event_handler = &cb_event;
-    client_reg.EventMask =
+    client_reg.EventMask = CS_EVENT_RESET_PHYSICAL |
 	CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
 	CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
 	CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
@@ -186,7 +190,7 @@
 	pcmcia_deregister_client(link->handle);
     
     *linkp = link->next;
-    kfree_s(link, sizeof(struct dev_link_t));
+    kfree(link);
     MOD_DEC_USE_COUNT;
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c
--- v2.3.39/linux/drivers/pcmcia/cistpl.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/pcmcia/cistpl.c	Tue Jan 18 22:29:17 2000
@@ -2,7 +2,7 @@
 
     PCMCIA Card Information Structure parser
 
-    cistpl.c 1.74 1999/11/08 20:47:02
+    cistpl.c 1.77 2000/01/16 19:19:01
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -52,6 +52,7 @@
 #include <pcmcia/ss.h>
 #include <pcmcia/cs.h>
 #include <pcmcia/bulkmem.h>
+#include <pcmcia/cisreg.h>
 #include <pcmcia/cistpl.h>
 #include "cs_internal.h"
 #include "rsrc_mgr.h"
@@ -83,12 +84,15 @@
     
 ======================================================================*/
 
+/* Bits in attr field */
+#define IS_ATTR		1
+#define IS_INDIRECT	8
+
 void read_cis_mem(socket_info_t *s, int attr, u_int addr,
 		  u_int len, void *ptr)
 {
     pccard_mem_map *mem = &s->cis_mem;
-    u_char *sys;
-    u_int inc = 1;
+    u_char *sys, *buf = ptr;
     
     DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
     if (setup_cis_mem(s) != 0) {
@@ -96,47 +100,81 @@
 	return;
     }
     mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
-    if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
-    sys = s->cis_virt + (addr & (s->cap.map_size-1));
-    mem->card_start = addr & ~(s->cap.map_size-1);
+    sys = s->cis_virt;
 
-    for (; len > 0; sys = s->cis_virt) {
+    if (attr & IS_INDIRECT) {
+	/* Indirect accesses use a bunch of special registers at fixed
+	   locations in common memory */
+	u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
+	if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
+	mem->card_start = 0;
 	s->ss_entry->set_mem_map(s->sock, mem);
-	DEBUG(3,  "cs:  %#2.2x %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
-	      bus_readb(s->cap.bus, sys),
-	      bus_readb(s->cap.bus, sys+inc),
-	      bus_readb(s->cap.bus, sys+2*inc),
-	      bus_readb(s->cap.bus, sys+3*inc),
-	      bus_readb(s->cap.bus, sys+4*inc));
-	for ( ; len > 0; len--, ((u_char *)ptr)++, sys += inc) {
-	    if (sys == s->cis_virt+s->cap.map_size) break;
-	    *(u_char *)ptr = bus_readb(s->cap.bus, sys);
+	bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
+	bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
+	bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
+	bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
+	bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
+	for ( ; len > 0; len--, buf++)
+	    *buf = bus_readb(s->cap.bus, sys+CISREG_IDATA0);
+    } else {
+	u_int inc = 1;
+	if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
+	sys += (addr & (s->cap.map_size-1));
+	mem->card_start = addr & ~(s->cap.map_size-1);
+
+	for (; len > 0; sys = s->cis_virt) {
+	    s->ss_entry->set_mem_map(s->sock, mem);
+	    for ( ; len > 0; len--, buf++, sys += inc) {
+		if (sys == s->cis_virt+s->cap.map_size) break;
+		*buf = bus_readb(s->cap.bus, sys);
+	    }
+	    mem->card_start += s->cap.map_size;
 	}
-	mem->card_start += s->cap.map_size;
     }
+    DEBUG(3, "cs:  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
+	  *(u_char *)(ptr+0), *(u_char *)(ptr+1),
+	  *(u_char *)(ptr+2), *(u_char *)(ptr+3));
 }
 
 void write_cis_mem(socket_info_t *s, int attr, u_int addr,
 		   u_int len, void *ptr)
 {
     pccard_mem_map *mem = &s->cis_mem;
-    u_char *sys;
-    int inc = 1;
+    u_char *sys, *buf = ptr;
     
     DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
     if (setup_cis_mem(s) != 0) return;
-    mem->flags &= ~MAP_ATTRIB;
-    if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
-    sys = s->cis_virt + (addr & (s->cap.map_size-1));
-    mem->card_start = addr & ~(s->cap.map_size-1);
-    
-    for (; len > 0; sys = s->cis_virt) {
+    mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
+    sys = s->cis_virt;
+
+    if (attr & IS_INDIRECT) {
+	/* Indirect accesses use a bunch of special registers at fixed
+	   locations in common memory */
+	u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
+	if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
+	mem->card_start = 0;
 	s->ss_entry->set_mem_map(s->sock, mem);
-	for ( ; len > 0; len--, ((u_char *)ptr)++, sys += inc) {
-	    if (sys == s->cis_virt+s->cap.map_size) break;
-	    bus_writeb(s->cap.bus, *(u_char *)ptr, sys);
+	bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
+	bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
+	bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
+	bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
+	bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
+	for ( ; len > 0; len--, buf++)
+	    bus_writeb(s->cap.bus, *buf, sys+CISREG_IDATA0);
+    } else {
+	int inc = 1;
+	if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
+	sys += (addr & (s->cap.map_size-1));
+	mem->card_start = addr & ~(s->cap.map_size-1);
+
+	for (; len > 0; sys = s->cis_virt) {
+	    s->ss_entry->set_mem_map(s->sock, mem);
+	    for ( ; len > 0; len--, buf++, sys += inc) {
+		if (sys == s->cis_virt+s->cap.map_size) break;
+		bus_writeb(s->cap.bus, *buf, sys);
+	    }
+	    mem->card_start += s->cap.map_size;
 	}
-	mem->card_start += s->cap.map_size;
     }
 }
 
@@ -342,10 +380,10 @@
 ======================================================================*/
 
 typedef struct tuple_flags {
-    u_int		link_space:3;
+    u_int		link_space:4;
     u_int		has_link:1;
     u_int		mfc_fn:3;
-    u_int		space:3;
+    u_int		space:4;
 } tuple_flags;
 
 #define LINK_SPACE(f)	(((tuple_flags *)(&(f)))->link_space)
@@ -469,17 +507,23 @@
 	    (link[0] == CISTPL_LONGLINK_C) ||
 	    (link[0] == CISTPL_LONGLINK_MFC) ||
 	    (link[0] == CISTPL_LINKTARGET) ||
+	    (link[0] == CISTPL_INDIRECT) ||
 	    (link[0] == CISTPL_NO_LINK)) {
 	    switch (link[0]) {
 	    case CISTPL_LONGLINK_A:
 		HAS_LINK(tuple->Flags) = 1;
-		LINK_SPACE(tuple->Flags) = 1;
+		LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
 		read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
 		break;
 	    case CISTPL_LONGLINK_C:
 		HAS_LINK(tuple->Flags) = 1;
-		LINK_SPACE(tuple->Flags) = 0;
+		LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
 		read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
+		break;
+	    case CISTPL_INDIRECT:
+		HAS_LINK(tuple->Flags) = 1;
+		LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
+		tuple->LinkOffset = 0;
 		break;
 	    case CISTPL_LONGLINK_MFC:
 		tuple->LinkOffset = ofs + 3;
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- v2.3.39/linux/drivers/pcmcia/cs.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/pcmcia/cs.c	Tue Jan 18 22:29:17 2000
@@ -2,7 +2,7 @@
 
     PCMCIA Card Services -- core services
 
-    cs.c 1.235 1999/11/11 17:52:05
+    cs.c 1.247 2000/01/15 04:30:35
     
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -59,7 +59,6 @@
 #include <pcmcia/cistpl.h>
 #include <pcmcia/cisreg.h>
 #include <pcmcia/bus_ops.h>
-
 #include "cs_internal.h"
 #include "rsrc_mgr.h"
 
@@ -72,28 +71,40 @@
 int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 static const char *version =
-"cs.c 1.235 1999/11/11 17:52:05 (David Hinds)";
+"cs.c 1.247 2000/01/15 04:30:35 (David Hinds)";
 #endif
 
-static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
-#ifdef MODULE
-static const char *kernel = "kernel build: " UTS_RELEASE " " UTS_VERSION;
-#endif
-static const char *options = "options: "
 #ifdef CONFIG_PCI
-" [pci]"
+#define PCI_OPT " [pci]"
+#else
+#define PCI_OPT ""
 #endif
 #ifdef CONFIG_CARDBUS
-" [cardbus]"
+#define CB_OPT " [cardbus]"
+#else
+#define CB_OPT ""
 #endif
 #ifdef CONFIG_APM
-" [apm]"
+#define APM_OPT " [apm]"
+#else
+#define APM_OPT ""
 #endif
 #if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && \
-    !defined(CONFIG_APM) && !defined(CONFIG_PNP_BIOS)
-" none"
+    !defined(CONFIG_APM)
+#define OPTIONS " none"
+#else
+#define OPTIONS PCI_OPT CB_OPT APM_OPT
 #endif
-;
+
+static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
+#ifdef MODULE
+static const char *kernel = "kernel build: " UTS_RELEASE " " UTS_VERSION;
+#endif
+static const char *options = "options: " OPTIONS;
+
+MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE
+		   "\n  options:" OPTIONS);
 
 /*====================================================================*/
 
@@ -263,11 +274,6 @@
 	return s->ss_entry->set_socket(s->sock, state);
 }
 
-static int get_io_map(socket_info_t *s, struct pccard_io_map *io)
-{
-	return s->ss_entry->get_io_map(s->sock, io);
-}
-
 static int set_io_map(socket_info_t *s, struct pccard_io_map *io)
 {
 	return s->ss_entry->set_io_map(s->sock, io);
@@ -734,18 +740,18 @@
     int i;
     ioaddr_t try, align;
 
-    align = (*base) ? (1<<lines) : 1;
+    align = (*base) ? (lines ? 1<<lines : 0) : 1;
     if (align && (align < num)) {
-	printk(KERN_INFO "odd IO request: num %04x align %04x\n",
-	       num, align);
-	if (*base)
+	if (*base) {
+	    DEBUG(0, "odd IO request: num %04x align %04x\n",
+		  num, align);
 	    align = 0;
-	else
+	} else
 	    while (align && (align < num)) align <<= 1;
     }
     if (*base & ~(align-1)) {
-	printk(KERN_INFO "odd IO request: base %04x align %04x\n",
-	       *base, align);
+	DEBUG(0, "odd IO request: base %04x align %04x\n",
+	      *base, align);
 	align = 0;
     }
     for (i = 0; i < MAX_IO_WIN; i++) {
@@ -862,6 +868,7 @@
     s = SOCKET(req);
 
     client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL);
+    if (!client) return CS_OUT_OF_RESOURCE;
     memset(client, '\0', sizeof(client_t));
     client->client_magic = CLIENT_MAGIC;
     strncpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
@@ -1122,18 +1129,18 @@
     if (win->ctl.flags & MAP_ACTIVE)
 	req->Attributes |= WIN_ENABLE;
     if (win->ctl.flags & MAP_16BIT)
-	req->Attributes |= WIN_DATA_WIDTH;
+	req->Attributes |= WIN_DATA_WIDTH_16;
     if (win->ctl.flags & MAP_USE_WAIT)
 	req->Attributes |= WIN_USE_WAIT;
     *handle = win;
     return CS_SUCCESS;
 } /* get_window */
 
-int pcmcia_get_first_window(client_handle_t *handle, win_req_t *req)
+int pcmcia_get_first_window(window_handle_t *win, win_req_t *req)
 {
-    if ((handle == NULL) || CHECK_HANDLE(*handle))
+    if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
 	return CS_BAD_HANDLE;
-    return pcmcia_get_window((window_handle_t *)handle, 0, req);
+    return pcmcia_get_window(win, 0, req);
 }
 
 int pcmcia_get_next_window(window_handle_t *win, win_req_t *req)
@@ -1331,7 +1338,7 @@
 	win->ctl.flags |= MAP_ATTRIB;
     if (req->Attributes & WIN_ENABLE)
 	win->ctl.flags |= MAP_ACTIVE;
-    if (req->Attributes & WIN_DATA_WIDTH)
+    if (req->Attributes & WIN_DATA_WIDTH_16)
 	win->ctl.flags |= MAP_16BIT;
     if (req->Attributes & WIN_USE_WAIT)
 	win->ctl.flags |= MAP_USE_WAIT;
@@ -1426,7 +1433,7 @@
 
 int pcmcia_release_configuration(client_handle_t handle)
 {
-    pccard_io_map io;
+    pccard_io_map io = { 0, 0, 0, 0, 1 };
     socket_info_t *s;
     int i;
     
@@ -1460,8 +1467,6 @@
 		if (s->io[i].Config != 0)
 		    continue;
 		io.map = i;
-		get_io_map(s, &io);
-		io.flags &= ~MAP_ACTIVE;
 		set_io_map(s, &io);
 	    }
 	c->state &= ~CONFIG_LOCKED;
@@ -1863,7 +1868,8 @@
 {
     socket_info_t *s;
     window_t *win;
-    int w, align;
+    u_long align;
+    int w;
     
     if (CHECK_HANDLE(*handle))
 	return CS_BAD_HANDLE;
@@ -1873,16 +1879,25 @@
     if (req->Attributes & (WIN_PAGED | WIN_SHARED))
 	return CS_BAD_ATTRIBUTE;
 
-    for (w = 0; w < MAX_WIN; w++)
-	if (!(s->state & SOCKET_WIN_REQ(w))) break;
-    if (w == MAX_WIN)
-	return CS_OUT_OF_RESOURCE;
-
     /* Window size defaults to smallest available */
     if (req->Size == 0)
 	req->Size = s->cap.map_size;
+    align = (((s->cap.features & SS_CAP_MEM_ALIGN) ||
+	      (req->Attributes & WIN_STRICT_ALIGN)) ?
+	     req->Size : s->cap.map_size);
+    if (req->Size & (s->cap.map_size-1))
+	return CS_BAD_SIZE;
+    if (req->Base & (align-1))
+	return CS_BAD_BASE;
+    if (req->Base)
+	align = 0;
     
     /* Allocate system memory window */
+    for (w = 0; w < MAX_WIN; w++)
+	if (!(s->state & SOCKET_WIN_REQ(w))) break;
+    if (w == MAX_WIN)
+	return CS_OUT_OF_RESOURCE;
+
     win = &s->win[w];
     win->magic = WINDOW_MAGIC;
     win->index = w;
@@ -1890,10 +1905,8 @@
     win->sock = s;
     win->base = req->Base;
     win->size = req->Size;
-    align = ((s->cap.features & SS_CAP_MEM_ALIGN) ||
-	     (req->Attributes & WIN_STRICT_ALIGN));
-    if (find_mem_region(&win->base, win->size,
-			(align ? req->Size : s->cap.map_size),
+	
+    if (find_mem_region(&win->base, win->size, align,
 			(req->Attributes & WIN_MAP_BELOW_1MB) ||
 			!(s->cap.features & SS_CAP_PAGE_REGS),
 			(*handle)->dev_info))
@@ -1909,7 +1922,7 @@
 	win->ctl.flags |= MAP_ATTRIB;
     if (req->Attributes & WIN_ENABLE)
 	win->ctl.flags |= MAP_ACTIVE;
-    if (req->Attributes & WIN_DATA_WIDTH)
+    if (req->Attributes & WIN_DATA_WIDTH_16)
 	win->ctl.flags |= MAP_16BIT;
     if (req->Attributes & WIN_USE_WAIT)
 	win->ctl.flags |= MAP_USE_WAIT;
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- v2.3.39/linux/drivers/pcmcia/ds.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/pcmcia/ds.c	Tue Jan 18 22:29:17 2000
@@ -2,7 +2,7 @@
 
     PC Card Driver Services
     
-    ds.c 1.100 1999/11/08 20:47:02
+    ds.c 1.104 2000/01/11 01:18:02
     
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -60,11 +60,14 @@
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 static const char *version =
-"ds.c 1.100 1999/11/08 20:47:02 (David Hinds)";
+"ds.c 1.104 2000/01/11 01:18:02 (David Hinds)";
 #else
 #define DEBUG(n, args...)
 #endif
 
+MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
+
 /*====================================================================*/
 
 typedef struct driver_info_t {
@@ -155,6 +158,7 @@
 	    break;
     if (!driver) {
 	driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
+	if (!driver) return -ENOMEM;
 	strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN);
 	driver->use_count = 0;
 	driver->status = init_status;
@@ -193,7 +197,7 @@
 			    DEV_NAME_LEN) != 0))
 	d = &(*d)->next;
     if (*d == NULL)
-	return -1;
+	return -ENODEV;
     
     target = *d;
     if (target->use_count == 0) {
@@ -377,6 +381,7 @@
 	    break;
     if (driver == NULL) {
 	driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
+	if (!driver) return -ENOMEM;
 	strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN);
 	driver->use_count = 0;
 	driver->next = root_driver;
@@ -522,11 +527,11 @@
 	    for (d = &root_driver; *d; d = &((*d)->next))
 		if (c->driver == *d) break;
 	    *d = (*d)->next;
-	    kfree_s(c->driver, sizeof(driver_info_t));
+	    kfree(c->driver);
 	}
     }
     *b = c->next;
-    kfree_s(c, sizeof(socket_bind_t));
+    kfree(c);
     
     return 0;
 } /* unbind_request */
@@ -554,8 +559,9 @@
 	    s->state |= SOCKET_BUSY;
     }
     
-    MOD_INC_USE_COUNT;
     user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
+    if (!user) return -ENOMEM;
+    MOD_INC_USE_COUNT;
     user->event_tail = user->event_head = 0;
     user->next = s->user;
     user->user_magic = USER_MAGIC;
@@ -593,7 +599,7 @@
 	return 0;
     *link = user->next;
     user->user_magic = 0;
-    kfree_s(user, sizeof(user_info_t));
+    kfree(user);
     
     MOD_DEC_USE_COUNT;
     return 0;
@@ -704,7 +710,7 @@
     if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
 
     /* Permission check */
-    if (!(cmd & IOC_OUT) && !suser())
+    if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
 	return -EPERM;
 	
     if (cmd & IOC_IN) {
@@ -773,7 +779,7 @@
 	ret = pcmcia_insert_card(s->handle, NULL);
 	break;
     case DS_ACCESS_CONFIGURATION_REGISTER:
-	if ((buf.conf_reg.Action == CS_WRITE) && !suser())
+	if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
 	    return -EPERM;
 	ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg);
 	break;
@@ -798,7 +804,7 @@
 	ret = pcmcia_replace_cis(s->handle, &buf.cisdump);
 	break;
     case DS_BIND_REQUEST:
-	if (!suser()) return -EPERM;
+	if (!capable(CAP_SYS_ADMIN)) return -EPERM;
 	err = bind_request(i, &buf.bind_info);
 	break;
     case DS_GET_DEVICE_INFO:
@@ -847,17 +853,12 @@
 /*====================================================================*/
 
 static struct file_operations ds_fops = {
-    NULL,		/* lseek */
-    ds_read,		/* read */
-    ds_write,		/* write */
-    NULL,		/* readdir */
-    ds_poll,		/* poll */
-    ds_ioctl,		/* ioctl */
-    NULL,		/* mmap */
-    ds_open,		/* open */
-    NULL,		/* flush */
-    ds_release,		/* release */
-    NULL		/* fsync */
+    open:	ds_open,
+    release:	ds_release,
+    ioctl:	ds_ioctl,
+    read:	ds_read,
+    write:	ds_write,
+    poll:	ds_poll
 };
 
 EXPORT_SYMBOL(register_pccard_driver);
@@ -887,6 +888,7 @@
     
     sockets = serv.Count;
     socket_table = kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL);
+    if (!socket_table) return -1;
     for (i = 0, s = socket_table; i < sockets; i++, s++) {
 	s->state = 0;
 	s->user = NULL;
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- v2.3.39/linux/drivers/pcmcia/i82365.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/pcmcia/i82365.c	Tue Jan 18 22:29:17 2000
@@ -66,7 +66,6 @@
 
 /* PCI-bus controllers */
 #include "old-yenta.h"
-#include "ti113x.h"
 #include "smc34c90.h"
 #include "topic.h"
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c
--- v2.3.39/linux/drivers/pcmcia/pci_socket.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/pcmcia/pci_socket.c	Tue Jan 11 16:01:49 2000
@@ -70,9 +70,8 @@
 {
 	pci_socket_t *socket = pci_socket_array + sock;
 
-	if (socket->op && socket->op->inquire)
-		return socket->op->inquire(socket, cap);
-	return -EINVAL;
+	*cap = socket->cap;
+	return 0;
 }
 
 static int pci_get_status(unsigned int sock, unsigned int *value)
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/pci_socket.h linux/drivers/pcmcia/pci_socket.h
--- v2.3.39/linux/drivers/pcmcia/pci_socket.h	Tue Jan 11 22:31:40 2000
+++ linux/drivers/pcmcia/pci_socket.h	Tue Jan 18 22:29:17 2000
@@ -4,6 +4,9 @@
  * (C) Copyright 1999 Linus Torvalds
  */
 
+#ifndef __PCI_SOCKET_H
+#define __PCI_SOCKET_H
+
 struct pci_socket_ops;
 
 typedef struct pci_socket {
@@ -16,6 +19,9 @@
 	socket_cap_t cap;
 	wait_queue_head_t wait;
 	unsigned int events;
+
+	/* A few words of private data for the low-level driver.. */
+	unsigned int private[8];
 } pci_socket_t;
 
 struct pci_socket_ops {
@@ -24,7 +30,6 @@
 
 	int (*init)(struct pci_socket *);
 	int (*suspend)(struct pci_socket *);
-	int (*inquire)(struct pci_socket *, socket_cap_t *cap);
 	int (*get_status)(struct pci_socket *, unsigned int *);
 	int (*get_socket)(struct pci_socket *, socket_state_t *);
 	int (*set_socket)(struct pci_socket *, socket_state_t *);
@@ -38,3 +43,4 @@
 extern struct pci_socket_ops yenta_operations;
 extern struct pci_socket_ops ricoh_operations;
 
+#endif
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/ricoh.h linux/drivers/pcmcia/ricoh.h
--- v2.3.39/linux/drivers/pcmcia/ricoh.h	Thu Nov 11 20:11:42 1999
+++ linux/drivers/pcmcia/ricoh.h	Tue Jan 18 22:29:17 2000
@@ -30,6 +30,8 @@
 #ifndef _LINUX_RICOH_H
 #define _LINUX_RICOH_H
 
+#include <linux/config.h>
+
 #define RF5C_MODE_CTL		0x1f	/* Mode control */
 #define RF5C_PWR_CTL		0x2f	/* Mixed voltage control */
 #define RF5C_CHIP_ID		0x3a	/* Chip identification */
@@ -70,25 +72,6 @@
 
 /* Register definitions for Ricoh PCI-to-CardBus bridges */
 
-#ifndef PCI_VENDOR_ID_RICOH
-#define PCI_VENDOR_ID_RICOH		0x1180
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C465
-#define PCI_DEVICE_ID_RICOH_RL5C465	0x0465
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C466
-#define PCI_DEVICE_ID_RICOH_RL5C466	0x0466
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C475
-#define PCI_DEVICE_ID_RICOH_RL5C475	0x0475
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C476
-#define PCI_DEVICE_ID_RICOH_RL5C476	0x0476
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C478
-#define PCI_DEVICE_ID_RICOH_RL5C478	0x0478
-#endif
-
 /* Extra bits in CB_BRIDGE_CONTROL */
 #define RL5C46X_BCR_3E0_ENA		0x0800
 #define RL5C46X_BCR_3E2_ENA		0x1000
@@ -128,5 +111,56 @@
 #define  RL5C4XX_CMD_SHIFT		4
 #define  RL5C4XX_HOLD_MASK		0x1c00
 #define  RL5C4XX_HOLD_SHIFT		10
+
+#ifdef __YENTA_H
+
+#define rl_misc(socket)		((socket)->private[0])
+#define rl_ctl(socket)		((socket)->private[1])
+#define rl_io(socket)		((socket)->private[2])
+#define rl_mem(socket)		((socket)->private[3])
+
+/*
+ * Magic Ricoh initialization code.. Save state at
+ * beginning, re-initialize it after suspend.
+ */
+static int ricoh_open(pci_socket_t *socket)
+{
+	rl_misc(socket) = config_readw(socket, RL5C4XX_MISC);
+	rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL);
+	rl_io(socket) = config_readw(socket, RL5C4XX_16BIT_IO_0);
+	rl_mem(socket) = config_readw(socket, RL5C4XX_16BIT_MEM_0);
+
+	/* Set the default timings, don't trust the original values */
+	rl_ctl(socket) = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
+	return 0;
+}
+
+static int ricoh_init(pci_socket_t *socket)
+{
+	yenta_init(socket);
+
+	config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
+	config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
+	config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
+	config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
+	return 0;
+}
+
+static struct pci_socket_ops ricoh_ops = {
+	ricoh_open,
+	yenta_close,
+	ricoh_init,
+	yenta_suspend,
+	yenta_get_status,
+	yenta_get_socket,
+	yenta_set_socket,
+	yenta_get_io_map,
+	yenta_set_io_map,
+	yenta_get_mem_map,
+	yenta_set_mem_map,
+	yenta_proc_setup
+};
+
+#endif /* CONFIG_CARDBUS */
 
 #endif /* _LINUX_RICOH_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- v2.3.39/linux/drivers/pcmcia/rsrc_mgr.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/pcmcia/rsrc_mgr.c	Tue Jan 18 22:29:17 2000
@@ -2,7 +2,7 @@
 
     Resource management routines
 
-    rsrc_mgr.c 1.76 1999/11/08 20:47:02
+    rsrc_mgr.c 1.77 1999/11/16 03:32:59
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -124,10 +124,11 @@
 	    break;
     }
     q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
+    if (!q) return CS_OUT_OF_RESOURCE;
     q->base = base; q->num = num;
     q->next = p->next; p->next = q;
-    return 0;
-} /* add_interval */
+    return CS_SUCCESS;
+}
 
 /*====================================================================*/
 
@@ -158,6 +159,7 @@
 	    } else {
 		/* Split the block into two pieces */
 		p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
+		if (!p) return CS_OUT_OF_RESOURCE;
 		p->base = base+num;
 		p->num = q->base+q->num - p->base;
 		q->num = base - q->base;
@@ -165,8 +167,8 @@
 	    }
 	}
     }
-    return 0;
-} /* sub_interval */
+    return CS_SUCCESS;
+}
 
 /*======================================================================
 
@@ -383,7 +385,7 @@
 	}
     }
     return -1;
-} /* find_io_region */
+}
 
 int find_mem_region(u_long *base, u_long num, u_long align,
 		    int force_low, char *name)
@@ -411,7 +413,7 @@
 	force_low++;
     }
     return -1;
-} /* find_mem_region */
+}
 
 /*======================================================================
 
@@ -482,7 +484,7 @@
 	}
     }
     return 0;
-} /* try_irq */
+}
 
 #endif
 
@@ -524,34 +526,35 @@
 static int adjust_memory(adjust_t *adj)
 {
     u_long base, num;
-    int i;
+    int i, ret;
 
     base = adj->resource.memory.Base;
     num = adj->resource.memory.Size;
     if ((num == 0) || (base+num-1 < base))
 	return CS_BAD_SIZE;
 
+    ret = CS_SUCCESS;
     switch (adj->Action) {
     case ADD_MANAGED_RESOURCE:
-	if (add_interval(&mem_db, base, num) != 0)
-	    return CS_IN_USE;
+	ret = add_interval(&mem_db, base, num);
 	break;
     case REMOVE_MANAGED_RESOURCE:
-	sub_interval(&mem_db, base, num);
-	for (i = 0; i < sockets; i++) {
-	    release_cis_mem(socket_table[i]);
+	ret = sub_interval(&mem_db, base, num);
+	if (ret == CS_SUCCESS) {
+	    for (i = 0; i < sockets; i++) {
+		release_cis_mem(socket_table[i]);
 #ifdef CONFIG_CARDBUS
-	    cb_release_cis_mem(socket_table[i]);
+		cb_release_cis_mem(socket_table[i]);
 #endif
+	    }
 	}
 	break;
     default:
-	return CS_UNSUPPORTED_FUNCTION;
-	break;
+	ret = CS_UNSUPPORTED_FUNCTION;
     }
     
-    return CS_SUCCESS;
-} /* adjust_mem */
+    return ret;
+}
 
 /*====================================================================*/
 
@@ -584,7 +587,7 @@
     }
 
     return CS_SUCCESS;
-} /* adjust_io */
+}
 
 /*====================================================================*/
 
@@ -625,7 +628,7 @@
     }
 #endif
     return CS_SUCCESS;
-} /* adjust_irq */
+}
 
 /*====================================================================*/
 
@@ -646,7 +649,7 @@
 	break;
     }
     return CS_UNSUPPORTED_FUNCTION;
-} /* adjust_resource_info */
+}
 
 /*====================================================================*/
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/tcic.c linux/drivers/pcmcia/tcic.c
--- v2.3.39/linux/drivers/pcmcia/tcic.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/pcmcia/tcic.c	Tue Jan 18 22:29:17 2000
@@ -2,7 +2,7 @@
 
     Device driver for Databook TCIC-2 PCMCIA controller
 
-    tcic.c 1.107 1999/10/25 20:03:34
+    tcic.c 1.108 1999/12/09 20:17:29
 
     The contents of this file are subject to the Mozilla Public
     License Version 1.1 (the "License"); you may not use this file
@@ -60,11 +60,14 @@
 static int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 static const char *version =
-"tcic.c 1.107 1999/10/25 20:03:34 (David Hinds)";
+"tcic.c 1.108 1999/12/09 20:17:29 (David Hinds)";
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 #else
 #define DEBUG(n, args...)
 #endif
+
+MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
 
 /*====================================================================*/
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/ti113x.h linux/drivers/pcmcia/ti113x.h
--- v2.3.39/linux/drivers/pcmcia/ti113x.h	Thu Nov 11 20:11:43 1999
+++ linux/drivers/pcmcia/ti113x.h	Thu Jan 20 16:06:18 2000
@@ -30,49 +30,7 @@
 #ifndef _LINUX_TI113X_H
 #define _LINUX_TI113X_H
 
-#ifndef PCI_VENDOR_ID_TI
-#define PCI_VENDOR_ID_TI		0x104c
-#endif
-
-#ifndef PCI_DEVICE_ID_TI_1130
-#define PCI_DEVICE_ID_TI_1130		0xac12
-#endif
-#ifndef PCI_DEVICE_ID_TI_1131
-#define PCI_DEVICE_ID_TI_1131		0xac15
-#endif
-#ifndef PCI_DEVICE_ID_TI_1031
-#define PCI_DEVICE_ID_TI_1031		0xac13
-#endif
-#ifndef PCI_DEVICE_ID_TI_1250A
-#define PCI_DEVICE_ID_TI_1250A		0xac16
-#endif
-#ifndef PCI_DEVICE_ID_TI_1220
-#define PCI_DEVICE_ID_TI_1220		0xac17
-#endif
-#ifndef PCI_DEVICE_ID_TI_1221
-#define PCI_DEVICE_ID_TI_1221		0xac19
-#endif
-#ifndef PCI_DEVICE_ID_TI_1210
-#define PCI_DEVICE_ID_TI_1210		0xac1a
-#endif
-#ifndef PCI_DEVICE_ID_TI_1450
-#define PCI_DEVICE_ID_TI_1450		0xac1b
-#endif
-#ifndef PCI_DEVICE_ID_TI_1225
-#define PCI_DEVICE_ID_TI_1225		0xac1c
-#endif
-#ifndef PCI_DEVICE_ID_TI_1251A
-#define PCI_DEVICE_ID_TI_1251A		0xac1d
-#endif
-#ifndef PCI_DEVICE_ID_TI_1211
-#define PCI_DEVICE_ID_TI_1211		0xac1e
-#endif
-#ifndef PCI_DEVICE_ID_TI_1251B
-#define PCI_DEVICE_ID_TI_1251B		0xac1f
-#endif
-#ifndef PCI_DEVICE_ID_TI_1420
-#define PCI_DEVICE_ID_TI_1420		0xac51
-#endif
+#include <linux/config.h>
 
 /* Register definitions for TI 113X PCI-to-CardBus bridges */
 
@@ -175,6 +133,87 @@
 
 /* ExCA IO offset registers */
 #define TI113X_IO_OFFSET(map)		(0x36+((map)<<1))
+
+#ifdef CONFIG_CARDBUS
+
+#define ti_sysctl(socket)	((socket)->private[0])
+#define ti_cardctl(socket)	((socket)->private[1])
+#define ti_devctl(socket)	((socket)->private[2])
+
+static int ti113x_open(pci_socket_t *socket)
+{
+	ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
+	ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
+	ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
+
+	ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
+	if (socket->cb_irq)
+		ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
+	return 0;
+}
+
+static int ti113x_init(pci_socket_t *socket)
+{
+	yenta_init(socket);
+
+	config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket));
+	config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket));
+	config_writeb(socket, TI113X_DEVICE_CONTROL, ti_devctl(socket));
+
+	return 0;
+}
+
+static struct pci_socket_ops ti113x_ops = {
+	ti113x_open,
+	yenta_close,
+	ti113x_init,
+	yenta_suspend,
+	yenta_get_status,
+	yenta_get_socket,
+	yenta_set_socket,
+	yenta_get_io_map,
+	yenta_set_io_map,
+	yenta_get_mem_map,
+	yenta_set_mem_map,
+	yenta_proc_setup
+};
+
+#define ti_diag(socket)		((socket)->private[0])
+
+static int ti1250_open(pci_socket_t *socket)
+{
+	ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+
+	ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
+	if (socket->cb_irq)
+		ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
+	return 0;
+}
+
+static int ti1250_init(pci_socket_t *socket)
+{
+	yenta_init(socket);
+
+	config_writeb(socket, TI1250_DIAGNOSTIC, ti_diag(socket));
+	return 0;
+}
+
+static struct pci_socket_ops ti1250_ops = {
+	ti1250_open,
+	yenta_close,
+	ti1250_init,
+	yenta_suspend,
+	yenta_get_status,
+	yenta_get_socket,
+	yenta_set_socket,
+	yenta_get_io_map,
+	yenta_set_io_map,
+	yenta_get_mem_map,
+	yenta_set_mem_map,
+	yenta_proc_setup
+};
+
+#endif /* CONFIG_CARDBUS */
 
 #endif /* _LINUX_TI113X_H */
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- v2.3.39/linux/drivers/pcmcia/yenta.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/pcmcia/yenta.c	Thu Jan 13 22:34:42 2000
@@ -15,7 +15,6 @@
 
 #include "yenta.h"
 #include "i82365.h"
-#include "ricoh.h"
 
 /* Don't ask.. */
 #define to_cycles(ns)	((ns)/120)
@@ -68,12 +67,6 @@
 	exca_writeb(socket, reg+1, val >> 8);
 }
 
-static int yenta_inquire(pci_socket_t *socket, socket_cap_t *cap)
-{
-	*cap = socket->cap;
-	return 0;
-}
-
 /*
  * Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
  * on what kind of card is inserted..
@@ -190,20 +183,22 @@
 	u16 bridge;
 
 	yenta_set_power(socket, state);
-	bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_CRST;
+	socket->io_irq = state->io_irq;
+	bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR);
 	if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
 		bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0;
-		bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
 
 		/* ISA interrupt control? */
-		if (bridge & CB_BRIDGE_INTR) {
+		if (!socket->cb_irq) {
 			u8 intr = exca_readb(socket, I365_INTCTL);
 			intr = (intr & ~0xf) | state->io_irq;
 			exca_writeb(socket, I365_INTCTL, intr);
+			bridge |= CB_BRIDGE_INTR;
 		}
 	} else {
 		u8 reg;
 
+		bridge |= CB_BRIDGE_INTR;
 		reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA);
 		reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
 		reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
@@ -426,7 +421,7 @@
  * more timely manner if the state change interrupt
  * works..)
  */
-static int socket_thread(void * data)
+static int yenta_socket_thread(void * data)
 {
 	pci_socket_t * socket = (pci_socket_t *) data;
 	DECLARE_WAITQUEUE(wait, current);
@@ -457,20 +452,10 @@
 	int i;
 	unsigned long val;
 	u16 bridge_ctrl;
+	u32 mask;
 
-	/* Are we set up to route the IO irq to the PCI irq? */
+	/* Set up ISA irq routing to probe the ISA irqs.. */
 	bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
-	if (socket->cb_irq) {
-		if (bridge_ctrl & CB_BRIDGE_INTR) {
-			bridge_ctrl &= ~CB_BRIDGE_INTR;
-			config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
-		}
-		printk("CardBus: using PCI interrupt %d\n", socket->cb_irq);
-		return 1 << socket->cb_irq;
-	}
-
-	/* Uhhuh. No PCI interrupt: try falling back on ISA interrupts */
-	printk("CardBus: Hmm.. No PCI irq routing (irq%d).\n", socket->cb_irq);
 	if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
 		bridge_ctrl |= CB_BRIDGE_INTR;
 		config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
@@ -492,7 +477,13 @@
 		cb_writel(socket, CB_SOCKET_EVENT, -1);
 	}
 	cb_writel(socket, CB_SOCKET_MASK, 0);
-	return probe_irq_mask(val) & 0xffff;
+	
+	mask = probe_irq_mask(val) & 0xffff;
+
+	bridge_ctrl &= ~CB_BRIDGE_INTR;
+	config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
+
+	return mask;
 }
 
 static void yenta_clear_maps(pci_socket_t *socket)
@@ -516,6 +507,7 @@
 /* Called at resume and initialization events */
 static int yenta_init(pci_socket_t *socket)
 {
+	u16 bridge;
 	struct pci_dev *dev = socket->dev;
 
 	pci_set_power_state(socket->dev, 0);
@@ -536,6 +528,19 @@
 	config_writeb(socket, PCI_SECONDARY_BUS, dev->subordinate->number);
 	config_writeb(socket, PCI_SUBORDINATE_BUS, dev->subordinate->number);
 
+	/*
+	 * Set up the bridging state:
+	 *  - enable write posting.
+	 *  - memory window 0 prefetchable, window 1 non-prefetchable
+	 *  - PCI interrupts enabled if a PCI interrupt exists..
+	 */
+	bridge = config_readw(socket, CB_BRIDGE_CONTROL);
+	bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
+	bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
+	if (!socket->cb_irq)
+		bridge |= CB_BRIDGE_INTR;
+	config_writew(socket, CB_BRIDGE_CONTROL, bridge);
+
 	exca_writeb(socket, I365_GBLCTL, 0x00);
 	exca_writeb(socket, I365_GENCTL, 0x00);
 
@@ -543,29 +548,6 @@
 	return 0;
 }
 
-/*
- * More of an example than anything else... The standard
- * yenta init code works well enough - but this is how
- * you'd do it if you wanted to have a special init sequence.
- */
-static int ricoh_init(pci_socket_t *socket)
-{
-	u16 misc = config_readw(socket, RL5C4XX_MISC);
-	u16 ctl = config_readw(socket, RL5C4XX_16BIT_CTL);
-	u16 io = config_readw(socket, RL5C4XX_16BIT_IO_0);
-	u16 mem = config_readw(socket, RL5C4XX_16BIT_MEM_0);
-
-	ctl = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
-
-	config_writew(socket, RL5C4XX_MISC, misc);
-	config_writew(socket, RL5C4XX_16BIT_CTL, ctl);
-	config_writew(socket, RL5C4XX_16BIT_IO_0, io);
-	config_writew(socket, RL5C4XX_16BIT_MEM_0, mem);
-
-	return yenta_init(socket);
-}
-
-
 static int yenta_suspend(pci_socket_t *socket)
 {
 	yenta_set_socket(socket, &dead_socket);
@@ -585,7 +567,7 @@
 	socket->cap.cb_dev = socket->dev;
 	socket->cap.bus = NULL;
 
-	printk("Yenta IRQ list %04x\n", socket->cap.irq_mask);
+	printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq);
 }
 
 static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
@@ -618,11 +600,11 @@
 	}
 
 	align = size = 4*1024*1024;
-	min = 0x10000000; max = ~0U;
+	min = PCIBIOS_MIN_MEM; max = ~0U;
 	if (type & IORESOURCE_IO) {
 		align = 1024;
 		size = 256;
-		min = 0x1000;
+		min = PCIBIOS_MIN_IO;
 		max = 0xffff;
 	}
 		
@@ -644,12 +626,50 @@
 }
 
 /*
+ * Close it down - release our resources and go home..
+ */
+static void yenta_close(pci_socket_t *sock)
+{
+	if (sock->cb_irq)
+		free_irq(sock->cb_irq, sock);
+	if (sock->base)
+		iounmap(sock->base);
+}
+
+#include "ti113x.h"
+#include "ricoh.h"
+
+/*
+ * Different cardbus controllers have slightly different
+ * initialization sequences etc details. List them here..
+ */
+#define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y
+static struct cardbus_override_struct {
+	unsigned short vendor;
+	unsigned short device;
+	struct pci_socket_ops *op;
+} cardbus_override[] = {
+	{ PD(TI,1130),	&ti113x_ops },
+	{ PD(TI,1131),	&ti113x_ops },
+	{ PD(TI,1250),	&ti1250_ops },
+
+	{ PD(RICOH,RL5C465), &ricoh_ops },
+	{ PD(RICOH,RL5C466), &ricoh_ops },
+	{ PD(RICOH,RL5C475), &ricoh_ops },
+	{ PD(RICOH,RL5C476), &ricoh_ops },
+	{ PD(RICOH,RL5C478), &ricoh_ops }
+};
+
+#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))
+
+/*
  * Initialize a cardbus controller. Make sure we have a usable
  * interrupt, and that we can map the cardbus area. Fill in the
  * socket information structure..
  */
 static int yenta_open(pci_socket_t *socket)
 {
+	int i;
 	struct pci_dev *dev = socket->dev;
 
 	/*
@@ -684,23 +704,25 @@
 	/* And figure out what the dang thing can do for the PCMCIA layer... */
 	yenta_get_socket_capabilities(socket);
 
-	kernel_thread(socket_thread, socket, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+	/* Do we have special options for the device? */
+	for (i = 0; i < NR_OVERRIDES; i++) {
+		struct cardbus_override_struct *d = cardbus_override+i;
+		if (dev->vendor == d->vendor && dev->device == d->device) {
+			socket->op = d->op;
+			if (d->op->open) {
+				int retval = d->op->open(socket);
+				if (retval < 0)
+					return retval;
+			}
+		}
+	}
+
+	kernel_thread(yenta_socket_thread, socket, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 	printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
 	return 0;
 }
 
 /*
- * Close it down - release our resources and go home..
- */
-static void yenta_close(pci_socket_t *sock)
-{
-	if (sock->cb_irq)
-		free_irq(sock->cb_irq, sock);
-	if (sock->base)
-		iounmap(sock->base);
-}
-
-/*
  * Standard plain cardbus - no frills, no extensions
  */
 struct pci_socket_ops yenta_operations = {
@@ -708,7 +730,6 @@
 	yenta_close,
 	yenta_init,
 	yenta_suspend,
-	yenta_inquire,
 	yenta_get_status,
 	yenta_get_socket,
 	yenta_set_socket,
@@ -728,7 +749,6 @@
 	yenta_close,
 	ricoh_init,
 	yenta_suspend,
-	yenta_inquire,
 	yenta_get_status,
 	yenta_get_socket,
 	yenta_set_socket,
diff -u --recursive --new-file v2.3.39/linux/drivers/pnp/Makefile linux/drivers/pnp/Makefile
--- v2.3.39/linux/drivers/pnp/Makefile	Tue Jan 11 22:31:41 2000
+++ linux/drivers/pnp/Makefile	Thu Jan 13 16:53:52 2000
@@ -12,16 +12,26 @@
 MOD_SUB_DIRS := $(SUB_DIRS)
 ALL_SUB_DIRS := $(SUB_DIRS)
 
-ifeq ($(CONFIG_ISAPNP),m)
-M_OBJS   := isa-pnp.o
+PROC_OBJS :=
+
+ifdef CONFIG_PROC_FS
+PROC_OBJS   += isapnp_proc.o
 endif
 
-O_TARGET := isa-pnp.o
-OX_OBJS  := isapnp.o
-O_OBJS   := quirks.o
+ifeq ($(CONFIG_ISAPNP),m)
+	M_OBJS   := isa-pnp.o
+	MIX_OBJS := isapnp.o
+	MI_OBJS  := quirks.o $(PROC_OBJS)
+endif
 
-ifdef CONFIG_PROC_FS
-O_OBJS   += isapnp_proc.o
+ifeq ($(CONFIG_ISAPNP),y)
+	O_TARGET := isa-pnp.o
+	OX_OBJS  := isapnp.o
+	O_OBJS   := quirks.o $(PROC_OBJS)
 endif
 
+
 include $(TOPDIR)/Rules.make
+
+isa-pnp.o: isapnp.o quirks.o $(PROC_OBJS)
+	$(LD) $(LD_RFLAG) -r -o $@ isapnp.o quirks.o $(PROC_OBJS)
diff -u --recursive --new-file v2.3.39/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c
--- v2.3.39/linux/drivers/pnp/isapnp.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/pnp/isapnp.c	Fri Jan 14 15:44:26 2000
@@ -18,7 +18,7 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  Changelog:
- *  2000-01-01	Added ISAPnP quirks handling
+ *  2000-01-01	Added quirks handling for buggy hardware
  *		Peter Denison <peterd@pnd-pc.demon.co.uk>
  */
 
@@ -984,6 +984,7 @@
 		card->device = (header[3] << 8) | header[2];
 		card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];
 		isapnp_checksum_value = 0x00;
+		INIT_LIST_HEAD(&card->children);
 		INIT_LIST_HEAD(&card->devices);
 		isapnp_parse_resource_map(card);
 		if (isapnp_checksum_value != 0x00)
@@ -1185,10 +1186,11 @@
 		struct list_head *list;
 
 		list = card->devices.next;
-		if (from)
+		if (from) {
 			list = from->bus_list.next;
-		if (from->bus != card)	/* something is wrong */
-			return NULL;
+			if (from->bus != card)	/* something is wrong */
+				return NULL;
+		}
 		while (list != &card->devices) {
 			int idx;
 			struct pci_dev *dev = pci_dev_b(list);
@@ -1765,8 +1767,8 @@
       	mem = cfg->mem[idx];
       	if (!mem)
       		return -EINVAL;
-      	value1 = &cfg->result.resource[idx].start;
-      	value2 = &cfg->result.resource[idx].end;
+      	value1 = &cfg->result.resource[idx + 8].start;
+      	value2 = &cfg->result.resource[idx + 8].end;
 	if (cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO) {
 		cfg->result.resource[idx + 8].flags &= ~IORESOURCE_AUTO;
 		*value1 = mem->min;
@@ -1777,7 +1779,7 @@
 	do {
 		*value1 += mem->align;
 		*value2 = *value1 + mem->size - 1;
-		if (*value1 >= 8 || !mem->align) {
+		if (*value1 > mem->max || !mem->align) {
 			if (mem->res && mem->res->alt) {
 				if ((err = isapnp_alternative_switch(cfg, mem->res, mem->res->alt))<0)
 					return err;
diff -u --recursive --new-file v2.3.39/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c
--- v2.3.39/linux/drivers/pnp/isapnp_proc.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/pnp/isapnp_proc.c	Fri Jan 14 11:21:50 2000
@@ -42,6 +42,8 @@
 typedef struct isapnp_info_buffer isapnp_info_buffer_t;
 
 static struct proc_dir_entry *isapnp_proc_entry = NULL;
+static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
+static struct proc_dir_entry *isapnp_proc_devices_entry = NULL;
 
 static void isapnp_info_read(isapnp_info_buffer_t *buffer);
 static void isapnp_info_write(isapnp_info_buffer_t *buffer);
@@ -67,6 +69,18 @@
 	return res;
 }
 
+static void isapnp_devid(char *str, unsigned short vendor, unsigned short device)
+{
+	sprintf(str, "%c%c%c%x%x%x%x",
+			'A' + ((vendor >> 2) & 0x3f) - 1,
+			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+			'A' + ((vendor >> 8) & 0x1f) - 1,
+			(device >> 4) & 0x0f,
+			device & 0x0f,
+			(device >> 12) & 0x0f,
+			(device >> 8) & 0x0f);
+}
+
 static loff_t isapnp_info_entry_lseek(struct file *file, loff_t offset, int orig)
 {
 	switch (orig) {
@@ -186,17 +200,6 @@
 	return POLLIN | POLLRDNORM;
 }
 
-static int isapnp_info_entry_ioctl(struct inode *inode, struct file *file,
-				   unsigned int cmd, unsigned long arg)
-{
-	return -EINVAL;
-}
-
-static int isapnp_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	return -ENXIO;
-}
-
 static struct file_operations isapnp_info_entry_operations =
 {
 	isapnp_info_entry_lseek,	/* lseek */
@@ -204,8 +207,8 @@
 	isapnp_info_entry_write,	/* write */
 	NULL,				/* readdir */
 	isapnp_info_entry_poll,		/* poll */
-	isapnp_info_entry_ioctl,	/* ioctl - default */
-	isapnp_info_entry_mmap,		/* mmap */
+	NULL,				/* ioctl - default */
+	NULL,				/* mmap */
 	isapnp_info_entry_open,		/* open */
 	NULL,				/* flush */
 	isapnp_info_entry_release,	/* release */
@@ -219,24 +222,210 @@
 	&isapnp_info_entry_operations,	/* default sound info directory file-ops */
 };
 
+static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
+{
+	loff_t new;
+	
+	switch (whence) {
+	case 0:
+		new = off;
+		break;
+	case 1:
+		new = file->f_pos + off;
+		break;
+	case 2:
+		new = 256 + off;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (new < 0 || new > 256)
+		return -EINVAL;
+	return (file->f_pos = new);
+}
+
+static ssize_t isapnp_proc_bus_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+	struct inode *ino = file->f_dentry->d_inode;
+	struct proc_dir_entry *dp = ino->u.generic_ip;
+	struct pci_dev *dev = dp->data;
+	int pos = *ppos;
+	int cnt, size = 256;
+
+	if (pos >= size)
+		return 0;
+	if (nbytes >= size)
+		nbytes = size;
+	if (pos + nbytes > size)
+		nbytes = size - pos;
+	cnt = nbytes;
+
+	if (!access_ok(VERIFY_WRITE, buf, cnt))
+		return -EINVAL;
+		
+	isapnp_cfg_begin(dev->bus->number, dev->devfn);
+	for ( ; pos < 256 && cnt > 0; pos++, buf++, cnt--) {
+		unsigned char val;
+		val = isapnp_read_byte(pos);
+		__put_user(val, buf);
+	}
+	isapnp_cfg_end();
+	
+	*ppos = pos;
+	return nbytes;
+}
+
+static struct file_operations isapnp_proc_bus_file_operations =
+{
+	isapnp_proc_bus_lseek,		/* lseek */
+	isapnp_proc_bus_read,		/* read */
+	NULL,				/* write */
+	NULL,				/* readdir */
+	NULL,				/* poll */
+	NULL,				/* ioctl - default */
+	NULL,				/* mmap */
+	NULL,				/* open */
+	NULL,				/* flush */
+	NULL,				/* release */
+	NULL,				/* can't fsync */
+	NULL,				/* fasync */
+	NULL,				/* lock */
+};
+
+static struct inode_operations isapnp_proc_bus_inode_operations =
+{
+	&isapnp_proc_bus_file_operations,
+};
+
+static int isapnp_proc_attach_device(struct pci_dev *dev)
+{
+	struct pci_bus *bus = dev->bus;
+	struct proc_dir_entry *de, *e;
+	char name[16];
+
+	if (!(de = bus->procdir)) {
+		sprintf(name, "%02x", bus->number);
+		de = bus->procdir = proc_mkdir(name, isapnp_proc_bus_dir);
+		if (!de)
+			return -ENOMEM;
+	}
+	sprintf(name, "%02x", dev->devfn);
+	e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO, de);
+	if (!e)
+		return -ENOMEM;
+	e->ops = &isapnp_proc_bus_inode_operations;
+	e->data = dev;
+	e->size = 256;
+	return 0;
+}
+
+#ifdef MODULE
+static int __exit isapnp_proc_detach_device(struct pci_dev *dev)
+{
+	struct pci_bus *bus = dev->bus;
+	struct proc_dir_entry *de;
+	char name[16];
+
+	if (!(de = bus->procdir))
+		return -EINVAL;
+	sprintf(name, "%02x", dev->devfn);
+	remove_proc_entry(name, de);
+	return 0;
+}
+
+static int __exit isapnp_proc_detach_bus(struct pci_bus *bus)
+{
+	struct proc_dir_entry *de;
+	char name[16];
+
+	if (!(de = bus->procdir))
+		return -EINVAL;
+	sprintf(name, "%02x", bus->number);
+	remove_proc_entry(name, isapnp_proc_bus_dir);
+	return 0;
+}
+#endif
+
+static int isapnp_proc_read_devices(char *buf, char **start, off_t pos, int count)
+{
+	struct pci_dev *dev;
+	off_t at = 0;
+	int len, cnt, i;
+	
+	cnt = 0;
+	isapnp_for_each_dev(dev) {
+		char bus_id[8], device_id[8];
+	
+		isapnp_devid(bus_id, dev->bus->vendor, dev->bus->device);
+		isapnp_devid(device_id, dev->vendor, dev->device);
+		len = sprintf(buf, "%02x%02x\t%s%s\t",
+			dev->bus->number,
+			dev->devfn,
+			bus_id,
+			device_id);
+		isapnp_cfg_begin(dev->bus->number, dev->devfn);
+		len += sprintf(buf+len, "%02x", isapnp_read_byte(ISAPNP_CFG_ACTIVATE));
+		for (i = 0; i < 8; i++)
+			len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)));
+		for (i = 0; i < 2; i++)
+			len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)));
+		for (i = 0; i < 2; i++)
+			len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_DMA + i));
+		for (i = 0; i < 4; i++)
+			len += sprintf(buf+len, "%08x", isapnp_read_dword(ISAPNP_CFG_MEM + (i << 3)));
+		isapnp_cfg_end();
+		buf[len++] = '\n';
+		at += len;
+		if (at >= pos) {
+			if (!*start) {
+				*start = buf + (pos - (at - len));
+				cnt = at - pos;
+			} else
+				cnt += len;
+			buf += len;
+		}
+	}
+	return (count > cnt) ? cnt : count;
+}
+
 int __init isapnp_proc_init(void)
 {
 	struct proc_dir_entry *p;
+	struct pci_dev *dev;
 
 	isapnp_proc_entry = NULL;
 	p = create_proc_entry("isapnp", S_IFREG | S_IRUGO | S_IWUSR, &proc_root);
-	if (!p)
-		return -ENOMEM;
-	p->ops = &isapnp_info_entry_inode_operations;
+	if (p)
+		p->ops = &isapnp_info_entry_inode_operations;
 	isapnp_proc_entry = p;
+	isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus);
+	isapnp_proc_devices_entry = create_proc_info_entry("devices", 0,
+							   isapnp_proc_bus_dir,
+							   isapnp_proc_read_devices);
+	isapnp_for_each_dev(dev) {
+		isapnp_proc_attach_device(dev);
+	}
 	return 0;
 }
 
 #ifdef MODULE
-int isapnp_proc_done(void)
+int __exit isapnp_proc_done(void)
 {
+	struct pci_dev *dev;
+	struct pci_bus *card;
+
+	isapnp_for_each_dev(dev) {
+		isapnp_proc_detach_device(dev);
+	}
+	isapnp_for_each_card(card) {
+		isapnp_proc_detach_bus(card);
+	}
+	if (isapnp_proc_devices_entry)
+		remove_proc_entry("devices", isapnp_proc_devices_entry);
+	if (isapnp_proc_bus_dir)
+		remove_proc_entry("isapnp", proc_bus);
 	if (isapnp_proc_entry)
-		remove_proc_entry("isapnp",&proc_root);
+		remove_proc_entry("isapnp", &proc_root);
 	return 0;
 }
 #endif /* MODULE */
@@ -249,14 +438,7 @@
 {
 	char tmp[8];
 	
-	sprintf(tmp, "%c%c%c%x%x%x%x",
-			'A' + ((vendor >> 2) & 0x3f) - 1,
-			'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
-			'A' + ((vendor >> 8) & 0x1f) - 1,
-			(device >> 4) & 0x0f,
-			device & 0x0f,
-			(device >> 12) & 0x0f,
-			(device >> 8) & 0x0f);
+	isapnp_devid(tmp, vendor, device);
 	isapnp_printf(buffer, tmp);
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/pnp/quirks.c linux/drivers/pnp/quirks.c
--- v2.3.39/linux/drivers/pnp/quirks.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/pnp/quirks.c	Fri Jan 14 11:21:50 2000
@@ -16,6 +16,8 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/isapnp.h>
+#include <linux/string.h>
+
 
 static void __init quirk_awe32_resources(struct pci_dev *dev)
 {
@@ -55,6 +57,10 @@
 static struct isapnp_fixup isapnp_fixups[] __initdata = {
 	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0021),
 		quirk_awe32_resources },
+	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0022),
+		quirk_awe32_resources },
+	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0023),
+		quirk_awe32_resources },
 	{ 0 }
 };
 
@@ -65,8 +71,8 @@
 	while (isapnp_fixups[i].vendor != 0) {
 		if ((isapnp_fixups[i].vendor == dev->vendor) &&
 		    (isapnp_fixups[i].device == dev->device)) {
-			printk(KERN_DEBUG "PnP: Calling quirk for %s\n",
-			       dev->slot_name);
+			printk(KERN_DEBUG "PnP: Calling quirk for %02x:%02x\n",
+			       dev->bus->number, dev->devfn);
 			isapnp_fixups[i].quirk_function(dev);
 		}
 		i++;
diff -u --recursive --new-file v2.3.39/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
--- v2.3.39/linux/drivers/sbus/char/envctrl.c	Wed Dec 29 13:13:17 1999
+++ linux/drivers/sbus/char/envctrl.c	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: envctrl.c,v 1.13 1999/12/19 23:28:07 davem Exp $
+/* $Id: envctrl.c,v 1.14 2000/01/09 15:43:45 ecd Exp $
  * envctrl.c: Temperature and Fan monitoring on Machines providing it.
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -29,8 +29,8 @@
 #undef U450_SUPPORT		/* might fry you machine, careful here !!! */
 
 
-#define DEBUG		1
-#define DEBUG_BUS_SCAN	1
+#undef DEBUG
+#undef DEBUG_BUS_SCAN
 
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v2.3.39/linux/drivers/scsi/fdomain.c	Wed Dec 29 13:13:18 1999
+++ linux/drivers/scsi/fdomain.c	Thu Jan 20 10:44:46 2000
@@ -879,6 +879,8 @@
    int              retcode;
    struct Scsi_Host *shpnt;
 #if DO_DETECT
+   int i = 0;
+   int j = 0;
    const int        buflen = 255;
    Scsi_Cmnd        SCinit;
    unsigned char    do_inquiry[] =       { INQUIRY, 0, 0, 0, buflen, 0 };
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c
--- v2.3.39/linux/drivers/scsi/g_NCR5380.c	Tue Dec 14 01:27:24 1999
+++ linux/drivers/scsi/g_NCR5380.c	Thu Jan 20 10:44:46 2000
@@ -165,21 +165,25 @@
 	    printk("generic_NCR5380_setup : usage ncr5380=" STRVAL(NCR5380_map_name) ",irq,dma\n");
 	    return;
 	}
+	break;
     case BOARD_NCR53C400:
 	if (ints[0] != 2) {
 	    printk("generic_NCR53C400_setup : usage ncr53c400=" STRVAL(NCR5380_map_name) ",irq\n");
 	    return;
 	}
+	break;
     case BOARD_NCR53C400A:
 	if (ints[0] != 2) {
 	    printk("generic_NCR53C400A_setup : usage ncr53c400a=" STRVAL(NCR5380_map_name) ",irq\n");
 	    return;
 	}
+	break;
     case BOARD_DTC3181E:
 	if (ints[0] != 2) {
 	    printk("generic_DTC3181E_setup : usage dtc3181e=" STRVAL(NCR5380_map_name) ",irq\n");
 	    return;
 	}
+	break;
     }
 
     if (commandline_current < NO_OVERRIDES) {
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- v2.3.39/linux/drivers/scsi/ide-scsi.c	Tue Jan  4 13:57:17 2000
+++ linux/drivers/scsi/ide-scsi.c	Mon Jan 17 22:22:52 2000
@@ -31,6 +31,7 @@
 
 #define IDESCSI_VERSION "0.9"
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -579,6 +580,17 @@
 	for (i = 0; media[i] != 255; i++) {
 		failed = 0;
 		while ((drive = ide_scan_devices (media[i], idescsi_driver.name, NULL, failed++)) != NULL) {
+
+#ifndef CONFIG_BLK_DEV_IDETAPE
+			/*
+			 * The Onstream DI-30 does not handle clean emulation, yet.
+			 */
+			if (strstr(drive->id->model, "OnStream DI-30")) {
+				printk("ide-tape: ide-scsi emulation is not supported for %s.\n", drive->id->model);
+				continue;
+			}
+#endif /* CONFIG_BLK_DEV_IDETAPE */
+
 			if ((scsi = (idescsi_scsi_t *) kmalloc (sizeof (idescsi_scsi_t), GFP_KERNEL)) == NULL) {
 				printk (KERN_ERR "ide-scsi: %s: Can't allocate a scsi structure\n", drive->name);
 				continue;
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.3.39/linux/drivers/scsi/megaraid.c	Thu Jan  6 12:57:47 2000
+++ linux/drivers/scsi/megaraid.c	Thu Jan 20 10:44:46 2000
@@ -9,7 +9,7 @@
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Version : 1.04
+ * Version : 1.05
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
@@ -111,6 +111,16 @@
  *    The addtional 32 bit field for 64bit address in the newly defined
  *      mailbox64 structure is set to 0 at this point.
  *
+ * Version 1.05
+ *    Changed the queing implementation for handling SCBs and completed
+ *      commands.
+ *    Added spinlocks in the interrupt service routine to enable the dirver
+ *      function in the SMP environment.
+ *    Fixed the problem of unnecessary aborts in the abort entry point, which
+ *      also enables the driver to handle large amount of I/O requests for
+ *      long duration of time.
+ *
+ *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
  *     fails to detect the controller as a pci device on the system.
@@ -125,7 +135,8 @@
 #define CRLFSTR "\n"
 #define IOCTL_CMD_NEW  0x81
 
-#define MEGARAID_VERSION "v1.04 (August 16, 1999)"
+#define MEGARAID_VERSION "v1.05 (October 27, 1999)"
+
 
 #include <linux/version.h>
 
@@ -143,8 +154,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/malloc.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
@@ -181,31 +190,6 @@
 #define MAX_SERBUF 160
 #define COM_BASE 0x2f8
 
-#define ENQUEUE(obj,type,list,next) \
-{ type **node; long cpuflag; \
-  spin_lock_irqsave(&mega_lock,cpuflag);\
-  for(node=&(list); *node; node=(type **)&(*node)->##next); \
-  (*node) = obj; \
-  (*node)->##next = NULL; \
-  spin_unlock_irqrestore(&mega_lock,cpuflag);\
-}
-
-/* a non-locking version (if we already have the lock) */
-#define ENQUEUE_NL(obj,type,list,next) \
-{ type **node; \
-  for(node=&(list); *node; node=(type **)&(*node)->##next); \
-  (*node) = obj; \
-  (*node)->##next = NULL; \
-}
-
-#define DEQUEUE(obj,type,list,next) \
-{ long cpuflag; \
-  spin_lock_irqsave(&mega_lock,cpuflag);\
-  if ((obj=list) != NULL) {\
-    list = (type *)(list)->##next; \
-  } \
-  spin_unlock_irqrestore(&mega_lock,cpuflag);\
-};
 
 u32 RDINDOOR (mega_host_config * megaCfg)
 {
@@ -239,19 +223,67 @@
 			 u_char * mboxData,
 			 mega_scb * scb,
 			 int intr);
-static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
 			 u32 * buffer, u32 * length);
 
 static int mega_busyWaitMbox(mega_host_config *);
 static void mega_runpendq (mega_host_config *);
-static void mega_rundoneq (void);
+static void mega_rundoneq (mega_host_config *);
 static void mega_cmd_done (mega_host_config *, mega_scb *, int);
 static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
-static inline void freeSgList(mega_host_config *megaCfg);
+static inline void mega_freeSgList(mega_host_config *megaCfg);
 static void mega_Convert8ldTo40ld(  mega_RAIDINQ  *inquiry,
                                     mega_Enquiry3 *enquiry3,
                                     megaRaidProductInfo *productInfo );
 
+
+
+
+
+#if LINUX_VERSION_CODE > 0x020100
+#  include <asm/spinlock.h>
+#  include <linux/smp.h>
+#  define cpuid smp_processor_id()
+#  if LINUX_VERSION_CODE < 0x020195
+#    define DRIVER_LOCK_T unsigned long cpu_flags = 0;
+#    define DRIVER_LOCK_INIT(p) \
+       spin_lock_init(&p->mega_lock);
+#    define DRIVER_LOCK(p) \
+       if(!p->cpu_lock_count[cpuid]) { \
+         spin_lock_irqsave(&p->mega_lock, cpu_flags); \
+         p->cpu_lock_count[cpuid]++; \
+       } else { \
+         p->cpu_lock_count[cpuid]++; \
+       }
+#    define DRIVER_UNLOCK(p) \
+       if(--p->cpu_lock_count[cpuid] == 0) \
+         spin_unlock_irqrestore(&p->mega_lock, cpu_flags);
+#    define IO_LOCK(p)   spin_lock_irqsave(&io_request_lock,cpu_flags);
+#    define IO_UNLOCK(p) spin_unlock_irqrestore(&io_request_lock,cpu_flags);
+#  else
+#    define DRIVER_LOCK_T
+#    define DRIVER_LOCK_INIT(p)
+#    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);
+#  endif
+#else
+#  define cpuid 0
+#  define DRIVER_LOCK_T long cpu_flags;
+#  define DRIVER_LOCK_INIT(p)
+#  define DRIVER_LOCK(p) \
+       save_flags(cpu_flags); \
+       cli();
+#  define DRIVER_UNLOCK(p) \
+       restore_flags(cpu_flags);
+#  define IO_LOCK(p)   DRIVER_LOCK(p)
+#  define IO_UNLOCK(p) DRIVER_UNLOCK(p)
+#  define le32_to_cpu(x) (x)
+#  define cpu_to_le32(x) (x)
+#endif
+
 /* set SERDEBUG to 1 to enable serial debugging */
 #define SERDEBUG 0
 #if SERDEBUG
@@ -286,13 +318,10 @@
 
 static mega_scb *pLastScb = NULL;
 
-/* Queue of pending/completed SCBs */
-static Scsi_Cmnd *qCompleted = NULL;
 
 #if SERDEBUG
 static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
 #endif
-static spinlock_t mega_lock = SPIN_LOCK_UNLOCKED;
 
 #if SERDEBUG
 static char strbuf[MAX_SERBUF + 1];
@@ -352,7 +381,7 @@
 #define TRACE(A)
 #endif
 
-void callDone (Scsi_Cmnd * SCpnt)
+static void callDone (Scsi_Cmnd * SCpnt)
 {
   if (SCpnt->result) {
     TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
@@ -372,37 +401,66 @@
  * Free a SCB structure
  *=======================
  */
-static void freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
+static void mega_freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
 {
-  mega_scb **ppScb;
+
+  mega_scb *pScbtmp;
+
+  if ((pScb == NULL) || (pScb->idx >= 0xFE)) {
+    return ;
+  }
 
   /* Unlink from pending queue */
-  for(ppScb=&megaCfg->qPending; *ppScb; ppScb=&(*ppScb)->next) {
-    if (*ppScb == pScb) {
-	*ppScb = pScb->next;
+
+  if(pScb == megaCfg->qPendingH) {
+    if(megaCfg->qPendingH == megaCfg->qPendingT ) 
+      megaCfg->qPendingH = megaCfg->qPendingT = NULL;
+    else {
+      megaCfg->qPendingH = megaCfg->qPendingH->next;
+    }
+    megaCfg->qPcnt--;
+  }
+  else {
+    for(pScbtmp=megaCfg->qPendingH; pScbtmp; pScbtmp=pScbtmp->next) {
+      if (pScbtmp->next == pScb) {
+        pScbtmp->next = pScb->next;
+        if(pScb == megaCfg->qPendingT) {
+          megaCfg->qPendingT = pScbtmp;
+        }
+        megaCfg->qPcnt--;
 	break;
     }
   }
+  }
 
-  /* Link back into list */
+  /* Link back into free list */
   pScb->state = SCB_FREE;
   pScb->SCpnt = NULL;
 
-  pScb->next     = megaCfg->qFree;
-  megaCfg->qFree = pScb;
+  if(megaCfg->qFreeH == (mega_scb *) NULL ) {
+    megaCfg->qFreeH = megaCfg->qFreeT = pScb;
+  }
+  else {
+    megaCfg->qFreeT->next  = pScb;
+    megaCfg->qFreeT = pScb;
+  }
+  megaCfg->qFreeT->next = NULL;
+  megaCfg->qFcnt++;
+
 }
 
 /*===========================
  * Allocate a SCB structure
  *===========================
  */
-static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
+static mega_scb * mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
 {
   mega_scb *pScb;
 
   /* Unlink command from Free List */
-  if ((pScb = megaCfg->qFree) != NULL) {
-    megaCfg->qFree = pScb->next;
+  if ((pScb = megaCfg->qFreeH) != NULL) {
+    megaCfg->qFreeH = pScb->next;
+    megaCfg->qFcnt--;
     
     pScb->isrcount = jiffies;
     pScb->next  = NULL;
@@ -421,62 +479,72 @@
  * Initialize SCB structures
  *================================================
  */
-static int initSCB (mega_host_config * megaCfg)
+static int mega_initSCB (mega_host_config * megaCfg)
 {
   int idx;
 
-  megaCfg->qFree = NULL;
+  megaCfg->qFreeH = NULL;
+  megaCfg->qFcnt = 0;
+#if DEBUG
+if(megaCfg->max_cmds >= MAX_COMMANDS) {
+printk("megaraid:ctlr max cmds = %x : MAX_CMDS = %x", megaCfg->max_cmds, MAX_COMMANDS);
+}
+#endif
+
   for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {
     megaCfg->scbList[idx].idx    = idx;
     megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
 					   GFP_ATOMIC | GFP_DMA);
     if (megaCfg->scbList[idx].sgList == NULL) {
       printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
-      freeSgList(megaCfg);
+      mega_freeSgList(megaCfg);
       return -1;
     }
     
     if (idx < MAX_COMMANDS) {
       /* Link to free list */
-      freeSCB(megaCfg, &megaCfg->scbList[idx]);
+      mega_freeSCB(megaCfg, &megaCfg->scbList[idx]);
     }
   }
   return 0;
 }
 
 /* Run through the list of completed requests */
-static void mega_rundoneq ()
+static void mega_rundoneq (mega_host_config *megaCfg)
 {
   Scsi_Cmnd *SCpnt;
 
-  while (1) {
-    DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
-    if (SCpnt == NULL)
-      return;
+  while ((SCpnt = megaCfg->qCompletedH) != NULL) {
+    megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
+    megaCfg->qCcnt--;
 
+    SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
     /* Callback */
     callDone (SCpnt);
   }
+  megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;
 }
 
 /*
-  Runs through the list of pending requests
-  Assumes that mega_lock spin_lock has been acquired.
-*/
+ * Runs through the list of pending requests
+ * Assumes that mega_lock spin_lock has been acquired.
+ */
 static void mega_runpendq(mega_host_config *megaCfg)
 {
   mega_scb *pScb;
 
   /* Issue any pending commands to the card */
-  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+  for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
     if (pScb->state == SCB_ACTIVE) {
-      megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1);
+      if(megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1))
+	return;
     }
   }
 }
 
 /* Add command to the list of completed requests */
-static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, 
+static void
+mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, 
 			   int status)
 {
   int islogical;
@@ -499,7 +567,7 @@
 	TRACE(("pScb->idx = ",pScb->idx));
 	TRACE(("pScb->state = ",pScb->state));
 	TRACE(("pScb->state = ",pScb->state));
-	printk("Problem...!\n");
+	printk("megaraid:Problem...!\n");
 	while(1);
   }
 
@@ -554,10 +622,18 @@
   /* not IOCTL_CMD_NEW SCB, freeSCB()*/
   /* For IOCTL_CMD_NEW SCB, delay freeSCB() in megaraid_queue()
    * after copy data back to user space*/
-     freeSCB(megaCfg, pScb);
+     mega_freeSCB(megaCfg, pScb);
 
   /* Add Scsi_Command to end of completed queue */
-  ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    if( megaCfg->qCompletedH == NULL ) {
+      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+    }
+    else {
+      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+      megaCfg->qCompletedT = SCpnt;
+   }
+   megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+   megaCfg->qCcnt++;
 }
 
 /*-------------------------------------------------------------------
@@ -627,7 +703,7 @@
     case READ_CAPACITY:
     case INQUIRY:
       /* Allocate a SCB and initialize passthru */
-      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+      if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
 	SCpnt->result = (DID_ERROR << 16);
 	callDone (SCpnt);
 	return NULL;
@@ -658,7 +734,7 @@
     case READ_10:
     case WRITE_10:
       /* Allocate a SCB and initialize mailbox */
-      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+      if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
 	SCpnt->result = (DID_ERROR << 16);
 	callDone (SCpnt);
 	return NULL;
@@ -694,7 +770,7 @@
       }
 
       /* Calculate Scatter-Gather info */
-      mbox->numsgelements = build_sglist (megaCfg, pScb,
+      mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
 					  (u32 *) & mbox->xferaddr,
 					  (u32 *) & seg);
 
@@ -713,7 +789,7 @@
    *-----------------------------------------------------*/
   else {
     /* Allocate a SCB and initialize passthru */
-    if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+    if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
       SCpnt->result = (DID_ERROR << 16);
       callDone (SCpnt);
       return NULL;
@@ -734,7 +810,7 @@
     pthru->cdblen = SCpnt->cmd_len;
     memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
-    pthru->numsgelements = build_sglist (megaCfg, pScb,
+    pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
 					 (u32 *) & pthru->dataxferaddr,
 					 (u32 *) & pthru->dataxferlen);
 
@@ -761,19 +837,12 @@
   unsigned char *data = (unsigned char *)SCpnt->request_buffer;
   int i;
 
-  if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+  if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
     SCpnt->result = (DID_ERROR << 16);
     callDone (SCpnt);
     return NULL;
   }
 
-#if 0
-  printk("\nBUF: ");
-  for (i=0;i<18;i++) {
-     printk(" %x",data[i]);
-  }
-  printk("......\n");
-#endif
 
   mboxdata = (u8 *) & pScb->mboxData;
   mbox = (mega_ioctl_mbox *) & pScb->mboxData;
@@ -797,7 +866,7 @@
     mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
     mailbox->xferaddr = virt_to_bus (pthru);
 
-    pthru->numsgelements = build_sglist (megaCfg, pScb,
+    pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
 					 (u32 *) & pthru->dataxferaddr,
 					 (u32 *) & pthru->dataxferlen);
 
@@ -856,7 +925,7 @@
   } 
   else {
 
-      mbox->numsgelements = build_sglist (megaCfg, pScb,
+      mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
 				      (u32 *) & mbox->xferaddr,
 				      (u32 *) & seg);
 
@@ -884,30 +953,32 @@
 }
 #endif
 
+#if DEBUG
+static unsigned int cum_time = 0;
+static unsigned int cum_time_cnt = 0;
+#endif
+
 /*--------------------------------------------------------------------
  * Interrupt service routine
  *--------------------------------------------------------------------*/
 static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 {
+  IO_LOCK_T
   mega_host_config    *megaCfg;
   u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
-  u32 dword;
+  u32 dword=0;
   mega_mailbox *mbox;
   mega_scb *pScb;
-  long flags;
-  int qCnt, qStatus;
+  u_char qCnt, qStatus;
+  u_char            completed[MAX_FIRMWARE_STATUS];
+  Scsi_Cmnd *SCpnt;
 
   megaCfg = (mega_host_config *) devp;
   mbox = (mega_mailbox *)tmpBox;
 
-  spin_lock_irqsave (&io_request_lock, flags);
-
-  while (megaCfg->host->irq == irq) {
-
-    spin_lock_irqsave (&mega_lock, flags);
-
+  if (megaCfg->host->irq == irq) {
     if (megaCfg->flag & IN_ISR) {
-      TRACE (("ISR called reentrantly!!\n"));
+      printk(KERN_ERR "ISR called reentrantly!!\n");
     }
 
     megaCfg->flag |= IN_ISR;
@@ -916,48 +987,73 @@
 	printk(KERN_WARNING "Error: mailbox busy in isr!\n");
     }
 
-
     /* Check if a valid interrupt is pending */
     if (megaCfg->flag & BOARD_QUARTZ) {
       dword = RDOUTDOOR (megaCfg);
       if (dword != 0x10001234) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-	spin_unlock_irqrestore (&mega_lock, flags);
-	break;
+//#if LINUX_VERSION_CODE >= 0x20100
+//        IO_UNLOCK;
+//#endif
+//	break;
+	return;
       }
-      WROUTDOOR (megaCfg, dword);
-
-      /* Copy to temp location */
-      memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
-
-      /* Acknowledge interrupt */
-      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
-      while (RDINDOOR (megaCfg) & 0x02);
     }
     else {
       byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
       if ((byte & VALID_INTR_BYTE) == 0) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-	spin_unlock_irqrestore (&mega_lock, flags);
-	break;
+//#if LINUX_VERSION_CODE >= 0x20100
+//	IO_UNLOCK;
+//#endif
+//	break;
+	return;
       }
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
+    }
+
+    for(idx=0;idx<MAX_FIRMWARE_STATUS;idx++ ) completed[idx] = 0;
+
+    IO_LOCK;
 
-      /* Copy to temp location */
-      memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+    qCnt = 0xff;
+    while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) 
+      ;
+
+    qStatus = 0xff;
+    while ((qStatus = megaCfg->mbox->status) == 0xFF)
+      ;
+
+    /* Get list of completed requests */
+    for (idx = 0; idx<qCnt; idx++) {
+      while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) {
+	printk("p");
+      }
+      completed[idx] = sIdx;
+      sIdx = 0xFF;
+    }
 
+    if (megaCfg->flag & BOARD_QUARTZ) {
+      WROUTDOOR (megaCfg, dword);
       /* Acknowledge interrupt */
+      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+      while (RDINDOOR (megaCfg) & 0x02);
+    }
+    else {
       CLEAR_INTR (megaCfg->host->io_port);
     }
 
-    qCnt = mbox->numstatus;
-    qStatus = mbox->status;
+#if DEBUG
+    if(qCnt >= MAX_FIRMWARE_STATUS) {
+      printk("megaraid_isr: cmplt=%d ", qCnt);
+    }
+#endif
 
     for (idx = 0; idx < qCnt; idx++) {
-      sIdx = mbox->completed[idx];
-      if (sIdx > 0) {
+      sIdx = completed[idx];
+      if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {
 	pScb = &megaCfg->scbList[sIdx - 1];
 
 	/* ASSERT(pScb->state == SCB_ISSUED); */
@@ -965,12 +1061,33 @@
 #if DEBUG
 	if (((jiffies) - pScb->isrcount) > maxCmdTime) {
 	  maxCmdTime = (jiffies) - pScb->isrcount;
-	  printk("cmd time = %u\n", maxCmdTime);
+	  printk("megaraid_isr : cmd time = %u\n", maxCmdTime);
 	}
 #endif
-
+/*
+ * Assuming that the scsi command, for which an abort request was received
+ * earlier has completed.
+ */
 	if (pScb->state == SCB_ABORTED) {
-	  printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
+          SCpnt = pScb->SCpnt;
+#if DEBUG
+printk("megaraid_isr:fcnt=%d, pcnt=%d, qcnt=%d\n",megaCfg->qFcnt, megaCfg->qPcnt, megaCfg->qCcnt); 
+#endif
+	}
+	if (pScb->state == SCB_RESET) {
+          SCpnt = pScb->SCpnt;
+	  mega_freeSCB (megaCfg, pScb);
+	  SCpnt->result = (DID_RESET << 16) ;
+          if( megaCfg->qCompletedH == NULL ) {
+            megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+          }
+          else {
+            megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+            megaCfg->qCompletedT = SCpnt;
+          }
+          megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+          megaCfg->qCcnt++;
+          continue;
 	}
 
         if (*(pScb->SCpnt->cmnd)==IOCTL_CMD_NEW) 
@@ -981,22 +1098,22 @@
 	mega_cmd_done(megaCfg, pScb, qStatus);
 
       }
-
+      else {
+        printk(KERN_ERR "megaraid: wrong cmd id completed from firmware:id=%x\n",sIdx);
+      }
     }
-    spin_unlock_irqrestore (&mega_lock, flags);
 
-    megaCfg->flag &= ~IN_ISR;
+    mega_rundoneq(megaCfg);
 
-    mega_rundoneq();
+    megaCfg->flag &= ~IN_ISR;
 
     /* Loop through any pending requests */
-    spin_lock_irqsave(&mega_lock, flags);
     mega_runpendq(megaCfg);
-    spin_unlock_irqrestore(&mega_lock,flags);
+#if LINUX_VERSION_CODE >= 0x20100
+    IO_UNLOCK;
+#endif
 
   }
-
-  spin_unlock_irqrestore (&io_request_lock, flags);
 }
 
 /*==================================================*/
@@ -1040,7 +1157,6 @@
   mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
   u_char byte;
   u32 cmdDone;
-  Scsi_Cmnd *SCpnt;
   u32 phys_mbox;
   u8 retval=-1;
 
@@ -1049,18 +1165,15 @@
 
   phys_mbox = virt_to_bus (megaCfg->mbox);
 
-#if 0
-  if (intr && mbox->busy) {
-    return 0;
-  }
-#endif
-
 #if DEBUG
   showMbox(pScb);
 #endif
 
   /* Wait until mailbox is free */
-  while (mega_busyWaitMbox (megaCfg)) {
+#if 0
+  while (mega_busyWaitMbox (megaCfg))
+#endif
+  if (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox......!!\n");
     udelay(1000);
 
@@ -1070,14 +1183,10 @@
     
     /* Abort command */
     if (pScb == NULL) {
-	printk("NULL pScb in megaIssue\n");
 	TRACE(("NULL pScb in megaIssue\n"));
+	printk("NULL pScb in megaIssue\n");
     }
-    SCpnt = pScb->SCpnt;
-    freeSCB(megaCfg, pScb);
-
-    SCpnt->result = (DID_ABORT << 16);
-    callDone(SCpnt);
+    mega_cmd_done (megaCfg, pScb, 0x08);
     return -1;
   }
 
@@ -1116,7 +1225,7 @@
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
-	mega_rundoneq ();
+//	mega_rundoneq (megaCfg);
       }
 
       WRINDOOR (megaCfg, phys_mbox | 0x2);
@@ -1130,26 +1239,26 @@
       while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID));
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
 
-
       ENABLE_INTR (megaCfg->host->io_port);
       CLEAR_INTR (megaCfg->host->io_port);
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
-	mega_rundoneq ();
+//	mega_rundoneq (megaCfg);
       }
       else {
 	TRACE (("Error: NULL pScb!\n"));
       }
-
     }
     enable_irq(megaCfg->host->irq);
     retval=mbox->status;
   }
+#if DEBUG
   while (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox on exit......!\n");
     udelay(1000);
   }
+#endif
 
   return retval;
 }
@@ -1157,7 +1266,7 @@
 /*-------------------------------------------------------------------
  * Copies data to SGLIST
  *-------------------------------------------------------------------*/
-static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
 	      u32 * buffer, u32 * length)
 {
   struct scatterlist *sgList;
@@ -1216,9 +1325,7 @@
   paddr = (paddr + 4 + 16) & 0xfffffff0;
 
   /* Register mailbox area with the firmware */
-  if (megaCfg->flag & BOARD_QUARTZ) {
-  }
-  else {
+  if (!(megaCfg->flag & BOARD_QUARTZ)) {
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
@@ -1276,7 +1383,6 @@
   u32 paddr;
   u8 retval;
 
-  spin_lock_init (&mega_lock);
 
   /* Initialize adapter inquiry mailbox*/
   paddr = virt_to_bus (megaCfg->mega_buffer);
@@ -1337,9 +1443,17 @@
     /*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1;*/ 
   megaCfg->host->max_lun =              /* max lun */
     (megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; 
+  megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
 
   megaCfg->numldrv = enquiry3Pnt->numLDrv;
   megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
+  if(megaCfg->max_cmds > MAX_COMMANDS) megaCfg->max_cmds = MAX_COMMANDS - 1;
+
+  megaCfg->host->can_queue   = megaCfg->max_cmds;
+
+  if (megaCfg->host->can_queue >= MAX_COMMANDS) {
+    megaCfg->host->can_queue = MAX_COMMANDS-1;
+  }
 
 #if 0 
   int i;
@@ -1405,7 +1519,7 @@
   return 0;
 }
 
-int findCard (Scsi_Host_Template * pHostTmpl,
+int mega_findCard (Scsi_Host_Template * pHostTmpl,
 	  u16 pciVendor, u16 pciDev,
 	  long flag)
 {
@@ -1429,6 +1543,21 @@
 	    pciDev,
 	    pdev->slot_name);
 
+    /*
+     *	Dont crash on boot with AMI cards configured for I2O. 
+     *  (our I2O code will find them then they will fail oddly until
+     *   we figure why they upset our I2O code). This driver will die
+     *   if it tries to boot an I2O mode board and we dont stop it now.
+     *     - Alan Cox , Red Hat Software, Jan 2000
+     */
+     	    
+    if((pdev->class >> 8) == PCI_CLASS_INTELLIGENT_I2O)
+    {
+    	printk( KERN_INFO "megaraid: Board configured for I2O, ignoring this card. Reconfigure the card\n"
+		KERN_INFO "megaraid: in the BIOS for \"mass storage\" to use it with this driver.\n");
+	continue;
+    }		
+
     /* Read the base port and IRQ from PCI */
     megaBase = pdev->resource[0].start;
     megaIrq  = pdev->irq;
@@ -1452,8 +1581,15 @@
 	    host->host_no, (u_int) megaBase, megaIrq);
 
     /* Copy resource info into structure */
-    megaCfg->qPending = NULL;
-    megaCfg->qFree    = NULL;
+    megaCfg->qCompletedH = NULL;
+    megaCfg->qCompletedT = NULL;
+    megaCfg->qPendingH = NULL;
+    megaCfg->qPendingT = NULL;
+    megaCfg->qFreeH    = NULL;
+    megaCfg->qFreeT    = NULL;
+    megaCfg->qFcnt = 0;
+    megaCfg->qPcnt = 0;
+    megaCfg->qCcnt = 0;
     megaCfg->flag = flag;
     megaCfg->host = host;
     megaCfg->base = megaBase;
@@ -1485,7 +1621,7 @@
     mega_i_query_adapter (megaCfg);
     
     /* Initialize SCBs */
-    if (initSCB (megaCfg)) {
+    if (mega_initSCB (megaCfg)) {
       scsi_unregister (host);
       continue;
     }
@@ -1511,9 +1647,9 @@
 
   printk ("megaraid: " MEGARAID_VERSION CRLFSTR);
 
-  count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
-  count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
-  count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+  count += mega_findCard (pHostTmpl, 0x101E, 0x9010, 0);
+  count += mega_findCard (pHostTmpl, 0x101E, 0x9060, 0);
+  count += mega_findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
 
   return count;
 }
@@ -1548,13 +1684,13 @@
     release_region (megaCfg->host->io_port, 16);
   }
 
-  freeSgList(megaCfg);
+  mega_freeSgList(megaCfg);
   scsi_unregister (pSHost);
 
   return 0;
 }
 
-static inline void freeSgList(mega_host_config *megaCfg)
+static inline void mega_freeSgList(mega_host_config *megaCfg)
 {
   int i;
 
@@ -1600,13 +1736,12 @@
  *-----------------------------------------------------------------*/
 int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
 {
+  DRIVER_LOCK_T
   mega_host_config *megaCfg;
   mega_scb *pScb;
-  long flags;
-
-  spin_lock_irqsave(&mega_lock,flags);
 
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
+  DRIVER_LOCK(megaCfg);
 
   if (!(megaCfg->flag & (1L << SCpnt->channel))) {
     if (SCpnt->channel < SCpnt->host->max_channel)
@@ -1623,33 +1758,69 @@
 
   /* If driver in abort or reset.. cancel this command */
   if (megaCfg->flag & IN_ABORT) {
+#if DEBUG
+printk("mq: got a request while in abort\n");
+#endif
     SCpnt->result = (DID_ABORT << 16);
-    ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    /* Add Scsi_Command to end of completed queue */
+    if( megaCfg->qCompletedH == NULL ) {
+      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+    }
+    else {
+      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+      megaCfg->qCompletedT = SCpnt;
+    }
+    megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+    megaCfg->qCcnt++;
 
-    spin_unlock_irqrestore(&mega_lock,flags);
+    DRIVER_UNLOCK(megaCfg);
     return 0;
   }
   else if (megaCfg->flag & IN_RESET) {
+#if DEBUG
+printk("mq: got a request while in reset\n");
+#endif
     SCpnt->result = (DID_RESET << 16);
-    ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    /* Add Scsi_Command to end of completed queue */
+    if( megaCfg->qCompletedH == NULL ) {
+      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+    }
+    else {
+      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+      megaCfg->qCompletedT = SCpnt;
+    }
+    megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+    megaCfg->qCcnt++;
 
-    spin_unlock_irqrestore(&mega_lock,flags);
+    DRIVER_UNLOCK(megaCfg);
     return 0;
   }
 
+  megaCfg->flag |= IN_QUEUE;
   /* Allocate and build a SCB request */
   if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
               /*build SCpnt for IOCTL_CMD_NEW cmd in mega_ioctl()*/
     /* Add SCB to the head of the pending queue */
-    ENQUEUE_NL (pScb, mega_scb, megaCfg->qPending, next);
-
-    /* Issue any pending command to the card if not in ISR */
-    if (!(megaCfg->flag & IN_ISR)) {
-      mega_runpendq(megaCfg);
+    /* Add SCB to the head of the pending queue */
+    if( megaCfg->qPendingH == NULL ) {
+      megaCfg->qPendingH = megaCfg->qPendingT = pScb;
     }
     else {
-      printk("IRQ pend...\n");
+      megaCfg->qPendingT->next = pScb;
+      megaCfg->qPendingT = pScb;
     }
+    megaCfg->qPendingT->next = NULL;
+    megaCfg->qPcnt++;
+
+
+    /* Issue any pending command to the card if not in ISR */
+//    if (!(megaCfg->flag & IN_ISR)) {
+      mega_runpendq(megaCfg);
+//    }
+/* 
+ * try running the pend queue, irrespective of the driver's context.
+ * -cn 
+ */
 
     if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
     {  /* user data from external user buffer */
@@ -1666,12 +1837,12 @@
 
           kfree(pScb->kern_area);
 
-          freeSCB(megaCfg, pScb);
+          mega_freeSCB(megaCfg, pScb);
     }
-
   }
 
-  spin_unlock_irqrestore(&mega_lock,flags);
+  megaCfg->flag &= ~IN_QUEUE;
+  DRIVER_UNLOCK(megaCfg);
 
   return 0;
 }
@@ -1709,41 +1880,70 @@
 /*---------------------------------------------------------------------
  * Abort a previous SCSI request
  *---------------------------------------------------------------------*/
-int megaraid_abort (Scsi_Cmnd * SCpnt)
+int
+megaraid_abort (Scsi_Cmnd * SCpnt)
 {
   mega_host_config *megaCfg;
-  int   rc, idx;
-  long  flags;
+  int   rc; //, idx;
   mega_scb *pScb;
 
-  rc = SCSI_ABORT_SUCCESS;
-
-  spin_lock_irqsave (&mega_lock, flags);
+  rc = SCSI_ABORT_NOT_RUNNING;
 
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   megaCfg->flag |= IN_ABORT;
 
-  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+#if DEBUG
+printk("ma:fcnt=%d, pcnt=%d, qcnt=%d\n",megaCfg->qFcnt, megaCfg->qPcnt, megaCfg->qCcnt); 
+#endif
+  for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
     if (pScb->SCpnt == SCpnt) {
       /* Found an aborting command */
 #if DEBUG
       showMbox(pScb);
 #endif
 
-      printk("Abort: %d %u\n", 
-	     SCpnt->timeout_per_command,
-	     (uint)((jiffies) - pScb->isrcount));
+/*
+ * If the command is queued to be issued to the firmware, abort the scsi cmd,
+ * If the command is already aborted in a previous call to the _abort entry
+ *  point, return SCSI_ABORT_SNOOZE, suggesting a reset.
+ * If the command is issued to the firmware, which might complete after
+ *  some time, we will mark the scb as aborted, and return to the mid layer, 
+ *  that abort could not be done.
+ *  In the ISR, when this command actually completes, we will perform a normal
+ *  completion.
+ *
+ * Oct 27, 1999
+ */
 
       switch(pScb->state) {
       case SCB_ABORTED: /* Already aborted */
 	rc = SCSI_ABORT_SNOOZE;
 	break;
       case SCB_ISSUED: /* Waiting on ISR result */
-	rc = SCSI_ABORT_PENDING;
+	rc = SCSI_ABORT_NOT_RUNNING;
 	pScb->state = SCB_ABORTED;
 	break;
+      case SCB_ACTIVE: /* still on the pending queue */
+	mega_freeSCB (megaCfg, pScb);
+	SCpnt->result = (DID_ABORT << 16) ;
+        if( megaCfg->qCompletedH == NULL ) {
+          megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+        }
+        else {
+          megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+          megaCfg->qCompletedT = SCpnt;
+        }
+        megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+        megaCfg->qCcnt++;
+	rc = SCSI_ABORT_SUCCESS;
+        break;
+      default:
+        printk("megaraid_abort: unknown command state!!\n");
+        rc = SCSI_ABORT_NOT_RUNNING;
+	break;
       }
+      break;
     }
   }
 
@@ -1761,26 +1961,29 @@
     }
   }
 #endif
-
-  /*
-   * Walk list of SCBs for any that are still outstanding
-   */
-  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
-    if (megaCfg->scbList[idx].state != SCB_FREE) {
-      if (megaCfg->scbList[idx].SCpnt == SCpnt) {
-	freeSCB (megaCfg, &megaCfg->scbList[idx]);
-
-	SCpnt->result = (DID_ABORT << 16) | (SUGGEST_RETRY << 24);
-	ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
-      }
-    }
-  }
-  
   megaCfg->flag &= ~IN_ABORT;
 
-  spin_unlock_irqrestore (&mega_lock, flags);
+#if DEBUG
+if(megaCfg->flag & IN_QUEUE)  printk("ma:flag is in queue\n");
+if(megaCfg->qCompletedH == NULL) printk("ma:qchead == null\n");
+#endif
+  
+/*
+ * This is required here to complete any completed requests to be communicated
+ * over to the mid layer.
+ * Calling just mega_rundoneq() did not work.
+ */
+if(megaCfg->qCompletedH) {
+  SCpnt = megaCfg->qCompletedH;
+  megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
+  megaCfg->qCcnt--;
+
+  SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
+  /* Callback */
+  callDone (SCpnt);
+}
+  mega_rundoneq(megaCfg);
 
-  mega_rundoneq();
 
   return rc;
 }
@@ -1792,14 +1995,18 @@
 {
   mega_host_config *megaCfg;
   int idx;
-  long flags;
-
-  spin_lock_irqsave (&mega_lock, flags);
+  int rc;
+  mega_scb *pScb;
 
+  rc = SCSI_RESET_NOT_RUNNING;
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   megaCfg->flag |= IN_RESET;
 
+  printk ("megaraid_RESET: %.08lx cmd=%.02x <c=%d.t=%d.l=%d>, flag = %x\n",
+	SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+	  SCpnt->lun, rstflags);
+
   TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
 	SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
 	  SCpnt->lun));
@@ -1810,20 +2017,18 @@
   for (idx = 0; idx < megaCfg->max_cmds; idx++) {
     if (megaCfg->scbList[idx].state != SCB_FREE) {
       SCpnt = megaCfg->scbList[idx].SCpnt;
+      pScb = &megaCfg->scbList[idx];
       if (SCpnt != NULL) {
-	freeSCB (megaCfg, &megaCfg->scbList[idx]);
-	SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
-	ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+        pScb->state = SCB_RESET;
+        break;
       }
     }
   }
 
   megaCfg->flag &= ~IN_RESET;
 
-  spin_unlock_irqrestore (&mega_lock, flags);
-
-  mega_rundoneq();
-  return SCSI_RESET_PUNT;
+  mega_rundoneq(megaCfg);
+  return rc;
 }
 
 /*-------------------------------------------------------------
@@ -1886,4 +2091,3 @@
 
 #include "scsi_module.c"
 #endif
-
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.3.39/linux/drivers/scsi/megaraid.h	Thu Nov 11 20:11:48 1999
+++ linux/drivers/scsi/megaraid.h	Thu Jan 20 16:07:26 2000
@@ -8,9 +8,11 @@
 #define IN_ISR                  0x80000000L
 #define IN_ABORT                0x40000000L
 #define IN_RESET                0x20000000L
+#define IN_QUEUE                0x10000000L
 #define BOARD_QUARTZ            0x08000000L
 #define BOARD_40LD              0x04000000L
 
+#ifndef HOSTS_C
 #define SCB_FREE     0x0
 #define SCB_ACTIVE   0x1
 #define SCB_WAITQ    0x2
@@ -18,12 +20,19 @@
 #define SCB_COMPLETE 0x4
 #define SCB_ABORTED  0x5
 #define SCB_RESET    0x6
+#endif
 
 #define MEGA_CMD_TIMEOUT        10
 
-#define MAX_SGLIST              17
-#define MAX_COMMANDS            250
+/* Feel free to fiddle with these.. max values are:
+   SGLIST     0..26
+   COMMANDS   0..253
+   CMDPERLUN  0..63
+*/
+#define MAX_SGLIST              0x1A
+#define MAX_COMMANDS            127
 #define MAX_CMD_PER_LUN         63
+#define MAX_FIRMWARE_STATUS     46
 
 #define MAX_LOGICAL_DRIVES      8
 #define MAX_CHANNEL             5
@@ -143,8 +152,8 @@
     sg_tablesize:     MAX_SGLIST,              /* Scatter/Gather Table Size */\
     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         */\
+    unchecked_isa_dma:1,                       /* Default Unchecked ISA DMA */\
+    use_clustering:   ENABLE_CLUSTERING        /* Enable Clustering         */\
   }
 #endif
 
@@ -505,7 +514,7 @@
     u32 dataxferlen;
 } mega_passthru;
 
-typedef struct _mega_mailbox {
+struct _mega_mailbox {
     /* 0x0 */ u8 cmd;
     /* 0x1 */ u8 cmdid;
     /* 0x2 */ u16 numsectors;
@@ -520,8 +529,9 @@
     /* 0x12 */ u8 completed[46];
     u8 mraid_poll;
     u8 mraid_ack;
-    u8 pad[16];
-} mega_mailbox;
+    u8 pad[16]; /* for alignment purposes */
+}__attribute__((packed));
+typedef struct _mega_mailbox mega_mailbox;
 
 typedef struct {
     u32 xferSegment;      /* for 64-bit controllers */
@@ -575,8 +585,16 @@
     u32 flag;
     u32 base;
  
-    mega_scb *qFree;
-    mega_scb *qPending;
+    mega_scb *qFreeH;
+    mega_scb *qFreeT;
+    mega_scb *qPendingH;
+    mega_scb *qPendingT;
+    
+    Scsi_Cmnd *qCompletedH;
+    Scsi_Cmnd *qCompletedT;
+    u32 qFcnt;
+    u32 qPcnt;
+    u32 qCcnt;
 
     u32 nReads[FC_MAX_LOGICAL_DRIVES];
     u32 nWrites[FC_MAX_LOGICAL_DRIVES];
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/psi240i.h linux/drivers/scsi/psi240i.h
--- v2.3.39/linux/drivers/scsi/psi240i.h	Thu Nov 11 20:11:48 1999
+++ linux/drivers/scsi/psi240i.h	Thu Jan 20 16:07:31 2000
@@ -211,6 +211,8 @@
 	}	READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
 
 // SCSI inquiry data
+#ifndef HOSTS_C
+
 typedef struct _INQUIRYDATA
 	{
 	UCHAR DeviceType			:5;
@@ -235,6 +237,7 @@
     UCHAR VendorSpecific[20];
     UCHAR Reserved3[40];
 	}	INQUIRYDATA, *PINQUIRYDATA;
+#endif
 
 // IDE IDENTIFY data
 typedef struct _IDENTIFY_DATA
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.3.39/linux/drivers/scsi/scsi.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/scsi/scsi.c	Thu Jan 20 15:15:22 2000
@@ -1768,14 +1768,24 @@
 {
 	struct Scsi_Host *host;
 	Scsi_Device *device;
+	unsigned long flags;
 
 	ASSERT_LOCK(&io_request_lock, 0);
 
 	host = SCpnt->host;
 	device = SCpnt->device;
 
+        /*
+         * We need to protect the decrement, as otherwise a race condition
+         * would exist.  Fiddling with SCpnt isn't a problem as the
+         * design only allows a single SCpnt to be active in only
+         * one execution context, but the device and host structures are
+         * shared.
+         */
+	spin_lock_irqsave(&io_request_lock, flags);
 	host->host_busy--;	/* Indicate that we are free */
 	device->device_busy--;	/* Decrement device usage counter. */
+	spin_unlock_irqrestore(&io_request_lock, flags);
 
         /*
          * Clear the flags which say that the device/host is no longer
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- v2.3.39/linux/drivers/scsi/scsi_lib.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/scsi/scsi_lib.c	Thu Jan 20 15:15:22 2000
@@ -947,23 +947,23 @@
 			 * get those allocated here.  
 			 */
 			if (!SDpnt->scsi_init_io_fn(SCpnt)) {
-				SHpnt->host_busy--;
-				SDpnt->device_busy--;
 				scsi_end_request(SCpnt, 0, 
 						 SCpnt->request.nr_sectors);
 				spin_lock_irq(&io_request_lock);
+				SHpnt->host_busy--;
+				SDpnt->device_busy--;
 				continue;
 			}
 			/*
 			 * Initialize the actual SCSI command for this request.
 			 */
 			if (!STpnt->init_command(SCpnt)) {
-				SHpnt->host_busy--;
-				SDpnt->device_busy--;
 				scsi_release_buffers(SCpnt);
 				scsi_end_request(SCpnt, 0, 
 						 SCpnt->request.nr_sectors);
 				spin_lock_irq(&io_request_lock);
+				SHpnt->host_busy--;
+				SDpnt->device_busy--;
 				continue;
 			}
 		}
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/scsi_queue.c linux/drivers/scsi/scsi_queue.c
--- v2.3.39/linux/drivers/scsi/scsi_queue.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/scsi/scsi_queue.c	Thu Jan 20 15:15:22 2000
@@ -79,6 +79,7 @@
 int scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason)
 {
 	struct Scsi_Host *host;
+	unsigned long flags;
 
 	SCSI_LOG_MLQUEUE(1, printk("Inserting command %p into mlqueue\n", cmd));
 
@@ -136,8 +137,10 @@
 	 * Decrement the counters, since these commands are no longer
 	 * active on the host/device.
 	 */
+	spin_lock_irqsave(&io_request_lock, flags);
 	cmd->host->host_busy--;
 	cmd->device->device_busy--;
+	spin_unlock_irqrestore(&io_request_lock, flags);
 
 	/*
 	 * Insert this command at the head of the queue for it's device.
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.3.39/linux/drivers/scsi/sd.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/scsi/sd.c	Tue Jan 18 18:54:21 2000
@@ -21,16 +21,6 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#ifdef MODULE
-/*
- * This is a variable in scsi.c that is set when we are processing something
- * after boot time.  By definition, this is true when we are a loadable module
- * ourselves.
- */
-#define MODULE_FLAG 1
-#else
-#define MODULE_FLAG scsi_loadable_module_flag
-#endif				/* MODULE */
 
 #include <linux/fs.h>
 #include <linux/kernel.h>
@@ -469,8 +459,6 @@
 	return 0;
 }
 
-static void sd_geninit(struct gendisk *);
-
 static struct block_device_operations sd_fops =
 {
 	open:			sd_open,
@@ -491,8 +479,6 @@
 	"sd",			/* Major name */
 	4,			/* Bits to shift to get real from partition */
 	1 << 4,			/* Number of partitions per real */
-	0,			/* maximum number of real */
-	sd_geninit,		/* init function */
 	NULL,			/* hd struct */
 	NULL,			/* block sizes */
 	0,			/* number */
@@ -505,15 +491,6 @@
 #define SD_GENDISK(i)    sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
 #define LAST_SD_GENDISK  sd_gendisks[N_USED_SD_MAJORS - 1]
 
-static void sd_geninit(struct gendisk *ignored)
-{
-	int i;
-
-	for (i = 0; i < sd_template.dev_max; ++i)
-		if (rscsi_disks[i].device)
-			sd[i << 4].nr_sects = rscsi_disks[i].capacity;
-}
-
 /*
  * rw_intr is the interrupt routine for the device driver.
  * It will be notified on the end of a SCSI read / write, and
@@ -1018,8 +995,6 @@
 		sd_gendisks[i].major_name = "sd";
 		sd_gendisks[i].minor_shift = 4;
 		sd_gendisks[i].max_p = 1 << 4;
-		sd_gendisks[i].max_nr = SCSI_DISKS_PER_MAJOR;
-		sd_gendisks[i].init = sd_geninit;
 		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].nr_real = 0;
@@ -1028,8 +1003,6 @@
 		    (void *) (rscsi_disks + i * SCSI_DISKS_PER_MAJOR);
 	}
 
-	LAST_SD_GENDISK.max_nr =
-	    (sd_template.dev_max - 1) % SCSI_DISKS_PER_MAJOR + 1;
 	LAST_SD_GENDISK.next = NULL;
 	return 0;
 }
@@ -1051,16 +1024,15 @@
 		gendisk_head = sd_gendisks;
 	}
 	for (i = 0; i < sd_template.dev_max; ++i)
-		if (!rscsi_disks[i].capacity &&
-		    rscsi_disks[i].device) {
-			if (MODULE_FLAG
-			    && !rscsi_disks[i].has_part_table) {
+		if (!rscsi_disks[i].capacity && rscsi_disks[i].device) {
+			sd_init_onedisk(i);
+			if (!rscsi_disks[i].has_part_table) {
 				sd_sizes[i << 4] = rscsi_disks[i].capacity;
-				/* revalidate does sd_init_onedisk via MAYBE_REINIT */
-				revalidate_scsidisk(MKDEV_SD(i), 0);
-			} else
-				i = sd_init_onedisk(i);
-			rscsi_disks[i].has_part_table = 1;
+				register_disk(&SD_GENDISK(i), MKDEV_SD(i),
+						1<<4, &sd_fops,
+						rscsi_disks[i].capacity);
+				rscsi_disks[i].has_part_table = 1;
+			}
 		}
 	/* If our host adapter is capable of scatter-gather, then we increase
 	 * the read-ahead to 60 blocks (120 sectors).  If not, we use
@@ -1175,11 +1147,8 @@
 	MAYBE_REINIT;
 #endif
 
-	sd_gendisks->part[start].nr_sects = CAPACITY;
-	if (!rscsi_disks[target].device)
-		return -EBUSY;
-	resetup_one_dev(&SD_GENDISK(target),
-			target % SCSI_DISKS_PER_MAJOR);
+	grok_partitions(&SD_GENDISK(target), target % SCSI_DISKS_PER_MAJOR,
+			1<<4, CAPACITY);
 
 	DEVICE_BUSY = 0;
 	return 0;
@@ -1216,6 +1185,7 @@
 				sd_gendisks->part[index].nr_sects = 0;
 				sd_sizes[index] = 0;
 			}
+			/* unregister_disk() */
 			dpnt->has_part_table = 0;
 			dpnt->device = NULL;
 			dpnt->capacity = 0;
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c
--- v2.3.39/linux/drivers/scsi/seagate.c	Tue Nov 23 22:42:21 1999
+++ linux/drivers/scsi/seagate.c	Thu Jan 20 10:48:35 2000
@@ -244,6 +244,10 @@
                                                    boards */
 static int irq = IRQ;
 
+MODULE_PARM(base_address, "i");
+MODULE_PARM(controller_type, "b");
+MODULE_PARM(irq, "i");
+
 #define retcode(result) (((result) << 16) | (message << 8) | status)
 #define STATUS ((u8) isa_readb(st0x_cr_sr))
 #define DATA ((u8) isa_readb(st0x_dr))
diff -u --recursive --new-file v2.3.39/linux/drivers/scsi/sym53c416.h linux/drivers/scsi/sym53c416.h
--- v2.3.39/linux/drivers/scsi/sym53c416.h	Thu Nov 11 20:11:49 1999
+++ linux/drivers/scsi/sym53c416.h	Thu Jan 20 16:07:26 2000
@@ -22,7 +22,9 @@
 #include <linux/version.h>
 #endif
 
+#ifndef LinuxVersionCode
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#endif
 
 #include <linux/types.h>
 #include <linux/kdev_t.h>
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.3.39/linux/drivers/sound/cmpci.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/cmpci.c	Thu Jan 20 10:44:46 2000
@@ -62,7 +62,7 @@
  *    18.08.99   1.5   Only deallocate DMA buffer when unloading.
  *    02.09.99   1.6   Enable SPDIF LOOP
  *                     Change the mixer read back
- *    21.09.99   2.33  Use RCS version aas driver version.
+ *    21.09.99   2.33  Use RCS version as driver version.
  *                     Add support for modem, S/PDIF loop and 4 channels.
  *                     (8738 only)
  *                     Fix bug cause x11amp cannot play.
@@ -2372,6 +2372,7 @@
 		init_waitqueue_head(&s->midi.iwait);
 		init_waitqueue_head(&s->midi.owait);
 		init_MUTEX(&s->open_sem);
+		spin_lock_init(&s->lock);
 		s->magic = CM_MAGIC;
 		s->iobase = pcidev->resource[0].start;
 		s->iosynth = 0x388;
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.3.39/linux/drivers/sound/es1370.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/es1370.c	Mon Jan 17 09:43:57 2000
@@ -114,6 +114,8 @@
  *    03.09.1999   0.30  change read semantics for MIDI to match
  *                       OSS more closely; remove possible wakeup race
  *    28.10.1999   0.31  More waitqueue races fixed
+ *    08.01.2000   0.32  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -1331,6 +1333,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	int val, mapped, ret;
 
 	VALIDATE_STATE(s);
@@ -1508,7 +1511,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
 		abinfo.fragsize = s->dma_dac2.fragsize;
-                abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count;
+		count = s->dma_dac2.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac2.dmasize - count;
                 abinfo.fragstotal = s->dma_dac2.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1522,7 +1528,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
 		abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1537,9 +1546,11 @@
 			return -EINVAL;
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
-                val = s->dma_dac2.count;
+                count = s->dma_dac2.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
@@ -1547,7 +1558,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1560,7 +1574,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
                 cinfo.bytes = s->dma_dac2.total_bytes;
-                cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift;
+		count = s->dma_dac2.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac2.fragshift;
                 cinfo.ptr = s->dma_dac2.hwptr;
 		if (s->dma_dac2.mapped)
 			s->dma_dac2.count &= s->dma_dac2.fragsize-1;
@@ -1853,6 +1870,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	unsigned ctrl;
 	int val, ret;
 
@@ -1961,7 +1979,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
 		abinfo.fragsize = s->dma_dac1.fragsize;
-                abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count;
+		count = s->dma_dac1.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac1.dmasize - count;
                 abinfo.fragstotal = s->dma_dac1.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1974,9 +1995,11 @@
         case SNDCTL_DSP_GETODELAY:
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
-                val = s->dma_dac1.count;
+                count = s->dma_dac1.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
@@ -1984,7 +2007,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1370_update_ptr(s);
                 cinfo.bytes = s->dma_dac1.total_bytes;
-                cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift;
+		count = s->dma_dac1.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac1.fragshift;
                 cinfo.ptr = s->dma_dac1.hwptr;
 		if (s->dma_dac1.mapped)
 			s->dma_dac1.count &= s->dma_dac1.fragsize-1;
@@ -2444,7 +2470,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.32 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
 		if (!RSRCISIOREGION(pcidev, 0))
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.3.39/linux/drivers/sound/es1371.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/es1371.c	Mon Jan 17 09:43:57 2000
@@ -96,6 +96,8 @@
  *                       detect ES137x chip and derivatives.
  *    05.01.2000   0.22  Should now work with rev7 boards; patch by
  *                       Eric Lemar, elemar@cs.washington.edu
+ *    08.01.2000   0.23  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
  */
 
 /*****************************************************************************/
@@ -1911,6 +1913,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	int val, mapped, ret;
 
 	VALIDATE_STATE(s);
@@ -2085,7 +2088,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
 		abinfo.fragsize = s->dma_dac2.fragsize;
-                abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count;
+		count = s->dma_dac2.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac2.dmasize - count;
                 abinfo.fragstotal = s->dma_dac2.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -2099,7 +2105,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
 		abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -2114,9 +2123,11 @@
 			return -EINVAL;
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
-                val = s->dma_dac2.count;
+                count = s->dma_dac2.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
@@ -2124,7 +2135,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -2137,7 +2151,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
                 cinfo.bytes = s->dma_dac2.total_bytes;
-                cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift;
+		count = s->dma_dac2.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac2.fragshift;
                 cinfo.ptr = s->dma_dac2.hwptr;
 		if (s->dma_dac2.mapped)
 			s->dma_dac2.count &= s->dma_dac2.fragsize-1;
@@ -2430,6 +2447,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	int val, ret;
 
 	VALIDATE_STATE(s);
@@ -2529,7 +2547,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
 		abinfo.fragsize = s->dma_dac1.fragsize;
-                abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count;
+		count = s->dma_dac1.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac1.dmasize - count;
                 abinfo.fragstotal = s->dma_dac1.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -2542,9 +2563,11 @@
         case SNDCTL_DSP_GETODELAY:
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
-                val = s->dma_dac1.count;
+                count = s->dma_dac1.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETOPTR:
 		if (!(file->f_mode & FMODE_WRITE))
@@ -2552,7 +2575,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		es1371_update_ptr(s);
                 cinfo.bytes = s->dma_dac1.total_bytes;
-                cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift;
+		count = s->dma_dac1.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac1.fragshift;
                 cinfo.ptr = s->dma_dac1.hwptr;
 		if (s->dma_dac1.mapped)
 			s->dma_dac1.count &= s->dma_dac1.fragsize-1;
@@ -3229,7 +3255,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1371: version v0.23 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))) {
 		if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) {
 			if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 &&
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- v2.3.39/linux/drivers/sound/esssolo1.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/esssolo1.c	Mon Jan 17 09:43:57 2000
@@ -3,7 +3,7 @@
 /*
  *      esssolo1.c  --  ESS Technology Solo1 (ES1946) audio driver.
  *
- *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *      Copyright (C) 1998-2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
  *      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
@@ -28,41 +28,44 @@
  *  /dev/midi   simple MIDI UART interface, no ioctl
  *
  *  Revision history
- *    10.11.98   0.1   Initial release (without any hardware)
- *    22.03.99   0.2   cinfo.blocks should be reset after GETxPTR ioctl.
- *                     reported by Johan Maes <joma@telindus.be>
- *                     return EAGAIN instead of EBUSY when O_NONBLOCK
- *                     read/write cannot be executed
- *    07.04.99   0.3   implemented the following ioctl's: SOUND_PCM_READ_RATE, 
- *                     SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
- *                     Alpha fixes reported by Peter Jones <pjones@redhat.com>
- *    15.06.99   0.4   Fix bad allocation bug.
- *                     Thanks to Deti Fliegl <fliegl@in.tum.de>
- *    28.06.99   0.5   Add pci_set_master
- *    12.08.99   0.6   Fix MIDI UART crashing the driver
- *                     Changed mixer semantics from OSS documented
- *                     behaviour to OSS "code behaviour".
- *                     Recording might actually work now.
- *                     The real DDMA controller address register is at PCI config
- *                     0x60, while the register at 0x18 is used as a placeholder
- *                     register for BIOS address allocation. This register
- *                     is supposed to be copied into 0x60, according
- *                     to the Solo1 datasheet. When I do that, I can access
- *                     the DDMA registers except the mask bit, which
- *                     is stuck at 1. When I copy the contents of 0x18 +0x10
- *                     to the DDMA base register, everything seems to work.
- *                     The fun part is that the Windows Solo1 driver doesn't
- *                     seem to do these tricks.
- *                     Bugs remaining: plops and clicks when starting/stopping playback
- *    31.08.99   0.7   add spin_lock_init
- *                     replaced current->state = x with set_current_state(x)
- *    03.09.99   0.8   change read semantics for MIDI to match
- *                     OSS more closely; remove possible wakeup race
- *    07.10.99   0.9   Fix initialization; complain if sequencer writes time out
- *                     Revised resource grabbing for the FM synthesizer
- *    28.10.99   0.10  More waitqueue races fixed
- *    09.12.99   0.11  Work around stupid Alpha port issue (virt_to_bus(kmalloc(GFP_DMA)) > 16M)
- *                     Disabling recording on Alpha
+ *    10.11.1998   0.1   Initial release (without any hardware)
+ *    22.03.1999   0.2   cinfo.blocks should be reset after GETxPTR ioctl.
+ *                       reported by Johan Maes <joma@telindus.be>
+ *                       return EAGAIN instead of EBUSY when O_NONBLOCK
+ *                       read/write cannot be executed
+ *    07.04.1999   0.3   implemented the following ioctl's: SOUND_PCM_READ_RATE, 
+ *                       SOUND_PCM_READ_CHANNELS, SOUND_PCM_READ_BITS; 
+ *                       Alpha fixes reported by Peter Jones <pjones@redhat.com>
+ *    15.06.1999   0.4   Fix bad allocation bug.
+ *                       Thanks to Deti Fliegl <fliegl@in.tum.de>
+ *    28.06.1999   0.5   Add pci_set_master
+ *    12.08.1999   0.6   Fix MIDI UART crashing the driver
+ *                       Changed mixer semantics from OSS documented
+ *                       behaviour to OSS "code behaviour".
+ *                       Recording might actually work now.
+ *                       The real DDMA controller address register is at PCI config
+ *                       0x60, while the register at 0x18 is used as a placeholder
+ *                       register for BIOS address allocation. This register
+ *                       is supposed to be copied into 0x60, according
+ *                       to the Solo1 datasheet. When I do that, I can access
+ *                       the DDMA registers except the mask bit, which
+ *                       is stuck at 1. When I copy the contents of 0x18 +0x10
+ *                       to the DDMA base register, everything seems to work.
+ *                       The fun part is that the Windows Solo1 driver doesn't
+ *                       seem to do these tricks.
+ *                       Bugs remaining: plops and clicks when starting/stopping playback
+ *    31.08.1999   0.7   add spin_lock_init
+ *                       replaced current->state = x with set_current_state(x)
+ *    03.09.1999   0.8   change read semantics for MIDI to match
+ *                       OSS more closely; remove possible wakeup race
+ *    07.10.1999   0.9   Fix initialization; complain if sequencer writes time out
+ *                       Revised resource grabbing for the FM synthesizer
+ *    28.10.1999   0.10  More waitqueue races fixed
+ *    09.12.1999   0.11  Work around stupid Alpha port issue (virt_to_bus(kmalloc(GFP_DMA)) > 16M)
+ *                       Disabling recording on Alpha
+ *    12.01.2000   0.12  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *                       Integrated (aka redid 8-)) APM support patch by Zach Brown
  *
  */
 
@@ -79,6 +82,7 @@
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
+#include <linux/apm_bios.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <linux/init.h>
@@ -1224,7 +1228,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
-	int val, mapped, ret;
+	int val, mapped, ret, count;
         int div1, div2;
         unsigned rate1, rate2;
 
@@ -1304,7 +1308,7 @@
 			stop_dac(s);
 			s->dma_adc.ready = s->dma_dac.ready = 0;
 			/* program channels */
-			s->channels = val ? 2 : 1;
+			s->channels = (val >= 2) ? 2 : 1;
 			prog_codec(s);
 		}
 		return put_user(s->channels, (int *)arg);
@@ -1368,7 +1372,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
 		abinfo.fragsize = s->dma_dac.fragsize;
-                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac.dmasize - count;
                 abinfo.fragstotal = s->dma_dac.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1397,9 +1404,11 @@
 			return -EINVAL;
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
-                val = s->dma_dac.count;
+                count = s->dma_dac.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
@@ -1420,7 +1429,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		solo1_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
-                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac.fragshift;
                 cinfo.ptr = s->dma_dac.hwptr;
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize-1;
@@ -2132,6 +2144,79 @@
 	{ SOUND_MIXER_WRITE_MIC, 0x4040 }
 };
 
+static int setup_solo1(struct solo1_state *s)
+{
+	struct pci_dev *pcidev = s->pcidev;
+	mm_segment_t fs;
+	int i, val;
+
+	/* initialize the chips */
+	if (!reset_ctrl(s)) {
+		printk(KERN_ERR "esssolo1: cannot reset controller\n");
+		return -1;
+	}
+	outb(0xb0, s->iobase+7); /* enable A1, A2, MPU irq's */
+	
+	/* initialize mixer regs */
+	write_mixer(s, 0x7f, 0); /* disable music digital recording */
+	write_mixer(s, 0x7d, 0x0c); /* enable mic preamp, MONO_OUT is 2nd DAC right channel */
+	write_mixer(s, 0x64, 0x45); /* volume control */
+	write_mixer(s, 0x48, 0x10); /* enable music DAC/ES6xx interface */
+	write_mixer(s, 0x50, 0);  /* disable spatializer */
+	write_mixer(s, 0x52, 0);
+	write_mixer(s, 0x14, 0);  /* DAC1 minimum volume */
+	write_mixer(s, 0x71, 0x20); /* enable new 0xA1 reg format */
+	outb(0, s->ddmabase+0xd); /* DMA master clear */
+	outb(1, s->ddmabase+0xf); /* mask channel */
+	/*outb(0, s->ddmabase+0x8);*/ /* enable controller (enable is low active!!) */
+
+	pci_set_master(pcidev);  /* enable bus mastering */
+	
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	val = SOUND_MASK_LINE;
+	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
+	for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
+		val = initvol[i].vol;
+		mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
+	}
+	val = 1; /* enable mic preamp */
+	mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long)&val);
+	set_fs(fs);
+	return 0;
+}
+
+#ifdef CONFIG_APM
+
+static int solo1_apm_callback(apm_event_t event)
+{
+	struct solo1_state *s;
+
+	switch(event) {
+	case APM_NORMAL_RESUME:
+	case APM_CRITICAL_RESUME:
+	case APM_STANDBY_RESUME:
+		for(s = devs ; s ; s = s->next)
+			setup_solo1(s);
+		break;
+
+		default: 
+			for(s = devs ; s ; s = s->next) {
+				outb(0, s->iobase+6);
+				/* DMA master clear */
+				outb(0, s->ddmabase+0xd); 
+				/* reset sequencer and FIFO */
+				outb(3, s->sbbase+6); 
+				/* turn off DDMA controller address space */
+				pci_write_config_word(s->pcidev, 0x60, 0); 
+			}
+	}
+	return 0;
+}
+
+#endif
+
+
 #define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
 				 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
 #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
@@ -2141,12 +2226,11 @@
 {
 	struct solo1_state *s;
 	struct pci_dev *pcidev = NULL;
-	mm_segment_t fs;
-	int i, val, index = 0;
+	int index = 0;
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "solo1: version v0.11 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "solo1: version v0.12 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) {
 		if (!RSRCISIOREGION(pcidev, 0) ||
@@ -2192,13 +2276,7 @@
 			printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
 			goto err_irq;
 		}
-		/* initialize DDMA base address */
 		printk(KERN_DEBUG "solo1: ddma base address: 0x%lx\n", s->ddmabase);
-		pci_write_config_word(pcidev, 0x60, (s->ddmabase & (~0xf)) | 1);
-		/* set DMA policy to DDMA, IRQ emulation off (CLKRUN disabled for now) */
-		pci_write_config_dword(pcidev, 0x50, 0);
-		/* disable legacy audio address decode */
-		pci_write_config_word(pcidev, 0x40, 0x907f);
 
 		printk(KERN_INFO "solo1: joystick port at %#lx\n", s->gpbase+1);
 
@@ -2211,39 +2289,8 @@
 			goto err_dev3;
 		if ((s->dev_dmfm = register_sound_special(&solo1_dmfm_fops, 15 /* ?? */)) < 0)
 			goto err_dev4;
-		/* initialize the chips */
-		if (!reset_ctrl(s)) {
-			printk(KERN_ERR "esssolo1: cannot reset controller\n");
+		if (setup_solo1(s))
 			goto err;
-		}
-		outb(0xb0, s->iobase+7); /* enable A1, A2, MPU irq's */
-
-		/* initialize mixer regs */
-		write_mixer(s, 0x7f, 0); /* disable music digital recording */
-		write_mixer(s, 0x7d, 0x0c); /* enable mic preamp, MONO_OUT is 2nd DAC right channel */
-		write_mixer(s, 0x64, 0x45); /* volume control */
-		write_mixer(s, 0x48, 0x10); /* enable music DAC/ES6xx interface */
-		write_mixer(s, 0x50, 0);  /* disable spatializer */
-		write_mixer(s, 0x52, 0);
-		write_mixer(s, 0x14, 0);  /* DAC1 minimum volume */
-		write_mixer(s, 0x71, 0x20); /* enable new 0xA1 reg format */
-		outb(0, s->ddmabase+0xd); /* DMA master clear */
-		outb(1, s->ddmabase+0xf); /* mask channel */
-		/*outb(0, s->ddmabase+0x8);*/ /* enable controller (enable is low active!!) */
-
-		pci_set_master(pcidev);  /* enable bus mastering */
-		
-		fs = get_fs();
-		set_fs(KERNEL_DS);
-		val = SOUND_MASK_LINE;
-		mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);
-		for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) {
-			val = initvol[i].vol;
-			mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
-		}
-		val = 1; /* enable mic preamp */
-		mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long)&val);
-		set_fs(fs);
 		/* queue it for later freeing */
 		s->next = devs;
 		devs = s;
@@ -2259,7 +2306,7 @@
 	err_dev2:
 		unregister_sound_dsp(s->dev_audio);
 	err_dev1:
-		printk(KERN_ERR "solo1: cannot register misc device\n");
+		printk(KERN_ERR "solo1: initialisation error\n");
 		free_irq(s->irq, s);
 	err_irq:
 		release_region(s->iobase, IOBASE_EXTENT);
@@ -2271,6 +2318,9 @@
 	}
 	if (!devs)
 		return -ENODEV;
+#ifdef CONFIG_APM
+	apm_register_callback(solo1_apm_callback);
+#endif
 	return 0;
 }
 
@@ -2302,6 +2352,9 @@
 		unregister_sound_special(s->dev_dmfm);
 		kfree_s(s, sizeof(struct solo1_state));
 	}
+#ifdef CONFIG_APM
+	apm_unregister_callback(solo1_apm_callback);
+#endif
 	printk(KERN_INFO "solo1: unloading\n");
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/msnd.c linux/drivers/sound/msnd.c
--- v2.3.39/linux/drivers/sound/msnd.c	Fri Sep 10 23:57:35 1999
+++ linux/drivers/sound/msnd.c	Thu Jan 20 10:44:46 2000
@@ -20,7 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd.c,v 1.16 1998/09/08 04:05:56 andrewtv Exp $
+ * $Id: msnd.c,v 1.17 1999/03/21 16:50:09 andrewtv Exp $
  *
  ********************************************************************/
 
@@ -66,7 +66,7 @@
 
 	if (i == MSND_MAX_DEVS)
 		return -ENOMEM;
-	
+
 	devs[i] = dev;
 	++num_devs;
 
@@ -106,13 +106,21 @@
 	for (i = 0; i < MSND_MAX_DEVS && j; ++i)
 		if (devs[i] != NULL)
 			--j;
-	
+
 	if (i == MSND_MAX_DEVS || j != 0)
 		return NULL;
 
 	return devs[i];
 }
 
+void msnd_init_queue(unsigned long base, int start, int size)
+{
+	isa_writew(PCTODSP_BASED(start), base + JQS_wStart);
+	isa_writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize);
+	isa_writew(0, base + JQS_wHead);
+	isa_writew(0, base + JQS_wTail);
+}
+
 void msnd_fifo_init(msnd_fifo *f)
 {
 	f->data = NULL;
@@ -152,11 +160,11 @@
 
 	if (f->len == f->n)
 		return 0;
-	
+
 	while ((count < len) && (f->len != f->n)) {
-		
+
 		int nwritten;
-		
+
 		if (f->head <= f->tail) {
 			nwritten = len - count;
 			if (nwritten > f->n - f->tail)
@@ -180,7 +188,7 @@
 		f->tail += nwritten;
 		f->tail %= f->n;
 	}
-	
+
 	return count;
 }
 
@@ -190,11 +198,11 @@
 
 	if (f->len == 0)
 		return f->len;
-	
+
 	while ((count < len) && (f->len > 0)) {
-		
+
 		int nread;
-		
+
 		if (f->tail <= f->head) {
 			nread = len - count;
 			if (nread > f->n - f->head)
@@ -205,20 +213,20 @@
 			if (nread > len - count)
 				nread = len - count;
 		}
-		
+
 		if (user) {
 			if (copy_to_user(buf, f->data + f->head, nread))
 				return -EFAULT;
 		} else
 			memcpy(buf, f->data + f->head, nread);
-		
+
 		count += nread;
 		buf += nread;
 		f->len -= nread;
 		f->head += nread;
 		f->head %= f->n;
 	}
-	
+
 	return count;
 }
 
@@ -259,7 +267,7 @@
 	spin_unlock_irqrestore(&dev->lock, flags);
 
 	printk(KERN_DEBUG LOGNAME ": Send DSP command timeout\n");
-	
+
 	return -EIO;
 }
 
@@ -307,7 +315,7 @@
 		return 0;
 
 	printk(KERN_DEBUG LOGNAME ": Enabling IRQ\n");
-	
+
 	spin_lock_irqsave(&dev->lock, flags);
 	if (msnd_wait_TXDE(dev) == 0) {
 		outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
@@ -316,6 +324,7 @@
 		outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
 		outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
 		enable_irq(dev->irq);
+		msnd_init_queue(dev->DSPQ, dev->dspq_data_buff, dev->dspq_buff_size);
 		spin_unlock_irqrestore(&dev->lock, flags);
 		return 0;
 	}
@@ -359,6 +368,8 @@
 EXPORT_SYMBOL(msnd_unregister);
 EXPORT_SYMBOL(msnd_get_num_devs);
 EXPORT_SYMBOL(msnd_get_dev);
+
+EXPORT_SYMBOL(msnd_init_queue);
 
 EXPORT_SYMBOL(msnd_fifo_init);
 EXPORT_SYMBOL(msnd_fifo_free);
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/msnd.h linux/drivers/sound/msnd.h
--- v2.3.39/linux/drivers/sound/msnd.h	Tue Jan  4 13:57:17 2000
+++ linux/drivers/sound/msnd.h	Thu Jan 20 10:44:46 2000
@@ -24,13 +24,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd.h,v 1.33 1998/11/05 20:26:18 andrewtv Exp $
+ * $Id: msnd.h,v 1.36 1999/03/21 17:05:42 andrewtv Exp $
  *
  ********************************************************************/
 #ifndef __MSND_H
 #define __MSND_H
 
-#define VERSION			"0.8.2.2"
+#define VERSION			"0.8.3.1"
 
 #define DEFSAMPLERATE		DSP_DEFAULT_SPEED
 #define DEFSAMPLESIZE		AFMT_U8
@@ -202,6 +202,7 @@
 	/* Linux device info */
 	char *name;
 	int dsp_minor, mixer_minor;
+	int ext_midi_dev, hdr_midi_dev;
 
 	/* Hardware resources */
 	int io, numio;
@@ -214,6 +215,7 @@
 	unsigned long SMA;
 	unsigned long DAPQ, DARQ, MODQ, MIDQ, DSPQ;
 	unsigned long pwDSPQData, pwMIDQData, pwMODQData;
+	int dspq_data_buff, dspq_buff_size;
 
 	/* State variables */
 	enum { msndClassic, msndPinnacle } type;
@@ -229,7 +231,7 @@
 #define F_READING			7
 #define F_READBLOCK			8
 #define F_EXT_MIDI_INUSE		9
-#define F_INT_MIDI_INUSE		10
+#define F_HDR_MIDI_INUSE		10
 #define F_DISABLE_WRITE_NDELAY		11
 	wait_queue_head_t writeblock;
 	wait_queue_head_t readblock;
@@ -268,6 +270,8 @@
 void				msnd_unregister(multisound_dev_t *dev);
 int				msnd_get_num_devs(void);
 multisound_dev_t *		msnd_get_dev(int i);
+
+void				msnd_init_queue(unsigned long, int start, int size);
 
 void				msnd_fifo_init(msnd_fifo *f);
 void				msnd_fifo_free(msnd_fifo *f);
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/msnd_classic.h linux/drivers/sound/msnd_classic.h
--- v2.3.39/linux/drivers/sound/msnd_classic.h	Thu Sep 10 16:37:26 1998
+++ linux/drivers/sound/msnd_classic.h	Thu Jan 20 10:44:46 2000
@@ -24,7 +24,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * 
- * $Id: msnd_classic.h,v 1.9 1998/09/10 04:11:18 andrewtv Exp $
+ * $Id: msnd_classic.h,v 1.10 1999/03/21 17:36:09 andrewtv Exp $
  *
  ********************************************************************/
 #ifndef __MSND_CLASSIC_H
@@ -108,13 +108,13 @@
 #define MIDQ_OFFSET				(SRAM_CNTL_START + 0x18)
 #define DSPQ_OFFSET				(SRAM_CNTL_START + 0x20)
 
-#define MOP_PROTEUS				0x10
+#define MOP_SYNTH				0x10
 #define MOP_EXTOUT				0x32
 #define MOP_EXTTHRU				0x02
 #define MOP_OUTMASK				0x01
 
 #define MIP_EXTIN				0x01
-#define MIP_PROTEUS				0x00
+#define MIP_SYNTH				0x00
 #define MIP_INMASK				0x32
 
 /* Classic SMA Common Data */
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- v2.3.39/linux/drivers/sound/msnd_pinnacle.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/msnd_pinnacle.c	Thu Jan 20 10:44:46 2000
@@ -29,7 +29,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd_pinnacle.c,v 1.73 1998/12/04 14:41:02 andrewtv Exp $
+ * $Id: msnd_pinnacle.c,v 1.75 1999/03/21 16:50:09 andrewtv Exp $
  *
  ********************************************************************/
 
@@ -254,7 +254,7 @@
 	case SNDCTL_DSP_SYNC:
 		dsp_write_flush();
 		return 0;
-		
+
 	case SNDCTL_DSP_GETBLKSIZE:
 		tmp = dsp_get_frag_size();
 		if (put_user(tmp, (int *)arg))
@@ -352,7 +352,7 @@
 				break;
 			}
 		}
-									
+
 		for (i = 0; i < 3; ++i, lpDAQ += DAQDS__size, lpDARQ += DAQDS__size) {
 			if (file->f_mode & FMODE_WRITE)
 				isa_writew(data, lpDAQ + DAQDS_wChannels);
@@ -570,7 +570,7 @@
 		return 0;
 	} else if (((cmd >> 8) & 0xff) == 'M') {
 		int val = 0;
-		
+
 		if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
 			switch (cmd & 0xff) {
 			case SOUND_MIXER_RECSRC:
@@ -578,7 +578,7 @@
 					return -EFAULT;
 				val = set_recsrc(val);
 				break;
-				
+
 			default:
 				if (get_user(val, (int *)arg))
 					return -EFAULT;
@@ -592,7 +592,7 @@
 			case SOUND_MIXER_RECSRC:
 				val = dev.recsrc;
 				break;
-				
+
 			case SOUND_MIXER_DEVMASK:
 			case SOUND_MIXER_STEREODEVS:
 				val =   SOUND_MASK_PCM |
@@ -620,7 +620,7 @@
 			case SOUND_MIXER_CAPS:
 				val =   SOUND_CAP_EXCL_INPUT;
 				break;
-				
+
 			default:
 				if ((val = mixer_get(cmd & 0xff)) < 0)
 					return -EINVAL;
@@ -787,7 +787,7 @@
 		/* nothing */
 	} else
 		err = -EINVAL;
-	
+
 	if (err >= 0)
 		mod_inc_ref();
 
@@ -873,7 +873,7 @@
 		register int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size);
 		register int n;
 		unsigned long flags;
-		
+
 		/* Write the data to the new tail */
 		if (protect) {
 			/* Critical section: protect fifo in non-interrupt */
@@ -910,11 +910,9 @@
 		/* Then advance the tail */
 		DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size);
 		isa_writew(DAPQ_tail, dev.DAPQ + JQS_wTail);
-		
 		/* Tell the DSP to play the bank */
 		msnd_send_dsp_cmd(&dev, HDEX_PLAY_START);
 	}
-	
 	return nbanks;
 }
 
@@ -999,7 +997,7 @@
 				return -EINTR;
 		}
 	}
-	
+
 	return len - count;
 }
 
@@ -1142,7 +1140,7 @@
 static int reset_dsp(void)
 {
 	int timeout = 100;
-		
+
 	outb(HPDSPRESET_ON, dev.io + HP_DSPR);
 	mdelay(1);
 #ifndef MSND_CLASSIC
@@ -1190,7 +1188,7 @@
 	case 0x3: xv = "1.4"; break;
 	default: xv = "unknown"; break;
 	}
-		
+
 	switch (dev.info & 0x7) {
 	case 0x0: rev = "I"; dev.name = pin; break;
 	case 0x1: rev = "F"; dev.name = pin; break;
@@ -1216,18 +1214,9 @@
 	       dev.base, dev.base + 0x7fff);
 
 	release_region(dev.io, dev.numio);
-	
 	return 0;
 }
 
-static void msnd_init_queue(unsigned long base, int start, int size)
-{
-	isa_writew(PCTODSP_BASED(start), base + JQS_wStart);
-	isa_writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize);
-	isa_writew(0, base + JQS_wHead);
-	isa_writew(0, base + JQS_wTail);
-}
-
 static int init_sma(void)
 {
 	static int initted;
@@ -1383,7 +1372,7 @@
 
 	if ((err = reset_dsp()) < 0)
 		return err;
-	
+
 	if ((err = upload_dsp_code()) < 0) {
 		printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n");
 		return err;
@@ -1462,12 +1451,14 @@
 		return dev.mixer_minor;
 	}
 
+	dev.ext_midi_dev = dev.hdr_midi_dev = -1;
+
 	disable_irq(dev.irq);
 	calibrate_adc(dev.play_sample_rate);
 #ifndef MSND_CLASSIC
 	force_recsrc(SOUND_MASK_IMIX);
 #endif
-	
+
 	return 0;
 }
 
@@ -1593,7 +1584,7 @@
 
 	/* Configure specified devices */
 	for (i = 0; i < 4; ++i) {
-		
+
 		switch (i) {
 		case 0:		/* DSP */
 			if (!(device[i].io0 && device[i].irq && device[i].mem))
@@ -1776,7 +1767,7 @@
 
 	printk(KERN_INFO LOGNAME ": Turtle Beach " LONGNAME " Linux Driver Version "
 	       VERSION ", Copyright (C) 1998 Andrew Veliath\n");
-	
+
 	if (io == -1 || irq == -1 || mem == -1)
 		printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n");
 
@@ -1792,7 +1783,7 @@
 		printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, or 0x3E0\n");
 		return -EINVAL;
 	}
-	
+
 	if (irq == -1 ||
 	    !(irq == 5 ||
 	      irq == 7 ||
@@ -1849,7 +1840,7 @@
 		pinnacle_devs[0].mem = mem;
 
 		/* The following are Pinnacle specific */
-		
+
 		/* MPU */
 		pinnacle_devs[1].io0 = mpu_io;
 		pinnacle_devs[1].irq = mpu_irq;
@@ -1896,6 +1887,8 @@
 	dev.fifosize = fifosize * 1024;
 	dev.calibrate_signal = calibrate_signal ? 1 : 0;
 	dev.recsrc = 0;
+	dev.dspq_data_buff = DSPQ_DATA_BUFF;
+	dev.dspq_buff_size = DSPQ_BUFF_SIZE;
 	dev.inc_ref = mod_inc_ref;
 	dev.dec_ref = mod_dec_ref;
 	if (write_ndelay == -1)
@@ -1934,7 +1927,7 @@
 		msnd_fifo_free(&dev.DARF);
 		return err;
 	}
-	
+
 	if ((err = attach_multisound()) < 0) {
 		printk(KERN_ERR LOGNAME ": Attach failed\n");
 		msnd_fifo_free(&dev.DAPF);
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/msnd_pinnacle.h linux/drivers/sound/msnd_pinnacle.h
--- v2.3.39/linux/drivers/sound/msnd_pinnacle.h	Thu Sep 10 16:37:26 1998
+++ linux/drivers/sound/msnd_pinnacle.h	Thu Jan 20 10:44:46 2000
@@ -24,7 +24,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd_pinnacle.h,v 1.10 1998/09/10 04:11:18 andrewtv Exp $
+ * $Id: msnd_pinnacle.h,v 1.11 1999/03/21 17:36:09 andrewtv Exp $
  *
  ********************************************************************/
 #ifndef __MSND_PINNACLE_H
@@ -141,18 +141,16 @@
 #define MIDQ_OFFSET				(SRAM_CNTL_START + 0x18)
 #define DSPQ_OFFSET				(SRAM_CNTL_START + 0x20)
 
-#define WAVEHDR_MOP				0
-#define EXTOUT_MOP				1
-#define HWINIT_MOP				0xFE
-#define NO_MOP					0xFF
-
-#define MAX_MOP					1
-
-#define EXTIN_MIP				0
-#define WAVEHDR_MIP				1
-#define HWINIT_MIP				0xFE
-
-#define MAX_MIP					1
+#define MOP_WAVEHDR				0
+#define MOP_EXTOUT				1
+#define MOP_HWINIT				0xfe
+#define MOP_NONE				0xff
+#define MOP_MAX					1
+
+#define MIP_EXTIN				0
+#define MIP_WAVEHDR				1
+#define MIP_HWINIT				0xfe
+#define MIP_MAX					1
 
 /* Pinnacle/Fiji SMA Common Data */
 #define SMA_wCurrPlayBytes			0x0000
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.3.39/linux/drivers/sound/sonicvibes.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/sound/sonicvibes.c	Mon Jan 17 09:43:57 2000
@@ -84,6 +84,9 @@
  *    28.10.1999   0.22  More waitqueue races fixed
  *    01.12.1999   0.23  New argument to allocate_resource
  *    07.12.1999   0.24  More allocate_resource semantics change
+ *    08.01.2000   0.25  Prevent some ioctl's from returning bad count values on underrun/overrun;
+ *                       Tim Janik's BSE (Bedevilled Sound Engine) found this
+ *                       use Martin Mares' pci_assign_resource
  *
  */
 
@@ -131,6 +134,10 @@
 #define SV_EXTENT_GAME    0x8
 #define SV_EXTENT_DMA     0x10
 
+/*
+ * we are not a bridge and thus use a resource for DDMA that is used for bridges but
+ * left empty for normal devices
+ */
 #define RESOURCE_SB       0
 #define RESOURCE_ENH      1
 #define RESOURCE_SYNTH    2
@@ -1533,6 +1540,7 @@
 	unsigned long flags;
         audio_buf_info abinfo;
         count_info cinfo;
+	int count;
 	int val, mapped, ret;
 	unsigned char fmtm, fmtd;
 
@@ -1700,7 +1708,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
 		abinfo.fragsize = s->dma_dac.fragsize;
-                abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = s->dma_dac.dmasize - count;
                 abinfo.fragstotal = s->dma_dac.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1714,7 +1725,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
 		abinfo.fragsize = s->dma_adc.fragsize;
-                abinfo.bytes = s->dma_adc.count;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                abinfo.bytes = count;
                 abinfo.fragstotal = s->dma_adc.numfrag;
                 abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
 		spin_unlock_irqrestore(&s->lock, flags);
@@ -1729,9 +1743,11 @@
 			return -EINVAL;
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
-                val = s->dma_dac.count;
+                count = s->dma_dac.count;
 		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *)arg);
+		if (count < 0)
+			count = 0;
+		return put_user(count, (int *)arg);
 
         case SNDCTL_DSP_GETIPTR:
 		if (!(file->f_mode & FMODE_READ))
@@ -1739,7 +1755,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
                 cinfo.bytes = s->dma_adc.total_bytes;
-                cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+		count = s->dma_adc.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_adc.fragshift;
                 cinfo.ptr = s->dma_adc.hwptr;
 		if (s->dma_adc.mapped)
 			s->dma_adc.count &= s->dma_adc.fragsize-1;
@@ -1752,7 +1771,10 @@
 		spin_lock_irqsave(&s->lock, flags);
 		sv_update_ptr(s);
                 cinfo.bytes = s->dma_dac.total_bytes;
-                cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+		count = s->dma_dac.count;
+		if (count < 0)
+			count = 0;
+                cinfo.blocks = count >> s->dma_dac.fragshift;
                 cinfo.ptr = s->dma_dac.hwptr;
 		if (s->dma_dac.mapped)
 			s->dma_dac.count &= s->dma_dac.fragsize-1;
@@ -2427,7 +2449,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.24 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.25 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
@@ -2444,20 +2466,20 @@
 			continue;
 		/* try to allocate a DDMA resource if not already available */
 		if (!RSRCISIOREGION(pcidev, RESOURCE_DDMA)) {
-			/* take care of ISA aliases */
+			pcidev->resource[RESOURCE_DDMA].start = 0;
+			pcidev->resource[RESOURCE_DDMA].end = 2*SV_EXTENT_DMA-1;
+			pcidev->resource[RESOURCE_DDMA].flags = PCI_BASE_ADDRESS_SPACE_IO | IORESOURCE_IO;
 			ddmanamelen = strlen(sv_ddma_name)+1;
 			if (!(ddmaname = kmalloc(ddmanamelen, GFP_KERNEL)))
 				continue;
 			memcpy(ddmaname, sv_ddma_name, ddmanamelen);
 			pcidev->resource[RESOURCE_DDMA].name = ddmaname;
-			if (allocate_resource(&ioport_resource, pcidev->resource+RESOURCE_DDMA, 
-					      2*SV_EXTENT_DMA, 0x1000, 0x10000-2*SV_EXTENT_DMA, 1024, NULL, NULL)) {
+			if (pci_assign_resource(pcidev, RESOURCE_DDMA)) {
 				pcidev->resource[RESOURCE_DDMA].name = NULL;
 				kfree(ddmaname);
 				printk(KERN_ERR "sv: cannot allocate DDMA controller io ports\n");
 				continue;
 			}
-			pcidev->resource[RESOURCE_DDMA].flags = PCI_BASE_ADDRESS_SPACE_IO | IORESOURCE_IO;
 		}
 		if (!(s = kmalloc(sizeof(struct sv_state), GFP_KERNEL))) {
 			printk(KERN_WARNING "sv: out of memory\n");
diff -u --recursive --new-file v2.3.39/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
--- v2.3.39/linux/drivers/sound/sscape.c	Mon Oct  4 15:49:30 1999
+++ linux/drivers/sound/sscape.c	Thu Jan 20 10:48:35 2000
@@ -3,7 +3,6 @@
  *
  * Low level driver for Ensoniq SoundScape
  */
-
 /*
  * Copyright (C) by Hannu Savolainen 1993-1997
  *
@@ -11,9 +10,10 @@
  * Version 2 (June 1991). See the "COPYING" file distributed with this software
  * for more info.
  */
-
+ 
 /*
- * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
+ * Thomas Sailer   	: ioctl code reworked (vmalloc/vfree removed)
+ * Sergey Smitienko	: ensoniq p'n'p support
  */
 
 #include <linux/config.h>
@@ -21,6 +21,26 @@
 
 #include "sound_config.h"
 #include "soundmodule.h"
+#include "sound_firmware.h"
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/fcntl.h>
+#include <linux/ctype.h>
+#include <linux/stddef.h>
+#include <linux/kmod.h>
+#ifdef __KERNEL__
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/segment.h>
+#include <linux/wait.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#endif				/* __KERNEL__ */
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+
 
 #ifdef CONFIG_SSCAPE
 
@@ -71,10 +91,10 @@
 #define CMD_GET_BOARD_TYPE	0x82
 #define CMD_SET_CONTROL		0x88	/* Old firmware only */
 #define CMD_GET_CONTROL		0x89	/* Old firmware only */
-#define 	CTL_MASTER_VOL		0
-#define 	CTL_MIC_MODE		2
-#define 	CTL_SYNTH_VOL		4
-#define 	CTL_WAVE_VOL		7
+#define CTL_MASTER_VOL		0
+#define CTL_MIC_MODE		2
+#define CTL_SYNTH_VOL		4
+#define CTL_WAVE_VOL		7
 #define CMD_SET_EXTMIDI		0x8a
 #define CMD_GET_EXTMIDI		0x8b
 #define CMD_SET_MT32		0x8c
@@ -82,9 +102,20 @@
 
 #define CMD_ACK			0x80
 
+#define	IC_ODIE			1
+#define	IC_OPUS			2
+
 typedef struct sscape_info
 {
 	int	base, irq, dma;
+	
+	int	codec, codec_irq;	/* required to setup pnp cards*/
+	int	codec_type;
+	int	ic_type;
+	char*	raw_buf;
+	unsigned long	raw_buf_phys;
+	int	buffsize;		/* -------------------------- */
+	
 	int	ok;	/* Properly detected */
 	int	failed;
 	int	dma_allocated;
@@ -152,6 +183,31 @@
 	restore_flags(flags);
 }
 
+static unsigned char sscape_pnp_read_codec(sscape_info* devc, unsigned char reg)
+{
+	unsigned char res;
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();	
+	outb( reg, devc -> codec);
+	res = inb (devc -> codec + 1);
+	restore_flags(flags);
+	return res;
+
+}
+
+static void sscape_pnp_write_codec(sscape_info* devc, unsigned char reg, unsigned char data)
+{
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+	outb( reg, devc -> codec);
+	outb( data, devc -> codec + 1);
+	restore_flags(flags);
+}
+
 static void host_open(struct sscape_info *devc)
 {
 	outb((0x00), PORT(HOST_CTRL));	/* Put the board to the host mode */
@@ -218,6 +274,13 @@
 	return data;
 }
 
+static int host_command1(struct sscape_info *devc, int cmd)
+{
+	unsigned char buf[10];
+	buf[0] = (unsigned char) (cmd & 0xff);
+	return host_write(devc, buf, 1);
+}
+
 
 static int host_command2(struct sscape_info *devc, int cmd, int parm1)
 {
@@ -544,6 +607,7 @@
 };
 
 static int sscape_detected = 0;
+static int sscape_is_pnp   = 0;
 
 void attach_sscape(struct address_info *hw_config)
 {
@@ -563,14 +627,14 @@
 	 */
 #define SSCAPE_REGS { \
 /* I0 */	0x00, \
-		0xf0, /* Note! Ignored. Set always to 0xf0 */ \
-		0x20, /* Note! Ignored. Set always to 0x20 */ \
-		0x20, /* Note! Ignored. Set always to 0x20 */ \
-		0xf5, /* Ignored */ \
-		0x10, \
-		0x00, \
-		0x2e, /* I7 MEM config A. Likely to vary between models */ \
-		0x00, /* I8 MEM config B. Likely to vary between models */ \
+/* I1 */	0xf0, /* Note! Ignored. Set always to 0xf0 */ \
+/* I2 */	0x20, /* Note! Ignored. Set always to 0x20 */ \
+/* I3 */	0x20, /* Note! Ignored. Set always to 0x20 */ \
+/* I4 */	0xf5, /* Ignored */ \
+/* I5 */	0x10, \
+/* I6 */	0x00, \
+/* I7 */	0x2e, /* I7 MEM config A. Likely to vary between models */ \
+/* I8 */	0x00, /* I8 MEM config B. Likely to vary between models */ \
 /* I9 */	0x40 /* Ignored */ \
 	}
 #endif
@@ -605,11 +669,13 @@
 		printk(KERN_ERR "Invalid IRQ%d\n", hw_config->irq);
 		return;
 	}
-	save_flags(flags);
-	cli();
-
-	for (i = 1; i < 10; i++)
-	{
+	
+	if (sscape_is_pnp == 0) {
+	
+	    save_flags(flags);
+	    cli();
+	    for (i = 1; i < 10; i++)
+	    {
 		switch (i)
 		{
 			case 1:	/* Host interrupt enable */
@@ -640,9 +706,9 @@
 			default:
 				sscape_write(devc, i, regs[i]);
 		}
+	    }
+	    restore_flags(flags);
 	}
-	restore_flags(flags);
-
 #ifdef SSCAPE_DEBUG2
 	/*
 	 * Temporary debugging aid. Print contents of the registers after
@@ -733,6 +799,452 @@
 	return 1;
 }
 
+static	int sscape_read_host_ctrl(sscape_info* devc)
+{
+	return host_read(devc);
+}
+
+static	void sscape_write_host_ctrl2(sscape_info *devc, int a, int b)
+{
+	host_command2(devc, a, b);
+}
+
+static int sscape_alloc_dma(sscape_info *devc)
+{
+	char *start_addr, *end_addr;
+	int i, dma_pagesize;
+	int sz, size;
+
+	if (devc->raw_buf != NULL) return 0;	/* Already done */
+	dma_pagesize = (devc->dma < 4) ? (64 * 1024) : (128 * 1024);
+	devc->raw_buf = NULL;
+	devc->buffsize = 8192*4;
+	if (devc->buffsize > dma_pagesize) devc->buffsize = dma_pagesize;
+	start_addr = NULL;
+	/*
+	 * Now loop until we get a free buffer. Try to get smaller buffer if
+	 * it fails. Don't accept smaller than 8k buffer for performance
+	 * reasons.
+	 */
+	while (start_addr == NULL && devc->buffsize > PAGE_SIZE) {
+		for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1);
+		devc->buffsize = PAGE_SIZE * (1 << sz);
+		start_addr = (char *) __get_free_pages(GFP_ATOMIC|GFP_DMA, sz);
+		if (start_addr == NULL) devc->buffsize /= 2;
+	}
+
+	if (start_addr == NULL) {
+		printk(KERN_ERR "sscape pnp init error: Couldn't allocate DMA buffer\n");
+		return 0;
+	} else {
+		/* make some checks */
+		end_addr = start_addr + devc->buffsize - 1;		
+		/* now check if it fits into the same dma-pagesize */
+
+		if (((long) start_addr & ~(dma_pagesize - 1)) != ((long) end_addr & ~(dma_pagesize - 1))
+		    || end_addr >= (char *) (MAX_DMA_ADDRESS)) {
+			printk(KERN_ERR "sscape pnp: Got invalid address 0x%lx for %db DMA-buffer\n", (long) start_addr, devc->buffsize);
+			return 0;
+		}
+	}
+	devc->raw_buf = start_addr;
+	devc->raw_buf_phys = virt_to_bus(start_addr);
+
+	for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++)
+		set_bit(PG_reserved, &mem_map[i].flags);;
+	return 1;
+}
+
+static void sscape_free_dma(sscape_info *devc)
+{
+	int sz, size, i;
+	unsigned long start_addr, end_addr;
+
+	if (devc->raw_buf == NULL) return;
+	for (sz = 0, size = PAGE_SIZE; size < devc->buffsize; sz++, size <<= 1);
+	start_addr = (unsigned long) devc->raw_buf;
+	end_addr = start_addr + devc->buffsize;
+
+	for (i = MAP_NR(start_addr); i <= MAP_NR(end_addr); i++)
+		clear_bit(PG_reserved, &mem_map[i].flags);;
+
+	free_pages((unsigned long) devc->raw_buf, sz);
+	devc->raw_buf = NULL;
+}
+
+/* Intel version !!!!!!!!! */
+
+static int sscape_start_dma(int chan, unsigned long physaddr, int count, int dma_mode)
+{
+	unsigned long flags;
+
+	flags = claim_dma_lock();
+	disable_dma(chan);
+	clear_dma_ff(chan);
+	set_dma_mode(chan, dma_mode);
+	set_dma_addr(chan, physaddr);
+	set_dma_count(chan, count);
+	enable_dma(chan);
+	release_dma_lock(flags);
+	return 0;
+}
+
+static void sscape_pnp_start_dma(sscape_info* devc, int arg )
+{
+	int reg;
+	if (arg == 0) reg = 2;
+	else reg = 3;
+
+	sscape_write(devc, reg, sscape_read( devc, reg) | 0x01);
+	sscape_write(devc, reg, sscape_read( devc, reg) & 0xFE);
+}
+
+static int sscape_pnp_wait_dma (sscape_info* devc, int arg )
+{
+	int		reg;
+	unsigned long	i;
+	unsigned char	d;
+
+	if (arg == 0) reg = 2;
+	else reg = 3;
+
+	sleep ( 1 );
+	i = 0;
+	do {
+		d = sscape_read(devc, reg) & 1;
+		if ( d == 1)  break;
+		i++;
+	} while (i < 500000);
+	d = sscape_read(devc, reg) & 1; 
+	return d;
+}
+
+static	int	sscape_pnp_alloc_dma(sscape_info* devc)
+{
+	/* printk(KERN_INFO "sscape: requesting dma\n"); */
+	if (request_dma(devc -> dma, "sscape")) return 0;
+	/* printk(KERN_INFO "sscape: dma channel allocated\n"); */
+	if (!sscape_alloc_dma(devc)) {
+		free_dma(devc -> dma);
+		return 0;
+	};
+	return 1;
+}
+
+static	void	sscape_pnp_free_dma(sscape_info* devc)
+{
+	sscape_free_dma( devc);
+	free_dma(devc -> dma );	
+	/* printk(KERN_INFO "sscape: dma released\n"); */
+}
+
+static	int	sscape_pnp_upload_file(sscape_info* devc, char* fn)
+{	
+	int	     	done = 0;
+	int	     	timeout_val;
+	char*	     	data,*dt;
+	int	     	len,l;
+	unsigned long	flags;
+
+	sscape_write( devc, 9, sscape_read(devc, 9 )  & 0x3F );
+	sscape_write( devc, 2, (devc -> dma << 4) | 0x80 );
+	sscape_write( devc, 3, 0x20 );
+	sscape_write( devc, 9, sscape_read( devc, 9 )  | 0x80 );
+	
+	len = mod_firmware_load(fn, &data);
+	if (len == 0) {
+		    printk(KERN_ERR "sscape: file not found: %s\n", fn);
+		    return 0;
+	}
+	dt = data;
+	save_flags(flags);
+	cli();
+	while ( len > 0 ) {
+		if (len > devc -> buffsize) l = devc->buffsize;
+		else l = len;
+		len -= l;		
+		memcpy(devc->raw_buf, dt, l); dt += l;
+		sscape_start_dma(devc->dma, devc->raw_buf_phys, l, 0x48);
+		sscape_pnp_start_dma ( devc, 0 );
+		if (sscape_pnp_wait_dma ( devc, 0 ) == 0) return 0;
+	}
+	
+	restore_flags(flags);	    
+	vfree(data);
+	
+	outb(0, devc -> base + 2);
+	outb(0, devc -> base);
+
+	sscape_write ( devc, 9, sscape_read( devc, 9 ) | 0x40);
+
+	timeout_val = 5 * HZ; 
+	while (!done && timeout_val-- > 0)
+	{
+		unsigned char x;
+		sleep(1);
+		x = inb( devc -> base + 3);
+		if (x == 0xff || x == 0xfe)		/* OBP startup acknowledge */
+		{
+			//printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
+			done = 1;
+		}
+	}
+	timeout_val = 5 * HZ;
+	done = 0;
+	while (!done && timeout_val-- > 0)
+	{
+		unsigned char x;
+		sleep(1);
+		x = inb( devc -> base + 3);
+		if (x == 0xfe)		/* OBP startup acknowledge */
+		{
+			//printk(KERN_ERR "Soundscape: Acknowledge = %x\n", x);
+			done = 1;
+		}
+	}
+
+	if ( !done ) printk(KERN_ERR "soundscape: OBP Initialization failed.\n");
+
+	sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
+	sscape_write( devc, 3, (devc -> dma << 4) + 0x80);
+	return 1;
+}
+
+static	void	sscape_pnp_init_hw(sscape_info* devc)
+{	
+	unsigned char midi_irq = 0, sb_irq = 0;
+	unsigned i;
+	static	char code_file_name[23] = "/sndscape/sndscape.cox";
+	
+	int sscape_sb_enable		= 0;
+	int sscape_joystic_enable	= 0x7f;
+	int sscape_mic_enable		= 0;
+	int sscape_ext_midi		= 0;		
+
+	if ( !sscape_pnp_alloc_dma(devc) ) {
+		printk(KERN_ERR "sscape: faild to allocate dma\n");
+		return;
+	}
+
+	for (i = 0; i < 4; i++) {
+		if ( devc -> irq   == valid_interrupts[i] ) 
+			midi_irq = i;
+		if ( devc -> codec_irq == valid_interrupts[i] ) 
+			sb_irq = i;
+	}
+
+	sscape_write( devc, 5, 0x50);
+	sscape_write( devc, 7, 0x2e);
+	sscape_write( devc, 8, 0x00);
+
+	sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
+	sscape_write( devc, 3, ( devc -> dma << 4) | 0x80);
+
+	if ( sscape_sb_enable )
+		sscape_write (devc, 4, 0xF0 | (sb_irq << 2) | midi_irq);
+	else	
+		sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);
+
+	i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0);
+	if ( sscape_sb_enable )
+		i |= devc->ic_type == IC_ODIE ? 0x05 : 0x07;	    
+	if (sscape_joystic_enable) i |= 8;
+	
+	sscape_write (devc, 9, i);
+	sscape_write (devc, 6, 0x80);
+	sscape_write (devc, 1, 0x80);
+
+	if (devc -> codec_type == 2) {
+		sscape_pnp_write_codec( devc, 0x0C, 0x50);
+		sscape_pnp_write_codec( devc, 0x10, sscape_pnp_read_codec( devc, 0x10) & 0x3F);
+		sscape_pnp_write_codec( devc, 0x11, sscape_pnp_read_codec( devc, 0x11) | 0xC0);
+		sscape_pnp_write_codec( devc, 29, 0x20);
+	}
+
+	if (sscape_pnp_upload_file(devc, "/sndscape/scope.cod") == 0 ) {
+		printk(KERN_ERR "sscape: faild to upload file /sndscape/scope.cod\n");
+		sscape_pnp_free_dma(devc);
+		return;
+	}
+
+	i = sscape_read_host_ctrl( devc );
+	
+	if ( (i & 0x0F) >  7 ) {
+		printk(KERN_ERR "sscape: scope.cod faild\n");
+		sscape_pnp_free_dma(devc);
+		return;
+	}
+	if ( i & 0x10 ) sscape_write( devc, 7, 0x2F);
+	code_file_name[21] = (char) ( i & 0x0F) + 0x30;
+	if (sscape_pnp_upload_file( devc, code_file_name) == 0) {
+		printk(KERN_ERR "sscape: faild to upload file %s\n", code_file_name);
+		sscape_pnp_free_dma(devc);
+		return;
+	}
+	
+	if (devc->ic_type != IC_ODIE) {
+		sscape_pnp_write_codec( devc, 10, (sscape_pnp_read_codec(devc, 10) & 0x7f) |
+		 ( sscape_mic_enable == 0 ? 0x00 : 0x80) );
+	}
+	sscape_write_host_ctrl2( devc, 0x84, 0x32 );
+	sscape_write_host_ctrl2( devc, 0x86, 0x32 );
+	sscape_write_host_ctrl2( devc, 0x8A, sscape_ext_midi);
+
+	sscape_pnp_write_codec ( devc, 6, 0x3f ); //WAV_VOL
+	sscape_pnp_write_codec ( devc, 7, 0x3f ); //WAV_VOL
+	sscape_pnp_write_codec ( devc, 2, 0x1F ); //WD_CDXVOLL
+	sscape_pnp_write_codec ( devc, 3, 0x1F ); //WD_CDXVOLR
+
+	if (devc -> codec_type == 1) {
+		sscape_pnp_write_codec ( devc, 4, 0x1F );
+		sscape_pnp_write_codec ( devc, 5, 0x1F );
+		sscape_write_host_ctrl2( devc, 0x88, sscape_mic_enable);
+	} else {
+		int t;
+		sscape_pnp_write_codec ( devc, 0x10, 0x1F << 1);
+		sscape_pnp_write_codec ( devc, 0x11, 0xC0 | (0x1F << 1));
+
+		t = sscape_pnp_read_codec( devc, 0x00) & 0xDF;
+		if ( (sscape_mic_enable == 0)) t |= 0;
+		else t |= 0x20;
+		sscape_pnp_write_codec ( devc, 0x00, t);
+		t = sscape_pnp_read_codec( devc, 0x01) & 0xDF;
+		if ( (sscape_mic_enable == 0) ) t |= 0;
+		else t |= 0x20;
+		sscape_pnp_write_codec ( devc, 0x01, t);
+		sscape_pnp_write_codec ( devc, 0x40 | 29 , 0x20);
+		outb(0, devc -> codec);
+	}
+	if (devc -> ic_type == IC_OPUS ) {
+		int i = sscape_read( devc, 9 );
+		sscape_write( devc, 9, i | 3 );
+		sscape_write( devc, 3, 0x40);
+
+		if (check_region(0x228, 1)) {
+		    	    outb(0, 0x228);
+			    release_region(0x228,1);
+		}
+		sscape_write( devc, 3, (devc -> dma << 4) | 0x80);
+		sscape_write( devc, 9, i );
+	}
+	
+	host_close ( devc );
+	sscape_pnp_free_dma(devc);
+}
+
+static int	detect_sscape_pnp(sscape_info* devc)
+{
+	long	 i, irq_bits = 0xff;
+	unsigned int d;
+
+	DDB(printk("Entered detect_sscape_pnp(%x)\n", devc->base));
+
+	if (check_region(devc->base, 8)) {
+		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->base);	
+		return 0;
+	}
+		
+	if (check_region(devc->codec, 2)) {
+		printk(KERN_ERR "detect_sscape_pnp: port %x is not free\n", devc->codec);	
+		return 0;
+	}
+
+	if ( (inb( devc -> base + 2) & 0x78) != 0) return 0;
+
+	d = inb ( devc -> base + 4) & 0xF0;
+	if (  (d & 0x80) != 0)  return 0;
+	
+	if (d == 0) {
+			devc->codec_type = 1;
+			devc->ic_type = IC_ODIE;
+	}
+	else if ( (d & 0x60) != 0) {
+			devc->codec_type = 2;
+			devc->ic_type = IC_OPUS;
+	}
+	else if ( (d & 0x40) != 0) {
+			devc->codec_type = 2;
+			devc->ic_type = IC_ODIE;
+	} 
+	else return 0;
+	
+	sscape_is_pnp = 1;
+		
+	outb(0xFA, devc -> base+4);
+	if  ((inb( devc -> base+4) & 0x9F) != 0x0A)
+		return 0;
+	outb(0xFE, devc -> base+4);
+	if  ( (inb(devc -> base+4) & 0x9F) != 0x0E)
+		return 0;
+	if  ( (inb(devc -> base+5) & 0x9F) != 0x0E)
+		return 0;
+
+	if (devc->codec_type == 2) {
+		if (devc -> codec != devc -> base + 8)
+			printk("soundscape warning: incorrect codec port specified\n");
+		devc -> codec = devc -> base + 8;
+		d = 0x10 | (sscape_read(devc, 9)  & 0xCF);
+		sscape_write(devc, 9, d);
+		sscape_write(devc, 6, 0x80);
+	} else {
+		//todo: check codec is not base + 8
+	}
+
+	d  = (sscape_read(devc, 9) & 0x3F) | 0xC0;
+	sscape_write(devc, 9, d);
+
+	for (i = 0; i < 550000; i++)
+		if ( !(inb(devc -> codec) & 0x80) ) break;
+
+	d = inb(devc -> codec);
+	if (d & 0x80)
+		return 0;
+	if ( inb(devc -> codec + 2) == 0xFF)
+		return 0;
+
+	sscape_write(devc, 9, sscape_read(devc, 9)  & 0x3F );
+
+	d  = inb(devc -> codec) & 0x80;
+	if ( d == 0) {
+		printk(KERN_INFO "soundscape: hardware detected\n");
+		valid_interrupts = valid_interrupts_new;
+	} else	{
+		printk(KERN_INFO "soundscape: board looks like media fx\n");
+		valid_interrupts = valid_interrupts_old;
+		old_hardware = 1;
+	}
+
+	sscape_write( devc, 9, 0xC0 | (sscape_read(devc, 9)  & 0x3F) );
+
+	for (i = 0; i < 550000; i++)
+		if ( !(inb(devc -> codec) & 0x80)) 
+			break;
+		
+	sscape_pnp_init_hw(devc);
+
+	for (i = 0; i < sizeof(valid_interrupts); i++)
+	{
+		if (devc->codec_irq == valid_interrupts[i]) {
+			irq_bits = i;
+			break;
+		}
+	}	
+	sscape_write(devc, GA_INTENA_REG, 0x00);
+	sscape_write(devc, GA_DMACFG_REG, 0x50);
+	sscape_write(devc, GA_DMAA_REG, 0x70);
+	sscape_write(devc, GA_DMAB_REG, 0x20);
+	sscape_write(devc, GA_INTCFG_REG, 0xf0);
+	sscape_write(devc, GA_CDCFG_REG, 0x89 | (devc->dma << 4) | (irq_bits << 1));
+
+	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20);
+	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20);
+	
+	release_region(devc->codec, 2);
+	release_region(devc->base, 8);		
+		
+	return 1;	
+}
+
 int probe_sscape(struct address_info *hw_config)
 {
 
@@ -758,8 +1270,13 @@
 #endif
 	devc->failed = 1;
 
-	if (!detect_ga(devc))
-		return 0;
+	if (!detect_ga(devc)) {
+		if (detect_sscape_pnp(devc)) {		        
+			sscape_detected = hw_config->io_base;
+			return 1;
+		} 
+		else return 0;
+	}
 
 	if (old_hardware)	/* Check that it's really an old Spea/Reveal card. */
 	{
@@ -781,11 +1298,11 @@
 {
 	int i, irq_bits = 0xff;
 	int ad_flags = 0;
-
+	
 	if (devc->failed)
 	{
-		  printk(KERN_ERR "soundscape: Card not detected\n");
-		  return 0;
+		printk(KERN_ERR "soundscape: Card not detected\n");
+		return 0;
 	}
 	if (devc->ok == 0)
 	{
@@ -805,9 +1322,19 @@
 		printk(KERN_ERR "soundscape: Invalid MSS IRQ%d\n", hw_config->irq);
 		return 0;
 	}
-	if (old_hardware)
-		ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
-	return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp);
+	
+	if (!sscape_is_pnp) {
+		if (old_hardware)
+			ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
+		return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp);
+	} 
+	else {
+		if (old_hardware)
+			ad_flags = 0x12345677;	/* Tell that we may have a CS4248 chip (Spea-V7 Media FX) */
+		else
+			ad_flags = 0x87654321;  /* Tell that we have a soundscape pnp with 1845 chip */
+		return ad1848_detect(hw_config->io_base, &ad_flags, hw_config->osp);
+	}
 }
 
 void attach_ss_ms_sound(struct address_info *hw_config)
@@ -820,44 +1347,52 @@
 
 	int i, irq_bits = 0xff;
 
-	hw_config->dma = devc->dma;	/* Share the DMA with the ODIE/OPUS chip */
-
-	/*
-	 * Setup the DMA polarity.
-	 */
-
-	sscape_write(devc, GA_DMACFG_REG, 0x50);
-
-	/*
-	 * Take the gate-array off of the DMA channel.
-	 */
-	
-	sscape_write(devc, GA_DMAB_REG, 0x20);
-
-	/*
-	 * Init the AD1848 (CD-ROM) config reg.
-	 */
-
-	for (i = 0; i < sizeof(valid_interrupts); i++)
-	{
-		if (hw_config->irq == valid_interrupts[i])
-		{
-			irq_bits = i;
-			break;
-		}
-	}
-	sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
-
-	if (hw_config->irq == devc->irq)
-		printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n");
-
-	hw_config->slots[0] = ad1848_init("SoundScape", hw_config->io_base,
-					  hw_config->irq,
-					  hw_config->dma,
-					  hw_config->dma,
-					  0,
-					  devc->osp);
-
+ 		
+ 	if (!sscape_is_pnp)  /*pnp is already setup*/
+ 	{
+ 		/*
+     		 * Setup the DMA polarity.
+ 	    	 */
+ 		sscape_write(devc, GA_DMACFG_REG, 0x50);
+ 	
+ 		/*
+ 		 * Take the gate-array off of the DMA channel.
+ 		 */
+ 		sscape_write(devc, GA_DMAB_REG, 0x20);
+ 	
+ 		/*
+ 		 * Init the AD1848 (CD-ROM) config reg.
+ 		 */
+ 		for (i = 0; i < sizeof(valid_interrupts); i++)
+ 		{
+ 			if (hw_config->irq == valid_interrupts[i])
+ 			{
+ 				irq_bits = i;
+ 				break;
+ 			}
+ 		}	
+ 		sscape_write(devc, GA_CDCFG_REG, 0x89 | (hw_config->dma << 4) | (irq_bits << 1));
+ 	}
+ 	
+ 	if (hw_config->irq == devc->irq)
+ 		printk(KERN_WARNING "soundscape: Warning! The WSS mode can't share IRQ with MIDI\n");
+ 				
+ 	if (! sscape_is_pnp )
+		hw_config->slots[0] = ad1848_init("SoundScape", hw_config->io_base,
+						  hw_config->irq,
+						  hw_config->dma,
+						  hw_config->dma,
+						  0,
+						  devc->osp);
+
+	else 
+		hw_config->slots[0] = ad1848_init("SoundScape PNP", hw_config->io_base,
+	 					  hw_config->irq,
+	 					  hw_config->dma,
+	 					  hw_config->dma,
+	 					  0,
+	 					  devc->osp);
+ 					  
 	if (hw_config->slots[0] != -1)	/* The AD1848 driver installed itself */
 	{
 		audio_devs[hw_config->slots[0]]->coproc = &sscape_coproc_operations;
@@ -867,6 +1402,7 @@
 		/* Set proper routings here (what are they) */
 		AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_LINE);
 	}
+		
 #ifdef SSCAPE_DEBUG5
 	/*
 	 * Temporary debugging aid. Print contents of the registers
@@ -937,6 +1473,13 @@
 		  printk(KERN_ERR "CONFIG_MPU_IRQ must be specified if CONFIG_MPU_IO is set.\n");
 		  return -EINVAL;
 	}
+	
+	devc->codec = io;
+	devc->codec_irq = irq;
+	devc->codec_type = 0;
+	devc->ic_type = 0;
+	devc->raw_buf = NULL;
+	
 	config.irq = irq;
 	config.dma = dma;
 	config.io_base = io;
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.39/linux/drivers/usb/Config.in	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/Config.in	Thu Jan 20 15:00:16 2000
@@ -12,17 +12,21 @@
    dep_tristate '  OHCI-HCD (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI_HCD $CONFIG_USB
 
 comment 'Miscellaneous USB options'
-   if [ "$CONFIG_PROC_FS" != "n" ]; then
-      bool '  /proc/bus/usb support' CONFIG_USB_PROC
-   fi
    bool '  Preliminary USB device filesystem' CONFIG_USB_DEVICEFS
 
 comment 'USB Devices'
    dep_tristate '  USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
    dep_tristate '  USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
    dep_tristate '  USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB
-   dep_tristate '  USB Communications Device Class (ACM) support' CONFIG_USB_ACM $CONFIG_USB
+   dep_tristate '  USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB
    dep_tristate '  USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB
+   if [ "$CONFIG_USB_SERIAL" != "n" ]; then
+      bool '    USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC
+      bool '    USB ConnectTech WhiteHEAT Serial Driver' CONFIG_USB_SERIAL_WHITEHEAT
+      bool '    USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR
+      bool '    USB Belkin Single Port Serial Driver' CONFIG_USB_SERIAL_BELKIN
+      bool '    USB Peracom Single Port Serial Driver' CONFIG_USB_SERIAL_PERACOM
+   fi
    dep_tristate '  USB CPiA Camera support' CONFIG_USB_CPIA $CONFIG_USB
    dep_tristate '  USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB
    dep_tristate '  USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
@@ -30,7 +34,6 @@
    if [ "$CONFIG_USB_SCSI" != "n" ]; then
       bool '    USB SCSI verbose debug' CONFIG_USB_SCSI_DEBUG
    fi
-   dep_tristate '  EZUSB Firmware downloader' CONFIG_USB_EZUSB $CONFIG_USB
    dep_tristate '  USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT
    dep_tristate '  DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB 
 
@@ -40,6 +43,8 @@
       dep_tristate '  USB HIDBP Keyboard support' CONFIG_USB_KBD $CONFIG_USB
       dep_tristate '  USB HIDBP Mouse support' CONFIG_USB_MOUSE $CONFIG_USB
    fi
+   dep_tristate '  Wacom Graphire tablet support' CONFIG_USB_GRAPHIRE $CONFIG_USB
+   dep_tristate '  Logitech WingMan Force joystick support' CONFIG_USB_WMFORCE $CONFIG_USB
    dep_tristate '  Keyboard support' CONFIG_INPUT_KEYBDEV $CONFIG_USB
    dep_tristate '  Mouse support' CONFIG_INPUT_MOUSEDEV $CONFIG_USB
    if [ "$CONFIG_INPUT_MOUSEDEV" != "n" ]; then
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.39/linux/drivers/usb/Makefile	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/Makefile	Thu Jan 20 15:00:16 2000
@@ -29,9 +29,6 @@
 
 # Optional parts of multipart objects.
 
-ifeq ($(CONFIG_USB_PROC),y)
-	usbcore-objs	+= proc_usb.o
-endif
 ifeq ($(CONFIG_USB_DEVICEFS),y)
 	usbcore-objs	+= devio.o inode.o drivers.o devices.o
 endif
@@ -55,6 +52,8 @@
 obj-$(CONFIG_USB_MOUSE)		+= usbmouse.o input.o
 obj-$(CONFIG_USB_HID)		+= hid.o input.o
 obj-$(CONFIG_USB_KBD)		+= usbkbd.o input.o
+obj-$(CONFIG_USB_GRAPHIRE)	+= graphire.o input.o
+obj-$(CONFIG_USB_WMFORCE)	+= wmforce.o input.o
 obj-$(CONFIG_INPUT_KEYBDEV)	+= keybdev.o input.o
 obj-$(CONFIG_INPUT_MOUSEDEV)	+= mousedev.o input.o
 obj-$(CONFIG_INPUT_JOYDEV)	+= joydev.o input.o
@@ -68,7 +67,6 @@
 obj-$(CONFIG_USB_CPIA)		+= cpia.o
 obj-$(CONFIG_USB_DC2XX)		+= dc2xx.o
 obj-$(CONFIG_USB_SCSI)		+= usb-scsi.o
-obj-$(CONFIG_USB_EZUSB)		+= ezusb.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
 obj-$(CONFIG_USB_DABUSB)	+= dabusb.o
 obj-$(CONFIG_USB_OV511)		+= ov511.o
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.39/linux/drivers/usb/acm.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/acm.c	Mon Jan 17 16:24:48 2000
@@ -1,10 +1,10 @@
 /*
- * acm.c  Version 0.12
+ * acm.c  Version 0.14
  *
  * Copyright (c) 1999 Armin Fuerst	<fuerst@in.tum.de>
  * Copyright (c) 1999 Pavel Machek	<pavel@suse.cz>
  * Copyright (c) 1999 Johannes Erdfelt	<jerdfelt@valinux.com>
- * Copyright (c) 1999 Vojtech Pavlik	<vojtech@suse.cz>
+ * Copyright (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
  *
  * USB Abstract Control Model driver for USB modems and ISDN adapters
  *
@@ -16,6 +16,7 @@
  *	v0.11 - fixed flow control, read error doesn't stop reads
  *	v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
  *	v0.13 - added termios, added hangup
+ *	v0.14 - sized down struct acm
  */
 
 /*
@@ -52,6 +53,14 @@
 #include "usb.h"
 
 /*
+ * CMSPAR, some architectures can't have space and mark parity.
+ */
+
+#ifndef CMSPAR
+#define CMSPAR			0
+#endif
+
+/*
  * Major and minor numbers.
  */
 
@@ -121,21 +130,20 @@
 	struct usb_device *dev;				/* the coresponding usb device */
 	struct usb_interface *iface;			/* the interfaces - +0 control +1 data */
 	struct tty_struct *tty;				/* the coresponding tty */
+	struct urb ctrlurb, readurb, writeurb;		/* urbs */
+	struct acm_line line;				/* line coding (bits, stop, parity) */
 	unsigned int ctrlin;				/* input control lines (DCD, DSR, RI, break, overruns) */
 	unsigned int ctrlout;				/* output control lines (DTR, RTS) */
-	struct acm_line line;				/* line coding (bits, stop, parity) */
 	unsigned int writesize;				/* max packet size for the output bulk endpoint */
-	struct urb ctrlurb, readurb, writeurb;		/* urbs */
-	unsigned int minor;				/* acm minor number */
-	unsigned int present;				/* this device is connected to the usb bus */
 	unsigned int used;				/* someone has this acm's device open */
-	unsigned int clocal;				/* termios CLOCAL */
+	unsigned int minor;				/* acm minor number */
+	unsigned char clocal;				/* termios CLOCAL */
 };
 
 static struct usb_driver acm_driver;
 static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, /* .... */ };
 
-#define ACM_READY(acm)	(acm && acm->present && acm->used)
+#define ACM_READY(acm)	(acm && acm->dev && acm->used)
 
 /*
  * Functions for ACM control messages.
@@ -180,7 +188,7 @@
 
 		case ACM_IRQ_LINE_STATE:
 
-			newctrl = le16_to_cpup(data);
+			newctrl = le16_to_cpup((__u16 *) data);
 
 			if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) {
 				dbg("calling hangup");
@@ -257,7 +265,7 @@
 {
 	struct acm *acm = acm_table[MINOR(tty->device)];
 
-	if (!acm || !acm->present) return -EINVAL;
+	if (!acm || !acm->dev) return -EINVAL;
 
 	tty->driver_data = acm;
 	acm->tty = tty;
@@ -287,7 +295,7 @@
 
 	if (--acm->used) return;
 	
-	if (acm->present) {
+	if (acm->dev) {
 		acm_set_control(acm, acm->ctrlout = 0);
 		usb_unlink_urb(&acm->ctrlurb);
 		usb_unlink_urb(&acm->writeurb);
@@ -496,11 +504,14 @@
 
 		for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
 		if (acm_table[minor]) {
-			dbg("no more free acm devices");
+			err("no more free acm devices");
 			return NULL;
 		}
 
-		if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) return NULL;
+		if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) {
+			err("out of memory");
+			return NULL;
+		}
 		memset(acm, 0, sizeof(struct acm));
 
 		ctrlsize = epctrl->wMaxPacketSize;
@@ -508,10 +519,10 @@
 		acm->writesize = epwrite->wMaxPacketSize;
 		acm->iface = cfacm->interface;
 		acm->minor = minor;
-		acm->present = 1;
 		acm->dev = dev;
 
 		if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) {
+			err("out of memory");
 			kfree(acm);
 			return NULL;
 		}
@@ -523,15 +534,15 @@
 			buf += ctrlsize, readsize, acm_read_bulk, acm);
 
 		FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
-			buf += readsize , acm->writesize, acm_write_bulk, acm);
+			buf += readsize, acm->writesize, acm_write_bulk, acm);
 	
 		printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor);
 
 		acm_set_control(acm, acm->ctrlout);
 
-		acm->linecoding.speed = 115200;
-		acm->linecoding.databits = 8;
-		acm_set_coding(acm, &acm->linecoding);
+		acm->line.speed = cpu_to_le32(9600);
+		acm->line.databits = 8;
+		acm_set_line(acm, &acm->line);
 
 		usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm);
 		usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm);
@@ -546,12 +557,12 @@
 {
 	struct acm *acm = ptr;
 
-	if (!acm || !acm->present) {
+	if (!acm || !acm->dev) {
 		dbg("disconnect on nonexisting interface");
 		return;
 	}
 
-	acm->present = 0;
+	acm->dev = NULL;
 
 	usb_unlink_urb(&acm->ctrlurb);
 	usb_unlink_urb(&acm->readurb);
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c
--- v2.3.39/linux/drivers/usb/dc2xx.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/usb/dc2xx.c	Thu Jan 20 09:47:10 2000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1999 by David Brownell <david-b@pacbell.net>
+ * Copyright (C) 1999-2000 by David Brownell <david-b@pacbell.net>
  *
  * 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
@@ -41,6 +41,7 @@
  * 12 Oct, 1999 -- handle DC-280 interface class (0xff not 0x0);
  *	added timeouts to bulk_msg calls.  Minor updates, docs.
  * 03 Nov, 1999 -- update for 2.3.25 kernel API changes.
+ * 08 Jan, 2000 .. multiple camera support
  *
  * Thanks to:  the folk who've provided USB product IDs, sent in
  * patches, and shared their sucesses!
@@ -61,11 +62,17 @@
 
 #include "usb.h"
 
-/* XXX need to get registered minor number, cdev 10/MINOR */
-/* XXX or: cdev USB_MAJOR(180)/USB_CAMERA_MINOR */
-#define	USB_CAMERA_MINOR	170
 
 
+/* current USB framework handles max of 16 USB devices per driver */
+#define	MAX_CAMERAS		8
+
+/* USB char devs use USB_MAJOR and from USB_CAMERA_MINOR_BASE up */
+#define	USB_CAMERA_MINOR_BASE	80
+
+
+// XXX remove packet size limit, now that bulk transfers seem fixed
+
 /* Application protocol limit is 0x8002; USB has disliked that limit! */
 #define	MAX_PACKET_SIZE		0x2000		/* e.g. image downloading */
 
@@ -80,39 +87,35 @@
 	short		idProduct;
 	/* plus hooks for camera-specific info if needed */
 } cameras [] = {
+	/* These have the same application level protocol */  
     { 0x040a, 0x0120 },		// Kodak DC-240
     { 0x040a, 0x0130 },		// Kodak DC-280
 
-	/* Kodak has several other USB-enabled devices, which (along with
-	 * models from other vendors) all use the Flashpoint "Digita
-	 * OS" and its wire protocol.  These use a different application
-	 * level protocol from the DC-240/280 models.  Note that Digita
-	 * isn't just for cameras -- Epson has a non-USB Digita printer.
-	 */
-//  { 0x040a, 0x0100 },		// Kodak DC-220
+	/* 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.
+	 */  
+    { 0x040a, 0x0100 },		// Kodak DC-220
     { 0x040a, 0x0110 },		// Kodak DC-260
     { 0x040a, 0x0111 },		// Kodak DC-265
     { 0x040a, 0x0112 },		// Kodak DC-290
-
 //  { 0x03f0, 0xffff },		// HP PhotoSmart C500
 
-	/* Other USB cameras may well work here too, so long as they
-	 * just stick to half duplex packet exchanges and bulk messages.
-	 * Some non-camera devices have also been shown to work.
+	/* Other USB devices may well work here too, so long as they
+	 * just stick to half duplex bulk packet exchanges.
 	 */
 };
 
 
 struct camera_state {
-	/* these fields valid (dev != 0) iff camera connected */
 	struct usb_device	*dev;		/* USB device handle */
 	char			inEP;		/* read endpoint */
 	char			outEP;		/* write endpoint */
 	const struct camera	*info;		/* DC-240, etc */
-
-	/* valid iff isOpen */
-	int			isOpen;		/* device opened? */
+	int			subminor;	/* which minor dev #? */
 	int			isActive;	/* I/O taking place? */
+
+	/* this is non-null iff the device is open */
 	char			*buf;		/* buffer for I/O */
 
 	/* always valid */
@@ -120,11 +123,8 @@
 };
 
 
-/* For now, we only support one camera at a time: there's one
- * application-visible device (e.g. /dev/kodak) and the second
- * (to Nth) camera detected on the bus is ignored.
- */
-static struct camera_state static_camera_state;
+/* Support multiple cameras, possibly of different types.  */
+static struct camera_state *minor_data [MAX_CAMERAS];
 
 
 static ssize_t camera_read (struct file *file,
@@ -133,9 +133,12 @@
 	struct camera_state	*camera;
 	int			retries;
 
-	camera = (struct camera_state *) file->private_data;
 	if (len > MAX_PACKET_SIZE)
 		return -EINVAL;
+
+	camera = (struct camera_state *) file->private_data;
+	if (!camera->dev)
+		return -ENODEV;
 	if (camera->isActive++)
 		return -EBUSY;
 
@@ -161,7 +164,7 @@
 			  usb_rcvbulkpipe (camera->dev, camera->inEP),
 			  camera->buf, len, &count, HZ*10);
 
-		dbg("read (%d) - 0x%x %ld", len, result, count);
+		dbg ("read (%d) - 0x%x %ld", len, result, count);
 
 		if (!result) {
 			if (copy_to_user (buf, camera->buf, count))
@@ -173,7 +176,7 @@
 			break;
 		interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
 
-		dbg("read (%d) - retry", len);
+		dbg ("read (%d) - retry", len);
 	}
 	camera->isActive = 0;
 	return -EIO;
@@ -185,9 +188,12 @@
 	struct camera_state	*camera;
 	ssize_t			bytes_written = 0;
 
-	camera = (struct camera_state *) file->private_data;
 	if (len > MAX_PACKET_SIZE)
 		return -EINVAL;
+
+	camera = (struct camera_state *) file->private_data;
+	if (!camera->dev)
+		return -ENODEV;
 	if (camera->isActive++)
 		return -EBUSY;
 	
@@ -228,7 +234,7 @@
 				 obuf, thistime, &count, HZ*10);
 
 			if (result)
-				dbg("write USB err - %x", result);
+				dbg ("write USB err - %x", result);
 
 			if (count) {
 				obuf += count;
@@ -258,26 +264,26 @@
 	}
 done:
 	camera->isActive = 0;
-
-	dbg("write %d", bytes_written); 
-
+	dbg ("wrote %d", bytes_written); 
 	return bytes_written;
 }
 
 static int camera_open (struct inode *inode, struct file *file)
 {
-	struct camera_state *camera = &static_camera_state;
+	struct camera_state	*camera;
+	int			subminor;
 
-	/* ignore camera->dev so it can be turned on "late" */
+	subminor = MINOR (inode->i_rdev) - USB_CAMERA_MINOR_BASE;
+	if (subminor < 0 || subminor >= MAX_CAMERAS
+			|| !(camera = minor_data [subminor])) {
+		return -ENODEV;
+	}
 
-	if (camera->isOpen++)
-		return -EBUSY;
 	if (!(camera->buf = (char *) kmalloc (MAX_PACKET_SIZE, GFP_KERNEL))) {
-		camera->isOpen = 0;
 		return -ENOMEM;
 	}
 
-	dbg("open"); 
+	dbg ("open"); 
 	
 	/* Keep driver from being unloaded while it's in use */
 	MOD_INC_USE_COUNT;
@@ -293,10 +299,16 @@
 
 	camera = (struct camera_state *) file->private_data;
 	kfree (camera->buf);
-	camera->isOpen = 0;
+
+	/* If camera was unplugged with open file ... */
+	if (!camera->dev) {
+		minor_data [camera->subminor] = NULL;
+		kfree (camera);
+	}
+
 	MOD_DEC_USE_COUNT;
 
-	dbg("close"); 
+	dbg ("close"); 
 
 	return 0;
 }
@@ -306,26 +318,11 @@
 	 * apps should be able to see the camera type.
 	 */
 static /* const */ struct file_operations usb_camera_fops = {
-	NULL,		/* llseek */
-	camera_read,
-	camera_write,
-	NULL, 		/* readdir */
-	NULL,		/* poll */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	camera_open,
-	NULL,		/* flush */
-	camera_release,
-	NULL,		/* async */
-	NULL,		/* fasync */
-	NULL,		/* lock */
-};
-
-static struct miscdevice usb_camera = {
-	USB_CAMERA_MINOR,
-	"USB camera (Kodak DC-2xx)",
-	&usb_camera_fops
-	// next, prev
+	    /* Uses GCC initializer extension; simpler to maintain */
+	read:		camera_read,
+	write:		camera_write,
+	open:		camera_open,
+	release:	camera_release,
 };
 
 
@@ -337,8 +334,7 @@
 	struct usb_interface_descriptor	*interface;
 	struct usb_endpoint_descriptor	*endpoint;
 	int				direction, ep;
-
-	struct camera_state		*camera = &static_camera_state;
+	struct camera_state		*camera;
 
 	/* Is it a supported camera? */
 	for (i = 0; i < sizeof (cameras) / sizeof (struct camera); i++) {
@@ -355,7 +351,7 @@
 	/* these have one config, one interface */
 	if (dev->descriptor.bNumConfigurations != 1
 			|| dev->config[0].bNumInterfaces != 1) {
-		dbg("Bogus camera config info");
+		dbg ("Bogus camera config info");
 		return NULL;
 	}
 
@@ -367,18 +363,34 @@
 			|| interface->bInterfaceProtocol != 0
 			|| interface->bNumEndpoints != 2
 			) {
-		dbg("Bogus camera interface info");
+		dbg ("Bogus camera interface info");
 		return NULL;
 	}
 
-	/* can only show one camera at a time through /dev ... */
-	if (!camera->dev) {
-		camera->dev = dev;
-		info("USB Camera is connected");
-	} else {
-		info("Ignoring additional USB Camera");
+
+	/* select "subminor" number (part of a minor number) */
+	for (i = 0; i < MAX_CAMERAS; i++) {
+		if (!minor_data [i])
+			break;
+	}
+	if (i >= MAX_CAMERAS) {
+		info ("Ignoring additional USB Camera");
+		return NULL;
+	}
+
+	/* allocate & init camera state */
+	camera = minor_data [i] = kmalloc (sizeof *camera, GFP_KERNEL);
+	if (!camera) {
+		err ("no memory!");
 		return NULL;
 	}
+	camera->dev = dev;
+	camera->subminor = i;
+	camera->isActive = 0;
+	camera->buf = NULL;
+	init_waitqueue_head (&camera->wait);
+	info ("USB Camera #%d connected", camera->subminor);
+
 
 	/* get input and output endpoints (either order) */
 	endpoint = interface->endpoint;
@@ -402,14 +414,14 @@
 			|| endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK
 			|| endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK
 			) {
-		dbg("Bogus camera endpoints");
+		dbg ("Bogus endpoints");
 		camera->dev = NULL;
 		return NULL;
 	}
 
 
 	if (usb_set_configuration (dev, dev->config[0].bConfigurationValue)) {
-		err("Failed usb_set_configuration");
+		err ("Failed usb_set_configuration");
 		camera->dev = NULL;
 		return NULL;
 	}
@@ -421,21 +433,18 @@
 static void camera_disconnect(struct usb_device *dev, void *ptr)
 {
 	struct camera_state	*camera = (struct camera_state *) ptr;
+	int			subminor = camera->subminor;
 
-	if (camera->dev != dev)
-		return;
-
-	/* Currently not reflecting this up to userland; at one point
-	 * it got called on bus reconfig, which we clearly don't want.
-	 * A good consequence is the ability to remove camera for
-	 * a while without apps needing to do much more than ignore
-	 * some particular error returns.  On the bad side, if one
-	 * camera is swapped for another one, we won't be telling.
+	/* If camera's not opened, we can clean up right away.
+	 * Else apps see a disconnect on next I/O; the release cleans.
 	 */
-	camera->info = NULL;
-	camera->dev = NULL;
+	if (!camera->buf) {
+		minor_data [subminor] = NULL;
+		kfree (camera);
+	} else
+		camera->dev = NULL;
 
-	info("USB Camera disconnected");
+	info ("USB Camera #%d disconnected", subminor);
 }
 
 static /* const */ struct usb_driver camera_driver = {
@@ -443,47 +452,26 @@
 	camera_probe,
 	camera_disconnect,
 	{ NULL, NULL },
-
-	NULL,	/* &usb_camera_fops, */
-	0	/* USB_CAMERA_MINOR */
+	&usb_camera_fops,
+	USB_CAMERA_MINOR_BASE
 };
 
 
-#ifdef MODULE
-static __init
-#endif
-int usb_dc2xx_init(void)
+int __init usb_dc2xx_init(void)
 {
-	struct camera_state *camera = &static_camera_state;
-
-	camera->dev = NULL;
-	camera->isOpen = 0;
-	camera->isActive = 0;
-	init_waitqueue_head (&camera->wait);
-
-	if (usb_register (&camera_driver) < 0)
-		return -1;
-	misc_register (&usb_camera);
-
+ 	if (usb_register (&camera_driver) < 0)
+ 		return -1;
 	return 0;
 }
 
-#ifdef MODULE
-static __exit
-#endif
-void usb_dc2xx_cleanup(void)
+void __exit usb_dc2xx_cleanup(void)
 {
 	usb_deregister (&camera_driver);
-	misc_deregister (&usb_camera);
 }
 
 
-#ifdef MODULE
-
 MODULE_AUTHOR("David Brownell, david-b@pacbell.net");
 MODULE_DESCRIPTION("USB Camera Driver for Kodak DC-2xx series cameras");
 
 module_init (usb_dc2xx_init);
 module_exit (usb_dc2xx_cleanup);
-
-#endif	/* MODULE */
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/devices.c linux/drivers/usb/devices.c
--- v2.3.39/linux/drivers/usb/devices.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/devices.c	Thu Jan 20 15:00:16 2000
@@ -4,6 +4,8 @@
  * (C) Copyright 1999,2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
  * (C) Copyright 1999 Deti Fliegl (new USB architecture)
  *
+ * $id$
+ *
  * 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
@@ -44,7 +46,7 @@
  * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
  *   Turned into its own filesystem
  *
- * $Id: proc_usb.c,v 1.16 1999/12/20 11:11:10 fliegl Exp $
+ * $Id: devices.c,v 1.5 2000/01/11 13:58:21 tom Exp $
  */
 
 #include <linux/fs.h>
@@ -67,16 +69,16 @@
 
 static char *format_string_manufacturer =
 /* S:  Manufacturer=xxxx */
-  "S:  Manufacturer=%s\n";
+  "S:  Manufacturer=%.100s\n";
 
 static char *format_string_product =
 /* S:  Product=xxxx */
-  "S:  Product=%s\n";
+  "S:  Product=%.100s\n";
 
 #ifdef ALLOW_SERIAL_NUMBER
 static char *format_string_serialnumber =
 /* S:  SerialNumber=xxxx */
-  "S:  SerialNumber=%s\n";
+  "S:  SerialNumber=%.100s\n";
 #endif
 
 static char *format_bandwidth =
@@ -213,7 +215,7 @@
  * 2. add <halted> status to each endpoint line
  */
 
-static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, const int active)
+static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, int active)
 {
 	if (start > end)
 		return start;
@@ -226,7 +228,7 @@
 	return start;
 }
 
-static char *usb_dump_config(char *start, char *end, const struct usb_config_descriptor *config, const int active)
+static char *usb_dump_config(char *start, char *end, const struct usb_config_descriptor *config, int active)
 {
 	int i, j;
 	struct usb_interface *interface;
@@ -275,38 +277,34 @@
 /*
  * Dump the different strings that this device holds.
  */
-static char *usb_dump_device_strings (char *start, char *end, const struct usb_device *dev)
+static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev)
 {
 	char *buf;
 
 	if (start > end)
 		return start;
-	buf = kmalloc(256, GFP_KERNEL);
+	buf = kmalloc(128, GFP_KERNEL);
 	if (!buf)
 		return start;
-
 	if (dev->descriptor.iManufacturer) {
-		if (usb_string(dev, dev->descriptor.iManufacturer, buf, 256) > 0)
+		if (usb_string(dev, dev->descriptor.iManufacturer, buf, 128) > 0)
 			start += sprintf(start, format_string_manufacturer, buf);
 	}				
 	if (start > end)
 		goto out;
-
 	if (dev->descriptor.iProduct) {
-		if (usb_string(dev, dev->descriptor.iProduct, buf, 256) > 0)
+		if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0)
 			start += sprintf(start, format_string_product, buf);
 	}
 	if (start > end)
 		goto out;
-
 #ifdef ALLOW_SERIAL_NUMBER
 	if (dev->descriptor.iSerialNumber) {
-		if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 256) > 0)
+		if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 128) > 0)
 			start += sprintf(start, format_string_serialnumber, buf);
 	}
 #endif
-
-out:
+ out:
 	kfree(buf);
 	return start;
 }
@@ -345,11 +343,11 @@
 	if (start > end)
 		return start;
 	start += sprintf(start, "Interface:");
-	while (leng) {
+	while (leng && start <= end) {
 		start += sprintf(start, " %02x", *ptr);
 		ptr++; leng--;
 	}
-	start += sprintf(start, "\n");
+	*start++ = '\n';
 	return start;
 }
 
@@ -359,7 +357,7 @@
 		return start;
 	start += sprintf(start, "Interface:");
 	if (index <= dev->maxstring && dev->stringindex && dev->stringindex[index])
-		start += sprintf(start, "%s: %s ", id, dev->stringindex[index]);
+		start += sprintf(start, "%s: %.100s ", id, dev->stringindex[index]);
 	return start;
 }
 
@@ -419,7 +417,7 @@
 		return 0;
 	if (!access_ok(VERIFY_WRITE, buf, nbytes))
 		return -EFAULT;
-        if (!(page = (char*) __get_free_page(GFP_KERNEL)))
+        if (!(page = (char*) __get_free_pages(GFP_KERNEL,1)))
                 return -ENOMEM;
 	pos = *ppos;
 	/* enumerate busses */
@@ -429,7 +427,7 @@
 		len = sprintf(page, format_bandwidth, bus->bandwidth_allocated, FRAME_TIME_MAX_USECS_ALLOC,
 			      (100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
 			      bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
-		end = usb_device_dump(page + len, page + (PAGE_SIZE - 100), bus->root_hub, bus->busnum, 0, 0, 0);
+		end = usb_device_dump(page + len, page + (2*PAGE_SIZE - 256), bus->root_hub, bus->busnum, 0, 0, 0);
 		len = end - page;
 		if (len > pos) {
 			len -= pos;
@@ -448,7 +446,7 @@
 		} else
 			pos -= len;
 	}
-	free_page((unsigned long)page);
+	free_pages((unsigned long)page, 1);
 	return ret;
 }
 
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/devio.c linux/drivers/usb/devio.c
--- v2.3.39/linux/drivers/usb/devio.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/devio.c	Thu Jan 20 15:00:16 2000
@@ -19,6 +19,8 @@
  *      along with this program; if not, write to the Free Software
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
+ *  $Id: devio.c,v 1.6 2000/01/11 23:26:33 tom Exp $
+ *
  *  This file implements the usbdevfs/x/y files, where
  *  x is the bus number and y the device number.
  *
@@ -37,6 +39,7 @@
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/signal.h>
+#include <linux/poll.h>
 #include <asm/uaccess.h>
 
 #include "usb.h"
@@ -52,6 +55,113 @@
         urb_t urb;
 };
 
+/*
+ * my own sync control and bulk methods. Here to experiment
+ * and because the kernel ones set the process to TASK_UNINTERRUPTIBLE.
+ */
+
+struct sync {
+	wait_queue_head_t wait;
+};
+
+static void sync_completed(purb_t urb)
+{
+        struct sync *s = (struct sync *)urb->context;
+ 
+        wake_up(&s->wait);	
+}
+
+static int do_sync(purb_t urb, int timeout)
+{
+        DECLARE_WAITQUEUE(wait, current);
+	unsigned long tm;
+	signed long tmdiff;
+	struct sync s;
+	int ret;
+
+	tm = jiffies+timeout;
+	init_waitqueue_head(&s.wait);
+	add_wait_queue(&s.wait, &wait);
+	urb->context = &s;
+	urb->complete = sync_completed;
+	set_current_state(TASK_INTERRUPTIBLE);
+	if ((ret = usb_submit_urb(urb)))
+		goto out;
+	while (urb->status == -EINPROGRESS) {
+		tmdiff = tm - jiffies;
+		if (tmdiff <= 0) {
+			ret = -ETIMEDOUT;
+			goto out;
+		}
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			goto out;
+		}
+		schedule_timeout(tmdiff);
+	}
+	ret = urb->status;
+ out:
+	set_current_state(TASK_RUNNING);
+	usb_unlink_urb(urb);
+	remove_wait_queue(&s.wait, &wait);
+	return ret;
+}
+
+static int my_usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
+			      __u16 value, __u16 index, void *data, __u16 size, int timeout)
+{
+	urb_t *urb;
+	int ret;
+
+	if (!(urb = usb_alloc_urb(0)))
+		return -ENOMEM;
+	if (!(urb->setup_packet = kmalloc(8, GFP_KERNEL))) {
+		usb_free_urb(urb);
+		return -ENOMEM;
+	}
+	urb->setup_packet[0] = requesttype;
+	urb->setup_packet[1] = request;
+	urb->setup_packet[2] = value;
+	urb->setup_packet[3] = value >> 8;
+	urb->setup_packet[4] = index;
+	urb->setup_packet[5] = index >> 8;
+	urb->setup_packet[6] = size;
+	urb->setup_packet[7] = size >> 8;
+	urb->dev = dev;
+        urb->pipe = pipe;
+        urb->transfer_buffer = data;
+        urb->transfer_buffer_length = size;
+	ret = do_sync(urb, timeout);
+	if (ret >= 0)
+		ret = urb->status;
+	if (ret >= 0)
+		ret = urb->actual_length;
+	kfree(urb->setup_packet);
+	usb_free_urb(urb);
+	return ret;
+}
+
+static int my_usb_bulk_msg(struct usb_device *dev, unsigned int pipe, 
+			   void *data, int len, int *actual_length, int timeout)
+{
+	urb_t *urb;
+	int ret;
+
+	if (!(urb = usb_alloc_urb(0)))
+		return -ENOMEM;
+        urb->dev = dev;
+        urb->pipe = pipe;
+        urb->transfer_buffer = data;
+        urb->transfer_buffer_length = len;
+	ret = do_sync(urb, timeout);
+	if (ret >= 0)
+		ret = urb->status;
+	if (ret >= 0 && actual_length != NULL)
+		*actual_length = urb->actual_length;
+	usb_free_urb(urb);
+	return ret;
+}
+
 static long long usbdev_lseek(struct file *file, long long offset, int orig)
 {
 	switch (orig) {
@@ -468,8 +578,8 @@
 			free_page((unsigned long)tbuf);
 			return -EINVAL;
 		}
-		i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
-				    ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
+		i = my_usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
+				       ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
 		if ((i > 0) && ctrl.length) {
 			copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
 		}
@@ -477,8 +587,8 @@
 		if (ctrl.length) {
 			copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
 		}
-		i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
-				    ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
+		i = my_usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
+				       ctrl.value, ctrl.index, tbuf, ctrl.length, tmo);
 	}
 	free_page((unsigned long)tbuf);
 	if (i<0) {
@@ -493,7 +603,7 @@
 	struct usb_device *dev = ps->dev;
 	struct usbdevfs_bulktransfer bulk;
 	unsigned int tmo, len1, pipe;
-	unsigned long len2;
+	int len2;
 	unsigned char *tbuf;
 	int i, ret;
 
@@ -519,7 +629,7 @@
 			free_page((unsigned long)tbuf);
 			return -EINVAL;
 		}
-		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+		i = my_usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
 		if (!i && len2) {
 			copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
 		}
@@ -527,7 +637,7 @@
 		if (len1) {
 			copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
 		}
-		i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
+		i = my_usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo);
 	}
 	free_page((unsigned long)tbuf);
 	if (i < 0) {
@@ -599,7 +709,7 @@
 	switch(uurb.type) {
 	case USBDEVFS_URB_TYPE_BULK:
 		uurb.number_of_packets = 0;
-		if (uurb.buffer_length > 8192)
+		if (uurb.buffer_length > 16384)
 			return -EINVAL;
 		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
 			return -EFAULT;
@@ -623,7 +733,7 @@
 			}
 			totlen += isopkt[u].length;
 		}
-		if (totlen > 8192) {
+		if (totlen > 32768) {
 			kfree(isopkt);
 			return -ENOMEM;
 		}
@@ -818,14 +928,20 @@
 	switch (cmd) {
 	case USBDEVFS_CONTROL:
 		ret = proc_control(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
 		break;
 
 	case USBDEVFS_BULK:
 		ret = proc_bulk(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
 		break;
 
 	case USBDEVFS_RESETEP:
 		ret = proc_resetep(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
 		break;
 
 	case USBDEVFS_SETINTERFACE:
@@ -838,6 +954,8 @@
 
 	case USBDEVFS_SUBMITURB:
 		ret = proc_submiturb(ps, (void *)arg);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
 		break;
 
 	case USBDEVFS_DISCARDURB:
@@ -866,15 +984,30 @@
 
 	}
 	up_read(&ps->devsem);
+	if (ret >= 0)
+		inode->i_atime = CURRENT_TIME;
 	return ret;
 }
 
+static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
+{
+	struct dev_state *ps = (struct dev_state *)file->private_data;
+        unsigned int mask = 0;
+
+	poll_wait(file, &ps->wait, wait);
+	if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
+		mask |= POLLOUT | POLLWRNORM;
+	if (!ps->dev)
+		mask |= POLLERR | POLLHUP;
+	return mask;
+}
+
 static struct file_operations usbdevfs_device_file_operations = {
 	usbdev_lseek,    /* lseek   */
 	usbdev_read,     /* read    */
 	NULL,            /* write   */
 	NULL,            /* readdir */
-	NULL,            /* poll    */
+	usbdev_poll,     /* poll    */
 	usbdev_ioctl,    /* ioctl   */
 	NULL,            /* mmap    */
 	usbdev_open,     /* open    */
@@ -886,4 +1019,3 @@
 struct inode_operations usbdevfs_device_inode_operations = {
         &usbdevfs_device_file_operations,  /* file-ops */
 };
-
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/drivers.c linux/drivers/usb/drivers.c
--- v2.3.39/linux/drivers/usb/drivers.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/drivers.c	Thu Jan 20 15:00:16 2000
@@ -4,6 +4,8 @@
  * (C) Copyright 1999, 2000 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
  * (C) Copyright 1999 Deti Fliegl (new USB architecture)
  *
+ * $id$
+ *
  * 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
@@ -29,7 +31,7 @@
  * 2000-01-04: Thomas Sailer <sailer@ife.ee.ethz.ch>
  *   Turned into its own filesystem
  *
- * $Id: proc_usb.c,v 1.16 1999/12/20 11:11:10 fliegl Exp $
+ * $Id: drivers.c,v 1.3 2000/01/11 13:58:24 tom Exp $
  */
 
 #include <linux/fs.h>
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/ezusb.c linux/drivers/usb/ezusb.c
--- v2.3.39/linux/drivers/usb/ezusb.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/usb/ezusb.c	Wed Dec 31 16:00:00 1969
@@ -1,1096 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	ezusb.c  --  Firmware download miscdevice for Anchorchips EZUSB microcontrollers.
- *
- *	Copyright (C) 1999
- *          Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  History:
- *   0.1  26.05.99  Created
- *   0.2  23.07.99  Removed EZUSB_INTERRUPT. Interrupt pipes may be polled with
- *                  bulk reads.
- *                  Implemented EZUSB_SETINTERFACE, more sanity checks for EZUSB_BULK.
- *                  Preliminary ISO support
- *   0.3  01.09.99  Async Bulk and ISO support
- *   0.4  01.09.99  Set callback_frames to the total number of frames to make
- *                  it work with OHCI-HCD
- *        03.12.99  Now that USB error codes are negative, return them to application
- *                  instead of ENXIO
- *  $Id: ezusb.c,v 1.22 1999/12/03 15:06:28 tom Exp $
- */
-
-/*****************************************************************************/
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/miscdevice.h>
-#include <linux/list.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-
-//#include <linux/spinlock.h>
-
-#include "usb.h"
-#include "ezusb.h"
-
-/* --------------------------------------------------------------------- */
-
-#define NREZUSB 1
-
-static struct ezusb {
-	struct semaphore mutex;
-	struct usb_device *usbdev;
-	struct list_head async_pending;
-	struct list_head async_completed;
-	wait_queue_head_t wait;
-	spinlock_t lock;
-} ezusb[NREZUSB];
-
-struct async {
-	struct list_head asynclist;
-	struct ezusb *ez;
-	void *userdata;
-	unsigned datalen;
-	void *context;
-	urb_t urb;
-};
-
-/*-------------------------------------------------------------------*/
-
-static struct async *alloc_async(unsigned int numisoframes)
-{
-	unsigned int assize = sizeof(struct async) + numisoframes * sizeof(iso_packet_descriptor_t);
-	struct async *as = kmalloc(assize, GFP_KERNEL);
-	if (!as)
-		return NULL;
-	memset(as, 0, assize);
-	as->urb.number_of_packets = numisoframes;
-	return as;
-}
-
-static void free_async(struct async *as)
-{
-	if (as->urb.transfer_buffer)
-		kfree(as->urb.transfer_buffer);
-	kfree(as);
-}
-
-/* --------------------------------------------------------------------- */
-
-extern inline unsigned int ld2(unsigned int x)
-{
-	unsigned int r = 0;
-	
-	if (x >= 0x10000) {
-		x >>= 16;
-		r += 16;
-	}
-	if (x >= 0x100) {
-		x >>= 8;
-		r += 8;
-	}
-	if (x >= 0x10) {
-		x >>= 4;
-		r += 4;
-	}
-	if (x >= 4) {
-		x >>= 2;
-		r += 2;
-	}
-	if (x >= 2)
-		r++;
-	return r;
-}
-
-#if 0
-/* why doesn't this work properly on i386? */
-extern inline unsigned int ld2(unsigned int x)
-{
-	unsigned int r;
-
-	__asm__("bsrl %1,%0" : "=r" (r) : "g" (x));
-	return r;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-extern __inline__ void async_removelist(struct async *as)
-{
-	struct ezusb *ez = as->ez;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ez->lock, flags);
-	list_del(&as->asynclist);
-	INIT_LIST_HEAD(&as->asynclist);
-	spin_unlock_irqrestore(&ez->lock, flags);
-}
-
-extern __inline__ void async_newpending(struct async *as)
-{
-	struct ezusb *ez = as->ez;
-	unsigned long flags;
-	
-	spin_lock_irqsave(&ez->lock, flags);
-	list_add_tail(&as->asynclist, &ez->async_pending);
-	spin_unlock_irqrestore(&ez->lock, flags);
-}
-
-extern __inline__ void async_removepending(struct async *as)
-{
-	struct ezusb *ez = as->ez;
-	unsigned long flags;
-	
-	spin_lock_irqsave(&ez->lock, flags);
-	list_del(&as->asynclist);
-	INIT_LIST_HEAD(&as->asynclist);
-	spin_unlock_irqrestore(&ez->lock, flags);
-}
-
-extern __inline__ struct async *async_getcompleted(struct ezusb *ez)
-{
-	unsigned long flags;
-	struct async *as = NULL;
-
-	spin_lock_irqsave(&ez->lock, flags);
-	if (!list_empty(&ez->async_completed)) {
-		as = list_entry(ez->async_completed.next, struct async, asynclist);
-		list_del(&as->asynclist);
-		INIT_LIST_HEAD(&as->asynclist);
-	}
-	spin_unlock_irqrestore(&ez->lock, flags);
-	return as;
-}
-
-extern __inline__ struct async *async_getpending(struct ezusb *ez, void *context)
-{
-	unsigned long flags;
-	struct async *as;
-	struct list_head *p;
-
-	spin_lock_irqsave(&ez->lock, flags);
-	for (p = ez->async_pending.next; p != &ez->async_pending; ) {
-		as = list_entry(p, struct async, asynclist);
-		p = p->next;
-		if (as->context != context)
-			continue;
-		list_del(&as->asynclist);
-		INIT_LIST_HEAD(&as->asynclist);
-		spin_unlock_irqrestore(&ez->lock, flags);
-		return as;
-	}
-	spin_unlock_irqrestore(&ez->lock, flags);
-	return NULL;
-}
-
-/* --------------------------------------------------------------------- */
-
-static void async_completed(purb_t urb)
-{
-	struct async *as = (struct async *)urb->context;
-	struct ezusb *ez = as->ez;
-	unsigned cnt;
-
-printk(KERN_DEBUG "ezusb: async_completed: status %d errcount %d actlen %d pipe 0x%x\n", 
-       urb->status, urb->error_count, urb->actual_length, urb->pipe);
-	spin_lock(&ez->lock);
-	list_del(&as->asynclist);
-	list_add_tail(&as->asynclist, &ez->async_completed);
-	spin_unlock(&ez->lock);
-	wake_up(&ez->wait);
-}
-
-static void destroy_all_async(struct ezusb *ez)
-{
-	struct async *as;
-	unsigned long flags;
-
-	spin_lock_irqsave(&ez->lock, flags);
-	if (!list_empty(&ez->async_pending)) {
-		as = list_entry(ez->async_pending.next, struct async, asynclist);
-		list_del(&as->asynclist);
-		INIT_LIST_HEAD(&as->asynclist);
-		spin_unlock_irqrestore(&ez->lock, flags);
-		/* discard_urb calls the completion handler with status == USB_ST_URB_KILLED */
-		usb_unlink_urb(&as->urb);
-		spin_lock_irqsave(&ez->lock, flags);
-	}
-	spin_unlock_irqrestore(&ez->lock, flags);
-	while ((as = async_getcompleted(ez)))
-		free_async(as);
-}
-
-/* --------------------------------------------------------------------- */
-
-static loff_t ezusb_llseek(struct file *file, loff_t offset, int origin)
-{
-	struct ezusb *ez = (struct ezusb *)file->private_data;
-
-	switch(origin) {
-	case 1:
-		offset += file->f_pos;
-		break;
-	case 2:
-		offset += 0x10000;
-		break;
-	}
-	if (offset < 0 || offset >= 0x10000)
-		return -EINVAL;
-	return (file->f_pos = offset);
-}
-
-static ssize_t ezusb_read(struct file *file, char *buf, size_t sz, loff_t *ppos)
-{
-	struct ezusb *ez = (struct ezusb *)file->private_data;
-	unsigned pos = *ppos;
-	unsigned ret = 0;
-	unsigned len;
-	unsigned char b[64];
-	int i;
-
-	if (*ppos < 0 || *ppos >= 0x10000)
-		return -EINVAL;
-	down(&ez->mutex);
-	if (!ez->usbdev) {
-		up(&ez->mutex);
-		return -EIO;
-	}
-	while (sz > 0 && pos < 0x10000) {
-		len = sz;
-		if (len > sizeof(b))
-			len = sizeof(b);
-		if (pos + len > 0x10000)
-			len = 0x10000 - pos;
-		i = usb_control_msg(ez->usbdev, usb_rcvctrlpipe(ez->usbdev, 0), 0xa0, 0xc0, pos, 0, b, len, HZ);
-		if (i < 0) {
-			up(&ez->mutex);
-			printk(KERN_WARNING "ezusb: upload failed pos %u len %u ret %d\n", pos, len, i);
-			*ppos = pos;
-			if (ret)
-				return ret;
-			return i;
-		}
-		if (copy_to_user(buf, b, len)) {
-			up(&ez->mutex);
-			*ppos = pos;
-			if (ret)
-				return ret;
-			return -EFAULT;
-		}
-		pos += len;
-		buf += len;
-		sz -= len;
-		ret += len;
-	}
-	up(&ez->mutex);
-	*ppos = pos;
-	return ret;
-}
-
-static ssize_t ezusb_write(struct file *file, const char *buf, size_t sz, loff_t *ppos)
-{
-	struct ezusb *ez = (struct ezusb *)file->private_data;
-	unsigned pos = *ppos;
-	unsigned ret = 0;
-	unsigned len;
-	unsigned char b[64];
-	int i;
-
-	if (*ppos < 0 || *ppos >= 0x10000)
-		return -EINVAL;
-	down(&ez->mutex);
-	if (!ez->usbdev) {
-		up(&ez->mutex);
-		return -EIO;
-	}
-	while (sz > 0 && pos < 0x10000) {
-		len = sz;
-		if (len > sizeof(b))
-			len = sizeof(b);
-		if (pos + len > 0x10000)
-			len = 0x10000 - pos;
-		if (copy_from_user(b, buf, len)) {
-			up(&ez->mutex);
-			*ppos = pos;
-			if (ret)
-				return ret;
-			return -EFAULT;
-		}
-		printk("writemem: %d %p %d\n",pos,b,len);
-		i = usb_control_msg(ez->usbdev, usb_sndctrlpipe(ez->usbdev, 0), 0xa0, 0x40, pos, 0, b, len, HZ);
-		if (i < 0) {
-			up(&ez->mutex);
-			printk(KERN_WARNING "ezusb: download failed pos %u len %u ret %d\n", pos, len, i);
-			*ppos = pos;
-			if (ret)
-				return ret;
-			return i;
-		}
-		pos += len;
-		buf += len;
-		sz -= len;
-		ret += len;
-	}
-	up(&ez->mutex);
-	*ppos = pos;
-	return ret;
-}
-
-static int ezusb_open(struct inode *inode, struct file *file)
-{
-	struct ezusb *ez = &ezusb[0];
-
-	down(&ez->mutex);
-	while (!ez->usbdev) {
-		up(&ez->mutex);
-		if (!(file->f_flags & O_NONBLOCK)) {
-			return -EIO;
-		}
-		schedule_timeout(HZ/2);
-		if (signal_pending(current))
-			return -EAGAIN;
-		down(&ez->mutex);
-	}
-	up(&ez->mutex);
-	file->f_pos = 0;
-	file->private_data = ez;
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-static int ezusb_release(struct inode *inode, struct file *file)
-{
-	struct ezusb *ez = (struct ezusb *)file->private_data;
-
-	down(&ez->mutex);
-	destroy_all_async(ez);
-	up(&ez->mutex);
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-static int ezusb_control(struct usb_device *usbdev, unsigned char requesttype,
-			 unsigned char request, unsigned short value, 
-			 unsigned short index, unsigned short length,
-			 unsigned int timeout, void *data)
-{
-	unsigned char *tbuf = NULL;
-	unsigned int pipe;
-	int i;
-
-	if (length > PAGE_SIZE)
-		return -EINVAL;
-	/* __range_ok is broken; 
-	   with unsigned short size, it gave
-	   addl %si,%edx ; sbbl %ecx,%ecx; cmpl %edx,12(%eax); sbbl $0,%ecx
-	*/
-	if (requesttype & 0x80) {
-		pipe = usb_rcvctrlpipe(usbdev, 0);
-		if (length > 0 && !access_ok(VERIFY_WRITE, data, (unsigned int)length))
-			return -EFAULT;
-	} else
-		pipe = usb_sndctrlpipe(usbdev, 0);
-	if (length > 0) {
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (!(requesttype & 0x80)) {
-			if (copy_from_user(tbuf, data, length)) {
-				free_page((unsigned long)tbuf);
-				return -EFAULT;
-			}
-		}
-	}
-	i = usb_control_msg(usbdev, pipe, request, requesttype, value, index, tbuf, length, timeout);
-	if (i < 0) {
-		if (length > 0)
-			free_page((unsigned long)tbuf);
-		printk(KERN_WARNING "ezusb: EZUSB_CONTROL failed rqt %u rq %u len %u ret %d\n", 
-		       requesttype, request, length, i);
-		return i;
-	}
-	if (requesttype & 0x80 && length > 0 && copy_to_user(data, tbuf, length))
-		i = -EFAULT;
-	if (length > 0)
-		free_page((unsigned long)tbuf);
-	return i;
-}
-
-static int ezusb_bulk(struct usb_device *usbdev, unsigned int ep, unsigned int length, unsigned int timeout, void *data)
-{
-	unsigned char *tbuf = NULL;
-	unsigned int pipe;
-	unsigned long len2 = 0;
-	int ret = 0;
-
-	if (length > PAGE_SIZE)
-		return -EINVAL;
-	if ((ep & ~0x80) >= 16)
-		return -EINVAL;
-	if (ep & 0x80) {
-		pipe = usb_rcvbulkpipe(usbdev, ep & 0x7f);
-		if (length > 0 && !access_ok(VERIFY_WRITE, data, length))
-			return -EFAULT;
-	} else
-		pipe = usb_sndbulkpipe(usbdev, ep & 0x7f);
-	if (!usb_maxpacket(usbdev, pipe, !(ep & 0x80)))
-		return -EINVAL;
-	if (length > 0) {
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (!(ep & 0x80)) {
-			if (copy_from_user(tbuf, data, length)) {
-				free_page((unsigned long)tbuf);
-				return -EFAULT;
-			}
-		}
-	}
-	ret = usb_bulk_msg(usbdev, pipe, tbuf, length, &len2, timeout);
-	if (ret < 0) {
-		if (length > 0)
-			free_page((unsigned long)tbuf);
-		printk(KERN_WARNING "ezusb: EZUSB_BULK failed ep 0x%x len %u ret %d\n", 
-		       ep, length, ret);
-		return -ENXIO;
-	}
-	if (len2 > length)
-		len2 = length;
-	ret = len2;
-	if (ep & 0x80 && len2 > 0 && copy_to_user(data, tbuf, len2))
-		ret = -EFAULT;
-	if (length > 0)
-		free_page((unsigned long)tbuf);
-	return ret;
-}
-
-static int ezusb_resetep(struct usb_device *usbdev, unsigned int ep)
-{
-	if ((ep & ~0x80) >= 16)
-		return -EINVAL;
-	usb_settoggle(usbdev, ep & 0xf, !(ep & 0x80), 0);
-	return 0;
-}
-
-static int ezusb_setinterface(struct usb_device *usbdev, unsigned int interface, unsigned int altsetting)
-{
-	if (usb_set_interface(usbdev, interface, altsetting) < 0)
-		return -EINVAL;
-	return 0;
-}
-
-static int ezusb_setconfiguration(struct usb_device *usbdev, unsigned int config)
-{
-	if (usb_set_configuration(usbdev, config) < 0)
-		return -EINVAL;
-	return 0;
-}
-
-#define usb_sndintpipe(dev,endpoint)   ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvintpipe(dev,endpoint)   ((PIPE_INTERRUPT << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-
-char* stuff[512];
-
-static void int_compl(purb_t purb)
-{
-  printk("INT_COMPL\n");
-  
-}
-
-static int ezusb_interrupt(struct ezusb *ez, struct ezusb_interrupt *ab)
-{
-  urb_t *urb;
-  unsigned int pipe;
-
-  urb=(urb_t*)kmalloc(sizeof(urb_t),GFP_KERNEL);
-  if (!urb)
-  {
-    return -ENOMEM;
-  }
-  memset(urb,0,sizeof(urb_t));
-  
- 
-  if ((ab->ep & ~0x80) >= 16)
-    return -EINVAL;
-  if (ab->ep & 0x80) 
-    {
-      pipe = usb_rcvintpipe(ez->usbdev, ab->ep & 0x7f);
-      if (ab->len > 0 && !access_ok(VERIFY_WRITE, ab->data, ab->len))
-	return -EFAULT;
-    } 
-  else
-    pipe = usb_sndintpipe(ez->usbdev, ab->ep & 0x7f);
-  
-  memcpy(stuff,ab->data,64);
-  urb->transfer_buffer=stuff;
-  urb->transfer_buffer_length=ab->len;
-  urb->complete=int_compl;
-  urb->pipe=pipe;
-  urb->dev=ez->usbdev;
-  urb->interval=ab->interval;
-  return usb_submit_urb(urb);
-}
-
-static int ezusb_requestbulk(struct ezusb *ez, struct ezusb_asyncbulk *ab)
-{
-	struct async *as = NULL;
-	void *data = NULL;
-	unsigned int pipe;
-	int ret;
-
-	if (ab->len > PAGE_SIZE)
-		return -EINVAL;
-	if ((ab->ep & ~0x80) >= 16)
-		return -EINVAL;
-	if (ab->ep & 0x80) {
-		pipe = usb_rcvbulkpipe(ez->usbdev, ab->ep & 0x7f);
-		if (ab->len > 0 && !access_ok(VERIFY_WRITE, ab->data, ab->len))
-			return -EFAULT;
-	} else
-		pipe = usb_sndbulkpipe(ez->usbdev, ab->ep & 0x7f);
-	if (!usb_maxpacket(ez->usbdev, pipe, !(ab->ep & 0x80)))
-		return -EINVAL;
-	if (ab->len > 0 && !(data = kmalloc(ab->len, GFP_KERNEL)))
-		return -ENOMEM;
-	if (!(as = alloc_async(0))) {
-		if (data)
-			kfree(data);
-		return -ENOMEM;
-	}
-	INIT_LIST_HEAD(&as->asynclist);
-	as->ez = ez;
-	as->userdata = ab->data;
-	as->datalen = ab->len;
-	as->context = ab->context;
-	as->urb.dev = ez->usbdev;
-	as->urb.pipe = pipe;
-	as->urb.transfer_flags = 0;
-	as->urb.transfer_buffer = data;
-	as->urb.transfer_buffer_length = ab->len;
-	as->urb.context = as;
-	as->urb.complete = (usb_complete_t)async_completed;
-	if (ab->len > 0 && !(ab->ep & 0x80)) {
-		if (copy_from_user(data, ab->data, ab->len)) {
-			free_async(as);
-			return -EFAULT;
-		}
-		as->userdata = NULL; /* no need to copy back at completion */
-	}
-	async_newpending(as);
-	if ((ret = usb_submit_urb(&as->urb))) {
- printk(KERN_DEBUG "ezusb: bulk: usb_submit_urb returned %d\n", ret);
-		async_removepending(as);
-		free_async(as);
-		return -EINVAL; /* return ret; */
-	}
-	return 0;
-}
-
-static int ezusb_requestiso(struct ezusb *ez, struct ezusb_asynciso *ai, unsigned char *cmd)
-{
-	struct async *as;
-	void *data = NULL;
-	unsigned int maxpkt, pipe, dsize, totsize, i, j;
-	int ret;
-
-	if ((ai->ep & ~0x80) >= 16 || ai->framecnt < 1 || ai->framecnt > 128)
-		return -EINVAL;
-	if (ai->ep & 0x80)
-		pipe = usb_rcvisocpipe(ez->usbdev, ai->ep & 0x7f);
-	else
-		pipe = usb_sndisocpipe(ez->usbdev, ai->ep & 0x7f);
-	if (!(maxpkt = usb_maxpacket(ez->usbdev, pipe, !(ai->ep & 0x80))))
-		return -EINVAL;
-	dsize = maxpkt * ai->framecnt;
-//printk(KERN_DEBUG "ezusb: iso: dsize %d\n", dsize);
-	if (dsize > 65536) 
-		return -EINVAL;
-	if (ai->ep & 0x80)
-		if (dsize > 0 && !access_ok(VERIFY_WRITE, ai->data, dsize))
-			return -EFAULT;
-	if (dsize > 0 && !(data = kmalloc(dsize, GFP_KERNEL)))
-	{
-		printk("dsize: %d failed\n",dsize);
-		return -ENOMEM;
-	}
-	if (!(as = alloc_async(ai->framecnt))) {
-		if (data)
-			kfree(data);
-		printk("alloc_async failed\n");			
-		return -ENOMEM;
-	}
-	INIT_LIST_HEAD(&as->asynclist);
-	
-	as->ez = ez;
-	as->userdata = ai->data;
-	as->datalen = dsize;
-	as->context = ai->context;
-	
-	as->urb.dev = ez->usbdev;
-	as->urb.pipe = pipe;
-	as->urb.transfer_flags = USB_ISO_ASAP;
-	as->urb.transfer_buffer = data;
-	as->urb.transfer_buffer_length = dsize;
-	as->urb.context = as;
-	as->urb.complete = (usb_complete_t)async_completed;
-
-	for (i = totsize = 0; i < as->urb.number_of_packets; i++) {
-		as->urb.iso_frame_desc[i].offset = totsize;
-		if (get_user(j, (int *)(cmd + i * sizeof(struct ezusb_isoframestat)))) {
-			free_async(as);
-			return -EFAULT;
-		}
-		as->urb.iso_frame_desc[i].length = j;
-		totsize += j;
-	}
-	if (dsize > 0 && totsize > 0 && !(ai->ep & 0x80)) {
-		if (copy_from_user(data, ai->data, totsize)) {
-			free_async(as);
-			return -EFAULT;
-		}
-		as->userdata = NULL; /* no need to copy back at completion */
-	}
-	async_newpending(as);
-	if ((ret = usb_submit_urb(&as->urb))) {
- printk(KERN_DEBUG "ezusb: iso: usb_submit_urb returned %d\n", ret);
-		async_removepending(as);
-		free_async(as);
-		return -EINVAL; /* return ret; */
-	}
-	return 0;
-}
-
-static int ezusb_terminateasync(struct ezusb *ez, void *context)
-{
-	struct async *as;
-	int ret = 0;
-
-	while ((as = async_getpending(ez, context))) {
-		usb_unlink_urb(&as->urb);
-		ret++;
-	}
-	return ret;
-}
-
-static int ezusb_asynccompl(struct async *as, void *arg)
-{
-	struct ezusb_asynccompleted *cpl;
-	unsigned int numframes, cplsize, i;
-
-	if (as->userdata) {
-		if (copy_to_user(as->userdata, as->urb.transfer_buffer, as->datalen)) {
-			free_async(as);
-			return -EFAULT;
-		}
-	}
-	numframes = as->urb.number_of_packets;
-	cplsize = sizeof(struct ezusb_asynccompleted) + numframes * sizeof(struct ezusb_isoframestat);
-	if (!(cpl = kmalloc(cplsize, GFP_KERNEL))) {
-		free_async(as);
-		return -ENOMEM;
-	}
-	cpl->status = as->urb.status;
-	cpl->length = as->urb.actual_length;
-	cpl->context = as->context;
-	for (i = 0; i < numframes; i++) {
-		cpl->isostat[i].length = as->urb.iso_frame_desc[i].length;
-		cpl->isostat[i].status = as->urb.iso_frame_desc[i].status;
-	}
-	free_async(as);
-	if (copy_to_user(arg, cpl, cplsize)) {
-		kfree(cpl);
-		return -EFAULT;
-	}
-	kfree(cpl);
-	return 0;
-}
-
-static int ezusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct ezusb *ez = (struct ezusb *)file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
-	struct usb_proc_ctrltransfer pctrl;
-	struct usb_proc_bulktransfer pbulk;
-	struct usb_proc_old_ctrltransfer opctrl;
-	struct usb_proc_old_bulktransfer opbulk;
-	struct usb_proc_setinterface psetintf;
-	struct ezusb_ctrltransfer ctrl;
-	struct ezusb_bulktransfer bulk;
-	struct ezusb_old_ctrltransfer octrl;
-	struct ezusb_old_bulktransfer obulk;
-	struct ezusb_setinterface setintf;
-	struct ezusb_asyncbulk abulk;
-	struct ezusb_asynciso aiso;
-	struct ezusb_interrupt ezint;
-	struct async *as;
-	void *context;
-	unsigned int ep, cfg;
-	int i, ret = 0;
-
-	down(&ez->mutex);
-	if (!ez->usbdev) {
-		up(&ez->mutex);
-		return -EIO;
-	}
-	switch (cmd) {
-	case USB_PROC_CONTROL:
-		if (copy_from_user(&pctrl, (void *)arg, sizeof(pctrl))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_control(ez->usbdev, pctrl.requesttype, pctrl.request, 
-				    pctrl.value, pctrl.index, pctrl.length, 
-				    (pctrl.timeout * HZ + 500) / 1000, pctrl.data);
-		break;
-
-	case USB_PROC_BULK:
-		if (copy_from_user(&pbulk, (void *)arg, sizeof(pbulk))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_bulk(ez->usbdev, pbulk.ep, pbulk.len, 
-				 (pbulk.timeout * HZ + 500) / 1000, pbulk.data);
-		break;
-
-	case USB_PROC_OLD_CONTROL:
-		if (copy_from_user(&opctrl, (void *)arg, sizeof(opctrl))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_control(ez->usbdev, opctrl.requesttype, opctrl.request, 
-				    opctrl.value, opctrl.index, opctrl.length, HZ, opctrl.data);
-		break;
-
-	case USB_PROC_OLD_BULK:
-		if (copy_from_user(&opbulk, (void *)arg, sizeof(opbulk))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_bulk(ez->usbdev, opbulk.ep, opbulk.len, 5*HZ, opbulk.data);
-		break;
-
-	case USB_PROC_RESETEP:
-		if (get_user(ep, (unsigned int *)arg)) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_resetep(ez->usbdev, ep);
-		break;
-	
-	case USB_PROC_SETINTERFACE:
-		if (copy_from_user(&psetintf, (void *)arg, sizeof(psetintf))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_setinterface(ez->usbdev, psetintf.interface, psetintf.altsetting);
-		break;
-
-	case USB_PROC_SETCONFIGURATION:
-		if (get_user(cfg, (unsigned int *)arg)) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_setconfiguration(ez->usbdev, cfg);
-		break;
-
-	case EZUSB_CONTROL:
-		if (copy_from_user(&ctrl, (void *)arg, sizeof(ctrl))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_control(ez->usbdev, ctrl.requesttype, ctrl.request, 
-				    ctrl.value, ctrl.index, ctrl.length, 
-				    (ctrl.timeout * HZ + 500) / 1000, ctrl.data);
-		break;
-
-	case EZUSB_BULK:
-		if (copy_from_user(&bulk, (void *)arg, sizeof(bulk))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_bulk(ez->usbdev, bulk.ep, bulk.len, 
-				 (bulk.timeout * HZ + 500) / 1000, bulk.data);
-		break;
-
-	case EZUSB_OLD_CONTROL:
-		if (copy_from_user(&octrl, (void *)arg, sizeof(octrl))) {
-			ret = -EFAULT;
-			break;
-		}
-		if (octrl.dlen != octrl.length) {
-			ret = -EINVAL;
-			break;
-		}
-		ret = ezusb_control(ez->usbdev, octrl.requesttype, octrl.request, 
-				    octrl.value, octrl.index, octrl.length, HZ, octrl.data);
-		break;
-
-	case EZUSB_OLD_BULK:
-		if (copy_from_user(&obulk, (void *)arg, sizeof(obulk))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_bulk(ez->usbdev, obulk.ep, obulk.len, 5*HZ, obulk.data);
-		break;
-
-	case EZUSB_RESETEP:
-		if (get_user(ep, (unsigned int *)arg)) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_resetep(ez->usbdev, ep);
-		break;
-	
-	case EZUSB_SETINTERFACE:
-		if (copy_from_user(&setintf, (void *)arg, sizeof(setintf))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_setinterface(ez->usbdev, setintf.interface, setintf.altsetting);
-		break;
-
-	case EZUSB_SETCONFIGURATION:
-		if (get_user(cfg, (unsigned int *)arg)) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_setconfiguration(ez->usbdev, cfg);
-		break;
-
-	case EZUSB_ASYNCCOMPLETED:
-		as = NULL;
-		current->state = TASK_INTERRUPTIBLE;
-		add_wait_queue(&ez->wait, &wait);
-		for (;;) {
-			if (!ez->usbdev)
-				break;
-			if ((as = async_getcompleted(ez)))
-				break;
-			if (signal_pending(current))
-				break;
-			up(&ez->mutex);
-			schedule();
-			down(&ez->mutex);
-		}
-		remove_wait_queue(&ez->wait, &wait);
-		current->state = TASK_RUNNING;
-		if (as) {
-			ret = ezusb_asynccompl(as, (void *)arg);
-			break;
-		}
-		if (signal_pending(current)) {
-			ret = -EINTR;
-			break;
-		}
-		ret = -EIO;
-		break;
-
-	case EZUSB_ASYNCCOMPLETEDNB:
-		if ((as = async_getcompleted(ez))) {
-			ret = ezusb_asynccompl(as, (void *)arg);
-			break;
-		}
-		ret = -EAGAIN;
-		break;
-
-	case EZUSB_REQUESTBULK:
-		if (copy_from_user(&abulk, (void *)arg, sizeof(abulk))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_requestbulk(ez, &abulk);
-		break;	
-
-	case EZUSB_REQUESTISO:
-		if (copy_from_user(&aiso, (void *)arg, sizeof(aiso))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_requestiso(ez, &aiso, ((unsigned char *)arg)+sizeof(aiso));
-		break;
-
-	case EZUSB_TERMINATEASYNC:
-		if (get_user(context, (void **)arg)) {
-			ret = -EFAULT;
-			break;
-		}
-		ret = ezusb_terminateasync(ez, context);
-		break;
-
-	case EZUSB_GETFRAMENUMBER:
-		i = usb_get_current_frame_number(ez->usbdev);
-		ret = put_user(i, (int *)arg);
-		break;
-
-	case EZUSB_INTERRUPT:
-	  printk("INT START\n");
-		if (copy_from_user(&ezint, (void *)arg, sizeof(ezint))) {
-			ret = -EFAULT;
-			break;
-		}
-		ret=ezusb_interrupt(ez,&ezint);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-	up(&ez->mutex);
-	return ret;
-}
-
-static struct file_operations ezusb_fops = {
-	ezusb_llseek,
-	ezusb_read,
-	ezusb_write,
-	NULL,  /* readdir */
-	NULL,  /* poll */
-	ezusb_ioctl,
-	NULL,  /* mmap */
-	ezusb_open,
-	NULL,  /* flush */
-	ezusb_release,
-	NULL,  /* fsync */
-	NULL,  /* fasync */
-	NULL   /* lock */
-};
-
-/* --------------------------------------------------------------------- */
-
-static void * ezusb_probe(struct usb_device *usbdev, unsigned int ifnum)
-{
-	struct ezusb *ez = &ezusb[0];
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-
-#undef KERN_DEBUG
-#define KERN_DEBUG ""
-	printk(KERN_DEBUG "ezusb: probe: vendor id 0x%x, device id 0x%x\n",
-	       usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
-
-	/* the 1234:5678 is just a self assigned test ID */
-	if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) 
-	#if 1
-		&&
-	    (usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x9999) &&
-	    (usbdev->descriptor.idVendor != 0x1234 || usbdev->descriptor.idProduct != 0x5678)
-	   #endif 
-	    )
-		return NULL;
-
-	/* We don't handle multiple configurations */
-	if (usbdev->descriptor.bNumConfigurations != 1)
-		return NULL;
-
-#if 0
-	/* We don't handle multiple interfaces */
-	if (usbdev->config[0].bNumInterfaces != 1)
-		return NULL;
-#endif
-
-	down(&ez->mutex);
-	if (ez->usbdev) {
-		up(&ez->mutex);
-		printk(KERN_INFO "ezusb: device already used\n");
-		return NULL;
-	}
-	ez->usbdev = usbdev;
-	if (usb_set_configuration(usbdev, usbdev->config[0].bConfigurationValue) < 0) {
-		printk(KERN_ERR "ezusb: set_configuration failed\n");
-		goto err;
-	}
-
-	interface = &usbdev->config[0].interface[0].altsetting[1];
-	if (usb_set_interface(usbdev, 0, 1) < 0) {
-		printk(KERN_ERR "ezusb: set_interface failed\n");
-		goto err;
-	}
-	up(&ez->mutex);
-	MOD_INC_USE_COUNT;
-	return ez;
-
- err:
-	up(&ez->mutex);
-	ez->usbdev = NULL;
-	return NULL;
-}
-
-static void ezusb_disconnect(struct usb_device *usbdev, void *ptr)
-{
-	struct ezusb *ez = (struct ezusb *)ptr;
-
-	down(&ez->mutex);
-	destroy_all_async(ez);
-	ez->usbdev = NULL;
-	up(&ez->mutex);
-	wake_up(&ez->wait);
-	MOD_DEC_USE_COUNT;
-}
-
-static struct usb_driver ezusb_driver = {
-	"ezusb",
-	ezusb_probe,
-	ezusb_disconnect,
-	{ NULL, NULL },
-	&ezusb_fops,
-	192
-};
-
-/* --------------------------------------------------------------------- */
-
-int ezusb_init(void)
-{
-	unsigned u;
-
-	/* initialize struct */
-	for (u = 0; u < NREZUSB; u++) {
-		init_MUTEX(&ezusb[u].mutex);
-		ezusb[u].usbdev = NULL;
-		INIT_LIST_HEAD(&ezusb[u].async_pending);
-		INIT_LIST_HEAD(&ezusb[u].async_completed);
-		init_waitqueue_head(&ezusb[u].wait);
-		spin_lock_init(&ezusb[u].lock);
-	}
-	/* register misc device */
-	usb_register(&ezusb_driver);
-	printk(KERN_INFO "ezusb: Anchorchip firmware download driver registered\n");
-	return 0;
-}
-
-void ezusb_cleanup(void)
-{
-	usb_deregister(&ezusb_driver);
-}
-
-/* --------------------------------------------------------------------- */
-
-#ifdef MODULE
-
-int minor = 192;
-
-int init_module(void)
-{
-	return ezusb_init();
-}
-
-void cleanup_module(void)
-{
-	ezusb_cleanup();
-}
-
-#endif
-
-/* --------------------------------------------------------------------- */
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/ezusb.h linux/drivers/usb/ezusb.h
--- v2.3.39/linux/drivers/usb/ezusb.h	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/ezusb.h	Wed Dec 31 16:00:00 1969
@@ -1,126 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	ezusb.h  --  Firmware download miscdevice for Anchorchips EZUSB microcontrollers.
- *
- *	Copyright (C) 1999
- *          Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the GNU General Public License as published by
- *	the Free Software Foundation; either version 2 of the License, or
- *	(at your option) any later version.
- *
- *	This program is distributed in the hope that it will be useful,
- *	but WITHOUT ANY WARRANTY; without even the implied warranty of
- *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *	GNU General Public License for more details.
- *
- *	You should have received a copy of the GNU General Public License
- *	along with this program; if not, write to the Free Software
- *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-/*****************************************************************************/
-
-#ifndef _LINUX_EZUSB_H
-#define _LINUX_EZUSB_H
-
-#include <linux/ioctl.h>
-
-/* --------------------------------------------------------------------- */
-
-struct ezusb_old_ctrltransfer {
-	/* keep in sync with usb.h:devrequest */
-	unsigned char requesttype;
-	unsigned char request;
-	unsigned short value;
-	unsigned short index;
-	unsigned short length;
-	unsigned int dlen;
-	void *data;
-};
-
-struct ezusb_old_bulktransfer {
-	unsigned int ep;
-	unsigned int len;
-	void *data;
-};
-
-struct ezusb_ctrltransfer {
-	/* keep in sync with usb.h:devrequest */
-	unsigned char requesttype;
-	unsigned char request;
-	unsigned short value;
-	unsigned short index;
-	unsigned short length;
-	unsigned int timeout;  /* in milliseconds */
-	void *data;
-};
-
-struct ezusb_bulktransfer {
-	unsigned int ep;
-	unsigned int len;
-	unsigned int timeout;  /* in milliseconds */
-	void *data;
-};
-
-struct ezusb_interrupt {
-	unsigned int ep;
-	unsigned int len;
-	unsigned int interval;  /* in milliseconds */
-	void *data;
-};
-struct ezusb_setinterface {
-	unsigned int interface;
-	unsigned int altsetting;
-};
-
-struct ezusb_isoframestat {
-	unsigned int length;
-	unsigned int status;
-};
-
-struct ezusb_asynccompleted {
-	int status;
-	unsigned length;
-	void *context;
-	struct ezusb_isoframestat isostat[0];
-};
-
-struct ezusb_asyncbulk {
-	unsigned int ep;
-	unsigned int len;
-	void *context;
-	void *data;
-};
-
-struct ezusb_asynciso {
-	unsigned int ep;
-	
-	unsigned int framecnt;
-	unsigned int startframe;
-
-	void *context;
-	void *data;
-	struct ezusb_isoframestat isostat[0];
-};
-
-#define EZUSB_CONTROL           _IOWR('E', 1, struct ezusb_ctrltransfer)
-#define EZUSB_BULK              _IOWR('E', 2, struct ezusb_bulktransfer)
-#define EZUSB_OLD_CONTROL       _IOWR('E', 0, struct ezusb_old_ctrltransfer)
-#define EZUSB_OLD_BULK          _IOWR('E', 2, struct ezusb_old_bulktransfer)
-#define EZUSB_RESETEP           _IOR('E', 3, unsigned int)
-#define EZUSB_SETINTERFACE      _IOR('E', 4, struct ezusb_setinterface)
-#define EZUSB_SETCONFIGURATION  _IOR('E', 5, unsigned int)
-#define EZUSB_ASYNCCOMPLETED    _IOW('E', 8, struct ezusb_asynccompleted)
-#define EZUSB_ASYNCCOMPLETEDNB  _IOW('E', 9, struct ezusb_asynccompleted)
-#define EZUSB_REQUESTBULK       _IOR('E', 16, struct ezusb_asyncbulk)
-#define EZUSB_REQUESTISO        _IOR('E', 17, struct ezusb_asynciso)
-#define EZUSB_TERMINATEASYNC    _IOR('E', 18, void *)
-#define EZUSB_GETFRAMENUMBER    _IOW('E', 19, unsigned int)
-#define EZUSB_INTERRUPT		_IOWR('E', 20, struct ezusb_interrupt)
-
-/* --------------------------------------------------------------------- */
-#endif /* _LINUX_EZUSB_H */
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/graphire.c linux/drivers/usb/graphire.c
--- v2.3.39/linux/drivers/usb/graphire.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/graphire.c	Thu Jan 20 09:48:48 2000
@@ -0,0 +1,186 @@
+/*
+ *  graphire.c  Version 0.1
+ *
+ *  Copyright (c) 1999 Vojtech Pavlik
+ *
+ *  USB Wacom Graphire tablet support
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * 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
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include "usb.h"
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+
+/*
+ * Thanks for the following information to: Andreas Bach Aaen <abach@mail1.stofanet.dk>
+ *
+ * The input report:
+ * 
+ * byte 0: report ID (2)
+ * byte 1: bit7 	mouse/pen/rubber near
+ *         bit5-6	0 - pen, 1 - rubber, 2 - mouse
+ * 	   bit4		1 ?
+ *         bit3		0 ?
+ *         bit2		mouse middle button / pen button2
+ *         bit1		mouse right button / pen button1
+ *         bit0		mouse left button / pen tip / rubber
+ * byte 2: X low bits
+ * byte 3: X high bits
+ * byte 4: Y low bits
+ * byte 5: Y high bits
+ * byte 6: pen pressure low bits / mouse wheel
+ * byte 7: pen presure high bits / mouse distance
+ * 
+ * There are also two single-byte feature reports (2 and 3).
+ */
+
+#define USB_VENDOR_ID_WACOM		0xffff	/* FIXME */
+#define USB_DEVICE_ID_WACOM_GRAPHIRE	0xffff	/* FIXME */
+
+struct graphire {
+	signed char data[8];
+	int oldx, oldy;
+	struct input_dev dev;
+	struct urb irq;
+};
+
+static void graphire_irq(struct urb *urb)
+{
+	struct graphire *graphire = urb->context;
+	unsigned char *data = graphire->data;
+	struct input_dev *dev = &graphire->dev;
+
+	if (urb->status) return;
+
+	if (data[0] != 2)
+		dbg("received unknown report #%d", data[0]);
+
+	input_report_abs(dev, ABS_X, data[2] | ((__u32)data[3] << 8));
+	input_report_abs(dev, ABS_Y, data[4] | ((__u32)data[5] << 8));
+
+	input_report_key(dev, BTN_NEAR, !!(data[1] & 0x80));
+
+	switch ((data[1] >> 5) & 3) {
+
+		case 0:	/* Pen */
+			input_report_key(dev, BTN_PEN, !!(data[1] & 0x01));
+			input_report_key(dev, BTN_PEN_SIDE, !!(data[1] & 0x02));
+			input_report_key(dev, BTN_PEN_SIDE2, !!(data[1] & 0x04));
+			input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+			break;
+
+		case 1: /* Rubber */
+			input_report_key(dev, BTN_RUBBER, !!(data[1] & 0x01));
+			input_report_key(dev, BTN_PEN_SIDE, !!(data[1] & 0x02));
+			input_report_key(dev, BTN_PEN_SIDE2, !!(data[1] & 0x04));
+			input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+			break;
+
+		case 2: /* Mouse */
+			input_report_key(dev, BTN_LEFT, !!(data[0] & 0x01));
+			input_report_key(dev, BTN_RIGHT, !!(data[0] & 0x02));
+			input_report_key(dev, BTN_MIDDLE, !!(data[0] & 0x04));
+			input_report_abs(dev, ABS_DISTANCE, data[7]);
+
+			if (data[1] & 0x80) {
+				input_report_rel(dev, REL_X, dev->abs[ABS_X] - graphire->oldx);
+				input_report_rel(dev, REL_Y, dev->abs[ABS_Y] - graphire->oldy);
+			}
+
+			input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+			break;
+	}
+
+	graphire->oldx = dev->abs[ABS_X];
+	graphire->oldy = dev->abs[ABS_Y];
+}
+
+static void *graphire_probe(struct usb_device *dev, unsigned int ifnum)
+{
+	struct usb_endpoint_descriptor *endpoint;
+	struct graphire *graphire;
+
+	if (dev->descriptor.idVendor != USB_VENDOR_ID_WACOM ||
+	    dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_GRAPHIRE)
+		return NULL;
+
+	endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
+
+	if (!(graphire = kmalloc(sizeof(struct graphire), GFP_KERNEL))) return NULL;
+	memset(graphire, 0, sizeof(struct graphire));
+
+	graphire->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+	graphire->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+	graphire->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_PEN) | BIT(BTN_RUBBER);
+	graphire->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_PEN_SIDE) | BIT(BTN_PEN_SIDE2) | BIT(BTN_NEAR);
+	graphire->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
+	graphire->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
+
+	FILL_INT_URB(&graphire->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+			graphire->data, 8, graphire_irq, graphire, endpoint->bInterval);
+
+	if (usb_submit_urb(&graphire->irq)) {
+		kfree(graphire);
+		return NULL;
+	}
+
+	input_register_device(&graphire->dev);
+
+	printk(KERN_INFO "input%d: Wacom Graphire USB\n", graphire->dev.number);
+
+	return graphire;
+}
+
+static void graphire_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct graphire *graphire = ptr;
+	usb_unlink_urb(&graphire->irq);
+	input_unregister_device(&graphire->dev);
+	kfree(graphire);
+}
+
+static struct usb_driver graphire_driver = {
+	name:		"graphire",
+	probe:		graphire_probe,
+	disconnect:	graphire_disconnect,
+};
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	usb_deregister(&graphire_driver);
+}
+
+int init_module(void)
+#else
+int graphire_init(void)
+#endif
+{
+	usb_register(&graphire_driver);
+	return 0;
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/hid-debug.h linux/drivers/usb/hid-debug.h
--- v2.3.39/linux/drivers/usb/hid-debug.h	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/hid-debug.h	Mon Jan 17 16:24:48 2000
@@ -1,8 +1,8 @@
 /*
  *  driver/usb/hid-debug.h
  *
- *  (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de>
- *  (c) 1999 Vojtech Pavlik <vojtech@suse.cz>
+ *  (c) 1999 Andreas Gal	<gal@cs.uni-magdeburg.de>
+ *  (c) 2000 Vojtech Pavlik	<vojtech@suse.cz>
  *
  *  Some debug stuff for the HID parser.
  *
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/hid.c linux/drivers/usb/hid.c
--- v2.3.39/linux/drivers/usb/hid.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/hid.c	Thu Jan 20 09:48:48 2000
@@ -2,7 +2,7 @@
  *  hid.c  Version 0.8
  *
  *  Copyright (c) 1999 Andreas Gal
- *  Copyright (c) 1999 Vojtech Pavlik
+ *  Copyright (c) 2000 Vojtech Pavlik
  *
  *  USB HID support for the Linux input drivers
  *
@@ -41,6 +41,7 @@
 #include <linux/spinlock.h>
 
 #undef DEBUG
+#undef DEBUG_DATA
 
 #include "usb.h"
 #include "hid.h"
@@ -709,7 +710,7 @@
 static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value)
 {
 	report += (offset >> 5) << 2; offset &= 31;
-	*(__u64*)report &= cpu_to_le64(~((1ULL << n) - 1) << offset);
+	*(__u64*)report &= cpu_to_le64(~((((__u64) 1 << n) - 1) << offset));
 	*(__u64*)report |= cpu_to_le64((__u64)value << offset);
 }
 
@@ -762,6 +763,12 @@
 			}
 			break;
 
+		case HID_UP_LED:
+
+			usage->code = (usage->hid - 1) & 0xf;
+			usage->type = EV_LED; bit = input->ledbit; max = LED_MAX; 
+			break;
+
 		default:
 
 			if (field->flags & HID_MAIN_ITEM_RELATIVE) {
@@ -904,7 +911,7 @@
 		return;
 	}
 
-#ifdef DEBUG
+#ifdef DEBUG_DATA
 	printk(KERN_DEBUG __FILE__ ": report (size %u) (%snumbered) = ", len, report_enum->numbered ? "" : "un");
 	for (n = 0; n < len; n++)
 		printk(" %02x", data[n]);
@@ -952,10 +959,10 @@
 static void hid_read_report(struct hid_device *hid, struct hid_report *report)
 {
 #if 0
-	int rlen = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
+	int rlen = ((report->size - 1) >> 3) + 1 +  hid->report_enum[HID_INPUT_REPORT].numbered;
 	char rdata[rlen];
 	struct urb urb;
-	int read;
+	int read, j;
 
 	memset(&urb, 0, sizeof(struct urb));
 	memset(rdata, 0, rlen);
@@ -973,7 +980,7 @@
 		for (j = 0; j < rlen; j++) printk(" %02x", rdata[j]);
 		printk("\n");
 #endif
-		continue;
+		return;
 	}
 
 	hid_irq(&urb);
@@ -981,33 +988,6 @@
 }
 
 /*
- * Configure the input layer interface
- * Read all reports and initalize the absoulte field values.
- */
-
-static void hid_init_input(struct hid_device *hid)
-{
-	struct hid_report_enum *report_enum = hid->report_enum + HID_INPUT_REPORT;
-	struct list_head *list;
-	int i, j;
-
-	list = report_enum->report_list.next;
-
-	while (list != &report_enum->report_list) {
-
-		struct hid_report *report = (struct hid_report *) list;
-
-		list = list->next;
-
-		for (i = 0; i < report->maxfield; i++)
-			for (j = 0; j < report->field[i]->maxusage; j++)
-				hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
-
-		hid_read_report(hid, report);
-	}
-}
-
-/*
  * Output the field into the report.
  */
 
@@ -1034,9 +1014,11 @@
 {
 	unsigned n;
 
+#if 0
 	/* skip the ID if we have a single report */
 	if (report->device->report_enum[report->type].numbered)
 		*data++ = report->id;
+#endif
 
 	for (n = 0; n < report->maxfield; n++)
 		hid_output_field(report->field[n], data);
@@ -1051,6 +1033,8 @@
 int hid_set_field(struct hid_field *field, unsigned offset, __s32 value)
 {
 	unsigned size = field->report_size;
+
+	hid_dump_input(field->usage + offset, value);
 	
 	if (offset >= field->report_count) {
 		dbg("offset exceeds report_count");
@@ -1071,10 +1055,104 @@
 	return 0;
 }
 
+static int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+{
+	struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
+	struct list_head *list = report_enum->report_list.next;
+	int i, j;
+
+	while (list != &report_enum->report_list) {
+		struct hid_report *report = (struct hid_report *) list;
+		list = list->next;
+		for (i = 0; i < report->maxfield; i++) {
+			*field = report->field[i];
+			for (j = 0; j < (*field)->maxusage; j++)
+				if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
+					return j;
+		}
+	}
+	return -1;
+}
+
+static void hid_ctrl(struct urb *urb)
+{
+        if (urb->status)
+                warn("ctrl urb status %d received", urb->status);
+}       
+
+static int hid_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
+{
+	struct hid_device *hid = dev->private;
+	struct hid_field *field = NULL;
+	int offset;
+
+	if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
+		warn("event field not found");
+		return -1;
+	}
+
+	hid_set_field(field, offset, value);
+
+	if (hid->urbout.status == -EINPROGRESS) {
+		warn("had to kill output urb");
+		usb_unlink_urb(&hid->urbout);
+	}
+
+	hid_output_report(field->report, hid->bufout);
+
+	hid->dr.value = 0x200 | field->report->id;
+	hid->dr.length = ((field->report->size - 1) >> 3) + 1;
+	hid->urbout.transfer_buffer_length = hid->dr.length;
+
+	if (usb_submit_urb(&hid->urbout)) {
+		err("usb_submit_urb(out) failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+/*
+ * Configure the input layer interface
+ * Read all reports and initalize the absoulte field values.
+ */
+
+static void hid_init_input(struct hid_device *hid)
+{
+	struct hid_report_enum *report_enum;
+	struct list_head *list;
+	int i, j, k;
+
+	hid->input.private = hid;
+	hid->input.event = hid_event;
+
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+
+		report_enum = hid->report_enum + k;
+		list = report_enum->report_list.next;
+
+		while (list != &report_enum->report_list) {
+
+			struct hid_report *report = (struct hid_report *) list;
+
+			list = list->next;
+
+			for (i = 0; i < report->maxfield; i++)
+				for (j = 0; j < report->field[i]->maxusage; j++)
+					hid_configure_usage(hid, report->field[i], report->field[i]->usage + j);
+
+			if (k == HID_INPUT_REPORT)  {
+				usb_set_idle(hid->dev, 0, report->id);
+				hid_read_report(hid, report);
+			}
+		}
+	}
+}
+
 static struct hid_device *usb_hid_configure(struct usb_device *dev, int ifnum)
 {
 	struct usb_interface_descriptor *interface = &dev->actconfig->interface[ifnum].altsetting[0];
-	struct usb_hid_descriptor *hdesc;
+	struct hid_descriptor *hdesc;
 	struct hid_device *hid;
 	unsigned rsize = 0;
 	int n;
@@ -1105,7 +1183,7 @@
 			return NULL;
 		}
 
-#ifdef DEBUG
+#ifdef DEBUG_DATA
 		printk(KERN_DEBUG __FILE__ ": report (size %u, read %d) = ", rsize, n);
 		for (n = 0; n < rsize; n++)
 			printk(" %02x", (unsigned) rdesc[n]);
@@ -1147,6 +1225,15 @@
 		hid_free_device(hid);
 		return NULL;
 	}
+
+	hid->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+	hid->dr.request = USB_REQ_SET_REPORT;
+	hid->dr.value = 0x200;
+	hid->dr.index = interface->bInterfaceNumber;
+	hid->dr.length = 1;
+
+	FILL_CONTROL_URB(&hid->urbout, dev, usb_sndctrlpipe(dev, 0),
+		(void*) &hid->dr, hid->bufout, 1, hid_ctrl, hid);
 
 	hid->version = hdesc->bcdHID;
 	hid->country = hdesc->bCountryCode;
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/hid.h linux/drivers/usb/hid.h
--- v2.3.39/linux/drivers/usb/hid.h	Tue Jan  4 13:57:17 2000
+++ linux/drivers/usb/hid.h	Thu Jan 20 09:48:48 2000
@@ -4,8 +4,8 @@
 /*
  *  drivers/usb/hid.h  Version 0.8
  *
- *  Copyright (c) 1999 Vojtech Pavlik
  *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000 Vojtech Pavlik
  *
  *  Sponsored by SuSE
  */
@@ -36,37 +36,12 @@
 #include <linux/list.h>
 
 /*
- * Enable/Disable debug information.
- */
-
-#ifdef CONFIG_USB_HID_DEBUG
-#define hid_debug(fmt,arg...) printk(KERN_DEBUG "hid: " fmt "\n" , ##arg)
-#else
-#define hid_debug(fmt,arg...) do { } while (0)
-#endif
-
-/*
  * USB HID (Human Interface Device) interface class code
  */
 
 #define USB_INTERFACE_CLASS_HID		3
 
 /*
- * USB interface subclass codes. 
- */
-
-#define USB_INTERFACE_SUBCLASS_NONE	0 
-#define USB_INTERFACE_SUBCLASS_HID_BP	1
-
-/*
- * HID protocol codes (only for boot protocol)
- */
-
-#define HID_PROTOCOL_NONE	0
-#define HID_PROTOCOL_KBD	1
-#define HID_PROTOCOL_MOUSE	2
-
-/*
  * We parse each description item into this structure. Short items data
  * values are expanded to 32-bit signed int, long items contain a pointer
  * into the data area.
@@ -122,7 +97,6 @@
 
 /*
  * HID report descriptor main item contents
- * Warning: VOLATILE is not available for TAG_INPUT
  */
 
 #define HID_MAIN_ITEM_CONSTANT		0x001
@@ -196,18 +170,6 @@
 #define HID_GD_HATSWITCH	0x00010039
 
 /*
- * HID interface requests (this belongs here, the USB_REQ_xxx stuff should
- * disapear).
- */
-
-#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 report types --- Ouch! HID spec says 1 2 3!
  */
 
@@ -216,13 +178,6 @@
 #define HID_FEATURE_REPORT	2
 
 /*
- * HID protocols
- */
-
-#define HID_PROTOCOL_BOOT	0
-#define HID_PROTOCOL_REPORT	1
-
-/*
  * This is the global enviroment of the parser. This information is
  * persistent for main-items. The global enviroment can be saved and
  * restored with PUSH/POP statements.
@@ -324,7 +279,10 @@
 	int ifnum;							/* USB interface number */
 
 	char buffer[32];						/* Receive buffer */
+	char bufout[32];						/* Transmit buffer */
+	devrequest dr;							/* Startup packet */
 	struct urb urb;							/* USB URB structure */
+	struct urb urbout;						/* Output URB */
 	struct input_dev input;						/* input device structure */
 };
 
@@ -340,6 +298,22 @@
 	unsigned              collection_stack_ptr;
 	struct hid_device    *device;
 };
+
+struct hid_class_descriptor {
+	__u8  bDescriptorType;
+	__u16 wDescriptorLength;
+} __attribute__ ((packed));
+
+struct hid_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u16 bcdHID;
+	__u8  bCountryCode;
+	__u8  bNumDescriptors;
+
+	struct hid_class_descriptor desc[1];
+} __attribute__ ((packed));
+
 
 #endif
 
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.39/linux/drivers/usb/hub.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/usb/hub.c	Thu Jan 13 13:45:34 2000
@@ -48,13 +48,11 @@
 		USB_DT_HUB << 8, 0, data, size, HZ);
 }
 
-#if 0
-static int usb_clear_hub_feature(struct usb_device *dev,  int feature)
+static int usb_clear_hub_feature(struct usb_device *dev, int feature)
 {
 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0 , NULL, 0, HZ);
+		USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ);
 }
-#endif
 
 static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
 {
@@ -359,7 +357,8 @@
 	}
 
 	if (tries==MAX_TRIES) {
-		err("can not enable port %i after %i retries, disabling port", port+1, MAX_TRIES);
+		err("Cannot enable port %i after %i retries, disabling port.", port+1, MAX_TRIES);
+		err("Maybe the USB cable is bad?");
 		return;
 	}
 	/* Allocate a new device struct for it */
@@ -392,6 +391,8 @@
 	struct list_head *tmp;
 	struct usb_device *dev;
 	struct usb_hub *hub;
+	struct usb_hub_status hubsts;
+	unsigned short hubstatus, hubchange;
 
 	/*
 	 *  We restart the list everytime to avoid a deadlock with
@@ -444,14 +445,32 @@
 			if (portchange & USB_PORT_STAT_C_SUSPEND)
 				dbg("port %d suspend change", i + 1);
 
-			if (portchange & USB_PORT_STAT_C_OVERCURRENT)
+			if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
 				dbg("port %d over-current change", i + 1);
+				usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
+			}
 
 			if (portchange & USB_PORT_STAT_C_RESET) {
 				dbg("port %d reset change", i + 1);
 				usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
 			}
 		} /* end for i */
+
+		/* deal with hub status changes */
+		if (usb_get_hub_status(dev, &hubsts) < 0) {
+			err("get_hub_status failed");
+		} else {
+			hubstatus = le16_to_cpup(&hubsts.wHubStatus);
+			hubchange = le16_to_cpup(&hubsts.wHubChange);
+			if (hubchange & HUB_CHANGE_LOCAL_POWER) {
+				dbg("hub power change");
+				usb_clear_hub_feature(dev, C_HUB_LOCAL_POWER);
+			}
+			if (hubchange & HUB_CHANGE_OVERCURRENT) {
+				dbg("hub overcurrent change");
+				usb_clear_hub_feature(dev, C_HUB_OVER_CURRENT);
+			}
+		}
         } /* end while (1) */
 
 he_unlock:
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/hub.h linux/drivers/usb/hub.h
--- v2.3.39/linux/drivers/usb/hub.h	Wed Oct 27 16:34:12 1999
+++ linux/drivers/usb/hub.h	Mon Jan 17 16:24:48 2000
@@ -4,6 +4,13 @@
 #include <linux/list.h>
 
 /*
+ * Hub request types
+ */
+
+#define USB_RT_HUB	(USB_TYPE_CLASS | USB_RECIP_DEVICE)
+#define USB_RT_PORT	(USB_TYPE_CLASS | USB_RECIP_OTHER)
+
+/*
  * Hub Class feature numbers
  */
 #define C_HUB_LOCAL_POWER	0
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/inode.c linux/drivers/usb/inode.c
--- v2.3.39/linux/drivers/usb/inode.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/inode.c	Thu Jan 20 15:00:16 2000
@@ -20,10 +20,10 @@
  *	along with this program; if not, write to the Free Software
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
+ *  $Id: inode.c,v 1.3 2000/01/11 13:58:25 tom Exp $
+ *
  *  History:
  *   0.1  04.01.2000  Created
- *
- *  $Id: ezusb.c,v 1.22 1999/12/03 15:06:28 tom Exp $
  */
 
 /*****************************************************************************/
@@ -34,6 +34,7 @@
 #include <linux/smp_lock.h>
 #include <linux/locks.h>
 #include <linux/init.h>
+#include <linux/proc_fs.h>
 #include <asm/uaccess.h>
 
 #include "usb.h"
@@ -696,6 +697,8 @@
 
 /* --------------------------------------------------------------------- */
 
+static struct proc_dir_entry *usbdir = NULL;
+
 int __init usbdevfs_init(void)
 {
 	int ret;
@@ -707,6 +710,8 @@
 		return ret;
 	if ((ret = register_filesystem(&usbdevice_fs_type)))
 		usb_deregister(&usbdevfs_driver);
+	/* create mount point for usbdevfs */
+	usbdir = proc_mkdir("usb", proc_bus);
 	return ret;
 }
 
@@ -714,6 +719,8 @@
 {
 	usb_deregister(&usbdevfs_driver);
 	unregister_filesystem(&usbdevice_fs_type);
+        if (usbdir)
+                remove_proc_entry("usb", proc_bus);
 }
 
 #if 0
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/joydev.c linux/drivers/usb/joydev.c
--- v2.3.39/linux/drivers/usb/joydev.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/usb/joydev.c	Thu Jan 20 09:48:48 2000
@@ -424,9 +424,13 @@
 	joydev->minor = ffz(joydev_minors);
 	set_bit(joydev->minor, &joydev_minors);
 	joydev_base[joydev->minor] = joydev;
-	
+
 	for (i = 0; i < joydev->nabs; i++) {
 		j = joydev->abspam[i];
+		if (dev->absmax[j] == dev->absmin[j]) {
+			joydev->corr[i].type = JS_CORR_NONE;
+			continue;
+		}
 		joydev->corr[i].type = JS_CORR_BROKEN;
 		joydev->corr[i].prec = dev->absfuzz[j];
 		joydev->corr[i].coef[0] = (dev->absmax[j] + dev->absmin[j]) / 2 - dev->absflat[j];
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/keybdev.c linux/drivers/usb/keybdev.c
--- v2.3.39/linux/drivers/usb/keybdev.c	Tue Jan 11 22:31:41 2000
+++ linux/drivers/usb/keybdev.c	Thu Jan 20 09:48:48 2000
@@ -34,6 +34,7 @@
 #include <linux/malloc.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/kbd_kern.h>
 
 #ifdef CONFIG_X86
 
@@ -57,6 +58,21 @@
 
 #endif
 
+struct input_handler keybdev_handler;
+
+void keybdev_ledfunc(unsigned int led)
+{
+	struct input_handle *handle;	
+
+	for (handle = keybdev_handler.handle; handle; handle = handle->hnext) {
+
+		input_event(handle->dev, EV_LED, LED_SCROLLL, !!(led & 0x01));
+		input_event(handle->dev, EV_LED, LED_NUML,    !!(led & 0x02));
+		input_event(handle->dev, EV_LED, LED_CAPSL,   !!(led & 0x04));
+
+	}
+}
+
 void keybdev_event(struct input_handle *handle, unsigned int type, unsigned int code, int down)
 {
 	if (type != EV_KEY || code > 255) return;
@@ -96,6 +112,7 @@
 #error "Cannot generate rawmode keyboard for your architecture yet."
 #endif
 
+	mark_bh(KEYBOARD_BH);
 }
 
 static int keybdev_connect(struct input_handler *handler, struct input_dev *dev)
@@ -137,6 +154,7 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
+	kbd_ledfunc = NULL;
 	input_unregister_handler(&keybdev_handler);
 }
 int init_module(void)
@@ -145,5 +163,6 @@
 #endif
 {
 	input_register_handler(&keybdev_handler);
+	kbd_ledfunc = keybdev_ledfunc;
 	return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/mousedev.c linux/drivers/usb/mousedev.c
--- v2.3.39/linux/drivers/usb/mousedev.c	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/mousedev.c	Thu Jan 13 13:39:15 2000
@@ -53,7 +53,7 @@
 	struct mousedev_list *next;
 	int dx, dy, dz;
 	unsigned char ps2[6];
-	unsigned char buttons;
+	unsigned long buttons;
 	unsigned char ready, buffer, bufsiz;
 	unsigned char mode, genseq, impseq;
 };
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/ohci-hcd.c linux/drivers/usb/ohci-hcd.c
--- v2.3.39/linux/drivers/usb/ohci-hcd.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/usb/ohci-hcd.c	Thu Jan 13 16:04:23 2000
@@ -47,6 +47,7 @@
 #include <asm/system.h>
 
 #undef DEBUG
+#define OHCI_USE_NPS
 
 #include "usb.h"
 #include "ohci-hcd.h"
@@ -154,8 +155,9 @@
 		printk (KERN_DEBUG __FILE__ " %s branch int %2d(%2x):", str, i, i);
 		ed_p = &(ohci->hcca.int_table [i]);
 		while (*ed_p != 0 && j--) {
-			printk (" ed: %4x;", (((ed_t *) bus_to_virt (*ed_p))->hwINFO));
-			ed_p = &(((ed_t *) bus_to_virt (*ed_p))->hwNextED);
+			ed_t *ed = (ed_t *) bus_to_virt(le32_to_cpup(ed_p));
+			printk (" ed: %4x;", ed->hwINFO);
+			ed_p = &ed->hwNextED;
 		}
 		printk ("\n");
 	}
@@ -174,7 +176,7 @@
 {
 	urb_priv_t * urb_priv = urb->hcpriv;
 	urb_t * urbt;
-	unsigned int flags;
+	unsigned long flags;
 	int i;
 	
 	/* just to be sure */
@@ -245,7 +247,7 @@
 	urb_priv_t * urb_priv;
 	unsigned int pipe = urb->pipe;
 	int i, size = 0;
-	unsigned int flags;
+	unsigned long flags;
 	
 	if (!urb->dev || !urb->dev->bus) return -EINVAL;
 	
@@ -346,7 +348,7 @@
  
 static int sohci_unlink_urb (urb_t * urb)
 {
-	unsigned int flags;
+	unsigned long flags;
 	ohci_t * ohci;
 	DECLARE_WAITQUEUE (wait, current);
 	
@@ -412,7 +414,7 @@
   
 static int sohci_free_dev (struct usb_device * usb_dev)
 {
-	unsigned int flags;
+	unsigned long flags;
 	int i, cnt = 0;
 	ed_t * ed;
 	DECLARE_WAITQUEUE (wait, current);
@@ -566,9 +568,9 @@
 		for (i = 0; i < ep_rev (6, interval); i += inter) {
 			inter = 1;
 			for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i) + int_branch]); 
-				(*ed_p != 0) && (((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval >= interval); 
-				ed_p = &(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->hwNextED)) 
-					inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval);
+				(*ed_p != 0) && (((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval >= interval); 
+				ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) 
+					inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
 			ed->hwNextED = *ed_p; 
 			*ed_p = cpu_to_le32 (virt_to_bus (ed));
 		}
@@ -588,8 +590,8 @@
 				inter = 1;
 				for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i)]); 
 					*ed_p != 0; 
-					ed_p = &(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->hwNextED)) 
-						inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval);
+					ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) 
+						inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
 				*ed_p = cpu_to_le32 (virt_to_bus (ed));	
 			}	
 			ed->ed_prev = NULL;
@@ -622,27 +624,27 @@
 	switch (ed->type) {
 	case CTRL: 
 		if (ed->ed_prev == NULL) {
-			writel (le32_to_cpu (ed->hwNextED), &ohci->regs->ed_controlhead);
+			writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_controlhead);
 		} else {
 			ed->ed_prev->hwNextED = ed->hwNextED;
 		}
 		if(ohci->ed_controltail == ed) {
 			ohci->ed_controltail = ed->ed_prev;
 		} else {
-			((ed_t *) bus_to_virt (le32_to_cpu (ed->hwNextED)))->ed_prev = ed->ed_prev;
+			((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
 		}
 		break;
       
 	case BULK: 
 		if (ed->ed_prev == NULL) {
-			writel (le32_to_cpu (ed->hwNextED), &ohci->regs->ed_bulkhead);
+			writel (le32_to_cpup (&ed->hwNextED), &ohci->regs->ed_bulkhead);
 		} else {
 			ed->ed_prev->hwNextED = ed->hwNextED;
 		}
 		if (ohci->ed_bulktail == ed) {
 			ohci->ed_bulktail = ed->ed_prev;
 		} else {
-			((ed_t *) bus_to_virt (le32_to_cpu (ed->hwNextED)))->ed_prev = ed->ed_prev;
+			((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
 		}
 		break;
       
@@ -653,9 +655,9 @@
 		for (i = 0; i < ep_rev (6, interval); i += inter) {
 			for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i) + int_branch]), inter = 1; 
 				(*ed_p != 0) && (*ed_p != ed->hwNextED); 
-				ed_p = &(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->hwNextED), 
-				inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval)) {				
-					if(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p))) == ed) {
+				ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED), 
+				inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval)) {				
+					if(((ed_t *) bus_to_virt (le32_to_cpup (ed_p))) == ed) {
 			  			*ed_p = ed->hwNextED;		
 			  			break;
 			  		}
@@ -670,7 +672,7 @@
     	if (ohci->ed_isotail == ed)
 				ohci->ed_isotail = ed->ed_prev;
 		if (ed->hwNextED != 0) 
-				((ed_t *) bus_to_virt (le32_to_cpu (ed->hwNextED)))->ed_prev = ed->ed_prev;
+				((ed_t *) bus_to_virt (le32_to_cpup (&ed->hwNextED)))->ed_prev = ed->ed_prev;
 				
 		if (ed->ed_prev != NULL) {
 			ed->ed_prev->hwNextED = ed->hwNextED;
@@ -679,9 +681,9 @@
 				inter = 1;
 				for (ed_p = &(ohci->hcca.int_table[ep_rev (5, i)]); 
 					*ed_p != 0; 
-					ed_p = &(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->hwNextED)) {
-						inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpu (*ed_p)))->int_interval);
-						if(((ed_t *) bus_to_virt (le32_to_cpu (*ed_p))) == ed) {
+					ed_p = &(((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->hwNextED)) {
+						inter = ep_rev (6, ((ed_t *) bus_to_virt (le32_to_cpup (ed_p)))->int_interval);
+						if(((ed_t *) bus_to_virt (le32_to_cpup (ed_p))) == ed) {
 			  				*ed_p = ed->hwNextED;		
 			  				break;
 			  			}
@@ -800,7 +802,7 @@
 	
 	td_pt = urb_priv->td [index];
 	/* fill the old dummy TD */
-	td = (td_t *) bus_to_virt (le32_to_cpu (urb_priv->ed->hwTailP) & 0xfffffff0);
+	td = (td_t *) bus_to_virt (le32_to_cpup (&urb_priv->ed->hwTailP) & 0xfffffff0);
 	td->ed = urb_priv->ed;
 	td->index = index;
 	td->urb = urb; 
@@ -900,20 +902,20 @@
 	td_t * td_rev = NULL;
 	td_t * td_list = NULL;
   	urb_priv_t * urb_priv = NULL;
-  	unsigned int flags;
+  	unsigned long flags;
   	
   	spin_lock_irqsave (&usb_ed_lock, flags);
   	
-	td_list_hc = le32_to_cpu (ohci->hcca.done_head) & 0xfffffff0;
+	td_list_hc = le32_to_cpup (&ohci->hcca.done_head) & 0xfffffff0;
 	ohci->hcca.done_head = 0;
 	
 	while (td_list_hc) {		
 		td_list = (td_t *) bus_to_virt (td_list_hc);
 
-		if (TD_CC_GET (le32_to_cpu (td_list->hwINFO))) {
+		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
 			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
 			dbg(" USB-error/status: %x : %p", 
-					TD_CC_GET (le32_to_cpu (td_list->hwINFO)), td_list);
+					TD_CC_GET (le32_to_cpup (&td_list->hwINFO)), td_list);
 			if (td_list->ed->hwHeadP & cpu_to_le32 (0x1)) {
 				if (urb_priv && ((td_list->index + 1) < urb_priv->length)) {
 					td_list->ed->hwHeadP = 
@@ -927,7 +929,7 @@
 
 		td_list->next_dl_td = td_rev;	
 		td_rev = td_list;
-		td_list_hc = le32_to_cpu (td_list->hwNextTD) & 0xfffffff0;	
+		td_list_hc = le32_to_cpup (&td_list->hwNextTD) & 0xfffffff0;	
 	}	
 	spin_unlock_irqrestore (&usb_ed_lock, flags);
 	return td_list;
@@ -941,7 +943,7 @@
  
 static void dl_del_list (ohci_t  * ohci, unsigned int frame)
 {
-	unsigned int flags;
+	unsigned long flags;
 	ed_t * ed;
 	__u32 edINFO;
 	td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP;
@@ -951,16 +953,16 @@
 	spin_lock_irqsave (&usb_ed_lock, flags);
 	for (ed = ohci->ed_rm_list[frame]; ed != NULL; ed = ed->ed_rm_list) {
 
-   	 	tdTailP = bus_to_virt (le32_to_cpu (ed->hwTailP) & 0xfffffff0);
-		tdHeadP = bus_to_virt (le32_to_cpu (ed->hwHeadP) & 0xfffffff0);
-		edINFO = le32_to_cpu (ed->hwINFO);
+   	 	tdTailP = bus_to_virt (le32_to_cpup (&ed->hwTailP) & 0xfffffff0);
+		tdHeadP = bus_to_virt (le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
+		edINFO = le32_to_cpup (&ed->hwINFO);
 		td_p = &ed->hwHeadP;
 			
 		for (td = tdHeadP; td != tdTailP; td = td_next) { 
 			urb_t * urb = td->urb;
 			urb_priv_t * urb_priv = td->urb->hcpriv;
 			
-			td_next = bus_to_virt (le32_to_cpu (td->hwNextTD) & 0xfffffff0);
+			td_next = bus_to_virt (le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
 			if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) {
 				*td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3));
 				if(++ (urb_priv->td_cnt) == urb_priv->length) 
@@ -1013,16 +1015,16 @@
 	urb_priv_t * urb_priv;
  	__u32 tdINFO, tdBE, tdCBP, edHeadP, edTailP;
  	__u16 tdPSW;
- 	unsigned int flags;
+ 	unsigned long flags;
  	
   	while (td_list) {
    		td_list_next = td_list->next_dl_td;
    		
   		urb = td_list->urb;
   		urb_priv = urb->hcpriv;
-  		tdINFO = le32_to_cpu (td_list->hwINFO);
-  		tdBE   = le32_to_cpu (td_list->hwBE);
-  		tdCBP  = le32_to_cpu (td_list->hwCBP);
+  		tdINFO = le32_to_cpup (&td_list->hwINFO);
+  		tdBE   = le32_to_cpup (&td_list->hwBE);
+  		tdCBP  = le32_to_cpup (&td_list->hwCBP);
   		
    		ed = td_list->ed;
    		
@@ -1071,8 +1073,8 @@
   		
   		spin_lock_irqsave (&usb_ed_lock, flags);
   		if (ed->state != ED_NEW) { 
-  			edHeadP = le32_to_cpu (ed->hwHeadP) & 0xfffffff0;
-  			edTailP = le32_to_cpu (ed->hwTailP);
+  			edHeadP = le32_to_cpup (&ed->hwHeadP) & 0xfffffff0;
+  			edTailP = le32_to_cpup (&ed->hwTailP);
 
      		if((edHeadP == edTailP) && (ed->state == ED_OPER)) 
      			ep_unlink (ohci, ed); /* unlink eds if they are not busy */
@@ -1185,9 +1187,9 @@
 	ret = *(__u8 *) data;
 
 	for ( i = 0; i < num_ports; i++) {
-		*(__u8 *) (data + i / 8) |= 
+		*(__u8 *) (data + (i + 1) / 8) |= 
 			((readl (&ohci->regs->roothub.portstatus[i]) & 0x001f0000) > 0? 1: 0) << ((i + 1) % 8);
-		ret += *(__u8 *) (data + i / 8);
+		ret += *(__u8 *) (data + (i + 1) / 8);
 	}
 	len = i/8 + 1;
   
@@ -1313,8 +1315,10 @@
 
 		case RH_CLEAR_FEATURE | RH_CLASS:
 			switch (wValue) {
+				case RH_C_HUB_LOCAL_POWER:
+					OK(0);
 				case (RH_C_HUB_OVER_CURRENT): 
-						WR_RH_STAT(RH_PS_OCIC); OK (0);
+						WR_RH_STAT(RH_HS_OCIC); OK (0);
 			}
 			break;
 		
@@ -1489,6 +1493,13 @@
 	writel (ohci->hc_control = 0xBF, &ohci->regs->control); /* USB Operational */
 	writel (mask, &ohci->regs->intrenable);
 	writel (mask, &ohci->regs->intrstatus);
+
+#ifdef OHCI_USE_NPS
+	writel ((readl(&ohci->regs->roothub.a) | 0x200) & ~0x100,
+		&ohci->regs->roothub.a);
+	writel (0x10000, &ohci->regs->roothub.status);
+	mdelay ((readl(&ohci->regs->roothub.a) >> 23) & 0x1fe);
+#endif /* OHCI_USE_NPS */
  
 	/* connect the virtual root hub */
 	
@@ -1516,7 +1527,7 @@
 	struct ohci_regs * regs = ohci->regs;
  	int ints; 
 
-	if ((ohci->hcca.done_head != 0) && !(le32_to_cpu (ohci->hcca.done_head) & 0x01)) {
+	if ((ohci->hcca.done_head != 0) && !(le32_to_cpup (&ohci->hcca.done_head) & 0x01)) {
 		ints =  OHCI_INTR_WDH;
 	} else { 
  		if ((ints = (readl (&regs->intrstatus) & readl (&regs->intrenable))) == 0)
@@ -1578,7 +1589,7 @@
 
 	bus = usb_alloc_bus (&sohci_device_operations);
 	if (!bus) {
-		free_pages ((unsigned int) ohci, 1);
+		free_pages ((unsigned long) ohci, 1);
 		return NULL;
 	}
 
@@ -1614,7 +1625,7 @@
 	/* unmap the IO address space */
 	iounmap (ohci->regs);
        
-	free_pages ((unsigned int) ohci, 1);	
+	free_pages ((unsigned long) ohci, 1);	
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1625,7 +1636,7 @@
 static int hc_found_ohci (int irq, void * mem_base)
 {
 	ohci_t * ohci;
-	dbg("USB HC found: irq= %d membase= %x", irq, (int) mem_base);
+	dbg("USB HC found: irq= %d membase= %lx", irq, (unsigned long) mem_base);
     
 	ohci = hc_alloc_ohci (mem_base);
 	if (!ohci) {
@@ -1655,15 +1666,15 @@
 static int hc_start_ohci (struct pci_dev * dev)
 {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	unsigned int mem_base = dev->resource[0].start;
+	unsigned long mem_base = dev->resource[0].start;
 #else
-	unsigned int mem_base = dev->base_address[0];
+	unsigned long mem_base = dev->base_address[0];
 	if (mem_base & PCI_BASE_ADDRESS_SPACE_IO) return -ENODEV;
 	mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
 #endif
 	
 	pci_set_master (dev);
-	mem_base = (unsigned int) ioremap_nocache (mem_base, 4096);
+	mem_base = (unsigned long) ioremap_nocache (mem_base, 4096);
 
 	if (!mem_base) {
 		err("Error mapping OHCI memory");
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/ohci-hcd.h linux/drivers/usb/ohci-hcd.h
--- v2.3.39/linux/drivers/usb/ohci-hcd.h	Mon Dec 20 18:48:22 1999
+++ linux/drivers/usb/ohci-hcd.h	Thu Jan 13 13:43:04 2000
@@ -314,6 +314,13 @@
 #define RH_PS_OCIC           0x00080000    
 #define RH_PS_PRSC           0x00100000   
 
+/* Root hub status bits */
+#define RH_HS_LPS	     0x00000001
+#define RH_HS_OCI	     0x00000002
+#define RH_HS_DRWE	     0x00008000
+#define RH_HS_LPSC	     0x00010000
+#define RH_HS_OCIC	     0x00020000
+#define RH_HS_CRWE	     0x80000000
 
 #define min(a,b) (((a)<(b))?(a):(b))  
  
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- v2.3.39/linux/drivers/usb/ov511.c	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/ov511.c	Mon Jan 17 16:24:48 2000
@@ -11,8 +11,11 @@
  *    DEBUG - Debugging code.
  *    FIXME - Something that is broken or needs improvement.
  *
- * Version History:
- *    Version 1.00 - Initial version
+ * Version: 1.05
+ *
+ * Please see the file: linux/Documentation/usb/ov511.txt 
+ * and the website at:  http://people.delphi.com/mmcclelland/linux/ 
+ * for more info.
  */
 
 /*
@@ -63,6 +66,8 @@
 
 #define OV511_I2C_RETRIES 3
 
+#define OV7610_AUTO_ADJUST 1
+
 /* Video Size 640 x 480 x 3 bytes for RGB */
 #define MAX_FRAME_SIZE (640 * 480 * 3)
 
@@ -201,7 +206,7 @@
 		0, (__u16)reg, &value, 1, HZ);	
 			
 #if 0
-	PDEBUG("reg write: 0x%02X:0x%02X\n", reg, value);
+	PDEBUG("reg write: 0x%02X:0x%02X", reg, value);
 #endif
 			
 	return rc;
@@ -220,7 +225,7 @@
 		0, (__u16)reg, buffer, 1, HZ);
                                
 #if 0
-	PDEBUG("reg read: 0x%02X:0x%02X\n", reg, buffer[0]);
+	PDEBUG("reg read: 0x%02X:0x%02X", reg, buffer[0]);
 #endif
 	
 	if(rc < 0)
@@ -234,7 +239,7 @@
 	int rc, retries;
 
 #if 0
-	PDEBUG("i2c write: 0x%02X:0x%02X\n", reg, value);
+	PDEBUG("i2c write: 0x%02X:0x%02X", reg, value);
 #endif
 	/* Three byte write cycle */
 	for(retries = OV511_I2C_RETRIES;;) {
@@ -316,7 +321,7 @@
 
 	value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);
 #if 0
-	PDEBUG("i2c read: 0x%02X:0x%02X\n", reg, value);
+	PDEBUG("i2c read: 0x%02X:0x%02X", reg, value);
 #endif
 		
 	/* This is needed to make ov511_i2c_write() work */
@@ -326,18 +331,22 @@
 	return (value);
 }
 
+#if 0
 static void ov511_dump_i2c_range( struct usb_device *dev, int reg1, int regn)
 {
 	int i;
 	int rc;
 	for(i=reg1; i<=regn; i++) {
 	  rc = ov511_i2c_read(dev, i);
+#if 0
+	  PDEBUG("OV7610[0x%X] = 0x%X", i, rc);
+#endif
 	}
 }
 
 static void ov511_dump_i2c_regs( struct usb_device *dev)
 {
-	PDEBUG("I2C REGS\n");
+	PDEBUG("I2C REGS");
 	ov511_dump_i2c_range(dev, 0x00, 0x38);
 }
 
@@ -347,54 +356,69 @@
 	int rc;
 	for(i=reg1; i<=regn; i++) {
 	  rc = ov511_reg_read(dev, i);
-	  PDEBUG("OV511[0x%X] = 0x%X\n", i, rc);
+	  PDEBUG("OV511[0x%X] = 0x%X", i, rc);
 	}
 }
 
 static void ov511_dump_regs( struct usb_device *dev)
 {
-	PDEBUG("CAMERA INTERFACE REGS\n");
+	PDEBUG("CAMERA INTERFACE REGS");
 	ov511_dump_reg_range(dev, 0x10, 0x1f);
-	PDEBUG("DRAM INTERFACE REGS\n");
+	PDEBUG("DRAM INTERFACE REGS");
 	ov511_dump_reg_range(dev, 0x20, 0x23);
-	PDEBUG("ISO FIFO REGS\n");
+	PDEBUG("ISO FIFO REGS");
 	ov511_dump_reg_range(dev, 0x30, 0x31);
-	PDEBUG("PIO REGS\n");
+	PDEBUG("PIO REGS");
 	ov511_dump_reg_range(dev, 0x38, 0x39);
 	ov511_dump_reg_range(dev, 0x3e, 0x3e);
-	PDEBUG("I2C REGS\n");
+	PDEBUG("I2C REGS");
 	ov511_dump_reg_range(dev, 0x40, 0x49);
-	PDEBUG("SYSTEM CONTROL REGS\n");
+	PDEBUG("SYSTEM CONTROL REGS");
 	ov511_dump_reg_range(dev, 0x50, 0x53);
 	ov511_dump_reg_range(dev, 0x5e, 0x5f);
-	PDEBUG("OmniCE REGS\n");
+	PDEBUG("OmniCE REGS");
 	ov511_dump_reg_range(dev, 0x70, 0x79);
 	ov511_dump_reg_range(dev, 0x80, 0x9f);
 	ov511_dump_reg_range(dev, 0xa0, 0xbf);
 
 }
+#endif
+
+int ov511_i2c_reset(struct usb_device *dev)
+{
+	int rc;
+
+	PDEBUG("Reset 7610");
+	rc = ov511_i2c_write(dev, 0x12, 0x80);
+	if (rc < 0)
+		err("i2c reset: command failed");
+
+	return rc;
+}
 
 int ov511_reset(struct usb_device *dev, unsigned char reset_type)
 {
 	int rc;
 	
-	PDEBUG("Reset: type=0x%X\n", reset_type);
+	PDEBUG("Reset: type=0x%X", reset_type);
 	rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);
 	if (rc < 0)
-		printk(KERN_ERR "ov511: reset: command failed\n");
+		err("reset: command failed");
 
 	rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);
 	if (rc < 0)
-		printk(KERN_ERR "ov511: reset: command failed\n");
+		err("reset: command failed");
 
 	return rc;
 }
 
 int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
 {
-	int alt, multiplier, err;
+	int alt, multiplier, rc;
 		
-	PDEBUG("set packet size: %d\n", size);
+#if 0
+	PDEBUG("set packet size: %d", size);
+#endif
 	
 	switch (size) {
 		case 992:
@@ -430,21 +454,19 @@
 			multiplier = 1; // FIXME - is this correct?
 			break;
 		default:
-			printk(KERN_ERR "ov511_set_packet_size: invalid size (%d)\n",
-			       size);
+			err("Set packet size: invalid size (%d)", size);
 			return -EINVAL;
 	}
 
-	err = ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
-	                          multiplier);
-	if (err < 0) {
-		printk(KERN_ERR "ov511: Set packet size: Set FIFO size ret %d\n",
-		       err);
+	rc = ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE,
+	                     multiplier);
+	if (rc < 0) {
+		err("Set packet size: Set FIFO size ret %d", rc);
 		return -ENOMEM;
 	}
 	
 	if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {
-		printk(KERN_ERR "ov511: Set packet size: set interface error\n");
+		err("Set packet size: set interface error");
 		return -EBUSY;
 	}
 
@@ -455,21 +477,151 @@
 	return 0;
 }
 
+static inline int ov7610_set_picture(struct usb_ov511 *ov511,
+                                     struct video_picture *p)
+{
+	if(ov511_i2c_write(ov511->dev, OV7610_REG_SAT, p->colour >> 8) < 0)
+		return -EIO;
+
+	if(ov511_i2c_write(ov511->dev, OV7610_REG_CNT, p->contrast >> 8) < 0)
+		return -EIO;
+
+	if(ov511_i2c_write(ov511->dev, OV7610_REG_BRT, p->brightness >> 8) < 0)
+		return -EIO;
+
+	return 0;
+}
+
+static inline int ov7610_get_picture(struct usb_ov511 *ov511,
+                                     struct video_picture *p)
+{
+	int ret;
+
+	if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_SAT)) < 0) return -EIO;
+	p->colour = ret << 8;
+
+	if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_CNT)) < 0) return -EIO;
+	p->contrast = ret << 8;
+
+	if((ret = ov511_i2c_read(ov511->dev, OV7610_REG_BRT)) < 0) return -EIO;
+	p->brightness = ret << 8;
+
+	p->hue = 0x8000;
+	p->whiteness = 105 << 8;
+	p->depth = 24;
+	p->palette = VIDEO_PALETTE_RGB24;
+
+	return 0;
+}
+
+static int ov511_mode_init_regs(struct usb_ov511 *ov511,
+				int width, int height, int mode)
+{
+	int rc = 0;
+	struct usb_device *dev = ov511->dev;
+
+#if 0
+	PDEBUG("ov511_mode_init_regs(ov511, %d, %d, %d)", width, height, mode);
+#endif
+	ov511_set_packet_size(ov511, 0);
+
+	/* Set mode consistent registers */
+	ov511_i2c_write(dev, 0x0f, 0x03);
+	ov511_i2c_write(dev, 0x10, 0xff);
+	ov511_i2c_write(dev, 0x13, 0x01);
+	ov511_i2c_write(dev, 0x16, 0x06);
+	ov511_i2c_write(dev, 0x20, 0x1c);
+	ov511_i2c_write(dev, 0x24, 0x2e); /* 10 */
+	ov511_i2c_write(dev, 0x25, 0x7c); /* 8a */
+	ov511_i2c_write(dev, 0x26, 0x70);
+	ov511_i2c_write(dev, 0x28, 0x24); /* 24 */
+	ov511_i2c_write(dev, 0x2b, 0xac);
+	ov511_i2c_write(dev, 0x2c, 0xfe);
+	ov511_i2c_write(dev, 0x2d, 0x93);
+	ov511_i2c_write(dev, 0x34, 0x8b);
+
+	if (width == 640 && height == 480) {
+		ov511_reg_write(dev, 0x12, 0x4f);
+		ov511_reg_write(dev, 0x13, 0x3d);
+		ov511_reg_write(dev, 0x14, 0x00);
+		ov511_reg_write(dev, 0x15, 0x00);
+		ov511_reg_write(dev, 0x18, 0x03);
+
+		ov511_i2c_write(dev, 0x11, 0x01);
+		ov511_i2c_write(dev, 0x12, 0x24);
+		ov511_i2c_write(dev, 0x14, 0x04);
+		ov511_i2c_write(dev, 0x35, 0x9e);
+	} else if (width == 320 && height == 240) {
+		ov511_reg_write(dev, 0x12, 0x27);
+		ov511_reg_write(dev, 0x13, 0x1f);
+		ov511_reg_write(dev, 0x14, 0x00);
+		ov511_reg_write(dev, 0x15, 0x00);
+		ov511_reg_write(dev, 0x18, 0x03);
+
+		ov511_i2c_write(dev, 0x11, 0x00);
+		ov511_i2c_write(dev, 0x12, 0x04);
+		ov511_i2c_write(dev, 0x14, 0x24);
+		ov511_i2c_write(dev, 0x35, 0x1e);
+	} else {
+		err("Unknown mode (%d, %d): %d", width, height, mode);
+		rc = -EINVAL;
+	}
+	ov511_set_packet_size(ov511, 993);
+
+	return rc;
+}
+
+	
+/*************************************************************
+
+Turn a YUV4:2:0 block into an RGB block
+
+*************************************************************/
+#define LIMIT(x) ((((x)>0xffffff)?0xff0000:(((x)<=0xffff)?0:(x)&0xff0000))>>16)
+static inline void ov511_move_420_block(int y00, int y01, int y10, int y11,
+					int u, int v, int w,
+					unsigned char * pOut)
+{
+	int r    = 68911 * v;
+	int g    = -16915 * u + -35101 * v;
+	int b    = 87097 * u;
+	y00 *= 49152;
+	y01 *= 49152;
+	y10 *= 49152;
+	y11 *= 49152;
+	*(pOut+w*3) = LIMIT(r + y10);
+	*pOut++     = LIMIT(r + y00);
+	*(pOut+w*3) = LIMIT(g + y10);
+	*pOut++     = LIMIT(g + y00);
+	*(pOut+w*3) = LIMIT(b + y10);
+	*pOut++     = LIMIT(b + y00);
+	*(pOut+w*3) = LIMIT(r + y11);
+	*pOut++     = LIMIT(r + y01);
+	*(pOut+w*3) = LIMIT(g + y11);
+	*pOut++     = LIMIT(g + y01);
+	*(pOut+w*3) = LIMIT(b + y11);
+	*pOut++     = LIMIT(b + y01);
+}
+
 /***************************************************************
 
-For a 640x480 images, data shows up in 1200 384 byte segments.  The
-first 128 bytes of each segment are probably some combo of UV but I
-haven't figured it out yet.  The next 256 bytes are apparently Y
-data and represent 4 squares of 8x8 pixels as follows:
+For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.  The
+first 64 bytes of each segment are V, the next 64 are U.  The V and
+U are arranged as follows:
+
+  0  1 ...  7
+  8  9 ... 15
+       ...   
+ 56 57 ... 63
+
+The next 256 bytes are Y data and represent 4 squares of 8x8 pixels as
+follows:
 
   0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
   8  9 ... 15    72  73 ...  79        200 201 ... 207
        ...              ...                    ...
  56 57 ... 63   120 121     127        248 249 ... 255
 
-Right now I'm only moving the Y data and haven't figured out
-the UV data.
-
 If OV511_DUMPPIX is defined, _parse_data just dumps the
 incoming segments, verbatim, in order, into the frame.
 When used with vidcat -f ppm -s 640x480 this puts the data
@@ -478,42 +630,102 @@
 this data is scrambled.
 
 ****************************************************************/ 
+#define HDIV 8
+#define WDIV (256/HDIV)
 
-static void ov511_parse_data(unsigned char * pIn,
-			    unsigned char * pOut,
-			    int iSegment)
+static void ov511_parse_data(unsigned char * pIn0,
+			     unsigned char * pOut0,
+			     int iWidth,
+			     int iSegment)
 			    
 {
-
 #ifndef OV511_DUMPPIX
-	int i, j, k, l, m;
-	int iOut;
-	unsigned char * pOut1;
-#define HDIV 8
-#define WDIV (256/HDIV)
-	i = iSegment / (DEFAULT_WIDTH/ WDIV);
-	j = iSegment - i * (DEFAULT_WIDTH/ WDIV);
-	iOut = (i*HDIV*DEFAULT_WIDTH + j*WDIV) * 3;
-	pOut += iOut;
-	pIn += 128;
+    int k, l, m;
+    unsigned char * pIn;
+    unsigned char * pOut, * pOut1;
+
+    int iHalf = (iSegment / (iWidth / 32)) & 1;
+    int iY     = iSegment / (iWidth / WDIV);
+    int jY     = iSegment - iY * (iWidth / WDIV);
+    int iOutY  = (iY*HDIV*iWidth + jY*WDIV) * 3;
+    int iUV    = iSegment / (iWidth / WDIV * 2);
+    int jUV    = iSegment - iUV * (iWidth / WDIV * 2);
+    int iOutUV = (iUV*HDIV*2*iWidth + jUV*WDIV/2) * 3;
+
+    /* Just copy the Y's if in the first stripe */
+    if (!iHalf) {
+	pIn = pIn0 + 128;
+	pOut = pOut0 + iOutY;
 	for(k=0; k<4; k++) {
 	    pOut1 = pOut;
 	    for(l=0; l<8; l++) {
 	      for(m=0; m<8; m++) {
-		*pOut1++ = *pIn;
-		*pOut1++ = *pIn;
-		*pOut1++ = *pIn++;
+		*pOut1 = *pIn++;
+		pOut1 += 3;
 	      }
-	      pOut1 += (DEFAULT_WIDTH - 8) * 3;
+	      pOut1 += (iWidth - 8) * 3;
 	    }
 	    pOut += 8 * 3;
 	}
+    }
+
+    /* Use the first half of VUs to calculate value */
+    pIn = pIn0;
+    pOut = pOut0 + iOutUV;
+    for(l=0; l<4; l++) {
+	for(m=0; m<8; m++) {
+	    int y00 = *(pOut);
+	    int y01 = *(pOut+3);
+	    int y10 = *(pOut+iWidth*3);
+	    int y11 = *(pOut+iWidth*3+3);
+	    int u   = *(pIn+64) - 128;
+	    int v   = *pIn++ - 128;
+	    ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut);
+	    pOut += 6;
+	}
+	pOut += (iWidth*2 - 16) * 3;
+    }
+
+    /* Just copy the other UV rows */
+    for(l=0; l<4; l++) {
+	for(m=0; m<8; m++) {
+	  *pOut++ = *(pIn + 64);
+	  *pOut = *pIn++;
+	  pOut += 5;
+	}
+	pOut += (iWidth*2 - 16) * 3;
+    }
+
+    /* Calculate values if it's the second half */
+    if (iHalf) {
+	pIn = pIn0 + 128;
+	pOut = pOut0 + iOutY;
+	for(k=0; k<4; k++) {
+	    pOut1 = pOut;
+	    for(l=0; l<4; l++) {
+	      for(m=0; m<4; m++) {
+		int y10 = *(pIn+8);
+		int y00 = *pIn++;
+		int y11 = *(pIn+8);
+		int y01 = *pIn++;
+		int u   = *pOut1 - 128;
+		int v   = *(pOut1+1) - 128;
+		ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, pOut1);
+		pOut1 += 6;
+	      }
+	      pOut1 += (iWidth*2 - 8) * 3;
+	      pIn += 8;
+	    }
+	    pOut += 8 * 3;
+	}
+    }
+
 #else
 	/* Just dump pix data straight out for debug */
 	int i;
-	pOut += iSegment * 384;
+	pOut0 += iSegment * 384;
 	for(i=0; i<384; i++) {
-	  *pOut++ = *pIn++;
+	  *pOut0++ = *pIn0++;
 	}
 #endif
 }
@@ -539,11 +751,8 @@
 
 		aPackNum[i] = n ? cdata[992] : -1;
 
-		if (st){ 
-			// Macro - must be in braces!
-			PDEBUG("data error: [%d] len=%d, status=%d\n",
-				i, n, st);
-		}
+		if (st)
+			PDEBUG("data error: [%d] len=%d, status=%d", i, n, st);
 
 		frame = &ov511->frame[ov511->curframe];
 		
@@ -552,13 +761,18 @@
 		     cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
 		    (cdata[8] & 8) && (cdata[8] & 0x80)) {
 
-		    PDEBUG("Found Frame End!, packnum = %d\n", (int)(cdata[992]));
-		    PDEBUG("Current frame = %d\n", ov511->curframe);
+#if 0
+		    PDEBUG("Found Frame End!, packnum = %d", (int)(cdata[992]));
+		    PDEBUG("Current frame = %d", ov511->curframe);
+#endif
 
 		    if (frame->scanstate == STATE_LINES) {
 		        if (waitqueue_active(&frame->wq)) {
-			  PDEBUG("About to wake up waiting processes\n");
+#if 0
+			  PDEBUG("About to wake up waiting processes");
+#endif
 			  frame->grabstate = FRAME_DONE;
+			  ov511->curframe = -1;
 			  wake_up_interruptible(&frame->wq);
 			}
 		    }
@@ -568,8 +782,10 @@
 		else if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] | 
 			  cdata[4] | cdata[5] | cdata[6] | cdata[7]) == 0 &&
 			 (cdata[8] & 8)) {
-			PDEBUG("ov511: Found Frame Start!, packnum = %d\n", (int)(cdata[992]));
-			PDEBUG("ov511: Frame Header Byte = 0x%x\n", (int)(cdata[8]));
+#if 0
+			PDEBUG("ov511: Found Frame Start!, packnum = %d", (int)(cdata[992]));
+			PDEBUG("ov511: Frame Header Byte = 0x%x", (int)(cdata[8]));
+#endif
 		    frame->scanstate = STATE_LINES;
 			frame->segment = 0;
 		}
@@ -589,15 +805,18 @@
 		  }
 
 			/* Parse the segments */
-			while(iPix <= 992 - 384 && frame->segment < 1200) {
-			  ov511_parse_data(pData, frame->data, frame->segment);
+			while(iPix <= 992 - 384 &&
+			      frame->segment < frame->width * frame->height / 256) {
+			  ov511_parse_data(pData, frame->data,
+					   frame->width,
+					   frame->segment);
 			  frame->segment++;
 			  iPix += 384;
 			  pData = &cdata[iPix];
 		}
 
 			/* Save extra data for next time */
-			if (frame->segment < 1200) {
+			if (frame->segment < frame->width * frame->height / 256) {
 			  memmove(ov511->scratch, pData, 992 - iPix);
 			  ov511->scratchlen = 992 - iPix;
 			}
@@ -619,18 +838,6 @@
 	struct ov511_sbuf *sbuf;
 	int i;
 
-#if 0
-	static int last_status, last_error_count, last_actual_length;
-	if (last_status != urb->status ||
-	    last_error_count != urb->error_count ||
-	    last_actual_length != urb->actual_length) {
-	  PDEBUG("ov511_isoc_irq: %p status %d, errcount = %d, length = %d\n", urb, urb->status, urb->error_count, urb->actual_length);
-	  last_status = urb->status;
-	  last_error_count = urb->error_count;
-	  last_actual_length = urb->actual_length;
-	}
-#endif
-
 	if (!ov511->streaming) {
 		PDEBUG("hmmm... not streaming, but got interrupt\n");
 		return;
@@ -639,17 +846,10 @@
 	sbuf = &ov511->sbuf[ov511->cursbuf];
 
 	/* Copy the data received into our scratch buffer */
-	len = ov511_move_data(ov511, urb);
-#if 0
-	/* If we don't have a frame we're current working on, complain */
-	if (ov511->scratchlen) {
-		if (ov511->curframe < 0) {
-			// Macro - must be in braces!!
-			PDEBUG("received data, but no frame available\n");
-		} else
-			ov511_parse_data(ov511);
+	if (ov511->curframe >= 0) {
+	  len = ov511_move_data(ov511, urb);
 	}
-#endif
+
 	for (i = 0; i < FRAMES_PER_DESC; i++) {
 		sbuf->urb->iso_frame_desc[i].status = 0;
 		sbuf->urb->iso_frame_desc[i].actual_length = 0;
@@ -672,185 +872,13 @@
 	ov511->cursbuf = 0;
 	ov511->scratchlen = 0;
 
-	ov511_reg_write(ov511->dev, 0x10, 0x00);
-	ov511_reg_write(ov511->dev, 0x11, 0x01);
-	ov511_reg_write(ov511->dev, 0x12, 0x4f);
-	ov511_reg_write(ov511->dev, 0x13, 0x3d);
-	ov511_reg_write(ov511->dev, 0x14, 0x00);
-	ov511_reg_write(ov511->dev, 0x15, 0x00);
-	ov511_reg_write(ov511->dev, 0x16, 0x01); /* 01 */
-	ov511_reg_write(ov511->dev, 0x17, 0x00);
-	ov511_reg_write(ov511->dev, 0x18, 0x03);
-	ov511_reg_write(ov511->dev, 0x19, 0x00);
-	ov511_reg_write(ov511->dev, 0x1a, 0x4f);
-	ov511_reg_write(ov511->dev, 0x1b, 0x3b);
-	ov511_reg_write(ov511->dev, 0x1c, 0x00);
-	ov511_reg_write(ov511->dev, 0x1d, 0x00);
-	ov511_reg_write(ov511->dev, 0x1e, 0x01);
-	ov511_reg_write(ov511->dev, 0x1f, 0x06);
-	
-	ov511_reg_write(ov511->dev, 0x20, 0x01);
-	ov511_reg_write(ov511->dev, 0x21, 0x01);
-	ov511_reg_write(ov511->dev, 0x22, 0x01);
-	ov511_reg_write(ov511->dev, 0x23, 0x1a);
-
-	ov511_reg_write(ov511->dev, 0x30, 0x1f);
-	ov511_reg_write(ov511->dev, 0x31, 0x03);
-	ov511_reg_write(ov511->dev, 0x38, 0x00);
-	ov511_reg_write(ov511->dev, 0x39, 0x00);
-	ov511_reg_write(ov511->dev, 0x3e, 0x00);
-
-	ov511_reg_write(ov511->dev, 0x50, 0x00);
-	ov511_reg_write(ov511->dev, 0x51, 0x00);
-	ov511_reg_write(ov511->dev, 0x52, 0x01);
-	ov511_reg_write(ov511->dev, 0x53, 0x01);
-	ov511_reg_write(ov511->dev, 0x5e, 0x5a);
-	ov511_reg_write(ov511->dev, 0x5f, 0x00);
-
-	ov511_reg_write(ov511->dev, 0x70, 0x01); /* 3f */
-	ov511_reg_write(ov511->dev, 0x71, 0x01); /* 3f */
-	ov511_reg_write(ov511->dev, 0x72, 0x01);
-	ov511_reg_write(ov511->dev, 0x73, 0x01);
-	ov511_reg_write(ov511->dev, 0x74, 0x01);
-	ov511_reg_write(ov511->dev, 0x75, 0x01);
-	ov511_reg_write(ov511->dev, 0x76, 0x01);
-	ov511_reg_write(ov511->dev, 0x77, 0x01);
-	ov511_reg_write(ov511->dev, 0x78, 0x00);
-	ov511_reg_write(ov511->dev, 0x79, 0x00); /* 03 */
-
-	ov511_reg_write(ov511->dev, 0x80, 0x10);
-	ov511_reg_write(ov511->dev, 0x81, 0x21);
-	ov511_reg_write(ov511->dev, 0x82, 0x32);
-	ov511_reg_write(ov511->dev, 0x83, 0x43);
-	ov511_reg_write(ov511->dev, 0x84, 0x11);
-	ov511_reg_write(ov511->dev, 0x85, 0x21);
-	ov511_reg_write(ov511->dev, 0x86, 0x32);
-	ov511_reg_write(ov511->dev, 0x87, 0x44);
-	ov511_reg_write(ov511->dev, 0x88, 0x11);
-	ov511_reg_write(ov511->dev, 0x89, 0x22);
-	ov511_reg_write(ov511->dev, 0x8a, 0x43);
-	ov511_reg_write(ov511->dev, 0x8b, 0x44);
-	ov511_reg_write(ov511->dev, 0x8c, 0x22);
-	ov511_reg_write(ov511->dev, 0x8d, 0x32);
-	ov511_reg_write(ov511->dev, 0x8e, 0x44);
-	ov511_reg_write(ov511->dev, 0x8f, 0x44);
-	ov511_reg_write(ov511->dev, 0x90, 0x22);
-	ov511_reg_write(ov511->dev, 0x91, 0x43);
-	ov511_reg_write(ov511->dev, 0x92, 0x54);
-	ov511_reg_write(ov511->dev, 0x93, 0x55);
-	ov511_reg_write(ov511->dev, 0x94, 0x33);
-	ov511_reg_write(ov511->dev, 0x95, 0x44);
-	ov511_reg_write(ov511->dev, 0x96, 0x55);
-	ov511_reg_write(ov511->dev, 0x97, 0x55);
-	ov511_reg_write(ov511->dev, 0x98, 0x43);
-	ov511_reg_write(ov511->dev, 0x99, 0x44);
-	ov511_reg_write(ov511->dev, 0x9a, 0x55);
-	ov511_reg_write(ov511->dev, 0x9b, 0x55);
-	ov511_reg_write(ov511->dev, 0x9c, 0x44);
-	ov511_reg_write(ov511->dev, 0x9d, 0x44);
-	ov511_reg_write(ov511->dev, 0x9e, 0x55);
-	ov511_reg_write(ov511->dev, 0x9f, 0x55);
-
-	ov511_reg_write(ov511->dev, 0xa0, 0x20);
-	ov511_reg_write(ov511->dev, 0xa1, 0x32);
-	ov511_reg_write(ov511->dev, 0xa2, 0x44);
-	ov511_reg_write(ov511->dev, 0xa3, 0x44);
-	ov511_reg_write(ov511->dev, 0xa4, 0x22);
-	ov511_reg_write(ov511->dev, 0xa5, 0x42);
-	ov511_reg_write(ov511->dev, 0xa6, 0x44);
-	ov511_reg_write(ov511->dev, 0xa7, 0x44);
-	ov511_reg_write(ov511->dev, 0xa8, 0x22);
-	ov511_reg_write(ov511->dev, 0xa9, 0x43);
-	ov511_reg_write(ov511->dev, 0xaa, 0x44);
-	ov511_reg_write(ov511->dev, 0xab, 0x44);
-	ov511_reg_write(ov511->dev, 0xac, 0x43);
-	ov511_reg_write(ov511->dev, 0xad, 0x44);
-	ov511_reg_write(ov511->dev, 0xae, 0x44);
-	ov511_reg_write(ov511->dev, 0xaf, 0x44);
-	ov511_reg_write(ov511->dev, 0xb0, 0x44);
-	ov511_reg_write(ov511->dev, 0xb1, 0x44);
-	ov511_reg_write(ov511->dev, 0xb2, 0x44);
-	ov511_reg_write(ov511->dev, 0xb3, 0x44);
-	ov511_reg_write(ov511->dev, 0xb4, 0x44);
-	ov511_reg_write(ov511->dev, 0xb5, 0x44);
-	ov511_reg_write(ov511->dev, 0xb6, 0x44);
-	ov511_reg_write(ov511->dev, 0xb7, 0x44);
-	ov511_reg_write(ov511->dev, 0xb8, 0x44);
-	ov511_reg_write(ov511->dev, 0xb9, 0x44);
-	ov511_reg_write(ov511->dev, 0xba, 0x44);
-	ov511_reg_write(ov511->dev, 0xbb, 0x44);
-	ov511_reg_write(ov511->dev, 0xbc, 0x44);
-	ov511_reg_write(ov511->dev, 0xbd, 0x44);
-	ov511_reg_write(ov511->dev, 0xbe, 0x44);
-	ov511_reg_write(ov511->dev, 0xbf, 0x44);
-
-	ov511_i2c_write(ov511->dev, 0x13, 0x01); /* 01 */
-	ov511_i2c_write(ov511->dev, 0x00, 0x1E); /* 1E */
-	ov511_i2c_write(ov511->dev, 0x01, 0x80); /* 80 */
-	ov511_i2c_write(ov511->dev, 0x02, 0x80); /* 80 */
-	ov511_i2c_write(ov511->dev, 0x03, 0x86); /* 86 */
-	ov511_i2c_write(ov511->dev, 0x04, 0x80);
-	ov511_i2c_write(ov511->dev, 0x05, 0xff); /* ff */
-	ov511_i2c_write(ov511->dev, 0x06, 0x5a);
-	ov511_i2c_write(ov511->dev, 0x07, 0xd4);
-	ov511_i2c_write(ov511->dev, 0x08, 0x80);
-	ov511_i2c_write(ov511->dev, 0x09, 0x80);
-	ov511_i2c_write(ov511->dev, 0x0a, 0x80);
-	ov511_i2c_write(ov511->dev, 0x0b, 0xe0);
-	ov511_i2c_write(ov511->dev, 0x0c, 0x1f); /* 1f */
-	ov511_i2c_write(ov511->dev, 0x0d, 0x1f); /* 1f */
-	ov511_i2c_write(ov511->dev, 0x0e, 0x15); /* 15 */
-	ov511_i2c_write(ov511->dev, 0x0f, 0x03);
-	ov511_i2c_write(ov511->dev, 0x10, 0xff);
-	ov511_i2c_write(ov511->dev, 0x11, 0x01);
-	ov511_i2c_write(ov511->dev, 0x12, 0x24); /* 24 */
-	ov511_i2c_write(ov511->dev, 0x14, 0x04);
-	ov511_i2c_write(ov511->dev, 0x15, 0x01);
-	ov511_i2c_write(ov511->dev, 0x16, 0x06);
-	ov511_i2c_write(ov511->dev, 0x17, 0x38);
-	ov511_i2c_write(ov511->dev, 0x18, 0x03);
-	ov511_i2c_write(ov511->dev, 0x19, 0x05);
-	ov511_i2c_write(ov511->dev, 0x1a, 0xf4);
-	ov511_i2c_write(ov511->dev, 0x1b, 0x28);
-	ov511_i2c_write(ov511->dev, 0x1c, 0x7f);
-	ov511_i2c_write(ov511->dev, 0x1d, 0xa2);
-	ov511_i2c_write(ov511->dev, 0x1e, 0xc4);
-	ov511_i2c_write(ov511->dev, 0x1f, 0x04);
-	ov511_i2c_write(ov511->dev, 0x20, 0x1c);
-	ov511_i2c_write(ov511->dev, 0x21, 0x80);
-	ov511_i2c_write(ov511->dev, 0x22, 0x80);
-	ov511_i2c_write(ov511->dev, 0x23, 0x2a);
-	ov511_i2c_write(ov511->dev, 0x24, 0x10); /* 10 */
-	ov511_i2c_write(ov511->dev, 0x25, 0x8a); /* 8a */
-	ov511_i2c_write(ov511->dev, 0x26, 0x70);
-	ov511_i2c_write(ov511->dev, 0x27, 0xc2);
-	ov511_i2c_write(ov511->dev, 0x28, 0x24);
-	ov511_i2c_write(ov511->dev, 0x29, 0x11);
-	ov511_i2c_write(ov511->dev, 0x2a, 0x04);
-	ov511_i2c_write(ov511->dev, 0x2b, 0xac);
-	ov511_i2c_write(ov511->dev, 0x2c, 0xfe);
-	ov511_i2c_write(ov511->dev, 0x2d, 0x93);
-	ov511_i2c_write(ov511->dev, 0x2e, 0x80);
-	ov511_i2c_write(ov511->dev, 0x2f, 0xb0);
-	ov511_i2c_write(ov511->dev, 0x30, 0x71);
-	ov511_i2c_write(ov511->dev, 0x31, 0x90);
-	ov511_i2c_write(ov511->dev, 0x32, 0x22);
-	ov511_i2c_write(ov511->dev, 0x33, 0x20);
-	ov511_i2c_write(ov511->dev, 0x34, 0x8b);
-	ov511_i2c_write(ov511->dev, 0x35, 0x9e);
-	ov511_i2c_write(ov511->dev, 0x36, 0x7f);
-	ov511_i2c_write(ov511->dev, 0x37, 0x7f);
-	ov511_i2c_write(ov511->dev, 0x38, 0x81);
-	
-	ov511_dump_i2c_regs(ov511->dev);
-
 	ov511_set_packet_size(ov511, 993);
 
 	/* We double buffer the Iso lists */
 	urb = usb_alloc_urb(FRAMES_PER_DESC);
 	
 	if (!urb) {
-		printk(KERN_ERR "ov511_init_isoc: usb_alloc_urb ret. NULL\n");
+		err("ov511_init_isoc: usb_alloc_urb ret. NULL");
 		return -ENOMEM;
 	}
 	ov511->sbuf[0].urb = urb;
@@ -869,7 +897,7 @@
 
 	urb = usb_alloc_urb(FRAMES_PER_DESC);
 	if (!urb) {
-		printk(KERN_ERR "ov511_init_isoc: usb_alloc_urb ret. NULL\n");
+		err("ov511_init_isoc: usb_alloc_urb ret. NULL");
 		return -ENOMEM;
 	}
 	ov511->sbuf[1].urb = urb;
@@ -891,12 +919,10 @@
 
 	err = usb_submit_urb(ov511->sbuf[0].urb);
 	if (err)
-		printk(KERN_ERR "ov511_init_isoc: usb_run_isoc(0) ret %d\n",
-			err);
+		err("ov511_init_isoc: usb_run_isoc(0) ret %d", err);
 	err = usb_submit_urb(ov511->sbuf[1].urb);
 	if (err)
-		printk(KERN_ERR "ov511_init_isoc: usb_run_isoc(1) ret %d\n",
-			err);
+		err("ov511_init_isoc: usb_run_isoc(1) ret %d\n", err);
 
 	ov511->streaming = 1;
 
@@ -968,7 +994,7 @@
 	int err = -EBUSY;
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
 
-	PDEBUG("ov511_open\n");
+	PDEBUG("ov511_open");
 	
 	down(&ov511->lock);
 	if (ov511->user)
@@ -987,8 +1013,8 @@
 	ov511->frame[0].data = ov511->fbuf;
 	ov511->frame[1].data = ov511->fbuf + MAX_FRAME_SIZE;
 
-	PDEBUG("frame [0] @ %p\n", ov511->frame[0].data);
-	PDEBUG("frame [1] @ %p\n", ov511->frame[1].data);
+	PDEBUG("frame [0] @ %p", ov511->frame[0].data);
+	PDEBUG("frame [1] @ %p", ov511->frame[1].data);
 
 	ov511->sbuf[0].data = kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
 	if (!ov511->sbuf[0].data)
@@ -997,17 +1023,8 @@
 	if (!ov511->sbuf[1].data)
 		goto open_err_on1;
 		
-	PDEBUG("sbuf[0] @ %p\n", ov511->sbuf[0].data);
-	PDEBUG("sbuf[1] @ %p\n", ov511->sbuf[1].data);
-
-	/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
-	 * (using read() instead). */
-	ov511->frame[0].width = DEFAULT_WIDTH;
-	ov511->frame[0].height = DEFAULT_HEIGHT;
-	ov511->frame[0].bytes_read = 0;
-	ov511->frame[1].width = DEFAULT_WIDTH;
-	ov511->frame[1].height = DEFAULT_HEIGHT;
-	ov511->frame[1].bytes_read = 0;
+	PDEBUG("sbuf[0] @ %p", ov511->sbuf[0].data);
+	PDEBUG("sbuf[1] @ %p", ov511->sbuf[1].data);
 
 	err = ov511_init_isoc(ov511);
 	if (err)
@@ -1038,7 +1055,7 @@
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
 
-	PDEBUG("ov511_close\n");
+	PDEBUG("ov511_close");
 	
 	down(&ov511->lock);	
 	ov511->user--;
@@ -1066,12 +1083,12 @@
 }
 
 // FIXME - Needs much work!!!
-static int ov511_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
+static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
 {
-	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
-	
-	PDEBUG("IOCtl: 0x%X\n", cmd);
-	
+	struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
+#if 0	
+	PDEBUG("IOCtl: 0x%X", cmd);
+#endif	
 	switch (cmd) {
 		case VIDIOCGCAP:
 		{
@@ -1127,14 +1144,9 @@
 		{
 			struct video_picture p;
 
-			p.colour = 0x8000;	/* Damn British people :) */
-			p.hue = 0x8000;
-			p.brightness = 180 << 8;	/* XXX */
-			p.contrast = 192 << 8;		/* XXX */
-			p.whiteness = 105 << 8;		/* XXX */
-			p.depth = 24;
-			p.palette = VIDEO_PALETTE_RGB24;
-
+			if (ov7610_get_picture(ov511, &p))
+				return -EIO;
+							
 			if (copy_to_user(arg, &p, sizeof(p)))
 				return -EFAULT;
 
@@ -1146,6 +1158,9 @@
 
 			if (copy_from_user(&p, arg, sizeof(p)))
 				return -EFAULT;
+			
+			if (ov7610_set_picture(ov511, &p))
+				return -EIO;
 
 			return 0;
 		}
@@ -1206,9 +1221,11 @@
 			if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
 				return -EFAULT;
 
-			PDEBUG("MCAPTURE\n");
-			PDEBUG("frame: %d, size: %dx%d, format: %d\n",
+#if 0
+			PDEBUG("MCAPTURE");
+			PDEBUG("frame: %d, size: %dx%d, format: %d",
 				vm.frame, vm.width, vm.height, vm.format);
+#endif
 
 			if (vm.format != VIDEO_PALETTE_RGB24)
 				return -EINVAL;
@@ -1221,8 +1238,15 @@
 
 			/* Don't compress if the size changed */
 			if ((ov511->frame[vm.frame].width != vm.width) ||
-			    (ov511->frame[vm.frame].height != vm.height))
+			    (ov511->frame[vm.frame].height != vm.height)) {
 				ov511->compress = 0;
+				ov511_mode_init_regs(ov511,
+						     vm.width, vm.height, 0);
+#if 0
+				PDEBUG("ov511: Setting frame %d to (%d, %d) : %d",
+				       vm.frame, vm.width, vm.height, 0);
+#endif
+			}
 
 			ov511->frame[vm.frame].width = vm.width;
 			ov511->frame[vm.frame].height = vm.height;
@@ -1239,8 +1263,9 @@
 			if (copy_from_user((void *)&frame, arg, sizeof(int)))
 				return -EFAULT;
 
-			PDEBUG("syncing to frame %d\n", frame);
-			
+#if 0
+			PDEBUG("syncing to frame %d", frame);
+#endif
 			switch (ov511->frame[frame].grabstate) {
 				case FRAME_UNUSED:
 					return -EINVAL;
@@ -1312,7 +1337,7 @@
 	int frmx = -1;
 	volatile struct ov511_frame *frame;
 
-	PDEBUG("ov511_read: %ld bytes, noblock=%d\n", count, noblock);
+	PDEBUG("ov511_read: %ld bytes, noblock=%d", count, noblock);
 
 	if (!dev || !buf)
 		return -EFAULT;
@@ -1343,20 +1368,20 @@
 
 restart:
 	while (frame->grabstate == FRAME_GRABBING) {
-		interruptible_sleep_on(&frame->wq);
+		interruptible_sleep_on(&ov511->frame[frmx].wq);
 		if (signal_pending(current))
 			return -EINTR;
 	}
 
 	if (frame->grabstate == FRAME_ERROR) {
 		frame->bytes_read = 0;
-		printk(KERN_ERR "ov511_read: errored frame %d\n", ov511->curframe);
+		err("ov511_read: errored frame %d", ov511->curframe);
 		if (ov511_new_frame(ov511, frmx))
-			printk(KERN_ERR "ov511_read: ov511_new_frame error\n");
+			err("ov511_read: ov511_new_frame error");
 		goto restart;
 	}
 
-	PDEBUG("ov511_read: frmx=%d, bytes_read=%ld, scanlength=%ld\n", frmx,
+	PDEBUG("ov511_read: frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
 		frame->bytes_read, frame->scanlength);
 
 	/* copy bytes to user space; we allow for partials reads */
@@ -1367,7 +1392,7 @@
 		return -EFAULT;
 
 	frame->bytes_read += count;
-	PDEBUG("ov511_read: {copy} count used=%ld, new bytes_read=%ld\n",
+	PDEBUG("ov511_read: {copy} count used=%ld, new bytes_read=%ld",
 		count, frame->bytes_read);
 
 	if (frame->bytes_read >= frame->scanlength) { /* All data has been read */
@@ -1376,7 +1401,7 @@
 		/* Mark it as available to be used again. */
 		ov511->frame[frmx].grabstate = FRAME_UNUSED;
 		if (ov511_new_frame(ov511, frmx ? 0 : 1))
-			printk(KERN_ERR "ov511_read: ov511_new_frame returned error\n");
+			err("ov511_read: ov511_new_frame returned error");
 	}
 
 	return count;
@@ -1388,7 +1413,7 @@
 	unsigned long start = (unsigned long)adr;
 	unsigned long page, pos;
 
-	PDEBUG("mmap: %ld (%lX) bytes\n", size, size);
+	PDEBUG("mmap: %ld (%lX) bytes", size, size);
 
 	if (size > (((2 * MAX_FRAME_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)))
 		return -EINVAL;
@@ -1428,14 +1453,52 @@
 	0
 };
 
+static int ov7610_configure(struct usb_device *dev)
+{
+	if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
+	                        OV7610_I2C_WRITE_ID) < 0)
+		return -1;
+
+	if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
+	                        OV7610_I2C_READ_ID) < 0)
+		return -1;
+	
+	/* Reset the camera chip */
+	if (ov511_i2c_reset(dev) < 0)
+		return -1;
+
+#if 0
+	if(usb_ov511_reg_write(dev, OV511_REG_I2C_CLOCK_PRESCALER,
+	                            OV511_I2C_CLOCK_PRESCALER))
+		return -1;
+#endif
+	
+	if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
+		return -1;
+	
+	/* Dummy read to sync I2C */
+	if(ov511_i2c_read(dev, 0x00) < 0)
+		return -1;
+	
+
+	if((ov511_i2c_read(dev, OV7610_REG_ID_HIGH) != 0x7F) ||
+	   (ov511_i2c_read(dev, OV7610_REG_ID_LOW) != 0xA2)) {
+		err("Failed to read OV7610 ID. You might not have an OV7610,");
+		err("or it may be not responding. Report this to");
+		err("mmcclelland@delphi.com");
+		return -1;
+	}
+
+	return 0;
+}
+
 static int ov511_configure(struct usb_ov511 *ov511)
 {
 	struct usb_device *dev = ov511->dev;
-	int temprc;   // DEBUG CODE
 
 	/* Set altsetting 0 */
 	if (usb_set_interface(dev, ov511->iface, 0) < 0) {
-		printk(KERN_ERR "ov511: usb_set_interface error\n");
+		err("usb_set_interface error");
 		return -EBUSY;
 	}
 
@@ -1445,7 +1508,7 @@
 	init_waitqueue_head(&ov511->frame[1].wq);
 
 	if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) == -1) {
-		printk(KERN_ERR "ov511: video_register_device failed\n");
+		err("video_register_device failed");
 		return -EBUSY;
 	}
 
@@ -1455,7 +1518,7 @@
 
 	/* Initialize system */
 	if (ov511_reg_write(dev, OV511_REG_SYSTEM_INIT, 0x01) < 0) {
-		printk(KERN_ERR "ov511: enable system: command failed\n");
+		err("enable system: command failed");
 		goto error;
 	}
 
@@ -1463,36 +1526,31 @@
 	if (ov511_reset(dev, OV511_RESET_ALL) < 0)
 		goto error;
 
+	if(ov7610_configure(dev) < 0) {
+		err("failed to configure OV7610");
+ 		goto error;	
+	}
+
 	/* Disable compression */
 	if (ov511_reg_write(dev, OV511_OMNICE_ENABLE, 0x00) < 0) {
-		printk(KERN_ERR "ov511: disable compression: command failed\n");
+		err("disable compression: command failed");
 		goto error;
 	}
 
-// FIXME - error checking needed
-	ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
-	                     OV7610_I2C_WRITE_ID);
-	ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_READ,
-	                     OV7610_I2C_READ_ID);
-
-// DEBUG CODE
-//	usb_ov511_reg_write(dev, OV511_REG_I2C_CLOCK_PRESCALER,
-//						 OV511_I2C_CLOCK_PRESCALER);
-	
-	if (ov511_reset(dev, OV511_RESET_NOREGS) < 0)
-		goto error;
-	
-	/* Dummy read to sync I2C */
-	ov511_i2c_read(dev, 0x1C);
-	
-// DEBUG - TEST CODE FOR CAMERA REG READ
-	temprc = ov511_i2c_read(dev, 0x1C);
-
-     	temprc = ov511_i2c_read(dev, 0x1D);
-// END DEBUG CODE
-     	
 	ov511->compress = 0;
 	
+	/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
+	 * (using read() instead). */
+	ov511->frame[0].width = DEFAULT_WIDTH;
+	ov511->frame[0].height = DEFAULT_HEIGHT;
+	ov511->frame[0].bytes_read = 0;
+	ov511->frame[1].width = DEFAULT_WIDTH;
+	ov511->frame[1].height = DEFAULT_HEIGHT;
+	ov511->frame[1].bytes_read = 0;
+
+	/* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */
+	ov511_mode_init_regs(ov511, DEFAULT_WIDTH, DEFAULT_HEIGHT, 0);
+
 	return 0;
 	
 error:
@@ -1511,7 +1569,7 @@
 	struct usb_ov511 *ov511;
 	int rc;
 
-	PDEBUG("probing for device...\n");
+	PDEBUG("probing for device...");
 
 	/* We don't handle multi-config cameras */
 	if (dev->descriptor.bNumConfigurations != 1)
@@ -1535,7 +1593,7 @@
 	printk(KERN_INFO "ov511: USB OV511-based camera found\n");
 
 	if ((ov511 = kmalloc(sizeof(*ov511), GFP_KERNEL)) == NULL) {
-		printk(KERN_ERR "ov511: couldn't kmalloc ov511 struct\n");
+		err("couldn't kmalloc ov511 struct");
 		return NULL;
 	}
 
@@ -1546,7 +1604,7 @@
 
 	rc = ov511_reg_read(dev, OV511_REG_SYSTEM_CUSTOM_ID);
 	if (rc < 0) {
-		printk("ov511: Unable to read camera bridge registers\n");
+		err("Unable to read camera bridge registers");
 		return NULL;
 	}
 	
@@ -1567,9 +1625,9 @@
 		printk("ov511: Camera is a AverMedia InterCam Elite\n");
 		break;
 	default:
-		printk("ov511: Specific camera type (%d) not recognized\n", rc);
-		printk("ov511: Please contact mmcclelland@delphi.com to request\n");
-		printk("ov511: support for your camera.\n");
+		err("Specific camera type (%d) not recognized", rc);
+		err("Please contact mmcclelland@delphi.com to request");
+		err("support for your camera.");
 		return NULL;
 	}
 
@@ -1579,7 +1637,7 @@
 		return ov511;
 	}
 	else {
-		printk(KERN_ERR "ov511: Failed to configure camera\n");
+		err("Failed to configure camera");
 		return NULL;
 	}
     	
@@ -1609,7 +1667,7 @@
 
 int usb_ov511_init(void)
 {
-	PDEBUG("usb_ov511_init()\n");
+	PDEBUG("usb_ov511_init()");
 	
 	EXPORT_NO_SYMBOLS;
 	
@@ -1631,7 +1689,7 @@
 {
 	usb_ov511_cleanup();
 	
-	PDEBUG("Module unloaded\n");
+	PDEBUG("Module unloaded");
 }
 #endif
 
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/ov511.h linux/drivers/usb/ov511.h
--- v2.3.39/linux/drivers/usb/ov511.h	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/ov511.h	Mon Jan 17 16:24:48 2000
@@ -6,9 +6,9 @@
 #define OV511_DEBUG	/* Turn on debug messages */
 
 #ifdef OV511_DEBUG
-#  define PDEBUG(fmt, args...) printk("ov511: " fmt, ## args)
+#  define PDEBUG(fmt, args...) printk("ov511: " fmt "\n" , ## args)
 #else
-#  define PDEBUG(fmt, args...) /* Nothing */
+#  define PDEBUG(fmt, args...) do {} while(0)
 #endif
 
 /* Camera interface register numbers */
@@ -102,6 +102,50 @@
 #define OV511_ALTERNATE_SIZE_513	5
 #define OV511_ALTERNATE_SIZE_257	6
 #define OV511_ALTERNATE_SIZE_0		7
+
+/* ov7610 registers */
+#define OV7610_REG_GAIN          0x00
+#define OV7610_REG_BLUE          0x01
+#define OV7610_REG_RED           0x02
+#define OV7610_REG_SAT           0x03
+#define OV7610_REG_CNT           0x05
+#define OV7610_REG_BRT           0x06
+#define OV7610_REG_BLUE_BIAS     0x0C
+#define OV7610_REG_RED_BIAS      0x0D
+#define OV7610_REG_GAMMA_COEFF   0x0E
+#define OV7610_REG_WB_RANGE      0x0F
+#define OV7610_REG_EXP           0x10
+#define OV7610_REG_CLOCK         0x11
+#define OV7610_REG_COM_A         0x12
+#define OV7610_REG_COM_B         0x13
+#define OV7610_REG_COM_C         0x14
+#define OV7610_REG_COM_D         0x15
+#define OV7610_REG_FIELD_DIVIDE  0x16
+#define OV7610_REG_HWIN_START    0x17
+#define OV7610_REG_HWIN_END      0x18
+#define OV7610_REG_VWIN_START    0x19
+#define OV7610_REG_VWIN_END      0x1A
+#define OV7610_REG_PIXEL_SHIFT   0x1B
+#define OV7610_REG_ID_HIGH       0x1C
+#define OV7610_REG_ID_LOW        0x1D
+#define OV7610_REG_COM_E         0x20
+#define OV7610_REG_YOFFSET       0x21
+#define OV7610_REG_UOFFSET       0x22
+#define OV7610_REG_ECW           0x24
+#define OV7610_REG_ECB           0x25
+#define OV7610_REG_COM_F         0x26
+#define OV7610_REG_COM_G         0x27
+#define OV7610_REG_COM_H         0x28
+#define OV7610_REG_COM_I         0x29
+#define OV7610_REG_FRAMERATE_H   0x2A
+#define OV7610_REG_FRAMERATE_L   0x2B
+#define OV7610_REG_ALC           0x2C
+#define OV7610_REG_COM_J         0x2D
+#define OV7610_REG_VOFFSET       0x2E
+#define OV7610_REG_YGAMMA        0x33
+#define OV7610_REG_BIAS_ADJUST   0x34
+#define OV7610_REG_COM_L         0x35
+#define OV7610_REG_COM_K         0x38
 
 
 #define STREAM_BUF_SIZE	(PAGE_SIZE * 4)
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.3.39/linux/drivers/usb/printer.c	Wed Dec 29 13:13:19 1999
+++ linux/drivers/usb/printer.c	Thu Jan 20 09:49:41 2000
@@ -1,481 +1,450 @@
-/* Driver for USB Printers
- * 
- * Copyright 1999 Michael Gee (michael@linuxspecific.com)
- * Copyright 1999 Pavel Machek (pavel@suse.cz)
+/*
+ * printer.c  Version 0.3
+ *
+ * Copyright (c) 1999 Michael Gee 	<michael@linuxspecific.com>
+ * Copyright (c) 1999 Pavel Machek      <pavel@suse.cz>
+ * Copyright (c) 2000 Vojtech Pavlik    <vojtech@suse.cz>
+ *
+ * USB Printer Device Class driver for USB printers and printer cables
+ *
+ * Sponsored by SuSE
+ *
+ * ChangeLog:
+ *	v0.1 - thorough cleaning, URBification, almost a rewrite
+ *	v0.2 - some more cleanups
+ *	v0.3 - cleaner again, waitqueue fixes
+ */
+
+/*
+ * 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.
  *
- * Distribute under GPL version 2 or later.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/lp.h>
-#include <linux/spinlock.h>
+
+#define DEBUG
 
 #include "usb.h"
 
-/* Define IEEE_DEVICE_ID if you want to see the IEEE-1284 Device ID string.
- * This may include the printer's serial number.
- * An example from an HP 970C DeskJet printer is (this is one long string,
- * with the serial number changed):
-MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:Hewlett-Packard DeskJet 970C;SERN:US970CSEPROF;VSTATUS:$HB0$NC0,ff,DN,IDLE,CUT,K1,C0,DP,NR,KP000,CP027;VP:0800,FL,B0;VJ:                    ;
+#define USBLP_BUF_SIZE		8192
+
+/*
+ * USB Printer Requests
  */
-#define IEEE_DEVICE_ID
 
-#define NAK_TIMEOUT (HZ)				/* stall wait for printer */
-#define MAX_RETRY_COUNT ((60*60*HZ)/NAK_TIMEOUT)	/* should not take 1 minute a page! */
+#define USBLP_REQ_GET_ID	0x00
+#define USBLP_REQ_GET_STATUS	0x01
+#define USBLP_REQ_RESET		0x02
+
+#define USBLP_MINORS		16
+#define USBLP_MINOR_BASE	0
+
+#define USBLP_WRITE_TIMEOUT	(60*HZ)			/* 60 seconds */
+
+struct usblp {
+	struct usb_device 	*dev;			/* USB device */
+	struct urb		readurb, writeurb;	/* The urbs */
+	wait_queue_head_t	wait;			/* Zzzzz ... */
+	int			readcount;		/* Counter for reads */
+	int			ifnum;			/* Interface number */
+	int			minor;			/* minor number of device */
+	unsigned char		used;			/* True if open */
+	unsigned char		bidir;			/* interface is bidirectional */
+};
 
-#define BIG_BUF_SIZE			8192
-#define SUBCLASS_PRINTERS		1
-#define PROTOCOL_UNIDIRECTIONAL		1
-#define PROTOCOL_BIDIRECTIONAL		2
+static struct usblp *usblp_table[USBLP_MINORS] = { NULL, /* ... */ };
 
 /*
- * USB Printer Requests
+ * Functions for usblp control messages.
  */
-#define USB_PRINTER_REQ_GET_DEVICE_ID	0
-#define USB_PRINTER_REQ_GET_PORT_STATUS	1
-#define USB_PRINTER_REQ_SOFT_RESET	2
-
-#define MAX_PRINTERS	8
-
-struct pp_usb_data {
-	struct usb_device 	*pusb_dev;
-	__u8			isopen;			/* True if open */
-	__u8			noinput;		/* True if no input stream */
-	__u8			minor;			/* minor number of device */
-	__u8			status;			/* last status from device */
-	int			maxin, maxout;		/* max transfer size in and out */
-	char			*obuf;			/* transfer buffer (out only) */
-	wait_queue_head_t	wait_q;			/* for timeouts */
-	unsigned int		last_error;		/* save for checking */
-	int			bulk_in_ep;		/* Bulk IN endpoint */
-	int			bulk_out_ep;		/* Bulk OUT endpoint */
-	int			bulk_in_index;		/* endpoint[bulk_in_index] */
-	int			bulk_out_index;		/* endpoint[bulk_out_index] */
-};
 
-static struct pp_usb_data *minor_data[MAX_PRINTERS];
+static int usblp_ctrl_msg(struct usblp *usblp, int request, int dir, int recip, void *buf, int len)
+{
+	int retval = usb_control_msg(usblp->dev,
+		dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
+		request, USB_TYPE_CLASS | dir | recip, 0, usblp->ifnum, buf, len, HZ * 5);
+	dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d len: %#x result: %d", request, !!dir, recip, len, retval);
+	return retval < 0 ? retval : 0;
+}
 
-#define PPDATA(x) ((struct pp_usb_data *)(x))
+#define usblp_read_status(usblp, status)\
+	usblp_ctrl_msg(usblp, USBLP_REQ_GET_STATUS, USB_DIR_IN, USB_RECIP_INTERFACE, status, 1)
+#define usblp_get_id(usblp, id, maxlen)\
+	usblp_ctrl_msg(usblp, USBLP_REQ_GET_ID, USB_DIR_IN, USB_RECIP_INTERFACE, id, maxlen)
+#define usblp_reset(usblp)\
+	usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_DIR_OUT, USB_RECIP_OTHER, NULL, 0)
+
+/*
+ * URB callback.
+ */
 
-static unsigned char printer_read_status(struct pp_usb_data *p)
+static void usblp_bulk(struct urb *urb)
 {
-	__u8 status;
-	int err;
-	struct usb_device *dev = p->pusb_dev;
+	struct usblp *usblp = urb->context;
 
-	err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
-		USB_PRINTER_REQ_GET_PORT_STATUS,
-		USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
-		0, 0, &status, sizeof(status), HZ);
-	if (err < 0) {
-		printk(KERN_ERR "usblp%d: read_status control_msg error = %d\n",
-			p->minor, err);
- 		return 0;
-	}
-	return status;
+	if (!usblp || !usblp->dev || !usblp->used)
+		return;
+
+	if (urb->status)
+		warn("nonzero read bulk status received: %d", urb->status);
+
+	wake_up_interruptible(&usblp->wait);
 }
 
-static int printer_check_status(struct pp_usb_data *p)
+/*
+ * Get and print printer errors.
+ */
+
+static int usblp_check_status(struct usblp *usblp)
 {
-	unsigned int last = p->last_error;
-	unsigned char status = printer_read_status(p);
+	unsigned char status;
 
-	if (status & LP_PERRORP)
-		/* No error. */
-		last = 0;
-	else if ((status & LP_POUTPA)) {
-		if (last != LP_POUTPA) {
-			last = LP_POUTPA;
-			printk(KERN_INFO "usblp%d out of paper (%x)\n", p->minor, status);
+	if (usblp_read_status(usblp, &status)) {
+		err("failed reading usblp status");
+		return -EIO;
+	}
+
+	if (status & LP_PERRORP) {
+	
+		if (status & LP_POUTPA) {
+			printk(KERN_INFO "usblp%d: out of paper", usblp->minor);
+			return -ENOSPC;
 		}
-	} else if (!(status & LP_PSELECD)) {
-		if (last != LP_PSELECD) {
-			last = LP_PSELECD;
-			printk(KERN_INFO "usblp%d off-line (%x)\n", p->minor, status);
+		if (~status & LP_PSELECD) {
+			printk(KERN_INFO "usblp%d: off-line", usblp->minor);
+			return -EIO;
 		}
-	} else {
-		if (last != LP_PERRORP) {
-			last = LP_PERRORP;
-			printk(KERN_INFO "usblp%d on fire (%x)\n", p->minor, status);
+		if (~status & LP_PERRORP) {
+			printk(KERN_INFO "usblp%d: on fire", usblp->minor);
+			return -EIO;
 		}
 	}
 
-	p->last_error = last;
-	return status;
+	return 0;
 }
 
-static void printer_reset(struct pp_usb_data *p)
-{
-	struct usb_device *dev = p->pusb_dev;
-	int err;
-
-	err = usb_control_msg(dev, usb_sndctrlpipe(dev,0),
-		USB_PRINTER_REQ_SOFT_RESET,
-		USB_TYPE_CLASS | USB_RECIP_OTHER,
-		0, 0, NULL, 0, HZ);
-	if (err < 0)
-		printk(KERN_ERR "usblp%d: reset control_msg error = %d\n",
-			p->minor, err);
-}
+/*
+ * File op functions.
+ */
 
-static int open_printer(struct inode *inode, struct file *file)
+static int usblp_open(struct inode *inode, struct file *file)
 {
-	struct pp_usb_data *p;
+	int minor = MINOR(inode->i_rdev) - USBLP_MINOR_BASE;
+	struct usblp *usblp;
+	int retval;
 
-	if (MINOR(inode->i_rdev) >= MAX_PRINTERS ||
-	   !minor_data[MINOR(inode->i_rdev)]) {
+	if (minor < 0 || minor >= USBLP_MINORS)
 		return -ENODEV;
-	}
 
-	p = minor_data[MINOR(inode->i_rdev)];
-	p->minor = MINOR(inode->i_rdev);
+	usblp  = usblp_table[minor];
 
-	if (p->isopen++) {
-		printk(KERN_ERR "usblp%d: printer is already open\n",
-			p->minor);
+	if (!usblp || !usblp->dev)
+		return -ENODEV;
+
+	if (usblp->used)
 		return -EBUSY;
-	}
-	if (!(p->obuf = (char *)__get_free_page(GFP_KERNEL))) {
-		p->isopen = 0;
-		printk(KERN_ERR "usblp%d: cannot allocate memory\n",
-			p->minor);
-		return -ENOMEM;
-	}
 
-	printer_check_status(p);
-
-	file->private_data = p;
-//	printer_reset(p);
-	init_waitqueue_head(&p->wait_q);
+	if ((retval = usblp_check_status(usblp)))
+		return retval;
 
 	MOD_INC_USE_COUNT;
+	usblp->used = 1;
+	file->private_data = usblp;
+
+	usblp->writeurb.transfer_buffer_length = 0;
+	usblp->writeurb.status = 0;
+	usblp->readcount = 0;
+
+	usb_submit_urb(&usblp->readurb);
 	return 0;
 }
 
-static int close_printer(struct inode *inode, struct file *file)
+static int usblp_release(struct inode *inode, struct file *file)
 {
-	struct pp_usb_data *p = file->private_data;
+	struct usblp *usblp = file->private_data;
 
-	free_page((unsigned long)p->obuf);
-	p->isopen = 0;
-	file->private_data = NULL;
-	/* free the resources if the printer is no longer around */
-	if (!p->pusb_dev) {
-		minor_data[p->minor] = NULL;
-		kfree(p);
-	}
 	MOD_DEC_USE_COUNT;
+	usblp->used = 0;
+			
+	if (usblp->dev) {
+        	usb_unlink_urb(&usblp->readurb);
+        	usb_unlink_urb(&usblp->writeurb);
+		return 0;
+	}
+
+	usblp_table[usblp->minor] = NULL;
+	kfree(usblp);
+
 	return 0;
 }
 
-static ssize_t write_printer(struct file *file,
-       const char *buffer, size_t count, loff_t *ppos)
+static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait)
 {
-	struct pp_usb_data *p = file->private_data;
-	unsigned long copy_size;
-	unsigned long bytes_written = 0;
-	unsigned long partial;
-	int result = USB_ST_NOERROR;
-	int maxretry;
-
-	do {
-		char *obuf = p->obuf;
-		unsigned long thistime;
-
-		thistime = copy_size = (count > p->maxout) ? p->maxout : count;
-		if (copy_from_user(p->obuf, buffer, copy_size))
-			return -EFAULT;
-		maxretry = MAX_RETRY_COUNT;
-
-		while (thistime) {
-			if (!p->pusb_dev)
-				return -ENODEV;
-			if (signal_pending(current)) {
-				return bytes_written ? bytes_written : -EINTR;
-			}
-			result = usb_bulk_msg(p->pusb_dev,
-					 usb_sndbulkpipe(p->pusb_dev, p->bulk_out_ep),
-					 obuf, thistime, &partial, HZ*20);
-			if (partial) {
-				obuf += partial;
-				thistime -= partial;
-				maxretry = MAX_RETRY_COUNT;
-			}
-			if (result == USB_ST_TIMEOUT) {	/* NAK - so hold for a while */
-				if (!maxretry--)
-					return -ETIME;
-                                interruptible_sleep_on_timeout(&p->wait_q, NAK_TIMEOUT);
-				continue;
-			} else if (!result && !partial) {
-				break;
+	struct usblp *usblp = file->private_data;
+	poll_wait(file, &usblp->wait, wait);
+	return (usblp->readurb.status  == -EINPROGRESS ? 0 : POLLIN  | POLLRDNORM)
+	     | (usblp->writeurb.status == -EINPROGRESS ? 0 : POLLOUT | POLLWRNORM);
+}
+
+static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct usblp *usblp = file->private_data;
+	int retval, timeout, writecount = 0;
+
+	while (writecount < count) {
+
+		if (usblp->writeurb.status == -EINPROGRESS) {
+
+			if (file->f_flags & O_NONBLOCK)
+				return -EAGAIN;
+
+			timeout = USBLP_WRITE_TIMEOUT;
+			while (timeout && usblp->writeurb.status == -EINPROGRESS) {
+
+				if (signal_pending(current))
+					return writecount ? writecount : -EINTR;
+
+				timeout = interruptible_sleep_on_timeout(&usblp->wait, timeout);	
 			}
-		};
-		if (result) {
-			/* whoops - let's reset and fail the request */
-//			printk("Whoops - %x\n", result);
-			printer_reset(p);
-			interruptible_sleep_on_timeout(&p->wait_q, 5*HZ);  /* let reset do its stuff */
+		}
+
+		if (usblp->writeurb.status == -EINPROGRESS) {
+			usb_unlink_urb(&usblp->writeurb);
+			printk(KERN_ERR "usblp%d: timed out\n", usblp->minor);
 			return -EIO;
 		}
-		bytes_written += copy_size;
-		count -= copy_size;
-		buffer += copy_size;
-	} while ( count > 0 );
-
-	return bytes_written ? bytes_written : -EIO;
-}
-
-static ssize_t read_printer(struct file *file,
-       char *buffer, size_t count, loff_t *ppos)
-{
-	struct pp_usb_data *p = file->private_data;
-	int read_count = 0;
-	int this_read;
-	char buf[64];
-	unsigned long partial;
-	int result;
+
+		if (!usblp->dev)
+			return -ENODEV;
+
+		if (!usblp->writeurb.status)
+			writecount += usblp->writeurb.transfer_buffer_length;
+		else {
+			if (!(retval = usblp_check_status(usblp))) {
+				printk(KERN_ERR "usblp%d: error %d writing to printer\n",
+					usblp->minor, usblp->writeurb.status);
+				return -EIO;
+			}
+
+			return retval;
+		}
 	
-	if (p->noinput)
+		if (writecount == count)
+			continue;
+
+		usblp->writeurb.transfer_buffer_length = (count - writecount) < USBLP_BUF_SIZE ?
+							 (count - writecount) : USBLP_BUF_SIZE;
+
+		if (copy_from_user(usblp->writeurb.transfer_buffer, buffer + writecount,
+				usblp->writeurb.transfer_buffer_length)) return -EFAULT;
+
+		usb_submit_urb(&usblp->writeurb);
+	}
+
+	return count;
+}
+
+static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	struct usblp *usblp = file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (!usblp->bidir)
 		return -EINVAL;
 
-	while (count) {
-		if (signal_pending(current)) {
-			return read_count ? read_count : -EINTR;
-		}
-		if (!p->pusb_dev)
-			return -ENODEV;
+	if (usblp->readurb.status == -EINPROGRESS) {
 
-		this_read = (count > sizeof(buf)) ? sizeof(buf) : count;
-		result = usb_bulk_msg(p->pusb_dev,
-			  usb_rcvbulkpipe(p->pusb_dev, p->bulk_in_ep),
-			  buf, this_read, &partial, HZ*20);
-		if (result < 0)
-			printk(KERN_ERR "usblp%d read_printer bulk_msg error = %d\n",
-				p->minor, result);
-
-		/* unlike writes, we don't retry a NAK, just stop now */
-		if (!result & partial)
-			count = this_read = partial;
-		else if (result)
-			return -EIO;
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
 
-		if (this_read) {
-			if (copy_to_user(buffer, buf, this_read))
-				return -EFAULT;
-			count -= this_read;
-			read_count += this_read;
-			buffer += this_read;
+		while (usblp->readurb.status == -EINPROGRESS) {
+			if (signal_pending(current))
+				return -EINTR;
+			interruptible_sleep_on(&usblp->wait);	
 		}
 	}
 
-	return read_count;
+	if (!usblp->dev)
+		return -ENODEV;
+
+	if (usblp->readurb.status) {
+		printk(KERN_ERR "usblp%d: error %d reading from printer\n",
+			usblp->minor, usblp->readurb.status);
+		usb_submit_urb(&usblp->readurb);
+		return -EIO;
+	}
+
+	count = count < usblp->readurb.actual_length - usblp->readcount ?
+		count :	usblp->readurb.actual_length - usblp->readcount;
+
+	if (copy_to_user(buffer, usblp->readurb.transfer_buffer + usblp->readcount, count))
+		return -EFAULT;
+
+	if ((usblp->readcount += count) == usblp->readurb.actual_length)
+		usb_submit_urb(&usblp->readurb);
+
+	return count;
 }
 
-static void *printer_probe(struct usb_device *dev, unsigned int ifnum)
+static void *usblp_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct usb_interface_descriptor *interface;
-	struct pp_usb_data *pp;
-	int i;
-	__u8 status;
-
-	/*
-	 * FIXME - this will not cope with combined printer/scanners
-	 */
-	if ((dev->descriptor.bDeviceClass != USB_CLASS_PRINTER &&
-	    dev->descriptor.bDeviceClass != 0) ||
-	    dev->descriptor.bNumConfigurations != 1 ||
-	    dev->actconfig->bNumInterfaces != 1) {
-		return NULL;
-	}
+	struct usb_endpoint_descriptor *epread, *epwrite;
+	struct usblp *usblp;
+	int minor, i, alts = -1, bidir = 0;
+	char *buf;
 
-	interface = &dev->actconfig->interface[ifnum].altsetting[0];
 
-	/* Let's be paranoid (for the moment). */
-	if (interface->bInterfaceClass != USB_CLASS_PRINTER ||
-	    interface->bInterfaceSubClass != SUBCLASS_PRINTERS ||
-	    (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL &&
-	    interface->bInterfaceProtocol != PROTOCOL_UNIDIRECTIONAL) ||
-	    interface->bNumEndpoints > 2) {
-		return NULL;
+	for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) {
+
+		interface = &dev->actconfig->interface[ifnum].altsetting[i];
+
+		if (interface->bInterfaceClass != 7 || interface->bInterfaceSubClass != 1 ||
+		   (interface->bInterfaceProtocol != 1 && interface->bInterfaceProtocol != 2) ||
+		   (interface->bInterfaceProtocol > interface->bNumEndpoints))
+			continue;
+
+		if (alts == -1)
+			alts = i;
+
+		if (!bidir && interface->bInterfaceProtocol == 2) {
+			bidir = 1;
+			alts = i;
+		}
 	}
 
-	/* Does this (these) interface(s) support bulk transfers? */
-	if ((interface->endpoint[0].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-	      != USB_ENDPOINT_XFER_BULK) {
+	if (alts == -1)
 		return NULL;
+
+	interface = &dev->actconfig->interface[ifnum].altsetting[alts];
+	if (usb_set_interface(dev, ifnum, alts))
+		err("can't set desired altsetting %d on interface %d", alts, ifnum);
+
+	epwrite = interface->endpoint + 0;
+	epread = NULL;
+
+	if (bidir) {
+		epread  = interface->endpoint + 1;
+		if ((epread->bEndpointAddress & 0x80) != 0x80) {
+			epwrite = interface->endpoint + 1;
+			epread  = interface->endpoint + 0;
+
+			if ((epread->bEndpointAddress & 0x80) != 0x80)
+				return NULL;
+		}
 	}
-	if ((interface->bNumEndpoints > 1) &&
-	      ((interface->endpoint[1].bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
-	      != USB_ENDPOINT_XFER_BULK)) {
+
+	if ((epwrite->bEndpointAddress & 0x80) == 0x80)
 		return NULL;
-	}
 
-	/*
-	 *  Does this interface have at least one OUT endpoint
-	 *  that we can write to: endpoint index 0 or 1?
-	 */
-	if ((interface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-	      != USB_DIR_OUT &&
-	    (interface->bNumEndpoints > 1 &&
-	      (interface->endpoint[1].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-	      != USB_DIR_OUT)) {
- 		return NULL;
- 	}
-
-	for (i=0; i<MAX_PRINTERS; i++) {
-		if (!minor_data[i])
-			break;
-	}
-	if (i >= MAX_PRINTERS) {
-		printk(KERN_ERR "No minor table space available for new USB printer\n");
+	for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
+	if (usblp_table[minor]) {
+		err("no more free usblp devices");
 		return NULL;
 	}
 
-	printk(KERN_INFO "USB printer found at address %d\n", dev->devnum);
+	if (!(usblp = kmalloc(sizeof(struct usblp), GFP_KERNEL))) {
+		err("out of memory");
+		return NULL;
+	}
+	memset(usblp, 0, sizeof(struct usblp));
 
-	if (!(pp = kmalloc(sizeof(struct pp_usb_data), GFP_KERNEL))) {
-		printk(KERN_DEBUG "USB printer: no memory!\n");
+	usblp->dev = dev;
+	usblp->ifnum = ifnum;
+	usblp->minor = minor;
+	usblp->bidir = bidir;
+
+	init_waitqueue_head(&usblp->wait);
+
+	if (!(buf = kmalloc(USBLP_BUF_SIZE * (bidir ? 2 : 1), GFP_KERNEL))) {
+		err("out of memory");
+		kfree(usblp);
 		return NULL;
 	}
 
-	memset(pp, 0, sizeof(struct pp_usb_data));
-	minor_data[i] = PPDATA(pp);
+	FILL_BULK_URB(&usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
+		buf, 0, usblp_bulk, usblp);
 
-	pp->minor = i;
-	pp->pusb_dev = dev;
-	pp->maxout = (BIG_BUF_SIZE > PAGE_SIZE) ? PAGE_SIZE : BIG_BUF_SIZE;
-	if (interface->bInterfaceProtocol != PROTOCOL_BIDIRECTIONAL)
-		pp->noinput = 1;
-
-	pp->bulk_out_index =
-		((interface->endpoint[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK)
-		  == USB_DIR_OUT) ? 0 : 1;
-	pp->bulk_in_index = pp->noinput ? -1 :
-		(pp->bulk_out_index == 0) ? 1 : 0;
-	pp->bulk_in_ep = pp->noinput ? -1 :
-		interface->endpoint[pp->bulk_in_index].bEndpointAddress &
-		USB_ENDPOINT_NUMBER_MASK;
-	pp->bulk_out_ep =
-		interface->endpoint[pp->bulk_out_index].bEndpointAddress &
-		USB_ENDPOINT_NUMBER_MASK;
-	if (interface->bInterfaceProtocol == PROTOCOL_BIDIRECTIONAL) {
-		pp->maxin =
-			interface->endpoint[pp->bulk_in_index].wMaxPacketSize;
-	}
-
-	printk(KERN_INFO "usblp%d Summary:\n", pp->minor);
-	printk(KERN_INFO "index=%d, maxout=%d, noinput=%d, maxin=%d\n",
-		i, pp->maxout, pp->noinput, pp->maxin);
-	printk(KERN_INFO "bulk_in_ix=%d, bulk_in_ep=%d, bulk_out_ix=%d, bulk_out_ep=%d\n",
-		pp->bulk_in_index,
-		pp->bulk_in_ep,
-		pp->bulk_out_index,
-		pp->bulk_out_ep);
-
-#ifdef IEEE_DEVICE_ID
-	{
-		__u8 ieee_id[64]; /* first 2 bytes are (big-endian) length */
-				/* This string space may be too short. */
-		int length = (ieee_id[0] << 8) + ieee_id[1]; /* high-low */
-				/* This calc. or be16_to_cpu() both get
-				 * some weird results for <length>. */
-		int err;
-
-		/* Let's get the device id if possible. */
-		err = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
-		    USB_PRINTER_REQ_GET_DEVICE_ID,
-		    USB_TYPE_CLASS | USB_RT_INTERFACE | USB_DIR_IN,
-		    0, 0, ieee_id,
-		    sizeof(ieee_id)-1, HZ);
-		if (err >= 0) {
-			if (ieee_id[1] < sizeof(ieee_id) - 1)
-				ieee_id[ieee_id[1]+2] = '\0';
-			else
-				ieee_id[sizeof(ieee_id)-1] = '\0';
-			printk(KERN_INFO "usblp%d Device ID length=%d [%x:%x]\n",
-				pp->minor, length, ieee_id[0], ieee_id[1]);
-			printk(KERN_INFO "usblp%d Device ID=%s\n",
-				pp->minor, &ieee_id[2]);
-		}
-		else
-			printk(KERN_INFO "usblp%d: error = %d reading IEEE-1284 Device ID\n",
-				pp->minor, err);
+	if (bidir) {
+		FILL_BULK_URB(&usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
+			buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp);
 	}
-#endif
 
-	status = printer_read_status(PPDATA(pp));
-	printk(KERN_INFO "usblp%d probe status is %x: %s,%s,%s\n",
-		pp->minor, status,
-		(status & LP_PSELECD) ? "Selected" : "Not Selected",
-		(status & LP_POUTPA)  ? "No Paper" : "Paper",
-		(status & LP_PERRORP) ? "No Error" : "Error");
+	printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d if %d alt %d\n",
+		minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
 
-	return pp;
+	return usblp_table[minor] = usblp;
 }
 
-static void printer_disconnect(struct usb_device *dev, void *ptr)
+static void usblp_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct pp_usb_data *pp = ptr;
+	struct usblp *usblp = ptr;
 
-	if (pp->isopen) {
-		/* better let it finish - the release will do whats needed */
-		pp->pusb_dev = NULL;
+	if (!usblp || !usblp->dev) {
+		err("disconnect on nonexisting interface");
 		return;
 	}
-	minor_data[pp->minor] = NULL;
-	kfree(pp);
+
+	usblp->dev = NULL;
+
+	usb_unlink_urb(&usblp->readurb);
+	usb_unlink_urb(&usblp->writeurb);
+
+	kfree(usblp->writeurb.transfer_buffer);
+
+	if (usblp->used) return;
+
+	usblp_table[usblp->minor] = NULL;
+	kfree(usblp);
 }
 
-static struct file_operations usb_printer_fops = {
-	NULL,		/* seek */
-	read_printer,
-	write_printer,
-	NULL,		/* readdir */
-	NULL,		/* poll - out for the moment */
-	NULL,		/* ioctl */
-	NULL,		/* mmap */
-	open_printer,
-	NULL,		/* flush ? */
-	close_printer,
-	NULL,
-	NULL
+static struct file_operations usblp_fops = {
+	read:		usblp_read,
+	write:		usblp_write,
+	open:		usblp_open,
+	release:	usblp_release,
+	poll:		usblp_poll
 };
 
-static struct usb_driver printer_driver = {
-	"printer",
-	printer_probe,
-	printer_disconnect,
-	{ NULL, NULL },
-	&usb_printer_fops,
-	0
+static struct usb_driver usblp_driver = {
+	name:		"usblp",
+	probe:		usblp_probe,
+	disconnect:	usblp_disconnect,
+	fops:		&usblp_fops,
+	minor:		USBLP_MINOR_BASE
 };
 
-int usb_printer_init(void)
+#ifdef MODULE
+void cleanup_module(void)
 {
-	if (usb_register(&printer_driver))
-		return -1;
-
-	printk(KERN_INFO "USB Printer driver registered.\n");
-	return 0;
+	usb_deregister(&usblp_driver);
 }
-
-#ifdef MODULE
 int init_module(void)
+#else
+int usb_printer_init(void)
+#endif
 {
-	return usb_printer_init();
-}
+	if (usb_register(&usblp_driver))
+		return -1;
 
-void cleanup_module(void)
-{
-	usb_deregister(&printer_driver);
+	return 0;
 }
-#endif
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/proc_usb.c linux/drivers/usb/proc_usb.c
--- v2.3.39/linux/drivers/usb/proc_usb.c	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/proc_usb.c	Wed Dec 31 16:00:00 1969
@@ -1,1170 +0,0 @@
-/*
- * drivers/usb/proc_usb.c
- * (C) Copyright 1999 Randy Dunlap.
- * (C) Copyright 1999 Thomas Sailer <sailer@ife.ee.ethz.ch>. (proc file per device)
- * (C) Copyright 1999 Deti Fliegl (new USB architecture)
- *
- * 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 /proc/bus/usb filesystem output module for USB.
- * It creates /proc/bus/usb/drivers and /proc/bus/usb/devices.
- *
- * /proc/bus/usb/devices contains USB topology, device, config, class,
- * interface, & endpoint data.
- *
- * I considered using /proc/bus/usb/devices/device# for each device
- * as it is attached or detached, but I didn't like this for some
- * reason -- maybe it's just too deep of a directory structure.
- * I also don't like looking in multiple places to gather and view
- * the data.  Having only one file for ./devices also prevents race
- * conditions that could arise if a program was reading device info
- * for devices that are being removed (unplugged).  (That is, the
- * program may find a directory for devnum_12 then try to open it,
- * but it was just unplugged, so the directory is now deleted.
- * But programs would just have to be prepared for situations like
- * this in any plug-and-play environment.)
- *
- * 1999-12-16: Thomas Sailer <sailer@ife.ee.ethz.ch>
- *   Converted the whole proc stuff to real
- *   read methods. Now not the whole device list needs to fit
- *   into one page, only the device list for one bus.
- *   Added a poll method to /proc/bus/usb/devices, to wake
- *   up an eventual usbd
- *
- * $Id: proc_usb.c,v 1.14 1999/12/17 10:51:41 fliegl Exp $
- */
-
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-#include <asm/uaccess.h>
-#include <linux/mm.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-
-#include "usb.h"
-
-
-#define MAX_TOPO_LEVEL		6
-
-/* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */
-#define ALLOW_SERIAL_NUMBER
-
-static char *format_topo =
-/* T:  Bus=dd Lev=dd Prnt=dd Port=dd Cnt=dd Dev#=ddd Spd=ddd MxCh=dd */
-  "T:  Bus=%2.2d Lev=%2.2d Prnt=%2.2d Port=%2.2d Cnt=%2.2d Dev#=%3d Spd=%3s MxCh=%2d\n";
-
-static char *format_string_manufacturer =
-/* S:  Manufacturer=xxxx */
-  "S:  Manufacturer=%s\n";
-
-static char *format_string_product =
-/* S:  Product=xxxx */
-  "S:  Product=%s\n";
-
-#ifdef ALLOW_SERIAL_NUMBER
-static char *format_string_serialnumber =
-/* S:  SerialNumber=xxxx */
-  "S:  SerialNumber=%s\n";
-#endif
-
-static char *format_bandwidth =
-/* B:  Alloc=ddd/ddd us (xx%), #Int=ddd, #Iso=ddd */
-  "B:  Alloc=%3d/%3d us (%2d%%), #Int=%3d, #Iso=%3d\n";
-  
-static char *format_device1 =
-/* D:  Ver=xx.xx Cls=xx(sssss) Sub=xx Prot=xx MxPS=dd #Cfgs=dd */
-  "D:  Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n";
-
-static char *format_device2 =
-/* P:  Vendor=xxxx ProdID=xxxx Rev=xx.xx */
-  "P:  Vendor=%04x ProdID=%04x Rev=%2x.%02x\n";
-
-static char *format_config =
-/* C:  #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */
-  "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n";
-  
-static char *format_iface =
-/* I:  If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/
-  "I:  If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n";
-
-static char *format_endpt =
-/* E:  Ad=xx(s) Atr=xx(ssss) MxPS=dddd Ivl=dddms */
-  "E:  Ad=%02x(%c) Atr=%02x(%-4s) MxPS=%4d Ivl=%3dms\n";
-
-
-/*
- * Need access to the driver and USB bus lists.
- * extern struct list_head usb_driver_list;
- * extern struct list_head usb_bus_list;
- * However, these will come from functions that return ptrs to each of them.
- */
-
-extern struct proc_dir_entry *proc_bus;
-
-static struct proc_dir_entry *usbdir = NULL, *driversdir = NULL;
-static struct proc_dir_entry *devicesdir = NULL;
-
-static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
-static unsigned int conndiscevcnt = 0;
-
-/* this struct stores the poll state for /proc/bus/usb/devices pollers */
-struct usb_device_status {
-	unsigned int lastev;
-};
-
-struct class_info {
-	int class;
-	char *class_name;
-};
-
-static const struct class_info clas_info[] =
-{					/* max. 5 chars. per name string */
-	{USB_CLASS_PER_INTERFACE,	">ifc"},
-	{USB_CLASS_AUDIO,		"audio"},
-	{USB_CLASS_COMM,		"comm."},
-	{USB_CLASS_HID,			"HID"},
-	{USB_CLASS_HUB,			"hub"},
-	{USB_CLASS_PRINTER,		"print"},
-	{USB_CLASS_MASS_STORAGE,	"stor."},
-	{USB_CLASS_DATA,		"data"},
-	{USB_CLASS_VENDOR_SPEC,		"vend."},
-	{-1,				"unk."}		/* leave as last */
-};
-
-/*****************************************************************/
-
-extern inline void conndiscevent(void)
-{
-	wake_up(&deviceconndiscwq);
-	conndiscevcnt++;
-}
-
-static const char *class_decode(const int class)
-{
-	int ix;
-
-	for (ix = 0; clas_info[ix].class != -1; ix++)
-		if (clas_info[ix].class == class)
-			break;
-	return (clas_info[ix].class_name);
-}
-
-static char *usb_dump_endpoint_descriptor(char *start, char *end, const struct usb_endpoint_descriptor *desc)
-{
-	char *EndpointType [4] = {"Ctrl", "Isoc", "Bulk", "Int."};
-
-	if (start > end)
-		return start;
-	start += sprintf(start, format_endpt, desc->bEndpointAddress,
-			 (desc->bEndpointAddress & USB_DIR_IN) ? 'I' : 'O',
-			 desc->bmAttributes, EndpointType[desc->bmAttributes & 3],
-			 desc->wMaxPacketSize, desc->bInterval);
-	return start;
-}
-
-static char *usb_dump_endpoint(char *start, char *end, const struct usb_endpoint_descriptor *endpoint)
-{
-	return usb_dump_endpoint_descriptor(start, end, endpoint);
-}
-
-static char *usb_dump_interface_descriptor(char *start, char *end, const struct usb_interface *iface, int setno)
-{
-	struct usb_interface_descriptor *desc = &iface->altsetting[setno];
-
-	if (start > end)
-		return start;
-	start += sprintf(start, format_iface,
-			 desc->bInterfaceNumber,
-			 desc->bAlternateSetting,
-			 desc->bNumEndpoints,
-			 desc->bInterfaceClass,
-			 class_decode(desc->bInterfaceClass),
-			 desc->bInterfaceSubClass,
-			 desc->bInterfaceProtocol,
-			 iface->driver ? iface->driver->name : "(none)");
-	return start;
-}
-
-static char *usb_dump_interface(char *start, char *end, const struct usb_interface *iface, int setno)
-{
-	struct usb_interface_descriptor *desc = &iface->altsetting[setno];
-	int i;
-
-	start = usb_dump_interface_descriptor(start, end, iface, setno);
-	for (i = 0; i < desc->bNumEndpoints; i++) {
-		if (start > end)
-			return start;
-		start = usb_dump_endpoint(start, end, desc->endpoint + i);
-	}
-	return start;
-}
-
-/* TBD:
- * 0. TBDs
- * 1. marking active config and ifaces (code lists all, but should mark
- *    which ones are active, if any)
- * 2. add <halted> status to each endpoint line
- */
-
-static char *usb_dump_config_descriptor(char *start, char *end, const struct usb_config_descriptor *desc, const int active)
-{
-	if (start > end)
-		return start;
-	start += sprintf(start, format_config,
-			 active ? '*' : ' ',	/* mark active/actual/current cfg. */
-			 desc->bNumInterfaces,
-			 desc->bConfigurationValue,
-			 desc->bmAttributes,
-			 desc->MaxPower * 2);
-	return start;
-}
-
-static char *usb_dump_config(char *start, char *end, const struct usb_config_descriptor *config, const int active)
-{
-	int i, j;
-	struct usb_interface *interface;
-
-	if (start > end)
-		return start;
-	if (!config)		/* getting these some in 2.3.7; none in 2.3.6 */
-		return start + sprintf(start, "(null Cfg. desc.)\n");
-	start = usb_dump_config_descriptor(start, end, config, active);
-	for (i = 0; i < config->bNumInterfaces; i++) {
-		interface = config->interface + i;
-		if (!interface)
-			break;
-		for (j = 0; j < interface->num_altsetting; j++) {
-			if (start > end)
-				return start;
-			start = usb_dump_interface(start, end, interface, j);
-		}
-	}
-	return start;
-}
-
-/*
- * Dump the different USB descriptors.
- */
-static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
-{
-	if (start > end)
-		return start;
-	start += sprintf (start, format_device1,
-			  desc->bcdUSB >> 8, desc->bcdUSB & 0xff,
-			  desc->bDeviceClass,
-			  class_decode (desc->bDeviceClass),
-			  desc->bDeviceSubClass,
-			  desc->bDeviceProtocol,
-			  desc->bMaxPacketSize0,
-			  desc->bNumConfigurations);
-	if (start > end)
-		return start;
-	start += sprintf(start, format_device2,
-			 desc->idVendor, desc->idProduct,
-			 desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
-	return start;
-}
-
-/*
- * Dump the different strings that this device holds.
- */
-static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev)
-{
-	char *buf;
-
-	if (start > end)
-		return start;
-	buf = kmalloc(256, GFP_KERNEL);
-	if (!buf)
-		return start;
-	if (dev->descriptor.iManufacturer) {
-		if (usb_string(dev, dev->descriptor.iManufacturer, buf, 256) > 0)
-			start += sprintf(start, format_string_manufacturer, buf);
-	}				
-	if (start > end)
-		goto out;
-	if (dev->descriptor.iProduct) {
-		if (usb_string(dev, dev->descriptor.iProduct, buf, 256) > 0)
-			start += sprintf(start, format_string_product, buf);
-	}
-	if (start > end)
-		goto out;
-#ifdef ALLOW_SERIAL_NUMBER
-	if (dev->descriptor.iSerialNumber) {
-		if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 256) > 0)
-			start += sprintf(start, format_string_serialnumber, buf);
-	}
-#endif
- out:
-	kfree(buf);
-	return start;
-}
-
-static char *usb_dump_desc(char *start, char *end, const struct usb_device *dev)
-{
-	int i;
-
-	if (start > end)
-		return start;
-		
-	start = usb_dump_device_descriptor(start, end, &dev->descriptor);
-
-	if (start > end)
-		return start;
-	
-	start = usb_dump_device_strings (start, end, dev);
-	
-	for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
-		if (start > end)
-			return start;
-		start = usb_dump_config(start, end, dev->config + i,
-					(dev->config + i) == dev->actconfig); /* active ? */
-	}
-	return start;
-}
-
-
-#ifdef PROC_EXTRA /* TBD: may want to add this code later */
-
-static char *usb_dump_hub_descriptor(char *start, char *end, const struct usb_hub_descriptor * desc)
-{
-	int leng = USB_DT_HUB_NONVAR_SIZE;
-	unsigned char *ptr = (unsigned char *)desc;
-
-	if (start > end)
-		return start;
-	start += sprintf(start, "Interface:");
-	while (leng) {
-		start += sprintf(start, " %02x", *ptr);
-		ptr++; leng--;
-	}
-	start += sprintf(start, "\n");
-	return start;
-}
-
-#endif /* PROC_EXTRA */
-
-/*****************************************************************/
-
-static char *usb_device_dump(char *start, char *end, const struct usb_device *usbdev,
-			     const struct usb_bus *bus, int level, int index, int count)
-{
-	int chix;
-	int cnt = 0;
-	int parent_devnum = 0;
-
-	if (level > MAX_TOPO_LEVEL)
-		return start;
-	if (usbdev->parent && usbdev->parent->devnum != -1)
-		parent_devnum = usbdev->parent->devnum;
-	/*
-	 * So the root hub's parent is 0 and any device that is
-	 * plugged into the root hub has a parent of 0.
-	 */
-	start += sprintf(start, format_topo, bus->busnum-1, level, parent_devnum, index, count,
-			 usbdev->devnum, usbdev->slow ? "1.5" : "12 ", usbdev->maxchild);
-	/*
-	 * level = topology-tier level;
-	 * parent_devnum = parent device number;
-	 * index = parent's connector number;
-	 * count = device count at this level
-	 */
-	/* If this is the root hub, display the bandwidth information */
-	if (level == 0)
-		start += sprintf(start, format_bandwidth, bus->bandwidth_allocated, 
-				FRAME_TIME_MAX_USECS_ALLOC,
-				(100 * bus->bandwidth_allocated + FRAME_TIME_MAX_USECS_ALLOC / 2) / FRAME_TIME_MAX_USECS_ALLOC,
-			         bus->bandwidth_int_reqs, bus->bandwidth_isoc_reqs);
-
-	/* show the descriptor information for this device */
-	start = usb_dump_desc(start, end, usbdev);
-	if (start > end)
-		return start + sprintf(start, "(truncated)\n");
-
-	/* Now look at all of this device's children. */
-	for (chix = 0; chix < usbdev->maxchild; chix++) {
-		if (start > end)
-			return start;
-		if (usbdev->children[chix])
-			start = usb_device_dump(start, end, usbdev->children[chix], bus, level + 1, chix, ++cnt);
-	}
-	return start;
-}
-
-static ssize_t usb_device_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
-{
-	struct list_head *buslist;
-	struct usb_bus *bus;
-	char *page, *end;
-	ssize_t ret = 0;
-	unsigned int pos, len;
-
-	if (*ppos < 0)
-		return -EINVAL;
-	if (nbytes <= 0)
-		return 0;
-	if (!access_ok(VERIFY_WRITE, buf, nbytes))
-		return -EFAULT;
-	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	pos = *ppos;
-	/* enumerate busses */
-	for (buslist = usb_bus_list.next; buslist != &usb_bus_list; buslist = buslist->next) {
-		bus = list_entry(buslist, struct usb_bus, bus_list);
-		end = usb_device_dump(page, page + (PAGE_SIZE - 100), bus->root_hub, bus, 0, 0, 0);
-		len = end - page;
-		if (len > pos) {
-			len -= pos;
-			if (len > nbytes)
-				len = nbytes;
-			if (copy_to_user(buf, page + pos, len)) {
-				if (!ret)
-					ret = -EFAULT;
-				break;
-			}
-			nbytes -= len;
-			buf += len;
-			ret += len;
-			pos = 0;
-			*ppos += len;
-		} else
-			pos -= len;
-	}
-	free_page((unsigned long)page);
-	return ret;
-}
-
-static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct usb_device_status *st = (struct usb_device_status *)file->private_data;
-	unsigned int mask = 0;
-	
-	if (!st) {
-		st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
-		if (!st)
-			return POLLIN;
-		/*
-		 * need to prevent the module from being unloaded, since
-		 * proc_unregister does not call the release method and
-		 * we would have a memory leak
-		 */
-		st->lastev = conndiscevcnt;
-		file->private_data = st;
-		MOD_INC_USE_COUNT;
-		mask = POLLIN;
-	}
-	if (file->f_mode & FMODE_READ)
-		poll_wait(file, &deviceconndiscwq, wait);
-	if (st->lastev != conndiscevcnt)
-		mask |= POLLIN;
-	st->lastev = conndiscevcnt;
-	return mask;
-}
-
-static int usb_device_open(struct inode *inode, struct file *file)
-{
-	file->private_data = NULL;
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-static int usb_device_release(struct inode *inode, struct file *file)
-{
-	if (file->private_data) {
-		kfree(file->private_data);
-		file->private_data = NULL;
-	}
-	MOD_DEC_USE_COUNT;	
-	return 0;
-}
-
-/*
- * Dump usb_driver_list.
- *
- * We now walk the list of registered USB drivers.
- */
-static ssize_t usb_driver_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
-{
-	struct list_head *tmp = usb_driver_list.next;
-	char *page, *start, *end;
-	ssize_t ret = 0;
-	unsigned int pos, len;
-
-	if (*ppos < 0)
-		return -EINVAL;
-	if (nbytes <= 0)
-		return 0;
-	if (!access_ok(VERIFY_WRITE, buf, nbytes))
-		return -EFAULT;
-	if (!(page = (char*) __get_free_page(GFP_KERNEL)))
-		return -ENOMEM;
-	start = page;
-	end = page + (PAGE_SIZE - 100);
-	pos = *ppos;
-	for (; tmp != &usb_driver_list; tmp = tmp->next) {
-		struct usb_driver *driver = list_entry(tmp, struct usb_driver, driver_list);
-		start += sprintf (start, "%s\n", driver->name);
-		if (start > end) {
-			start += sprintf(start, "(truncated)\n");
-			break;
-		}
-	}
-	if (start == page)
-		start += sprintf(start, "(none)\n");
-	len = start - page;
-	if (len > pos) {
-		len -= pos;
-		if (len > nbytes)
-			len = nbytes;
-		ret = len;
-		if (copy_to_user(buf, page + pos, len))
-			ret = -EFAULT;
-		else
-			*ppos += len;
-	}
-	free_page((unsigned long)page);
-	return ret;
-}
-
-static long long usbdev_lseek(struct file * file, long long offset, int orig);
-
-static struct file_operations proc_usb_devlist_file_operations = {
-	usbdev_lseek,       /* lseek   */
-	usb_device_read,    /* read    */
-	NULL,               /* write   */
-	NULL,               /* readdir */
-	usb_device_poll,    /* poll    */
-	NULL,               /* ioctl   */
-	NULL,               /* mmap    */
-	usb_device_open,    /* open    */
-	NULL,               /* flush   */
-	usb_device_release, /* release */
-	NULL                /* fsync   */
-};
-
-static struct inode_operations proc_usb_devlist_inode_operations = {
-	&proc_usb_devlist_file_operations,  /* file-ops */
-};
-
-static struct file_operations proc_usb_drvlist_file_operations = {
-	usbdev_lseek,    /* lseek   */
-	usb_driver_read, /* read    */
-	NULL,            /* write   */
-	NULL,            /* readdir */
-	NULL,            /* poll    */
-	NULL,            /* ioctl   */
-	NULL,            /* mmap    */
-	NULL,            /* no special open code    */
-	NULL,            /* flush */
-	NULL,            /* no special release code */
-	NULL             /* can't fsync */
-};
-
-static struct inode_operations proc_usb_drvlist_inode_operations = {
-	&proc_usb_drvlist_file_operations,  /* file-ops */
-};
-
-
-/*
- * proc entry for every device
- */
-
-static long long usbdev_lseek(struct file * file, long long offset, int orig)
-{
-	switch (orig) {
-	case 0:
-		file->f_pos = offset;
-		return file->f_pos;
-
-	case 1:
-		file->f_pos += offset;
-		return file->f_pos;
-
-	case 2:
-		return -EINVAL;
-
-	default:
-		return -EINVAL;
-	}
-}
-
-static ssize_t usbdev_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
-{
-	struct inode *inode = file->f_dentry->d_inode;
-	struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
-	struct usb_device *dev = (struct usb_device *)dp->data;
-	ssize_t ret = 0;
-	unsigned len;
-
-	if (*ppos < 0)
-		return -EINVAL;
-	if (*ppos < sizeof(struct usb_device_descriptor)) {
-		len = sizeof(struct usb_device_descriptor);
-		if (len > nbytes)
-			len = nbytes;
-		copy_to_user_ret(buf, ((char *)&dev->descriptor) + *ppos, len, -EFAULT);
-		*ppos += len;
-		buf += len;
-		nbytes -= len;
-		ret += len;
-	}
-	return ret;
-}
-
-/* note: this is a compatibility kludge that will vanish soon. */
-#include "ezusb.h"
-
-static int usbdev_ioctl_ezusbcompat(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	static unsigned obsolete_warn = 0;
-	struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
-	struct usb_device *dev = (struct usb_device *)dp->data;
-	struct ezusb_ctrltransfer ctrl;
-	struct ezusb_bulktransfer bulk;
-	struct ezusb_old_ctrltransfer octrl;
-	struct ezusb_old_bulktransfer obulk;
-	struct ezusb_setinterface setintf;
-	unsigned int len1, ep, pipe, cfg;
-	unsigned long len2;
-	unsigned char *tbuf;
-	int i;
-
-	switch (cmd) {
-	case EZUSB_CONTROL:
-		if (obsolete_warn < 20) {
-			warn("process %d (%s) used obsolete EZUSB_CONTROL ioctl",
-			       current->pid, current->comm);
-			obsolete_warn++;
-		}
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
-		if (ctrl.length > PAGE_SIZE)
-			return -EINVAL;
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (ctrl.requesttype & 0x80) {
-			if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
-				free_page((unsigned long)tbuf);
-				return -EINVAL;
-			}
-			i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
-					    ctrl.value, ctrl.index, tbuf, ctrl.length, 
-					    (ctrl.timeout * HZ + 500) / 1000);
-			if ((i > 0) && ctrl.length) {
-				copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
-			}
-		} else {
-			if (ctrl.length) {
-				copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
-			}
-			i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype,
-					    ctrl.value, ctrl.index, tbuf, ctrl.length, 
-					    (ctrl.timeout * HZ + 500) / 1000);
-		}
-		free_page((unsigned long)tbuf);
-		if (i < 0) {
-			warn("EZUSB_CONTROL failed rqt %u rq %u len %u ret %d", 
-			       ctrl.requesttype, ctrl.request, ctrl.length, i);
-			return i;
-		}
-		return i;
-
-	case EZUSB_BULK:
-		if (obsolete_warn < 20) {
-			warn("process %d (%s) used obsolete EZUSB_BULK ioctl",
-			       current->pid, current->comm);
-			obsolete_warn++;
-		}
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
-		if (bulk.ep & 0x80)
-			pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
-		else
-			pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
-		if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
-			return -EINVAL;
-		len1 = bulk.len;
-		if (len1 > PAGE_SIZE)
-			len1 = PAGE_SIZE;
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (bulk.ep & 0x80) {
-			if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
-				free_page((unsigned long)tbuf);
-				return -EINVAL;
-			}
-			i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (ctrl.timeout * HZ + 500) / 1000);
-			if ((i > 0) && len2) {
-				copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
-			}
-		} else {
-			if (len1) {
-				copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
-			}
-			i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (ctrl.timeout * HZ + 500) / 1000);
-		}
-		free_page((unsigned long)tbuf);
-		if (i < 0) {
-			warn("EZUSB_BULK failed ep 0x%x len %u ret %d", 
-			       bulk.ep, bulk.len, i);
-			return i;
-		}
-		return len2;
-
-	case EZUSB_OLD_CONTROL:
-		if (obsolete_warn < 20) {
-			warn("process %d (%s) used obsolete EZUSB_OLD_CONTROL ioctl",
-			       current->pid, current->comm);
-			obsolete_warn++;
-		}
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&octrl, (void *)arg, sizeof(octrl), -EFAULT);
-		if (octrl.dlen > PAGE_SIZE)
-			return -EINVAL;
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (octrl.requesttype & 0x80) {
-			if (octrl.dlen && !access_ok(VERIFY_WRITE, octrl.data, octrl.dlen)) {
-				free_page((unsigned long)tbuf);
-				return -EINVAL;
-			}
-			i = usb_internal_control_msg(dev, usb_rcvctrlpipe(dev, 0), (devrequest *)&octrl, tbuf, octrl.dlen, HZ);
-			if ((i > 0) && octrl.dlen) {
-				copy_to_user_ret(octrl.data, tbuf, octrl.dlen, -EFAULT);
-			}
-		} else {
-			if (octrl.dlen) {
-				copy_from_user_ret(tbuf, octrl.data, octrl.dlen, -EFAULT);
-			}
-			i = usb_internal_control_msg(dev, usb_sndctrlpipe(dev, 0), (devrequest *)&octrl, tbuf, octrl.dlen, HZ);
-					}
-		free_page((unsigned long)tbuf);
-		if (i < 0) {
-			warn("EZUSB_OLD_CONTROL failed rqt %u rq %u len %u ret %d", 
-			       octrl.requesttype, octrl.request, octrl.length, i);
-			return i;
-		}
-		return i;
-
-	case EZUSB_OLD_BULK:
-		if (obsolete_warn < 20) {
-			warn("process %d (%s) used obsolete EZUSB_OLD_BULK ioctl",
-			       current->pid, current->comm);
-			obsolete_warn++;
-		}
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&obulk, (void *)arg, sizeof(obulk), -EFAULT);
-		if (obulk.ep & 0x80)
-			pipe = usb_rcvbulkpipe(dev, obulk.ep & 0x7f);
-		else
-			pipe = usb_sndbulkpipe(dev, obulk.ep & 0x7f);
-		if (!usb_maxpacket(dev, pipe, !(obulk.ep & 0x80)))
-			return -EINVAL;
-		len1 = obulk.len;
-		if (len1 > PAGE_SIZE)
-			len1 = PAGE_SIZE;
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (obulk.ep & 0x80) {
-			if (len1 && !access_ok(VERIFY_WRITE, obulk.data, len1)) {
-				free_page((unsigned long)tbuf);
-				return -EINVAL;
-			}
-			i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
-			if ((i > 0) && len2) {
-				copy_to_user_ret(obulk.data, tbuf, len2, -EFAULT);
-			}
-		} else {
-			if (len1) {
-				copy_from_user_ret(tbuf, obulk.data, len1, -EFAULT);
-			}
-			i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
-		}
-		free_page((unsigned long)tbuf);
-		if (i < 0) {
-			warn("EZUSB_OLD_BULK failed ep 0x%x len %u ret %d", 
-			       obulk.ep, obulk.len, i);
-			return i;
-		}
-		return len2;
-
-	case EZUSB_RESETEP:
-		if (obsolete_warn < 20) {
-			warn("process %d (%s) used obsolete EZUSB_RESETEP ioctl",
-			       current->pid, current->comm);
-			obsolete_warn++;
-		}
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		get_user_ret(ep, (unsigned int *)arg, -EFAULT);
-		if ((ep & ~0x80) >= 16)
-			return -EINVAL;
-		usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
-		return 0;
-
-	case EZUSB_SETINTERFACE:
-		if (obsolete_warn < 20) {
-			warn("process %d (%s) used obsolete EZUSB_SETINTERFACE ioctl",
-			       current->pid, current->comm);
-			obsolete_warn++;
-		}
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
-		if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
-			return -EINVAL;
-		return 0;
-
-	case EZUSB_SETCONFIGURATION:
-		if (obsolete_warn < 20) {
-			warn("process %d (%s) used obsolete EZUSB_SETCONFIGURATION ioctl",
-			       current->pid, current->comm);
-			obsolete_warn++;
-		}
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		get_user_ret(cfg, (unsigned int *)arg, -EFAULT);
-		if (usb_set_configuration(dev, cfg) < 0)
-			return -EINVAL;
-		return 0;
-
-	}
-	return -ENOIOCTLCMD;
-}
-
-
-
-static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct proc_dir_entry *dp = (struct proc_dir_entry *)inode->u.generic_ip;
-	struct usb_device *dev = (struct usb_device *)dp->data;
-	struct usb_proc_ctrltransfer ctrl;
-	struct usb_proc_bulktransfer bulk;
-	struct usb_proc_old_ctrltransfer octrl;
-	struct usb_proc_old_bulktransfer obulk;
-	struct usb_proc_setinterface setintf;
-	unsigned int len1, ep, pipe, cfg;
-	unsigned long len2;
-	unsigned char *tbuf;
-	int i;
-
-	switch (cmd) {
-	case USB_PROC_CONTROL:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&ctrl, (void *)arg, sizeof(ctrl), -EFAULT);
-		if (ctrl.length > PAGE_SIZE)
-			return -EINVAL;
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (ctrl.requesttype & 0x80) {
-			if (ctrl.length && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.length)) {
-				free_page((unsigned long)tbuf);
-				return -EINVAL;
-			}
-			i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, 
-					    ctrl.requesttype, ctrl.value, ctrl.index, tbuf, 
-					    ctrl.length, (ctrl.timeout * HZ + 500) / 1000);
-			if ((i > 0) && ctrl.length) {
-				copy_to_user_ret(ctrl.data, tbuf, ctrl.length, -EFAULT);
-			}
-		} else {
-			if (ctrl.length) {
-				copy_from_user_ret(tbuf, ctrl.data, ctrl.length, -EFAULT);
-			}
-			i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, 
-					    ctrl.requesttype, ctrl.value, ctrl.index, tbuf, 
-					    ctrl.length, (ctrl.timeout * HZ + 500) / 1000);
-		}
-		free_page((unsigned long)tbuf);
-		if (i<0) {
-			warn("USB_PROC_CONTROL failed rqt %u rq %u len %u ret %d", 
-			       ctrl.requesttype, ctrl.request, ctrl.length, i);
-			return i;
-		}
-		return 0;
-
-	case USB_PROC_BULK:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&bulk, (void *)arg, sizeof(bulk), -EFAULT);
-		if (bulk.ep & 0x80)
-			pipe = usb_rcvbulkpipe(dev, bulk.ep & 0x7f);
-		else
-			pipe = usb_sndbulkpipe(dev, bulk.ep & 0x7f);
-		if (!usb_maxpacket(dev, pipe, !(bulk.ep & 0x80)))
-			return -EINVAL;
-		len1 = bulk.len;
-		if (len1 > PAGE_SIZE)
-			len1 = PAGE_SIZE;
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (bulk.ep & 0x80) {
-			if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
-				free_page((unsigned long)tbuf);
-				return -EINVAL;
-			}
-			i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (bulk.timeout * HZ + 500) / 1000);
-			if (!i && len2) {
-				copy_to_user_ret(bulk.data, tbuf, len2, -EFAULT);
-			}
-		} else {
-			if (len1) {
-				copy_from_user_ret(tbuf, bulk.data, len1, -EFAULT);
-			}
-			i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, (bulk.timeout * HZ + 500) / 1000);
-		}
-		free_page((unsigned long)tbuf);
-		if (i) {
-			warn("USB_PROC_BULK failed ep 0x%x len %u ret %d", 
-			       bulk.ep, bulk.len, i);
-			return -ENXIO;
-		}
-		return len2;
-
-	case USB_PROC_OLD_CONTROL:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&octrl, (void *)arg, sizeof(octrl), -EFAULT);
-		if (octrl.length > PAGE_SIZE)
-			return -EINVAL;
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (octrl.requesttype & 0x80) {
-			if (octrl.length && !access_ok(VERIFY_WRITE, octrl.data, octrl.length)) {
-				free_page((unsigned long)tbuf);
-				return -EINVAL;
-			}
-			i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), octrl.request, 
-					    octrl.requesttype, octrl.value, octrl.index, tbuf, 
-					    octrl.length, HZ);
-			if ((i > 0) && octrl.length) {
-				copy_to_user_ret(octrl.data, tbuf, octrl.length, -EFAULT);
-			}
-		} else {
-			if (octrl.length) {
-				copy_from_user_ret(tbuf, octrl.data, octrl.length, -EFAULT);
-			}
-			i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), octrl.request, 
-					    octrl.requesttype, octrl.value, octrl.index, tbuf, 
-					    octrl.length, HZ);
-		}
-		free_page((unsigned long)tbuf);
-		if (i < 0) {
-			warn("USB_PROC_OLD_CONTROL failed rqt %u rq %u len %u ret %d", 
-			       octrl.requesttype, octrl.request, octrl.length, i);
-			return i;
-		}
-		return 0;
-
-	case USB_PROC_OLD_BULK:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&obulk, (void *)arg, sizeof(obulk), -EFAULT);
-		if (obulk.ep & 0x80)
-			pipe = usb_rcvbulkpipe(dev, obulk.ep & 0x7f);
-		else
-			pipe = usb_sndbulkpipe(dev, obulk.ep & 0x7f);
-		if (!usb_maxpacket(dev, pipe, !(obulk.ep & 0x80)))
-			return -EINVAL;
-		len1 = obulk.len;
-		if (len1 > PAGE_SIZE)
-			len1 = PAGE_SIZE;
-		if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
-			return -ENOMEM;
-		if (obulk.ep & 0x80) {
-			if (len1 && !access_ok(VERIFY_WRITE, obulk.data, len1)) {
-				free_page((unsigned long)tbuf);
-				return -EINVAL;
-			}
-			i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
-			if ((i > 0) && len2) {
-				copy_to_user_ret(obulk.data, tbuf, len2, -EFAULT);
-			}
-		} else {
-			if (len1) {
-				copy_from_user_ret(tbuf, obulk.data, len1, -EFAULT);
-			}
-			i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, HZ*5);
-		}
-		free_page((unsigned long)tbuf);
-		if (i < 0) {
-			warn("USB_PROC_OLD_BULK failed ep 0x%x len %u ret %d", 
-			       obulk.ep, obulk.len, i);
-			return i;
-		}
-		return len2;
-
-	case USB_PROC_RESETEP:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		get_user_ret(ep, (unsigned int *)arg, -EFAULT);
-		if ((ep & ~0x80) >= 16)
-			return -EINVAL;
-		usb_settoggle(dev, ep & 0xf, !(ep & 0x80), 0);
-		return 0;
-
-	case USB_PROC_SETINTERFACE:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		copy_from_user_ret(&setintf, (void *)arg, sizeof(setintf), -EFAULT);
-		if (usb_set_interface(dev, setintf.interface, setintf.altsetting))
-			return -EINVAL;
-		return 0;
-
-	case USB_PROC_SETCONFIGURATION:
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-		get_user_ret(cfg, (unsigned int *)arg, -EFAULT);
-		if (usb_set_configuration(dev, cfg) < 0)
-			return -EINVAL;
-		return 0;
-
-	case EZUSB_CONTROL:
-	case EZUSB_BULK:
-	case EZUSB_OLD_CONTROL:
-	case EZUSB_OLD_BULK:
-	case EZUSB_RESETEP:
-	case EZUSB_SETINTERFACE:
-	case EZUSB_SETCONFIGURATION:
-		return usbdev_ioctl_ezusbcompat(inode, file, cmd, arg);
-	}
-	return -ENOIOCTLCMD;
-}
-
-static struct file_operations proc_usb_device_file_operations = {
-	usbdev_lseek,    /* lseek   */
-	usbdev_read,     /* read    */
-	NULL,            /* write   */
-	NULL,            /* readdir */
-	NULL,            /* poll    */
-	usbdev_ioctl,    /* ioctl   */
-	NULL,            /* mmap    */
-	NULL,            /* no special open code    */
-	NULL,            /* flush */
-	NULL,            /* no special release code */
-	NULL             /* can't fsync */
-};
-
-static struct inode_operations proc_usb_device_inode_operations = {
-	&proc_usb_device_file_operations,  /* file-ops */
-};
-
-void proc_usb_add_bus(struct usb_bus *bus)
-{
-	char buf[16];
-
-	bus->proc_entry = NULL;
-	if (!usbdir)
-		return;
-	sprintf(buf, "%03d", bus->busnum);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,31)
-	if (!(bus->proc_entry = create_proc_entry(buf, S_IFDIR, usbdir)))
-#else
-	if (!(bus->proc_entry = proc_mkdir(buf, usbdir)))
-#endif
-		return;
-	bus->proc_entry->data = bus;
-	conndiscevent();
-}
-
-/* devices need already be removed! */
-void proc_usb_remove_bus(struct usb_bus *bus)
-{
-	if (!bus->proc_entry)
-		return;
-	remove_proc_entry(bus->proc_entry->name, usbdir);
-	conndiscevent();
-}
-
-void proc_usb_add_device(struct usb_device *dev)
-{
-	char buf[16];
-
-	dev->proc_entry = NULL;
-	if (!dev->bus->proc_entry)
-		return;
-	sprintf(buf, "%03d", dev->devnum);
-	if (!(dev->proc_entry = create_proc_entry(buf, 0, dev->bus->proc_entry)))
-		return;
-	dev->proc_entry->ops = &proc_usb_device_inode_operations;
-	dev->proc_entry->data = dev;
-	conndiscevent();
-}
-
-void proc_usb_remove_device(struct usb_device *dev)
-{
-	if (dev->proc_entry)
-		remove_proc_entry(dev->proc_entry->name, dev->bus->proc_entry);
-	conndiscevent();
-}
-
-
-void proc_usb_cleanup (void)
-{
-	if (driversdir)
-		remove_proc_entry("drivers", usbdir);
-	if (devicesdir)
-		remove_proc_entry("devices", usbdir);
-	if (usbdir)
-		remove_proc_entry("usb", proc_bus);
-}
-
-int proc_usb_init (void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,31)
-	usbdir = create_proc_entry("usb", S_IFDIR, proc_bus);
-#else
-	usbdir = proc_mkdir("usb", proc_bus);
-#endif	
-	if (!usbdir) {
-		err("cannot create /proc/bus/usb entry");
-		return -1;
-	}
-
-	driversdir = create_proc_entry("drivers", 0, usbdir);
-	if (!driversdir) {
-		err("cannot create /proc/bus/usb/drivers entry");
-		proc_usb_cleanup();
-		return -1;
-	}
-	driversdir->ops = &proc_usb_drvlist_inode_operations;
-
-	devicesdir = create_proc_entry("devices", 0, usbdir);
-	if (!devicesdir) {
-		err("cannot create /proc/bus/usb/devices entry");
-		proc_usb_cleanup ();
-		return -1;
-	}
-	devicesdir->ops = &proc_usb_devlist_inode_operations;
-
-	return 0;
-}
-
-/* end proc_usb.c */
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c
--- v2.3.39/linux/drivers/usb/scanner.c	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/scanner.c	Fri Jan 14 11:25:21 2000
@@ -125,7 +125,7 @@
 MODULE_AUTHOR("David E. Nelson, dnelson@jump.net, http://www.jump.net/~dnelson");
 MODULE_DESCRIPTION("USB Scanner Driver");
 
-static __u16 vendor=0, product=0;
+static __u16 vendor=0x05f9, product=0xffff;
 MODULE_PARM(vendor, "i");
 MODULE_PARM_DESC(vendor, "User specified USB idVendor");
 
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/usb-core.c linux/drivers/usb/usb-core.c
--- v2.3.39/linux/drivers/usb/usb-core.c	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/usb-core.c	Thu Jan 20 15:00:16 2000
@@ -24,8 +24,6 @@
 void usb_hub_cleanup(void);
 int usb_major_init(void);
 void usb_major_cleanup(void);
-int proc_usb_init(void);
-void proc_usb_cleanup(void);
 
 /*
  * USB device drivers
@@ -45,6 +43,7 @@
 int input_init(void);
 int usb_mouse_init(void);
 int usb_kbd_init(void);
+int graphire_init(void);
 
 /*
  * HCI drivers
@@ -62,9 +61,6 @@
 void cleanup_module(void)
 {
 	usb_major_cleanup();
-#ifdef CONFIG_USB_PROC
-	proc_usb_cleanup ();
-#endif
         usbdevfs_cleanup();
 	usb_hub_cleanup();
 
@@ -80,9 +76,6 @@
 #endif
 {
 	usb_major_init();
-#ifdef CONFIG_USB_PROC
-	proc_usb_init();
-#endif
         usbdevfs_init();
 	usb_hub_init();
 
@@ -117,7 +110,7 @@
 #ifdef CONFIG_USB_DABUSB
 	dabusb_init();
 #endif
-#if defined(CONFIG_USB_HID) || defined(CONFIG_USB_MOUSE) || defined(CONFIG_USB_KBD)
+#if defined(CONFIG_USB_HID) || defined(CONFIG_USB_MOUSE) || defined(CONFIG_USB_KBD) || defined(CONFIG_USB_GRAPHIRE)
 	input_init();
 #endif
 #ifdef CONFIG_USB_HID
@@ -128,6 +121,9 @@
 #endif
 #ifdef CONFIG_USB_KBD
 	usb_kbd_init();
+#endif
+#ifdef CONFIG_USB_GRAPHIRE
+	graphire_init();
 #endif
 #ifdef CONFIG_USB_UHCI
 	uhci_init();
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c
--- v2.3.39/linux/drivers/usb/usb-debug.c	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/usb-debug.c	Mon Jan 17 16:24:48 2000
@@ -132,24 +132,6 @@
 	printk("    iInterface          =   %02x\n", desc->iInterface);
 }
 
-void usb_show_hid_descriptor(struct usb_hid_descriptor * desc)
-{
-	int i;
-    
-	printk("    HID:\n");
-	printk("      HID version %x.%02x\n", desc->bcdHID >> 8, desc->bcdHID & 0xff);
-	printk("      bLength             = %4d\n", desc->bLength);
-	printk("      bDescriptorType     =   %02x\n", desc->bDescriptorType);
-	printk("      bCountryCode        =   %02x\n", desc->bCountryCode);
-	printk("      bNumDescriptors     =   %02x\n", desc->bNumDescriptors);
-
-	for (i=0; i<desc->bNumDescriptors; i++) {
-		printk("        %d:\n", i);
-		printk("            bDescriptorType      =   %02x\n", desc->desc[i].bDescriptorType);
-		printk("            wDescriptorLength    =   %04x\n", desc->desc[i].wDescriptorLength);
-	}
-}
-
 void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *desc)
 {
 	char *LengthCommentString = (desc->bLength ==
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
--- v2.3.39/linux/drivers/usb/usb-serial.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/usb/usb-serial.c	Thu Jan 20 09:48:48 2000
@@ -1,7 +1,7 @@
 /*
  * USB Serial Converter driver
  *
- *	(C) Copyright (C) 1999
+ *	(C) Copyright (C) 1999, 2000
  *	    Greg Kroah-Hartman (greg@kroah.com)
  *
  *	This program is free software; you can redistribute it and/or modify
@@ -12,8 +12,42 @@
  * This driver was originally based on the ACM driver by Armin Fuerst (which was 
  * based on a driver by Brad Keryan)
  *
- * See README.serial for more information on using this driver.
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (01/19/2000) gkh
+ *	Removed lots of cruft that was around from the old (pre urb) driver 
+ *	interface.
+ *	Made the serial_table dynamic. This should save lots of memory when
+ *	the number of minor nodes goes up to 256.
+ *	Added initial support for devices that have more than one port. 
+ *	Added more debugging comments for the Visor, and added a needed 
+ *	set_configuration call.
+ *
+ * (01/17/2000) gkh
+ *	Fixed the WhiteHEAT firmware (my processing tool had a bug)
+ *	and added new debug loader firmware for it.
+ *	Removed the put_char function as it isn't really needed.
+ *	Added visor startup commands as found by the Win98 dump.
+ * 
+ * (01/13/2000) gkh
+ *	Fixed the vendor id for the generic driver to the one I meant it to be.
+ *
+ * (01/12/2000) gkh
+ *	Forget the version numbering...that's pretty useless...
+ *	Made the driver able to be compiled so that the user can select which
+ *	converter they want to use. This allows people who only want the Visor
+ *	support to not pay the memory size price of the WhiteHEAT.
+ *	Fixed bug where the generic driver (idVendor=0000 and idProduct=0000)
+ *	grabbed the root hub. Not good.
+ * 
+ * version 0.4.0 (01/10/2000) gkh
+ *	Added whiteheat.h containing the firmware for the ConnectTech WhiteHEAT
+ *	device. Added startup function to allow firmware to be downloaded to
+ *	a device if it needs to be.
+ *	Added firmware download logic to the WhiteHEAT device.
+ *	Started to add #defines to split up the different drivers for potential
+ *	configuration option.
+ *	
  * version 0.3.1 (12/30/99) gkh
  *      Fixed problems with urb for bulk out.
  *      Added initial support for multiple sets of endpoints. This enables
@@ -63,6 +97,7 @@
  * 
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -77,21 +112,31 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
-#undef DEBUG
+#define DEBUG
 
 #include "usb.h"
 
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
+#include "whiteheat.h"		/* firmware for the ConnectTech WhiteHEAT device */
+#endif
+
 /* Module information */
 MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
 MODULE_DESCRIPTION("USB Serial Driver");
 
-static __u16	vendor	= 0;
-static __u16	product	= 0;
+#ifdef CONFIG_USB_SERIAL_GENERIC
+static __u16	vendor	= 0x05f9;
+static __u16	product	= 0xffff;
 MODULE_PARM(vendor, "i");
 MODULE_PARM_DESC(vendor, "User specified USB idVendor");
 
 MODULE_PARM(product, "i");
 MODULE_PARM_DESC(product, "User specified USB idProduct");
+#endif
+
+
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
+static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
 
 
 /* USB Serial devices vendor ids and device ids that this driver supports */
@@ -106,12 +151,36 @@
 #define HANDSPRING_VISOR_ID		0x0100
 
 
-#define SERIAL_MAJOR	188	/* Nice legal number now */
-#define NUM_PORTS	16	/* Actually we are allowed 255, but this is good for now */
+#define SERIAL_TTY_MAJOR	188	/* Nice legal number now */
+#define SERIAL_TTY_MINORS	16	/* Actually we are allowed 255, but this is good for now */
 
 
-static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
-static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
+#define MAX_NUM_PORTS	8	/* The maximum number of ports one device can grab at once */
+
+struct usb_serial {
+	struct usb_device *		dev;
+	struct usb_serial_device_type *	type;
+	void *				irq_handle;
+	unsigned int			irqpipe;
+	struct tty_struct *		tty;			/* the coresponding tty for this device */
+	unsigned char			minor;
+	unsigned char			num_ports;		/* the number of ports this device has */
+	char				active[MAX_NUM_PORTS];	/* someone has this device open */
+
+	char			num_interrupt_in;		/* number of interrupt in endpoints we have */
+	__u8			interrupt_in_interval[MAX_NUM_PORTS];
+	unsigned char *		interrupt_in_buffer[MAX_NUM_PORTS];
+	struct urb		control_urb[MAX_NUM_PORTS];
+
+	char			num_bulk_in;			/* number of bulk in endpoints we have */
+	unsigned char *		bulk_in_buffer[MAX_NUM_PORTS];
+	struct urb		read_urb[MAX_NUM_PORTS];
+
+	char			num_bulk_out;			/* number of bulk out endpoints we have */
+	unsigned char *		bulk_out_buffer[MAX_NUM_PORTS];
+	int			bulk_out_size[MAX_NUM_PORTS];
+	struct urb		write_urb[MAX_NUM_PORTS];
+};
 
 
 #define MUST_HAVE_NOT	0x01
@@ -127,7 +196,6 @@
 static int serial_open (struct tty_struct *tty, struct file * filp);
 static void serial_close (struct tty_struct *tty, struct file * filp);
 static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count);
-static void serial_put_char (struct tty_struct *tty, unsigned char ch);
 static int serial_write_room (struct tty_struct *tty);
 static int serial_chars_in_buffer (struct tty_struct *tty);
 static void serial_throttle (struct tty_struct * tty);
@@ -145,15 +213,15 @@
 	char	num_interrupt_in;
 	char	num_bulk_in;
 	char	num_bulk_out;
+	char	num_ports;		/* number of serial ports this device has */
 
 	/* function call to make before accepting driver */
-	void (*startup) (void);
+	int (*startup) (struct usb_serial *serial);	/* return 0 to continue initialization, anything else to abort */
 	
 	/* serial function calls */
 	int  (*open)(struct tty_struct * tty, struct file * filp);
 	void (*close)(struct tty_struct * tty, struct file * filp);
 	int  (*write)(struct tty_struct * tty, int from_user,const unsigned char *buf, int count);
-	void (*put_char)(struct tty_struct *tty, unsigned char ch);
 	int  (*write_room)(struct tty_struct *tty);
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	void (*throttle)(struct tty_struct * tty);
@@ -162,13 +230,14 @@
 
 
 /* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */
+/* need to always compile these in, as some of the other devices use these functions as their own. */
 static int  generic_serial_open		(struct tty_struct *tty, struct file *filp);
 static void generic_serial_close	(struct tty_struct *tty, struct file *filp);
 static int  generic_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
-static void generic_serial_put_char	(struct tty_struct *tty, unsigned char ch);
 static int  generic_write_room		(struct tty_struct *tty);
 static int  generic_chars_in_buffer	(struct tty_struct *tty);
 
+#ifdef CONFIG_USB_SERIAL_GENERIC
 /* All of the device info needed for the Generic Serial Converter */
 static struct usb_serial_device_type generic_device = {
 	name:			"Generic",
@@ -180,19 +249,22 @@
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
+	num_ports:		1,
 	open:			generic_serial_open,
 	close:			generic_serial_close,
 	write:			generic_serial_write,
-	put_char:		generic_serial_put_char,
 	write_room:		generic_write_room,
 	chars_in_buffer:	generic_chars_in_buffer,
 };
+#endif
 
-
+#if defined(CONFIG_USB_SERIAL_BELKIN) || defined(CONFIG_USB_SERIAL_PERACOM)
 /* function prototypes for the eTek type converters (this includes Belkin and Peracom) */
 static int  etek_serial_open		(struct tty_struct *tty, struct file *filp);
 static void etek_serial_close		(struct tty_struct *tty, struct file *filp);
+#endif
 
+#ifdef CONFIG_USB_SERIAL_BELKIN
 /* All of the device info needed for the Belkin Serial Converter */
 static __u16	belkin_vendor_id	= BELKIN_VENDOR_ID;
 static __u16	belkin_product_id	= BELKIN_SERIAL_CONVERTER;
@@ -206,14 +278,17 @@
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
+	num_ports:		1,
 	open:			etek_serial_open,
 	close:			etek_serial_close,
 	write:			generic_serial_write,
-	put_char:		generic_serial_put_char,
 	write_room:		generic_write_room,
 	chars_in_buffer:	generic_chars_in_buffer,
 };
+#endif
 
+
+#ifdef CONFIG_USB_SERIAL_PERACOM
 /* All of the device info needed for the Peracom Serial Converter */
 static __u16	peracom_vendor_id	= PERACOM_VENDOR_ID;
 static __u16	peracom_product_id	= PERACOM_SERIAL_CONVERTER;
@@ -224,23 +299,26 @@
 	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_ports:		1,
 	num_interrupt_in:	1,
 	num_bulk_in:		1,
 	num_bulk_out:		1,
 	open:			etek_serial_open,
 	close:			etek_serial_close,
 	write:			generic_serial_write,
-	put_char:		generic_serial_put_char,
 	write_room:		generic_write_room,
 	chars_in_buffer:	generic_chars_in_buffer,
 };
+#endif
 
 
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
 static int  whiteheat_serial_open	(struct tty_struct *tty, struct file *filp);
 static void whiteheat_serial_close	(struct tty_struct *tty, struct file *filp);
 static void whiteheat_throttle		(struct tty_struct *tty);
 static void whiteheat_unthrottle	(struct tty_struct *tty);
+static int  whiteheat_startup		(struct usb_serial *serial);
 
 /* All of the device info needed for the Connect Tech WhiteHEAT */
 static __u16	connecttech_vendor_id			= CONNECT_TECH_VENDOR_ID;
@@ -256,6 +334,7 @@
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
+	startup:		whiteheat_startup	
 };
 static struct usb_serial_device_type whiteheat_device = {
 	name:			"Connect Tech - WhiteHEAT",
@@ -267,22 +346,25 @@
 	num_interrupt_in:	NUM_DONT_CARE,
 	num_bulk_in:		NUM_DONT_CARE,
 	num_bulk_out:		NUM_DONT_CARE,
+	num_ports:		4,
 	open:			whiteheat_serial_open,
 	close:			whiteheat_serial_close,
 	write:			generic_serial_write,
-	put_char:		generic_serial_put_char,
 	write_room:		generic_write_room,
 	chars_in_buffer:	generic_chars_in_buffer,
 	throttle:		whiteheat_throttle,
 	unthrottle:		whiteheat_unthrottle
 };
+#endif
 
 
+#ifdef CONFIG_USB_SERIAL_VISOR
 /* function prototypes for a handspring visor */
 static int  visor_serial_open		(struct tty_struct *tty, struct file *filp);
 static void visor_serial_close		(struct tty_struct *tty, struct file *filp);
 static void visor_throttle		(struct tty_struct *tty);
 static void visor_unthrottle		(struct tty_struct *tty);
+static int  visor_startup		(struct usb_serial *serial);
 
 /* All of the device info needed for the Handspring Visor */
 static __u16	handspring_vendor_id	= HANDSPRING_VENDOR_ID;
@@ -297,72 +379,42 @@
 	num_interrupt_in:	0,
 	num_bulk_in:		2,
 	num_bulk_out:		2,
+	num_ports:		2,
 	open:			visor_serial_open,
 	close:			visor_serial_close,
 	write:			generic_serial_write,
-	put_char:		generic_serial_put_char,
 	write_room:		generic_write_room,
 	chars_in_buffer:	generic_chars_in_buffer,
 	throttle:		visor_throttle,
-	unthrottle:		visor_unthrottle
+	unthrottle:		visor_unthrottle,
+	startup:		visor_startup
 };
-
+#endif
 
 /* To add support for another serial converter, create a usb_serial_device_type
    structure for that device, and add it to this list, making sure that the last
    entry is NULL. */
 static struct usb_serial_device_type *usb_serial_devices[] = {
+#ifdef CONFIG_USB_SERIAL_GENERIC
 	&generic_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
 	&whiteheat_fake_device,
 	&whiteheat_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_BELKIN
 	&belkin_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_PERACOM
 	&peracom_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_VISOR
 	&handspring_device,
+#endif
 	NULL
 };
 
 
-#define MAX_ENDPOINTS	8
-
-struct usb_serial_state {
-	struct usb_device *		dev;
-	struct usb_serial_device_type *	type;
-	void *				irq_handle;
-	unsigned int			irqpipe;
-	struct tty_struct *		tty;		/* the coresponding tty for this device */
-	unsigned char			number;
-	char				present;
-	char				active;
-
-	char			num_interrupt_in;	/* number of interrupt in endpoints we have */
-	char			interrupt_in_inuse;	/* if the interrupt in endpoint is in use */
-	__u8			interrupt_in_endpoint[MAX_ENDPOINTS];
-	__u8			interrupt_in_interval[MAX_ENDPOINTS];
-	__u16			interrupt_in_size[MAX_ENDPOINTS];	/* the size of the interrupt in endpoint */
-	unsigned int		interrupt_in_pipe[MAX_ENDPOINTS];
-	unsigned char *		interrupt_in_buffer[MAX_ENDPOINTS];
-	void *			interrupt_in_transfer[MAX_ENDPOINTS];
-	struct urb		control_urb;
-
-	char			num_bulk_in;		/* number of bulk in endpoints we have */
-	__u8			bulk_in_endpoint[MAX_ENDPOINTS];
-	__u8			bulk_in_interval[MAX_ENDPOINTS];
-	__u16			bulk_in_size[MAX_ENDPOINTS];		/* the size of the bulk in endpoint */
-	unsigned int		bulk_in_pipe[MAX_ENDPOINTS];
-	unsigned char *		bulk_in_buffer[MAX_ENDPOINTS];
-	void *			bulk_in_transfer[MAX_ENDPOINTS];
-	struct urb		read_urb;
-
-	char			num_bulk_out;		/* number of bulk out endpoints we have */
-	__u8			bulk_out_endpoint[MAX_ENDPOINTS];
-	__u8			bulk_out_interval[MAX_ENDPOINTS];
-	__u16			bulk_out_size[MAX_ENDPOINTS];		/* the size of the bulk out endpoint */
-	unsigned int		bulk_out_pipe[MAX_ENDPOINTS];
-	unsigned char *		bulk_out_buffer[MAX_ENDPOINTS];
-	void *			bulk_out_transfer[MAX_ENDPOINTS];
-	struct urb		write_urb;
-};
-
 static struct usb_driver usb_serial_driver = {
 	"serial",
 	usb_serial_probe,
@@ -371,16 +423,61 @@
 };
 
 static int			serial_refcount;
-static struct tty_struct *	serial_tty[NUM_PORTS];
-static struct termios *		serial_termios[NUM_PORTS];
-static struct termios *		serial_termios_locked[NUM_PORTS];
-static struct usb_serial_state	serial_state_table[NUM_PORTS];
+static struct tty_struct *	serial_tty[SERIAL_TTY_MINORS];
+static struct termios *		serial_termios[SERIAL_TTY_MINORS];
+static struct termios *		serial_termios_locked[SERIAL_TTY_MINORS];
+static struct usb_serial	*serial_table[SERIAL_TTY_MINORS] = {NULL, };
+
+
+
+#define SERIAL_PTR_EMPTY ((void *)(-1))
 
+static struct usb_serial *get_serial_by_minor (int minor)
+{
+	int i;
+
+	dbg("get_serial_by_minor %d", minor);
+
+	for (i = 0; i < SERIAL_TTY_MINORS; ++i)
+		if (serial_table[i])
+			if (serial_table[i] != SERIAL_PTR_EMPTY)
+				if (serial_table[i]->minor == minor)
+					return (serial_table[i]);
+
+	return (NULL);
+}
+
+
+static struct usb_serial *get_free_serial (int num_ports, int *minor)
+{
+	struct usb_serial *serial = NULL;
+	int i;
+
+	dbg("get_free_serial %d", num_ports);
+
+	*minor = 0;
+	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+		if (serial_table[i])
+			continue;
+		if (!(serial = kmalloc(sizeof(struct usb_serial), GFP_KERNEL))) {
+			err("Out of memory");
+			return NULL;
+		}
+		memset(serial, 0, sizeof(struct usb_serial));
+		serial_table[i] = serial;
+		*minor = i;
+		dbg("minor base = %d", *minor);
+		for (i = *minor+1; (i < num_ports) && (i < SERIAL_TTY_MINORS); ++i)
+			serial_table[i] = SERIAL_PTR_EMPTY;
+		return (serial);
+		}
+	return (NULL);
+}
 
 
 static void serial_read_bulk (struct urb *urb)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *)urb->context;
+	struct usb_serial *serial = (struct usb_serial *)urb->context;
        	struct tty_struct *tty = serial->tty; 
        	unsigned char *data = urb->transfer_buffer;
 	int i;
@@ -412,7 +509,7 @@
 
 static void serial_write_bulk (struct urb *urb)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) urb->context; 
+	struct usb_serial *serial = (struct usb_serial *) urb->context; 
        	struct tty_struct *tty = serial->tty; 
 
 	dbg("serial_write_irq");
@@ -437,12 +534,12 @@
  *****************************************************************************/
 static int serial_open (struct tty_struct *tty, struct file * filp)
 {
-	struct usb_serial_state *serial;
+	struct usb_serial *serial;
 	
 	dbg("serial_open");
 
-	/* assign a serial object to the tty pointer */
-	serial = &serial_state_table [MINOR(tty->device)-tty->driver.minor_start];
+	/* get the serial object associated with this tty pointer */
+	serial = get_serial_by_minor (MINOR(tty->device));
 
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
@@ -469,8 +566,10 @@
 
 static void serial_close(struct tty_struct *tty, struct file * filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	dbg("serial_close");
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("serial_close port %d", port);
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
@@ -481,11 +580,7 @@
 		dbg("serial->type == NULL!");
 		return;
 	}
-	if (!serial->present) {
-		dbg("no device registered");
-		return;
-	}
-	if (!serial->active) {
+	if (!serial->active[port]) {
 		dbg ("device already open");
 		return;
 	}
@@ -499,9 +594,10 @@
 
 static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 	
-	dbg("serial_write");
+	dbg("serial_write port %d, %d byte(s)", port, count);
 
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
@@ -512,11 +608,7 @@
 		dbg("serial->type == NULL!");
 		return (-ENODEV);
 	}
-	if (!serial->present) {
-		dbg("device not registered");
-		return (-EINVAL);
-	}
-	if (!serial->active) {
+	if (!serial->active[port]) {
 		dbg ("device not opened");
 		return (-EINVAL);
 	}
@@ -531,44 +623,12 @@
 }
 
 
-static void serial_put_char (struct tty_struct *tty, unsigned char ch)
-{
-	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
-	
-	dbg("serial_put_char");
-	
-	/* do some sanity checking that we really have a device present */
-	if (!serial) {
-		dbg("serial == NULL!");
-		return;
-	}
-	if (!serial->type) {
-		dbg("serial->type == NULL!");
-		return;
-	}
-	if (!serial->present) {
-		dbg("no device registered");
-		return;
-	}
-	if (!serial->active) {
-		dbg ("device not open");
-		return;
-	}
-
-	/* pass on to the driver specific version of this function */
-	if (serial->type->put_char) {
-		serial->type->put_char(tty, ch);
-	}
-
-	return;
-}	
-
-
 static int serial_write_room (struct tty_struct *tty) 
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("serial_write_room");
+	dbg("serial_write_room port %d", port);
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
@@ -579,11 +639,7 @@
 		dbg("serial->type == NULL!");
 		return (-ENODEV);
 	}
-	if (!serial->present) {
-		dbg("no device registered");
-		return (-EINVAL);
-	}
-	if (!serial->active) {
+	if (!serial->active[port]) {
 		dbg ("device not open");
 		return (-EINVAL);
 	}
@@ -599,9 +655,10 @@
 
 static int serial_chars_in_buffer (struct tty_struct *tty) 
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("serial_chars_in_buffer");
+	dbg("serial_chars_in_buffer port %d", port);
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
@@ -612,11 +669,7 @@
 		dbg("serial->type == NULL!");
 		return (-ENODEV);
 	}
-	if (!serial->present) {
-		dbg("no device registered");
-		return (-EINVAL);
-	}
-	if (!serial->active) {
+	if (!serial->active[port]) {
 		dbg ("device not open");
 		return (-EINVAL);
 	}
@@ -632,9 +685,10 @@
 
 static void serial_throttle (struct tty_struct * tty)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("serial_throttle");
+	dbg("serial_throttle port %d", port);
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
@@ -645,11 +699,7 @@
 		dbg("serial->type == NULL!");
 		return;
 	}
-	if (!serial->present) {
-		dbg("no device registered");
-		return;
-	}
-	if (!serial->active) {
+	if (!serial->active[port]) {
 		dbg ("device not open");
 		return;
 	}
@@ -665,9 +715,10 @@
 
 static void serial_unthrottle (struct tty_struct * tty)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("serial_unthrottle");
+	dbg("serial_unthrottle port %d", port);
 	
 	/* do some sanity checking that we really have a device present */
 	if (!serial) {
@@ -678,16 +729,11 @@
 		dbg("serial->type == NULL!");
 		return;
 	}
-	if (!serial->present) {
-		dbg("no device registered");
-		return;
-	}
-	if (!serial->active) {
+	if (!serial->active[port]) {
 		dbg ("device not open");
 		return;
 	}
 
-
 	/* pass on to the driver specific version of this function */
 	if (serial->type->unthrottle) {
 		serial->type->unthrottle(tty);
@@ -697,28 +743,25 @@
 }
 
 
+#if defined(CONFIG_USB_SERIAL_BELKIN) || defined(CONFIG_USB_SERIAL_PERACOM)
 /*****************************************************************************
  * eTek specific driver functions
  *****************************************************************************/
 static int etek_serial_open (struct tty_struct *tty, struct file *filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-
-	dbg("etek_serial_open");
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 
-	if (!serial->present) {
-		dbg("no device registered");
-		return -EINVAL;
-	}
+	dbg("etek_serial_open port %d", port);
 
-	if (serial->active) {
+	if (serial->active[port]) {
 		dbg ("device already open");
 		return -EINVAL;
 	}
-	serial->active = 1;
+	serial->active[port] = 1;
  
 	/*Start reading from the device*/
-	if (usb_submit_urb(&serial->read_urb))
+	if (usb_submit_urb(&serial->read_urb[port]))
 		dbg("usb_submit_urb(read bulk) failed");
 
 	/* Need to do device specific setup here (control lines, baud rate, etc.) */
@@ -730,41 +773,42 @@
 
 static void etek_serial_close(struct tty_struct *tty, struct file * filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	dbg("etek_serial_close");
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("etek_serial_close port %d", port);
 	
 	/* Need to change the control lines here */
 	/* FIXME */
 	
 	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (&serial->write_urb);
-	usb_unlink_urb (&serial->read_urb);
-	serial->active = 0;
+	usb_unlink_urb (&serial->write_urb[port]);
+	usb_unlink_urb (&serial->read_urb[port]);
+	serial->active[port] = 0;
 }
+#endif	/* defined(CONFIG_USB_SERIAL_BELKIN) || defined(CONFIG_USB_SERIAL_PERACOM) */
 
 
+
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
 /*****************************************************************************
  * Connect Tech's White Heat specific driver functions
  *****************************************************************************/
 static int whiteheat_serial_open (struct tty_struct *tty, struct file *filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("whiteheat_serial_open");
+	dbg("whiteheat_serial_open port %d", port);
 
-	if (!serial->present) {
-		dbg("no device registered");
-		return -EINVAL;
-	}
-
-	if (serial->active) {
+	if (serial->active[port]) {
 		dbg ("device already open");
 		return -EINVAL;
 	}
-	serial->active = 1;
+	serial->active[port] = 1;
  
 	/*Start reading from the device*/
-	if (usb_submit_urb(&serial->read_urb))
+	if (usb_submit_urb(&serial->read_urb[port]))
 		dbg("usb_submit_urb(read bulk) failed");
 
 	/* Need to do device specific setup here (control lines, baud rate, etc.) */
@@ -776,23 +820,28 @@
 
 static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	dbg("whiteheat_serial_close");
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("whiteheat_serial_close port %d", port);
 	
 	/* Need to change the control lines here */
 	/* FIXME */
 	
 	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (&serial->write_urb);
-	usb_unlink_urb (&serial->read_urb);
-	serial->active = 0;
+	usb_unlink_urb (&serial->write_urb[port]);
+	usb_unlink_urb (&serial->read_urb[port]);
+	serial->active[port] = 0;
 }
 
 
 static void whiteheat_throttle (struct tty_struct * tty)
 {
-	dbg("whiteheat_throttle");
-	
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("whiteheat_throttle port %d", port);
+
 	/* Change the control signals */
 	/* FIXME!!! */
 
@@ -802,8 +851,11 @@
 
 static void whiteheat_unthrottle (struct tty_struct * tty)
 {
-	dbg("whiteheat_unthrottle");
-	
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("whiteheat_unthrottle port %d", port);
+
 	/* Change the control signals */
 	/* FIXME!!! */
 
@@ -811,28 +863,131 @@
 }
 
 
+static int whiteheat_writememory (struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest)
+{
+	int result;
+	unsigned char *transfer_buffer =  kmalloc (length, GFP_KERNEL);
+
+//	dbg("whiteheat_writememory %x, %d", address, length);
+
+	if (!transfer_buffer) {
+		err("whiteheat_writememory: kmalloc(%d) failed.\n", length);
+		return -ENOMEM;
+	}
+	memcpy (transfer_buffer, data, length);
+	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 300);
+	kfree (transfer_buffer);
+	return result;
+}
+
+/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
+#define CPUCS_REG    0x7F92
+
+static int whiteheat_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+{
+	int	response;
+	dbg("whiteheat_set_reset: %d", reset_bit);
+	response = whiteheat_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+	if (response < 0) {
+		err("whiteheat_set_reset %d failed", reset_bit);
+	}
+	return (response);
+}
+
+
+/* steps to download the firmware to the WhiteHEAT device:
+ - hold the reset (by writing to the reset bit of the CPUCS register)
+ - download the VEND_AX.HEX file to the chip using VENDOR_REQUEST-ANCHOR_LOAD
+ - release the reset (by writing to the CPUCS register)
+ - download the WH.HEX file for all addresses greater than 0x1b3f using
+   VENDOR_REQUEST-ANCHOR_EXTERNAL_RAM_LOAD
+ - hold the reset
+ - download the WH.HEX file for all addresses less than 0x1b40 using
+   VENDOR_REQUEST_ANCHOR_LOAD
+ - release the reset
+ - device renumerated itself and comes up as new device id with all
+   firmware download completed.
+*/
+static int  whiteheat_startup (struct usb_serial *serial)
+{
+	int response;
+	const struct whiteheat_hex_record *record;
+	
+	dbg("whiteheat_startup");
+	
+	response = whiteheat_set_reset (serial, 1);
+
+	record = &whiteheat_loader[0];
+	while (record->address != 0xffff) {
+		response = whiteheat_writememory (serial, record->address, 
+				(unsigned char *)record->data, record->data_size, 0xa0);
+		if (response < 0) {
+			err("whiteheat_writememory failed for loader (%d %04X %p %d)", 
+				response, record->address, record->data, record->data_size);
+			break;
+		}
+		++record;
+	}
+
+	response = whiteheat_set_reset (serial, 0);
+
+	record = &whiteheat_firmware[0];
+	while (record->address < 0x1b40) {
+		++record;
+	}
+	while (record->address != 0xffff) {
+		response = whiteheat_writememory (serial, record->address, 
+				(unsigned char *)record->data, record->data_size, 0xa0);
+		if (response < 0) {
+			err("whiteheat_writememory failed for first firmware step (%d %04X %p %d)", 
+				response, record->address, record->data, record->data_size);
+			break;
+		}
+		++record;
+	}
+	
+	response = whiteheat_set_reset (serial, 1);
+
+	record = &whiteheat_firmware[0];
+	while (record->address < 0x1b40) {
+		response = whiteheat_writememory (serial, record->address, 
+				(unsigned char *)record->data, record->data_size, 0xa0);
+		if (response < 0) {
+			err("whiteheat_writememory failed for second firmware step (%d %04X %p %d)\n", 
+				response, record->address, record->data, record->data_size);
+			break;
+		}
+		++record;
+	}
+
+	response = whiteheat_set_reset (serial, 0);
+
+	/* we want this device to fail to have a driver assigned to it. */
+	return (1);
+}
+#endif	/* CONFIG_USB_SERIAL_WHITEHEAT */
+
+
+#ifdef CONFIG_USB_SERIAL_VISOR
 /******************************************************************************
  * Handspring Visor specific driver functions
  ******************************************************************************/
 static int visor_serial_open (struct tty_struct *tty, struct file *filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
-	dbg("visor_serial_open");
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int port = MINOR(tty->device) - serial->minor;
 
-	if (!serial->present) {
-		dbg("no device registered");
-		return -EINVAL;
-	}
+	dbg("visor_serial_open port %d", port);
 
-	if (serial->active) {
+	if (serial->active[port]) {
 		dbg ("device already open");
 		return -EINVAL;
 	}
 
-	serial->active = 1;
+	serial->active[port] = 1;
 
 	/*Start reading from the device*/
-	if (usb_submit_urb(&serial->read_urb))
+	if (usb_submit_urb(&serial->read_urb[port]))
 		dbg("usb_submit_urb(read bulk) failed");
 
 	return (0);
@@ -840,66 +995,146 @@
 
 static void visor_serial_close(struct tty_struct *tty, struct file * filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int port = MINOR(tty->device) - serial->minor;
 	
-	dbg("USB: visor_serial_close");
+	dbg("visor_serial_close port %d", port);
 			 
 	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (&serial->write_urb);
-	usb_unlink_urb (&serial->read_urb);
-	serial->active = 0;
+	usb_unlink_urb (&serial->write_urb[port]);
+	usb_unlink_urb (&serial->read_urb[port]);
+	serial->active[port] = 0;
 }
 
 
 static void visor_throttle (struct tty_struct * tty)
 {
-/*	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("visor_throttle");
+	dbg("visor_throttle port %d", port);
 
-	/* Change the control signals */
-	/* FIXME!!! */
+	usb_unlink_urb (&serial->read_urb[port]);
 
 	return;
 }
 
+
 static void visor_unthrottle (struct tty_struct * tty)
 {
-/*	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("visor_unthrottle");
+	dbg("visor_unthrottle port %d", port);
 
-	/* Change the control signals */
-	/* FIXME!!! */
+	if (usb_unlink_urb (&serial->read_urb[port]))
+		dbg("usb_submit_urb(read bulk) failed");
 
 	return;
 }
 
 
+/*
+ Here's the raw dump of the vendor specific command data that the Visor sends on Win98
+______________________________________________________________________
+SETUP(0xB4) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA0(0xC3) DATA(C2 03 00 00 00 00 12 00 ) CRC16(0xB0BB)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+IN(0x96) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA1(0xD2) DATA(02 00 00 01 02 02 ) CRC16(0xF4E6)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+OUT(0x87) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA1(0xD2) DATA() CRC16(0x0000)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+SETUP(0xB4) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA0(0xC3) DATA(C2 01 00 00 05 00 02 00 ) CRC16(0xC488)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+IN(0x96) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA1(0xD2) DATA(01 00 ) CRC16(0xFFFB)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+OUT(0x87) ADDR(0x02) ENDP(0x0) CRC5(0x15)
+______________________________________________________________________
+DATA1(0xD2) DATA() CRC16(0x0000)
+______________________________________________________________________
+ACK(0x4B)
+______________________________________________________________________
+*/
+
+static int  visor_startup (struct usb_serial *serial)
+{
+	/* send out two unknown commands that I found by looking at a Win98 trace */
+	int response;
+	unsigned char *transfer_buffer =  kmalloc (256, GFP_KERNEL);
+
+	if (!transfer_buffer) {
+		err("visor_startup: kmalloc(%d) failed.\n", 256);
+		return -ENOMEM;
+	}
+
+	dbg("visor_startup");
+
+	dbg("visor_setup: Set config to 1");
+	usb_set_configuration (serial->dev, 1);
+
+	response = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x03, 0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
+	if (response < 0) {
+		err("visor_startup: error getting first vendor specific message");
+	} else {
+		dbg("visor_startup: First vendor specific message successful");
+	}
+
+	response = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), 0x01, 0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
+	if (response < 0) {
+		err("visor_startup: error getting second vendor specific message");
+	} else {
+		dbg("visor_startup: Second vendor specific message successful");
+	}
+
+	kfree (transfer_buffer);
+
+	/* continue on with initialization */
+	return (0);
+}
+
+
+#endif	/* CONFIG_USB_SERIAL_VISOR*/
+
+
 /*****************************************************************************
  * generic devices specific driver functions
  *****************************************************************************/
 static int generic_serial_open (struct tty_struct *tty, struct file *filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("generic_serial_open");
+	dbg("generic_serial_open port %d", port);
 
-	if (!serial->present) {
-		dbg("no device registered");
-		return -EINVAL;
-	}
-
-	if (serial->active) {
+	if (serial->active[port]) {
 		dbg ("device already open");
 		return -EINVAL;
 	}
-	serial->active = 1;
+	serial->active[port] = 1;
  
 	/* if we have a bulk interrupt, start reading from it */
 	if (serial->num_bulk_in) {
 		/*Start reading from the device*/
-		if (usb_submit_urb(&serial->read_urb))
+		if (usb_submit_urb(&serial->read_urb[port]))
 			dbg("usb_submit_urb(read bulk) failed");
 	}
 
@@ -909,26 +1144,29 @@
 
 static void generic_serial_close(struct tty_struct *tty, struct file * filp)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	dbg("generic_serial_close");
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("generic_serial_close port %d", port);
 	
 	/* shutdown any bulk reads that might be going on */
 	if (serial->num_bulk_out) {
-		usb_unlink_urb (&serial->write_urb);
+		usb_unlink_urb (&serial->write_urb[port]);
 	}
 	if (serial->num_bulk_in) {
-		usb_unlink_urb (&serial->read_urb);
+		usb_unlink_urb (&serial->read_urb[port]);
 	}
 
-	serial->active = 0;
+	serial->active[port] = 0;
 }
 
 
 static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; 
-	
-	dbg("generic_serial_write");
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("generic_serial_write port %d", port);
 
 	if (count == 0) {
 		dbg("write request of 0 bytes");
@@ -937,24 +1175,24 @@
 
 	/* only do something if we have a bulk out endpoint */
 	if (serial->num_bulk_out) {
-		if (serial->write_urb.status == -EINPROGRESS) {
+		if (serial->write_urb[port].status == -EINPROGRESS) {
 			dbg ("already writing");
 			return (0);
 		}
 
-		count = (count > serial->bulk_out_size[0]) ? serial->bulk_out_size[0] : count;
+		count = (count > serial->bulk_out_size[port]) ? serial->bulk_out_size[port] : count;
 
 		if (from_user) {
-			copy_from_user(serial->write_urb.transfer_buffer, buf, count);
+			copy_from_user(serial->write_urb[port].transfer_buffer, buf, count);
 		}
 		else {
-			memcpy (serial->write_urb.transfer_buffer, buf, count);
+			memcpy (serial->write_urb[port].transfer_buffer, buf, count);
 		}  
 
 		/* send the data out the bulk port */
-		serial->write_urb.transfer_buffer_length = count;
+		serial->write_urb[port].transfer_buffer_length = count;
 
-		if (usb_submit_urb(&serial->write_urb))
+		if (usb_submit_urb(&serial->write_urb[port]))
 			dbg("usb_submit_urb(write bulk) failed");
 
 		return (count);
@@ -965,39 +1203,19 @@
 } 
 
 
-static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch)
-{
-	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
-	
-	dbg("generic_serial_put_char");
-	
-	/* if we have a bulk out endpoint, then shove a character out it */
-	if (serial->num_bulk_out) {
-		/* send the single character out the bulk port */
-		memcpy (serial->write_urb.transfer_buffer, &ch, 1);
-		serial->write_urb.transfer_buffer_length = 1;
-
-		if (usb_submit_urb(&serial->write_urb))
-			dbg("usb_submit_urb(write bulk) failed");
-
-	}
-
-	return;
-}
-
-
 static int generic_write_room (struct tty_struct *tty) 
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 	int room;
 
-	dbg("generic_write_room");
+	dbg("generic_write_room port %d", port);
 	
 	if (serial->num_bulk_out) {
-		if (serial->write_urb.status == -EINPROGRESS)
+		if (serial->write_urb[port].status == -EINPROGRESS)
 			room = 0;
 		else
-			room = serial->bulk_out_size[0];
+			room = serial->bulk_out_size[port];
 		dbg("generic_write_room returns %d", room);
 		return (room);
 	}
@@ -1008,13 +1226,14 @@
 
 static int generic_chars_in_buffer (struct tty_struct *tty) 
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; 
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
 
-	dbg("generic_chars_in_buffer");
+	dbg("generic_chars_in_buffer port %d", port);
 	
 	if (serial->num_bulk_out) {
-		if (serial->write_urb.status == -EINPROGRESS) {
-			return (serial->bulk_out_size[0]);
+		if (serial->write_urb[port].status == -EINPROGRESS) {
+			return (serial->bulk_out_size[port]);
 		}
 	}
 
@@ -1022,29 +1241,18 @@
 }
 
 
-static int Get_Free_Serial (void)
-{
-	int i;
- 
-	for (i=0; i < NUM_PORTS; ++i) {
-		if (!serial_state_table[i].present)
-			return (i);
-	}
-	return (-1);
-}
-
-
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
 {
-	struct usb_serial_state *serial = NULL;
+	struct usb_serial *serial = NULL;
 	struct usb_interface_descriptor *interface;
 	struct usb_endpoint_descriptor *endpoint;
-	struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_ENDPOINTS];
-	struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_ENDPOINTS];
-	struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_ENDPOINTS];
+	struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS];
+	struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS];
+	struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS];
 	struct usb_serial_device_type *type;
 	int device_num;
-	int serial_num;
+	int minor;
+	int buffer_size;
 	int i;
 	char interrupt_pipe;
 	char bulk_in_pipe;
@@ -1109,83 +1317,69 @@
 				/* found all that we need */
 				info("%s converter detected", type->name);
 
-				if (0>(serial_num = Get_Free_Serial())) {
-					dbg("Too many devices connected");
+				serial = get_free_serial (type->num_ports, &minor);
+				if (serial == NULL) {
+					err("No more free serial devices");
 					return NULL;
 				}
 	
-				serial = &serial_state_table[serial_num];
-
-			       	memset(serial, 0, sizeof(struct usb_serial_state));
 			       	serial->dev = dev;
 				serial->type = type;
-				serial->number = serial_num;
+				serial->minor = minor;
+				serial->num_ports = type->num_ports;
 				serial->num_bulk_in = num_bulk_in;
 				serial->num_bulk_out = num_bulk_out;
 				serial->num_interrupt_in = num_interrupt_in;
 
+				/* if this device type has a startup function, call it */
+				if (type->startup) {
+					if (type->startup (serial))
+						return NULL;
+				}
+
 				/* set up the endpoint information */
 				for (i = 0; i < num_bulk_in; ++i) {
-					serial->bulk_in_endpoint[i] = bulk_in_endpoint[i]->bEndpointAddress;
-					serial->bulk_in_size[i] = bulk_in_endpoint[i]->wMaxPacketSize;
-					serial->bulk_in_interval[i] = bulk_in_endpoint[i]->bInterval;
-					serial->bulk_in_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint[i]);
-					serial->bulk_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL);
+					buffer_size = bulk_in_endpoint[i]->wMaxPacketSize;
+					serial->bulk_in_buffer[i] = kmalloc (buffer_size, GFP_KERNEL);
 					if (!serial->bulk_in_buffer[i]) {
 						err("Couldn't allocate bulk_in_buffer");
 						goto probe_error;
 					}
+					FILL_BULK_URB(&serial->read_urb[i], dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
+							serial->bulk_in_buffer[i], buffer_size, serial_read_bulk, serial);
 				}
-				if (num_bulk_in)
-					FILL_BULK_URB(&serial->read_urb, dev, usb_rcvbulkpipe (dev, serial->bulk_in_endpoint[0]),
-							serial->bulk_in_buffer[0], serial->bulk_in_size[0], serial_read_bulk, serial);
 
 				for (i = 0; i < num_bulk_out; ++i) {
-					serial->bulk_out_endpoint[i] = bulk_out_endpoint[i]->bEndpointAddress;
 					serial->bulk_out_size[i] = bulk_out_endpoint[i]->wMaxPacketSize;
-					serial->bulk_out_interval[i] = bulk_out_endpoint[i]->bInterval;
-					serial->bulk_out_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint[i]);
 					serial->bulk_out_buffer[i] = kmalloc (serial->bulk_out_size[i], GFP_KERNEL);
 					if (!serial->bulk_out_buffer[i]) {
 						err("Couldn't allocate bulk_out_buffer");
 						goto probe_error;
 					}
+					FILL_BULK_URB(&serial->write_urb[i], dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
+							serial->bulk_out_buffer[i], serial->bulk_out_size[i], serial_write_bulk, serial);
 				}
-				if (num_bulk_out)
-					FILL_BULK_URB(&serial->write_urb, dev, usb_sndbulkpipe (dev, serial->bulk_in_endpoint[0]),
-							serial->bulk_in_buffer[0], serial->bulk_in_size[0], serial_write_bulk, serial);
 
+#if 0 /* use this code when WhiteHEAT is up and running */
 				for (i = 0; i < num_interrupt_in; ++i) {
-					serial->interrupt_in_inuse = 0;
-					serial->interrupt_in_endpoint[i] = interrupt_in_endpoint[i]->bEndpointAddress;
-					serial->interrupt_in_size[i] = interrupt_in_endpoint[i]->wMaxPacketSize;
-					serial->interrupt_in_interval[i] = interrupt_in_endpoint[i]->bInterval;
-					/* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */
-					serial->interrupt_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL);
+					buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize;
+					serial->interrupt_in_buffer[i] = kmalloc (buffer_size, GFP_KERNEL);
 					if (!serial->interrupt_in_buffer[i]) {
 						err("Couldn't allocate interrupt_in_buffer");
 						goto probe_error;
 					}
+					FILL_INT_URB(&serial->control_urb[i], dev, usb_rcvintpipe (dev, interrupt_in_endpoint[i]->bEndpointAddress),
+							serial->interrupt_in_buffer[i], buffer_size, serial_control_irq,
+							serial, interrupt_in_endpoint[i]->bInterval);
 				}
+#endif
 
-				#if 0
-				/* set up an interrupt for out bulk in pipe */
-				/* ask for a bulk read */
-				serial->bulk_in_inuse = 1;
-				serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial);
-
-				/* set up our interrupt to be the time for the bulk in read */
-				ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle);
-				if (ret) {
-					info("failed usb_request_irq (0x%x)", ret);
-					goto probe_error;
+				for (i = 0; i < serial->num_ports; ++i) {
+					info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i);
 				}
-				#endif
 
-				serial->present = 1;
 				MOD_INC_USE_COUNT;
 
-				info("%s converter now attached to ttyUSB%d", type->name, serial_num);
 				return serial;
 			} else {
 				info("descriptors matched, but endpoints did not");
@@ -1214,19 +1408,16 @@
 
 static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
 {
-	struct usb_serial_state *serial = (struct usb_serial_state *) ptr;
+	struct usb_serial *serial = (struct usb_serial *) ptr;
 	int i;
 
 	if (serial) {
-		if (!serial->present) {
-			/* something strange is going on */
-			dbg("disconnect but not present?");
-			return;
-			}
-
 		/* need to stop any transfers...*/
-		usb_unlink_urb (&serial->write_urb);
-		usb_unlink_urb (&serial->read_urb);
+		for (i = 0; i < serial->num_ports; ++i) {
+			usb_unlink_urb (&serial->write_urb[i]);
+			usb_unlink_urb (&serial->read_urb[i]);
+			serial->active[i] = 0;
+		}
 
 		/* free up any memory that we allocated */
 		for (i = 0; i < serial->num_bulk_in; ++i)
@@ -1239,17 +1430,18 @@
 			if (serial->interrupt_in_buffer[i])
 				kfree (serial->interrupt_in_buffer[i]);
 
-		serial->present = 0;
-		serial->active = 0;
+		for (i = 0; i < serial->num_ports; ++i) {
+			info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->minor + i);
+		}
 
-		info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->number);
+		serial_table[serial->minor] = NULL;
+		kfree (serial);
 
 	} else {
 		info("device disconnected");
 	}
 	
 	MOD_DEC_USE_COUNT;
-
 }
 
 
@@ -1257,9 +1449,9 @@
 	magic:			TTY_DRIVER_MAGIC,
 	driver_name:		"usb",
 	name:			"ttyUSB",
-	major:			SERIAL_MAJOR,
+	major:			SERIAL_TTY_MAJOR,
 	minor_start:		0,
-	num:			NUM_PORTS,
+	num:			SERIAL_TTY_MINORS,
 	type:			TTY_DRIVER_TYPE_SERIAL,
 	subtype:		SERIAL_TYPE_NORMAL,
 	flags:			TTY_DRIVER_REAL_RAW,
@@ -1273,7 +1465,7 @@
 	open:			serial_open,
 	close:			serial_close,
 	write:			serial_write,
-	put_char:		serial_put_char,
+	put_char:		NULL,
 	flush_chars:		NULL,
 	write_room:		serial_write_room,
 	ioctl:			NULL,
@@ -1298,8 +1490,8 @@
 	int i;
 
 	/* Initalize our global data */
-	for (i = 0; i < NUM_PORTS; ++i) {
-		memset(&serial_state_table[i], 0x00, sizeof(struct usb_serial_state));
+	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+		serial_table[i] = NULL;
 	}
 
 	/* register the tty driver */
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.39/linux/drivers/usb/usb.c	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/usb.c	Thu Jan 20 15:00:16 2000
@@ -264,8 +264,6 @@
 	} else
 		warn("too many buses");
 
-	proc_usb_add_bus(bus);
-
 	/* Add it to the list of buses */
 	list_add(&bus->bus_list, &usb_bus_list);
 
@@ -285,8 +283,6 @@
 	 */
 	list_del(&bus->bus_list);
 
-	proc_usb_remove_bus(bus);
-
         usbdevfs_remove_bus(bus);
 
 	clear_bit(bus->busnum, busmap.busmap);
@@ -566,9 +562,10 @@
 		return status;
 	}
 
-	if (urb->status == -EINPROGRESS)
-		status=schedule_timeout(timeout); // ZZzzzz....
-	else
+	if (urb->status == -EINPROGRESS) {
+		while (timeout && urb->status == -EINPROGRESS)
+			status = timeout = schedule_timeout(timeout);
+	} else
 		status = 1;
 
 	remove_wait_queue(&wqh, &wait);
@@ -653,8 +650,6 @@
 void *usb_request_bulk(struct usb_device *dev, unsigned int pipe, usb_device_irq handler, void *data, int len, void *dev_id)
 {
 	urb_t *urb;
-	DECLARE_WAITQUEUE(wait, current);
-	DECLARE_WAIT_QUEUE_HEAD(wqh);
 	api_wrapper_data *awd;
 
 	if (!(urb=usb_alloc_urb(0)))
@@ -1231,7 +1226,6 @@
 	}
 
 	/* remove /proc/bus/usb entry */
-	proc_usb_remove_device(dev);
         usbdevfs_remove_device(dev);
 
 	/* Free up the device itself, including its device number */
@@ -1293,7 +1287,7 @@
 		unsigned char id, unsigned char index, void *buf, int size)
 {
 	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_DESCRIPTOR, USB_RT_INTERFACE | USB_DIR_IN,
+		USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
 		(type << 8) + id, index, buf, size, HZ * GET_TIMEOUT);
 }
 
@@ -1329,7 +1323,7 @@
 	int ret;
 
 	if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-	    USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_RT_HIDD,
+	    USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 	    0, 1, &type, 1, HZ * GET_TIMEOUT)) < 0)
 		return ret;
 
@@ -1339,13 +1333,15 @@
 int usb_set_protocol(struct usb_device *dev, int protocol)
 {
 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_SET_PROTOCOL, USB_RT_HIDD, protocol, 1, NULL, 0, HZ * SET_TIMEOUT);
+		USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		protocol, 1, NULL, 0, HZ * SET_TIMEOUT);
 }
 
 int usb_set_idle(struct usb_device *dev,  int duration, int report_id)
 {
-	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_IDLE,
-		USB_RT_HIDD, (duration << 8) | report_id, 1, NULL, 0, HZ * SET_TIMEOUT);
+	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+		USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		(duration << 8) | report_id, 1, NULL, 0, HZ * SET_TIMEOUT);
 }
 
 static void usb_set_maxpacket(struct usb_device *dev)
@@ -1388,14 +1384,14 @@
 */
 
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RT_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT);
+		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT);
 
 	/* don't clear if failed */
 	if (result < 0)
 		return result;
 
 	result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_ENDPOINT, 0, endp,
+		USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
 		&status, sizeof(status), HZ * SET_TIMEOUT);
 	if (result < 0)
 		return result;
@@ -1429,7 +1425,7 @@
 	}
 
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-	    USB_REQ_SET_INTERFACE, USB_RT_INTERFACE, alternate,
+	    USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
 	    interface, NULL, 0, HZ * 5)) < 0)
 		return ret;
 
@@ -1469,14 +1465,14 @@
 int usb_get_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size)
 {
 	return usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-		USB_REQ_GET_REPORT, USB_DIR_IN | USB_RT_HIDD,
+		USB_REQ_GET_REPORT, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 		(type << 8) + id, index, buf, size, HZ * GET_TIMEOUT);
 }
 
 int usb_set_report(struct usb_device *dev, unsigned char type, unsigned char id, unsigned char index, void *buf, int size)
 {
 	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		USB_REQ_SET_REPORT, USB_RT_HIDD,
+		USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 		(type << 8) + id, index, buf, size, HZ);
 }
 
@@ -1693,7 +1689,6 @@
 	usb_show_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
 
 	/* now that the basic setup is over, add a /proc/bus/usb entry */
-	proc_usb_add_device(dev);
         usbdevfs_add_device(dev);
 
 	/* find drivers willing to handle this device */
@@ -1785,6 +1780,7 @@
 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);
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.3.39/linux/drivers/usb/usb.h	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/usb.h	Thu Jan 20 15:00:16 2000
@@ -21,6 +21,28 @@
 #define USB_CLASS_VENDOR_SPEC		0xff
 
 /*
+ * USB types
+ */
+#define USB_TYPE_STANDARD		(0x00 << 5)
+#define USB_TYPE_CLASS			(0x01 << 5)
+#define USB_TYPE_VENDOR			(0x02 << 5)
+#define USB_TYPE_RESERVED		(0x03 << 5)
+
+/*
+ * USB recipients
+ */
+#define USB_RECIP_DEVICE		0x00
+#define USB_RECIP_INTERFACE		0x01
+#define USB_RECIP_ENDPOINT		0x02
+#define USB_RECIP_OTHER			0x03
+
+/*
+ * USB directions
+ */
+#define USB_DIR_OUT			0
+#define USB_DIR_IN			0x80
+
+/*
  * Descriptor types
  */
 #define USB_DT_DEVICE			0x01
@@ -29,10 +51,10 @@
 #define USB_DT_INTERFACE		0x04
 #define USB_DT_ENDPOINT			0x05
 
-#define USB_DT_HUB			0x29
-#define USB_DT_HID			0x21
-#define USB_DT_REPORT			0x22
-#define USB_DT_PHYSICAL			0x23
+#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
@@ -46,11 +68,8 @@
 #define USB_DT_HID_SIZE			9
 
 /*
- * USB Request Type and Endpoint Directions
+ * Endpoints
  */
-#define USB_DIR_OUT			0
-#define USB_DIR_IN			0x80
-
 #define USB_ENDPOINT_NUMBER_MASK	0x0f	/* in bEndpointAddress */
 #define USB_ENDPOINT_DIR_MASK		0x80
 
@@ -72,9 +91,7 @@
  */
 #define USB_REQ_GET_STATUS		0x00
 #define USB_REQ_CLEAR_FEATURE		0x01
-/* 0x02 is reserved */
 #define USB_REQ_SET_FEATURE		0x03
-/* 0x04 is reserved */
 #define USB_REQ_SET_ADDRESS		0x05
 #define USB_REQ_GET_DESCRIPTOR		0x06
 #define USB_REQ_SET_DESCRIPTOR		0x07
@@ -85,7 +102,7 @@
 #define USB_REQ_SYNCH_FRAME		0x0C
 
 /*
- * HIDD requests
+ * HID requests
  */
 #define USB_REQ_GET_REPORT		0x01
 #define USB_REQ_GET_IDLE		0x02
@@ -94,79 +111,6 @@
 #define USB_REQ_SET_IDLE		0x0A
 #define USB_REQ_SET_PROTOCOL		0x0B
 
-#define USB_TYPE_STANDARD		(0x00 << 5)
-#define USB_TYPE_CLASS			(0x01 << 5)
-#define USB_TYPE_VENDOR			(0x02 << 5)
-#define USB_TYPE_RESERVED		(0x03 << 5)
-
-#define USB_RECIP_DEVICE		0x00
-#define USB_RECIP_INTERFACE		0x01
-#define USB_RECIP_ENDPOINT		0x02
-#define USB_RECIP_OTHER			0x03
-
-#define USB_HID_RPT_INPUT		0x01
-#define USB_HID_RPT_OUTPUT		0x02
-#define USB_HID_RPT_FEATURE		0x03
-
-/*
- * Request target types.
- */
-#define USB_RT_DEVICE			0x00
-#define USB_RT_INTERFACE		0x01
-#define USB_RT_ENDPOINT			0x02
-
-#define USB_RT_HUB			(USB_TYPE_CLASS | USB_RECIP_DEVICE)
-#define USB_RT_PORT			(USB_TYPE_CLASS | USB_RECIP_OTHER)
-
-#define USB_RT_HIDD			(USB_TYPE_CLASS | USB_RECIP_INTERFACE)
-
-/* /proc/bus/usb/xxx/yyy ioctl codes */
-
-struct usb_proc_ctrltransfer {
-	__u8 requesttype;
-	__u8 request;
-	__u16 value;
-	__u16 index;
-	__u16 length;
-	__u32 timeout;  /* in milliseconds */
- 	void *data;
-};
-
-struct usb_proc_bulktransfer {
-	unsigned int ep;
-	unsigned int len;
-	unsigned int timeout; /* in milliseconds */
-	void *data;
-};
-
-struct usb_proc_old_ctrltransfer {
-	__u8 requesttype;
-	__u8 request;
-	__u16 value;
-	__u16 index;
-	__u16 length;
-	/* pointer to data */
-	void *data;
-};
-
-struct usb_proc_old_bulktransfer {
-	unsigned int ep;
-	unsigned int len;
-	void *data;
-};
-
-struct usb_proc_setinterface {
-	unsigned int interface;
-	unsigned int altsetting;
-};
-
-#define USB_PROC_CONTROL           _IOWR('U', 0, struct usb_proc_ctrltransfer)
-#define USB_PROC_BULK              _IOWR('U', 2, struct usb_proc_bulktransfer)
-#define USB_PROC_OLD_CONTROL       _IOWR('U', 0, struct usb_proc_old_ctrltransfer)
-#define USB_PROC_OLD_BULK          _IOWR('U', 2, struct usb_proc_old_bulktransfer)
-#define USB_PROC_RESETEP           _IOR('U', 3, unsigned int)
-#define USB_PROC_SETINTERFACE      _IOR('U', 4, struct usb_proc_setinterface)
-#define USB_PROC_SETCONFIGURATION  _IOR('U', 5, unsigned int)
 
 #ifdef __KERNEL__
 
@@ -227,9 +171,10 @@
 	__u16 length;
 } devrequest __attribute__ ((packed));
 
-/* USB-status codes:
+/*
+ * 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)
@@ -318,22 +263,6 @@
 	int extralen;
 } __attribute__ ((packed));
 
-/* HID descriptor */
-struct usb_hid_class_descriptor {
-	__u8  bDescriptorType;
-	__u16 wDescriptorLength;
-} __attribute__ ((packed));
-
-struct usb_hid_descriptor {
-	__u8  bLength;
-	__u8  bDescriptorType;
-	__u16 bcdHID;
-	__u8  bCountryCode;
-	__u8  bNumDescriptors;
-
-	struct usb_hid_class_descriptor desc[1];
-} __attribute__ ((packed));
-
 /* Interface descriptor */
 struct usb_interface_descriptor {
 	__u8  bLength;
@@ -548,9 +477,7 @@
 	int bandwidth_int_reqs;		/* number of Interrupt requesters */
 	int bandwidth_isoc_reqs;	/* number of Isoc. requesters */
 
-	/* procfs entry */
-	struct proc_dir_entry *proc_entry;
-        /* usbdevfs inode list */
+	/* usbdevfs inode list */
         struct list_head inodes;
 };
 
@@ -580,8 +507,6 @@
   
 	void *hcpriv;			/* Host Controller private data */
 	
-	/* procfs entry */
-	struct proc_dir_entry *proc_entry;
         /* usbdevfs inode list */
         struct list_head inodes;
         struct list_head filelist;
@@ -782,19 +707,18 @@
 void usb_show_device_descriptor(struct usb_device_descriptor *);
 void usb_show_config_descriptor(struct usb_config_descriptor *);
 void usb_show_interface_descriptor(struct usb_interface_descriptor *);
-void usb_show_hid_descriptor(struct usb_hid_descriptor * desc);
 void usb_show_endpoint_descriptor(struct usb_endpoint_descriptor *);
 void usb_show_device(struct usb_device *);
 void usb_show_string(struct usb_device *dev, char *id, int index);
 
 #ifdef DEBUG
-#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n", ## arg)
+#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
 #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)
+#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)
 
 
 /*
@@ -803,22 +727,6 @@
 
 extern struct list_head usb_driver_list;
 extern struct list_head usb_bus_list;
-
-/*
- * procfs stuff
- */
-
-#ifdef CONFIG_USB_PROC
-void proc_usb_add_bus(struct usb_bus *bus);
-void proc_usb_remove_bus(struct usb_bus *bus);
-void proc_usb_add_device(struct usb_device *dev);
-void proc_usb_remove_device(struct usb_device *dev);
-#else
-extern inline void proc_usb_add_bus(struct usb_bus *bus) {}
-extern inline void proc_usb_remove_bus(struct usb_bus *bus) {}
-extern inline void proc_usb_add_device(struct usb_device *dev) {}
-extern inline void proc_usb_remove_device(struct usb_device *dev) {}
-#endif
 
 /*
  * USB device fs stuff
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/usb_scsi.c linux/drivers/usb/usb_scsi.c
--- v2.3.39/linux/drivers/usb/usb_scsi.c	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/usb_scsi.c	Mon Jan 17 16:24:48 2000
@@ -288,7 +288,7 @@
 	cmd[0] = SEND_DIAGNOSTIC;
 	cmd[1] = 4;
 	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-				 US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+				 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 				 0, us->ifnum, cmd, sizeof(cmd), HZ*5);
 
 	/* long wait for reset */
@@ -346,7 +346,7 @@
 			} /* switch */
 
 			result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-						 US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+						 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 						 0, us->ifnum,
 						 cmd, us->fixedlength, HZ*5);
 			US_DEBUGP("First usb_control_msg returns %d\n", result);
@@ -367,7 +367,7 @@
 
 				result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
 							 US_CBI_ADSC, 
-							 USB_TYPE_CLASS | USB_RT_INTERFACE,
+							 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 							 0, us->ifnum,
 							 cmd, us->fixedlength, HZ*5);
 				US_DEBUGP("Next usb_control_msg returns %d\n", result);
@@ -378,7 +378,7 @@
 			}
 		} else { /* !US_FL_FIXED_COMMAND */
 			result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-						 US_CBI_ADSC, USB_TYPE_CLASS | USB_RT_INTERFACE,
+						 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 						 0, us->ifnum,
 						 srb->cmnd, srb->cmd_len, HZ*5);
 		}
@@ -411,7 +411,7 @@
 		while (retry--) {
 			result = usb_control_msg(us->pusb_dev, usb_rcvctrlpipe(us->pusb_dev,0),
 						 USB_REQ_GET_STATUS, USB_DIR_IN |
-						 USB_TYPE_STANDARD | USB_RT_DEVICE,
+						 USB_TYPE_STANDARD | USB_RECIP_DEVICE,
 						 0, us->ifnum, status, sizeof(status), HZ*5);
 			if (result != USB_ST_TIMEOUT)
 				break;
@@ -517,7 +517,7 @@
 	int result;
 
 	result = usb_control_msg(us->pusb_dev, usb_sndctrlpipe(us->pusb_dev,0),
-				 US_BULK_RESET, USB_TYPE_CLASS | USB_RT_INTERFACE,
+				 US_BULK_RESET, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 				 US_BULK_RESET_HARD, us->ifnum,
 				 NULL, 0, HZ*5);
 	if (result)
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/usbdevice_fs.h linux/drivers/usb/usbdevice_fs.h
--- v2.3.39/linux/drivers/usb/usbdevice_fs.h	Tue Jan 11 22:31:42 2000
+++ linux/drivers/usb/usbdevice_fs.h	Thu Jan 20 15:00:16 2000
@@ -23,7 +23,7 @@
  *  History:
  *   0.1  04.01.2000  Created
  *
- *  $Id: ezusb.c,v 1.22 1999/12/03 15:06:28 tom Exp $
+ *  $Id: usbdevice_fs.h,v 1.1 2000/01/06 18:40:41 tom Exp $
  */
 
 /*****************************************************************************/
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- v2.3.39/linux/drivers/usb/usbkbd.c	Fri Jan  7 19:13:22 2000
+++ linux/drivers/usb/usbkbd.c	Thu Jan 20 09:48:48 2000
@@ -99,19 +99,28 @@
 
 	if (type != EV_LED) return -1;
 
+	if (kbd->led.status == -EINPROGRESS) {
+		warn("had to kill led urb");
+		usb_unlink_urb(&kbd->led);
+	}
+
 	kbd->leds = (!!test_bit(LED_KANA,    dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
 		    (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL,   dev->led) << 1) |
 		    (!!test_bit(LED_NUML,    dev->led));
-		
-	usb_submit_urb(&kbd->led);
 
-	return -1;
+
+	if (usb_submit_urb(&kbd->led)) {
+		err("usb_submit_urb(leds) failed");
+		return -1;
+	}
+
+	return 0;
 }
 
 static void usb_kbd_led(struct urb *urb)
 {
 	if (urb->status)
-		printk(KERN_DEBUG "nonzero control status received: %d\n", urb->status);
+		warn("led urb status %d received", urb->status);
 }
 
 static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
@@ -148,12 +157,6 @@
 	kbd->dev.private = kbd;
 	kbd->dev.event = usb_kbd_event;
 
-	kbd->dr.requesttype = USB_RT_HIDD;
-	kbd->dr.request = USB_REQ_SET_REPORT;
-	kbd->dr.value = 0x200;
-	kbd->dr.index = 1;
-	kbd->dr.length = 1;
-
 	{
 		int pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
 		int maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
@@ -162,7 +165,13 @@
 			usb_kbd_irq, kbd, endpoint->bInterval);
 	}
 
-	FILL_CONTROL_URB(&kbd->led, dev, usb_sndctrlpipe(dev, endpoint->bEndpointAddress),
+	kbd->dr.requesttype = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+	kbd->dr.request = USB_REQ_SET_REPORT;
+	kbd->dr.value = 0x200;
+	kbd->dr.index = interface->bInterfaceNumber;
+	kbd->dr.length = 1;
+
+	FILL_CONTROL_URB(&kbd->led, dev, usb_sndctrlpipe(dev, 0),
 		(void*) &kbd->dr, &kbd->leds, 1, usb_kbd_led, kbd);
 			
 	if (usb_submit_urb(&kbd->irq)) {
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/whiteheat.h linux/drivers/usb/whiteheat.h
--- v2.3.39/linux/drivers/usb/whiteheat.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/whiteheat.h	Mon Jan 17 16:24:48 2000
@@ -0,0 +1,1542 @@
+/*****************************************************************************
+ *
+ *      whiteheat.h  --  ConnectTech WhiteHEAT Firmware.
+ *
+ *      Copyright (C) 2000  ConnectTech Inc (http://www.connecttech.com/)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      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.
+ *
+ * (01/16/2000) gkh
+ *	Fixed my intel hex processing tool, so now the firmware actually
+ *	matches the original file (this was causing a few problems...)
+ *
+ * (01/15/2000) gkh
+ *	Added debug loader firmware if DEBUG is #defined:
+ *		Port 1 LED flashes when the vend_ax program is running
+ *		Port 2 LED flashes when any SETUP command arrives
+ *		Port 3 LED flashes when any valid VENDOR request occurs
+ *		Port 4 LED flashes when the EXTERNAL RAM DOWNLOAD request occurs
+ *
+ * version 1.0 (01/09/2000) gkh
+ *	Original firmware from ConnectTech massaged a little to be program
+ *	readable.
+ *
+ *****************************************************************************/
+
+#define whiteheat_DATE "20000106"
+
+struct whiteheat_hex_record {
+	__u16	address;
+	__u8	data_size;
+	__u8	data[16];
+};
+
+static const struct whiteheat_hex_record whiteheat_firmware[] = {
+{ 0x0000,	3,	{0x02, 0x91, 0xc9} },
+{ 0x0003,	3,	{0x02, 0x13, 0x12} },
+{ 0x000b,	3,	{0x02, 0x0a, 0x8d} },
+{ 0x0033,	3,	{0x02, 0x07, 0x84} },
+{ 0x0043,	3,	{0x02, 0x09, 0x00} },
+{ 0x0053,	3,	{0x02, 0x0f, 0x6e} },
+{ 0x005b,	3,	{0x02, 0x11, 0xb9} },
+{ 0x0300,	16,	{0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x03, 0x14, 0x70, 0x03, 0x02, 0x04, 0x77, 0x24} },
+{ 0x0310,	16,	{0xfe, 0x70, 0x03, 0x02, 0x04, 0xca, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x03, 0xf4, 0x14, 0x70, 0x03} },
+{ 0x0320,	16,	{0x02, 0x03, 0xe2, 0x14, 0x70, 0x03, 0x02, 0x03, 0xca, 0x14, 0x70, 0x03, 0x02, 0x03, 0xd9, 0x24} },
+{ 0x0330,	16,	{0x05, 0x60, 0x03, 0x02, 0x05, 0x19, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60} },
+{ 0x0340,	16,	{0x36, 0x24, 0x02, 0x70, 0x7b, 0x74, 0x12, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5} },
+{ 0x0350,	16,	{0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x09, 0x58, 0xea, 0x49, 0x60, 0x0d} },
+{ 0x0360,	16,	{0xea, 0x90, 0x7f, 0xd4, 0xf0, 0xe9, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4} },
+{ 0x0370,	16,	{0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x08, 0xa9, 0xea} },
+{ 0x0380,	16,	{0x49, 0x60, 0x33, 0x12, 0x9a, 0x48, 0xf5, 0x5e, 0x90, 0x7f, 0xee, 0xe0, 0xff, 0xe5, 0x5e, 0xd3} },
+{ 0x0390,	16,	{0x9f, 0x40, 0x03, 0xe0, 0xf5, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x40, 0x40, 0x03, 0x75, 0x5e, 0x40} },
+{ 0x03a0,	16,	{0xae, 0x02, 0xaf, 0x01, 0x7c, 0x7f, 0x7d, 0x00, 0xab, 0x5e, 0x12, 0x1b, 0x0c, 0x90, 0x7f, 0xb5} },
+{ 0x03b0,	16,	{0xe5, 0x5e, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20} },
+{ 0x03c0,	16,	{0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0x00, 0xe5, 0x21, 0xf0} },
+{ 0x03d0,	16,	{0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x21, 0x02} },
+{ 0x03e0,	16,	{0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x31, 0xd2, 0x02, 0x43, 0x88, 0x10, 0xd2, 0xeb, 0xd2} },
+{ 0x03f0,	16,	{0xa8, 0x02, 0x05, 0x20, 0x90, 0x7f, 0x00, 0xe5, 0x31, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0} },
+{ 0x0400,	16,	{0x02, 0x05, 0x20, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02} },
+{ 0x0410,	16,	{0x70, 0x5b, 0xa2, 0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x05, 0xe4, 0x33, 0x4f, 0x90} },
+{ 0x0420,	16,	{0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0xe4} },
+{ 0x0430,	16,	{0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0x90} },
+{ 0x0440,	16,	{0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25} },
+{ 0x0450,	16,	{0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0x01, 0x90, 0x7f, 0x00} },
+{ 0x0460,	16,	{0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xb4} },
+{ 0x0470,	16,	{0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24} },
+{ 0x0480,	16,	{0x02, 0x60, 0x03, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02} },
+{ 0x0490,	16,	{0x05, 0x20, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0x20, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x04a0,	16,	{0x70, 0x1f, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54} },
+{ 0x04b0,	16,	{0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x80} },
+{ 0x04c0,	16,	{0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x56, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe} },
+{ 0x04d0,	16,	{0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04, 0xd2, 0x00, 0x80} },
+{ 0x04e0,	16,	{0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x36, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x20} },
+{ 0x04f0,	16,	{0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f} },
+{ 0x0500,	16,	{0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x10} },
+{ 0x0510,	16,	{0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0520,	7,	{0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} },
+{ 0x0527,	1,	{0x22} },
+{ 0x0528,	16,	{0x75, 0x5a, 0xff, 0x75, 0x59, 0xff, 0x75, 0x58, 0x0f, 0x75, 0x57, 0x00, 0xd2, 0x03, 0xc2, 0x06} },
+{ 0x0538,	16,	{0xc2, 0x02, 0xc2, 0x00, 0xc2, 0x05, 0xc2, 0x01, 0x90, 0x02, 0x9e, 0x74, 0x19, 0xf0, 0xe4, 0x90} },
+{ 0x0548,	16,	{0x01, 0x5b, 0xf0, 0xc2, 0x04, 0x90, 0x01, 0x5e, 0xf0, 0xa3, 0xf0, 0xc2, 0xaf, 0xc2, 0xa8, 0x12} },
+{ 0x0558,	16,	{0x0a, 0xfa, 0xe4, 0x90, 0x02, 0x4d, 0xf0, 0x90, 0x01, 0x00, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x0568,	16,	{0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0x7e} },
+{ 0x0578,	16,	{0x01, 0x7f, 0x00, 0x12, 0x19, 0xc1, 0x75, 0x5c, 0x12, 0x75, 0x5d, 0x0a, 0x90, 0x01, 0x0b, 0xe0} },
+{ 0x0588,	16,	{0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83} },
+{ 0x0598,	16,	{0xef, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x80, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70} },
+{ 0x05a8,	16,	{0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0d, 0xe0, 0xff, 0x05} },
+{ 0x05b8,	16,	{0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
+{ 0x05c8,	16,	{0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14} },
+{ 0x05d8,	16,	{0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x12, 0x0a, 0xe4, 0x93, 0xff, 0x74, 0x01, 0x93, 0x90} },
+{ 0x05e8,	16,	{0x01, 0x1c, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0xff, 0xa3, 0xe0, 0xfe, 0xef} },
+{ 0x05f8,	16,	{0x6e, 0xff, 0x90, 0x01, 0x1c, 0xf0, 0xa3, 0xe0, 0x6f, 0xff, 0xf0, 0x90, 0x01, 0x1c, 0xe0, 0x6f} },
+{ 0x0608,	16,	{0xf0, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xe4, 0xfc, 0xfd, 0x75, 0x62, 0x10, 0x75, 0x63, 0x02, 0x75} },
+{ 0x0618,	16,	{0x64, 0x12, 0x75, 0x65, 0xac, 0x12, 0x8e, 0x35, 0x75, 0x5c, 0x12, 0x75, 0x5d, 0xb2, 0x90, 0x01} },
+{ 0x0628,	16,	{0x0d, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82} },
+{ 0x0638,	16,	{0x8c, 0x83, 0xef, 0xf0, 0x90, 0x01, 0x0e, 0xe0, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70} },
+{ 0x0648,	16,	{0x02, 0x05, 0x5c, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4} },
+{ 0x0658,	16,	{0x54, 0x0f, 0x24, 0x41, 0xff, 0x05, 0x5d, 0xe5, 0x5d, 0xac, 0x5c, 0x70, 0x02, 0x05, 0x5c, 0x14} },
+{ 0x0668,	16,	{0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x05, 0x5d, 0xe5, 0x5d, 0xae, 0x5c, 0x70, 0x02, 0x05, 0x5c} },
+{ 0x0678,	16,	{0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x75, 0x82, 0x10, 0x75, 0x83, 0x01, 0xe0, 0xfc, 0xa3} },
+{ 0x0688,	16,	{0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x90, 0x01, 0x18, 0x12, 0x9b, 0xfb, 0x7e, 0x01} },
+{ 0x0698,	16,	{0x7f, 0x18, 0x12, 0x84, 0x61, 0x90, 0x01, 0x18, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} },
+{ 0x06a8,	16,	{0xa3, 0xe0, 0xff, 0x75, 0x62, 0x0a, 0x75, 0x63, 0x06, 0x75, 0x64, 0x12, 0x75, 0x65, 0xb8, 0x12} },
+{ 0x06b8,	16,	{0x8e, 0x35, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x53, 0x91, 0xef} },
+{ 0x06c8,	16,	{0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0, 0x44, 0x1f, 0xf0, 0xd2, 0xaf} },
+{ 0x06d8,	16,	{0x20, 0x01, 0x2e, 0x20, 0x01, 0x2b, 0xa2, 0x03, 0x92, 0x07, 0x12, 0x09, 0xa7, 0x75, 0x56, 0x50} },
+{ 0x06e8,	16,	{0x75, 0x55, 0x6d, 0x75, 0x54, 0x33, 0x75, 0x53, 0x00, 0x20, 0x01, 0xe4, 0x7f, 0xff, 0x7e, 0xff} },
+{ 0x06f8,	16,	{0x7d, 0xff, 0x7c, 0xff, 0x78, 0x53, 0x12, 0x9b, 0xe4, 0xec, 0x4d, 0x4e, 0x4f, 0x60, 0xd1, 0x80} },
+{ 0x0708,	16,	{0xe8, 0x30, 0x01, 0x05, 0x12, 0x03, 0x00, 0xc2, 0x01, 0x30, 0x06, 0x0d, 0x12, 0x08, 0xfb, 0x50} },
+{ 0x0718,	16,	{0x06, 0x12, 0x0a, 0x00, 0x12, 0x09, 0xf4, 0xc2, 0x06, 0x12, 0x90, 0x58, 0x12, 0x98, 0x7d, 0xe4} },
+{ 0x0728,	16,	{0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x90, 0x01, 0x5b} },
+{ 0x0738,	16,	{0xe0, 0x5e, 0x60, 0x14, 0x74, 0x27, 0x2f, 0xf8, 0xe6, 0xd3, 0x94, 0x0a, 0x40, 0x04, 0x7e, 0x01} },
+{ 0x0748,	16,	{0x80, 0x02, 0x7e, 0x00, 0x8e, 0x5b, 0x80, 0x03, 0x75, 0x5b, 0x01, 0x74, 0x68, 0x2f, 0xf5, 0x82} },
+{ 0x0758,	16,	{0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe5, 0x5b, 0xf0, 0x0f, 0xbf, 0x04, 0xc5, 0xe5, 0x2b, 0xd3, 0x94} },
+{ 0x0768,	16,	{0x0a, 0x40, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x20, 0x6c, 0xef, 0xf0, 0x90, 0x02} },
+{ 0x0778,	11,	{0x4d, 0xe0, 0x64, 0x0f, 0x70, 0x8b, 0x12, 0x93, 0x50, 0x80, 0x86} },
+{ 0x0783,	1,	{0x22} },
+{ 0x0784,	4,	{0x53, 0xd8, 0xef, 0x32} },
+{ 0x0788,	16,	{0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0x74, 0x89} },
+{ 0x0798,	16,	{0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x08, 0x92, 0x90, 0x7f} },
+{ 0x07a8,	16,	{0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x02, 0x7d, 0xff} },
+{ 0x07b8,	16,	{0x12, 0x11, 0x4b, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02} },
+{ 0x07c8,	16,	{0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0} },
+{ 0x07d8,	16,	{0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf} },
+{ 0x07e8,	16,	{0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f} },
+{ 0x07f8,	7,	{0x32, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x22} },
+{ 0x07ff,	16,	{0x90, 0x7f, 0x96, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x80, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12} },
+{ 0x080f,	16,	{0x08, 0x92, 0x7f, 0x02, 0xe4, 0xfd, 0x12, 0x11, 0x4b, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92} },
+{ 0x081f,	16,	{0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f} },
+{ 0x082f,	16,	{0x96, 0xe0, 0x44, 0x04, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0} },
+{ 0x083f,	16,	{0x54, 0xf7, 0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x01} },
+{ 0x084f,	12,	{0xf0, 0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x12, 0x0a, 0x00, 0x22} },
+{ 0x085b,	16,	{0x90, 0x11, 0xef, 0xe4, 0x93, 0x70, 0x2f, 0x90, 0x7f, 0x93, 0x74, 0x30, 0xf0, 0x90, 0x7f, 0x94} },
+{ 0x086b,	16,	{0x74, 0x3c, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0xc6, 0xf0, 0xe4, 0x90, 0x7f, 0x97, 0xf0, 0x90, 0x7f} },
+{ 0x087b,	16,	{0x9d, 0x74, 0x02, 0xf0, 0x90, 0x7f, 0xe2, 0x74, 0x12, 0xf0, 0x12, 0x07, 0x88, 0x75, 0x82, 0xef} },
+{ 0x088b,	7,	{0x75, 0x83, 0x11, 0x74, 0xff, 0xf0, 0x22} },
+{ 0x0892,	16,	{0x8e, 0x6d, 0x8f, 0x6e, 0xe5, 0x6e, 0x15, 0x6e, 0xae, 0x6d, 0x70, 0x02, 0x15, 0x6d, 0x4e, 0x60} },
+{ 0x08a2,	7,	{0x05, 0x12, 0x08, 0xea, 0x80, 0xee, 0x22} },
+{ 0x08a9,	2,	{0x8f, 0x5f} },
+{ 0x08ab,	16,	{0xe4, 0xf5, 0x60, 0x75, 0x61, 0xff, 0x75, 0x62, 0x12, 0x75, 0x63, 0x6a, 0xab, 0x61, 0xaa, 0x62} },
+{ 0x08bb,	16,	{0xa9, 0x63, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0xb4, 0x03, 0x1d, 0xaf, 0x60, 0x05, 0x60, 0xef} },
+{ 0x08cb,	16,	{0xb5, 0x5f, 0x01, 0x22, 0x12, 0x9a, 0x48, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
+{ 0x08db,	14,	{0x61, 0xff, 0xf5, 0x62, 0x89, 0x63, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x08e9,	1,	{0x22} },
+{ 0x08ea,	16,	{0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
+{ 0x08fa,	1,	{0x22} },
+{ 0x08fb,	5,	{0x12, 0x07, 0xff, 0xd3, 0x22} },
+{ 0x0900,	16,	{0x02, 0x0b, 0x17, 0x00, 0x02, 0x0b, 0x4a, 0x00, 0x02, 0x0b, 0x2f, 0x00, 0x02, 0x0b, 0x89, 0x00} },
+{ 0x0910,	16,	{0x02, 0x0b, 0x73, 0x00, 0x02, 0x09, 0xf9, 0x00, 0x02, 0x09, 0xfa, 0x00, 0x02, 0x09, 0xfb, 0x00} },
+{ 0x0920,	16,	{0x02, 0x0b, 0xa4, 0x00, 0x02, 0x0c, 0x78, 0x00, 0x02, 0x0b, 0xd9, 0x00, 0x02, 0x0c, 0xc5, 0x00} },
+{ 0x0930,	16,	{0x02, 0x0c, 0x0e, 0x00, 0x02, 0x0d, 0x12, 0x00, 0x02, 0x0c, 0x43, 0x00, 0x02, 0x0d, 0x5f, 0x00} },
+{ 0x0940,	16,	{0x02, 0x09, 0xfc, 0x00, 0x02, 0x09, 0xfe, 0x00, 0x02, 0x09, 0xfd, 0x00, 0x02, 0x09, 0xff, 0x00} },
+{ 0x0950,	8,	{0x02, 0x0d, 0xac, 0x00, 0x02, 0x0d, 0xc2, 0x00} },
+{ 0x0958,	16,	{0xe4, 0xfe, 0x75, 0x61, 0xff, 0x75, 0x62, 0x12, 0x75, 0x63, 0x12, 0xab, 0x61, 0xaa, 0x62, 0xa9} },
+{ 0x0968,	16,	{0x63, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} },
+{ 0x0978,	16,	{0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x9a, 0xba, 0x85, 0xf0, 0x5f, 0xf5, 0x60, 0x62, 0x5f} },
+{ 0x0988,	16,	{0xe5, 0x5f, 0x62, 0x60, 0xe5, 0x60, 0x62, 0x5f, 0x29, 0xfd, 0xe5, 0x5f, 0x3a, 0xa9, 0x05, 0x75} },
+{ 0x0998,	14,	{0x61, 0xff, 0xf5, 0x62, 0x89, 0x63, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x09a6,	1,	{0x22} },
+{ 0x09a7,	16,	{0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x07, 0x04, 0xe0, 0x44} },
+{ 0x09b7,	16,	{0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x08, 0x92, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
+{ 0x09c7,	5,	{0xe0, 0x44, 0x04, 0xf0, 0x22} },
+{ 0x09cc,	16,	{0x53, 0x8e, 0xf7, 0xe5, 0x89, 0x54, 0xf1, 0x44, 0x01, 0xf5, 0x89, 0x75, 0x8c, 0xb1, 0xd2, 0xa9} },
+{ 0x09dc,	16,	{0x75, 0x98, 0x40, 0x75, 0xcb, 0xff, 0x75, 0xca, 0xf3, 0x75, 0xc8, 0x34, 0xe4, 0xff, 0x7f, 0x05} },
+{ 0x09ec,	7,	{0x78, 0x27, 0xe4, 0xf6, 0x08, 0xdf, 0xfc} },
+{ 0x09f3,	1,	{0x22} },
+{ 0x09f4,	5,	{0x12, 0x07, 0x88, 0xd3, 0x22} },
+{ 0x09f9,	1,	{0x32} },
+{ 0x09fa,	1,	{0x32} },
+{ 0x09fb,	1,	{0x32} },
+{ 0x09fc,	1,	{0x32} },
+{ 0x09fd,	1,	{0x32} },
+{ 0x09fe,	1,	{0x32} },
+{ 0x09ff,	1,	{0x32} },
+{ 0x0a00,	9,	{0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} },
+{ 0x0a7d,	16,	{0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} },
+{ 0x0a8d,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0, 0x06, 0xc0} },
+{ 0x0a9d,	1,	{0x07} },
+{ 0x0a9e,	16,	{0x30, 0x04, 0x16, 0x75, 0x8c, 0xf8, 0x75, 0x8a, 0x30, 0x7f, 0x2f, 0xae, 0x07, 0x1f, 0xee, 0x60} },
+{ 0x0aae,	16,	{0x3c, 0x90, 0x20, 0x00, 0x74, 0x55, 0xf0, 0x80, 0xf2, 0x75, 0x8c, 0xb1, 0x7f, 0x27, 0xef, 0xd3} },
+{ 0x0abe,	16,	{0x94, 0x2b, 0x50, 0x09, 0xa8, 0x07, 0xe6, 0x60, 0x01, 0x16, 0x0f, 0x80, 0xf1, 0x90, 0x02, 0x9e} },
+{ 0x0ace,	16,	{0xe0, 0x60, 0x02, 0x14, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x0e, 0x90} },
+{ 0x0ade,	13,	{0x01, 0x5f, 0xe0, 0x24, 0xff, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x34, 0xff, 0xf0} },
+{ 0x0aeb,	15,	{0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0afa,	16,	{0xd2, 0x00, 0x75, 0x8e, 0x10, 0xe4, 0x90, 0x7f, 0x92, 0xf0, 0x12, 0x0f, 0x72, 0x12, 0x08, 0x5b} },
+{ 0x0b0a,	13,	{0x12, 0x0e, 0x0f, 0x12, 0x8f, 0x06, 0x12, 0x11, 0x9c, 0x12, 0x09, 0xcc, 0x22} },
+{ 0x0b17,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} },
+{ 0x0b27,	8,	{0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0b2f,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0b3f,	11,	{0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0b4a,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0x90} },
+{ 0x0b5a,	16,	{0x7f, 0xd8, 0xe0, 0x70, 0x0d, 0x90, 0x7f, 0xd9, 0xe0, 0x70, 0x07, 0xe5, 0x2b, 0x70, 0x03, 0x75} },
+{ 0x0b6a,	9,	{0x2b, 0x14, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0b73,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} },
+{ 0x0b83,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0b89,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x30, 0x02, 0x02, 0xd2, 0x06, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0b99,	11,	{0xab, 0x74, 0x08, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0ba4,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x02, 0xf0, 0xe5} },
+{ 0x0bb4,	16,	{0x30, 0x30, 0xe0, 0x13, 0xe5, 0x3b, 0x30, 0xe0, 0x07, 0x90, 0x20, 0x04, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0bc4,	16,	{0x90, 0x20, 0x01, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} },
+{ 0x0bd4,	5,	{0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0bd9,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x04, 0xf0, 0xe5} },
+{ 0x0be9,	16,	{0x30, 0x30, 0xe1, 0x13, 0xe5, 0x3b, 0x30, 0xe1, 0x07, 0x90, 0x20, 0x0c, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0bf9,	16,	{0x90, 0x20, 0x09, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} },
+{ 0x0c09,	5,	{0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c0e,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x08, 0xf0, 0xe5} },
+{ 0x0c1e,	16,	{0x30, 0x30, 0xe2, 0x13, 0xe5, 0x3b, 0x30, 0xe2, 0x07, 0x90, 0x20, 0x14, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0c2e,	16,	{0x90, 0x20, 0x11, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} },
+{ 0x0c3e,	5,	{0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c43,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x10, 0xf0, 0xe5} },
+{ 0x0c53,	16,	{0x30, 0x30, 0xe3, 0x13, 0xe5, 0x3b, 0x30, 0xe3, 0x07, 0x90, 0x20, 0x1c, 0xe0, 0x44, 0x01, 0xf0} },
+{ 0x0c63,	16,	{0x90, 0x20, 0x19, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14, 0xd0, 0x82} },
+{ 0x0c73,	5,	{0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0c78,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} },
+{ 0x0c88,	16,	{0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x02, 0xf0, 0xe5, 0x30, 0x20, 0xe0, 0x06, 0x90, 0x7f, 0xc7} },
+{ 0x0c98,	16,	{0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe0, 0x0a, 0x90, 0x7f, 0xc7, 0xe0, 0x90, 0x02, 0x96, 0xf0} },
+{ 0x0ca8,	16,	{0x80, 0x07, 0x90, 0x20, 0x01, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} },
+{ 0x0cb8,	13,	{0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0cc5,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} },
+{ 0x0cd5,	16,	{0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x04, 0xf0, 0xe5, 0x30, 0x20, 0xe1, 0x06, 0x90, 0x7f, 0xc9} },
+{ 0x0ce5,	16,	{0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe1, 0x0a, 0x90, 0x7f, 0xc9, 0xe0, 0x90, 0x02, 0x97, 0xf0} },
+{ 0x0cf5,	16,	{0x80, 0x07, 0x90, 0x20, 0x09, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} },
+{ 0x0d05,	13,	{0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d12,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} },
+{ 0x0d22,	16,	{0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x08, 0xf0, 0xe5, 0x30, 0x20, 0xe2, 0x06, 0x90, 0x7f, 0xcb} },
+{ 0x0d32,	16,	{0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe2, 0x0a, 0x90, 0x7f, 0xcb, 0xe0, 0x90, 0x02, 0x98, 0xf0} },
+{ 0x0d42,	16,	{0x80, 0x07, 0x90, 0x20, 0x11, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} },
+{ 0x0d52,	13,	{0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d5f,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x53} },
+{ 0x0d6f,	16,	{0x91, 0xef, 0x90, 0x7f, 0xaa, 0x74, 0x10, 0xf0, 0xe5, 0x30, 0x20, 0xe3, 0x06, 0x90, 0x7f, 0xcd} },
+{ 0x0d7f,	16,	{0xf0, 0x80, 0x16, 0xe5, 0x3b, 0x30, 0xe3, 0x0a, 0x90, 0x7f, 0xcd, 0xe0, 0x90, 0x02, 0x99, 0xf0} },
+{ 0x0d8f,	16,	{0x80, 0x07, 0x90, 0x20, 0x19, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x2b, 0x70, 0x03, 0x75, 0x2b, 0x14} },
+{ 0x0d9f,	13,	{0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dac,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xa9, 0x74, 0x80, 0xf0, 0xd0} },
+{ 0x0dbc,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dc2,	16,	{0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, 0x00, 0xc0} },
+{ 0x0dd2,	16,	{0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x53, 0x91, 0xef} },
+{ 0x0de2,	16,	{0x90, 0x7f, 0xaa, 0x74, 0x80, 0xf0, 0x7e, 0x7b, 0x7f, 0x40, 0x12, 0x8c, 0xfb, 0x90, 0x7f, 0xd3} },
+{ 0x0df2,	16,	{0xe4, 0xf0, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01} },
+{ 0x0e02,	13,	{0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32} },
+{ 0x0e0f,	16,	{0x90, 0x01, 0x20, 0x12, 0x9c, 0x07, 0x00, 0x00, 0x25, 0x80, 0x90, 0x01, 0x24, 0x74, 0x08, 0xf0} },
+{ 0x0e1f,	16,	{0xa3, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x6e, 0xf0, 0xa3, 0xf0, 0xe4, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x0e2f,	16,	{0xf0, 0xa3, 0xf0, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50} },
+{ 0x0e3f,	16,	{0x13, 0xef, 0x04, 0xa3, 0xf0, 0x7e, 0x01, 0x7f, 0x1f, 0x12, 0x84, 0xf4, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0e4f,	16,	{0x04, 0xf0, 0x80, 0xe3, 0xe4, 0xf5, 0x26, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff} },
+{ 0x0e5f,	16,	{0xc3, 0x94, 0x04, 0x50, 0x1a, 0x74, 0x96, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4} },
+{ 0x0e6f,	16,	{0xf0, 0x74, 0x22, 0x2f, 0xf8, 0xe4, 0xf6, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xdc, 0xe4} },
+{ 0x0e7f,	16,	{0xf5, 0x30, 0xe5, 0xc0, 0x60, 0x2f, 0x90, 0x01, 0x1e, 0x74, 0x01, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0e8f,	16,	{0xff, 0xd3, 0x94, 0x04, 0x50, 0x1f, 0xef, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02} },
+{ 0x0e9f,	16,	{0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x30, 0x7e, 0x01, 0x7f, 0x1e, 0x12, 0x82, 0xea, 0x90, 0x01, 0x1e} },
+{ 0x0eaf,	16,	{0xe0, 0x04, 0xf0, 0x80, 0xd7, 0xe4, 0xf5, 0x3a, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0ebf,	16,	{0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54} },
+{ 0x0ecf,	16,	{0xf0, 0xfe, 0x74, 0x63, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xee, 0xf0, 0x74, 0x36} },
+{ 0x0edf,	16,	{0x2f, 0xf8, 0xa6, 0x06, 0x74, 0x32, 0x2f, 0xf8, 0xe4, 0xf6, 0x74, 0x2c, 0x2f, 0xf8, 0xe4, 0xf6} },
+{ 0x0eef,	16,	{0x74, 0x9a, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x01, 0x1e, 0xe0} },
+{ 0x0eff,	16,	{0x04, 0xf0, 0xe0, 0xb4, 0x04, 0xb6, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0x5e, 0x60, 0x5e} },
+{ 0x0f0f,	16,	{0xe4, 0x90, 0x01, 0x1e, 0xf0, 0x90, 0x01, 0x1e, 0xe0, 0xff, 0xc3, 0x94, 0x04, 0x50, 0xe7, 0x74} },
+{ 0x0f1f,	16,	{0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x55, 0x5e, 0x60, 0x38, 0x90, 0x01} },
+{ 0x0f2f,	1,	{0x1e} },
+{ 0x0f30,	16,	{0xe0, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0} },
+{ 0x0f40,	16,	{0xfe, 0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0} },
+{ 0x0f50,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0xfe} },
+{ 0x0f60,	14,	{0x7d, 0x06, 0x12, 0x82, 0x60, 0x90, 0x01, 0x1e, 0xe0, 0x04, 0xf0, 0x80, 0xa7, 0x22} },
+{ 0x0f6e,	4,	{0x53, 0x91, 0xbf, 0x32} },
+{ 0x0f72,	16,	{0x7b, 0xff, 0x7a, 0x12, 0x79, 0x1b, 0x90, 0x00, 0x04, 0x12, 0x9a, 0x61, 0xfd, 0x8b, 0x60, 0x75} },
+{ 0x0f82,	16,	{0x61, 0x12, 0x75, 0x62, 0x24, 0xe4, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x7f, 0xe0, 0xf0, 0xf5, 0x5e} },
+{ 0x0f92,	16,	{0xf5, 0x5f, 0x90, 0x02, 0x4c, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f} },
+{ 0x0fa2,	16,	{0xa9, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0xe4, 0xfc, 0xec, 0x25, 0xe0, 0x24, 0xb4, 0xf5} },
+{ 0x0fb2,	16,	{0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x0c, 0xbc, 0x10, 0xee, 0xe4, 0x90, 0x7f, 0xdd} },
+{ 0x0fc2,	16,	{0xf0, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03, 0x02, 0x11, 0x38, 0xab, 0x60, 0xaa, 0x61, 0xa9, 0x62} },
+{ 0x0fd2,	16,	{0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0x64, 0x05, 0x60, 0x03, 0x02, 0x11, 0x27, 0x90, 0x00, 0x03} },
+{ 0x0fe2,	16,	{0x12, 0x9a, 0x61, 0x64, 0x01, 0x60, 0x03, 0x02, 0x10, 0xae, 0x90, 0x00, 0x02, 0x12, 0x9a, 0x61} },
+{ 0x0ff2,	16,	{0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50, 0x03, 0x02, 0x10, 0x88, 0xec, 0xc3, 0x94, 0x10} },
+{ 0x1002,	16,	{0x40, 0x03, 0x02, 0x10, 0x88, 0xef, 0x30, 0xe7, 0x42, 0xe5, 0x5f, 0xae, 0x5e, 0x78, 0x02, 0xce} },
+{ 0x1012,	16,	{0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xf0, 0x2c, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5} },
+{ 0x1022,	16,	{0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe0, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01, 0xa8, 0x06} },
+{ 0x1032,	16,	{0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe0, 0xf0, 0x90, 0x02, 0x4c, 0xe0} },
+{ 0x1042,	16,	{0x04, 0xf0, 0x90, 0x7f, 0xdd, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x3e, 0xe5, 0x5f, 0xae, 0x5e, 0x78} },
+{ 0x1052,	16,	{0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0x74, 0xe8, 0x2c, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x1062,	16,	{0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0xe1, 0xe0, 0xff, 0xec, 0x24, 0xf8, 0xfe, 0x74, 0x01} },
+{ 0x1072,	16,	{0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x4f, 0x90, 0x7f, 0xe1, 0xf0, 0x90, 0x02} },
+{ 0x1082,	16,	{0x4c, 0xe0, 0x04, 0xf0, 0x80, 0x03, 0x7f, 0xff, 0x22, 0x90, 0x00, 0x04, 0x12, 0x9a, 0x61, 0x25} },
+{ 0x1092,	16,	{0x5f, 0xf5, 0x5f, 0xe4, 0x35, 0x5e, 0xf5, 0x5e, 0x90, 0x00, 0x05, 0x12, 0x9a, 0x61, 0xfe, 0xe4} },
+{ 0x10a2,	16,	{0x25, 0x5f, 0xf5, 0x5f, 0xee, 0x35, 0x5e, 0xf5, 0x5e, 0x02, 0x11, 0x2a, 0xab, 0x60, 0xaa, 0x61} },
+{ 0x10b2,	16,	{0xa9, 0x62, 0x90, 0x00, 0x03, 0x12, 0x9a, 0x61, 0xff, 0x64, 0x02, 0x60, 0x05, 0xef, 0x64, 0x03} },
+{ 0x10c2,	16,	{0x70, 0x60, 0x90, 0x00, 0x02, 0x12, 0x9a, 0x61, 0xff, 0x54, 0x7f, 0xfc, 0xd3, 0x94, 0x07, 0x50} },
+{ 0x10d2,	16,	{0x4e, 0xef, 0x30, 0xe7, 0x1e, 0x90, 0x7f, 0xde, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80} },
+{ 0x10e2,	16,	{0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xde, 0xf0, 0x90, 0x7f, 0xac, 0xe0, 0x4e} },
+{ 0x10f2,	16,	{0xf0, 0x80, 0x35, 0x90, 0x7f, 0xdf, 0xe0, 0xff, 0x74, 0x01, 0xa8, 0x04, 0x08, 0x80, 0x02, 0xc3} },
+{ 0x1102,	16,	{0x33, 0xd8, 0xfc, 0xfe, 0x4f, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xad, 0xe0, 0x4e, 0xf0, 0xec} },
+{ 0x1112,	16,	{0x25, 0xe0, 0x24, 0xc5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x09, 0x7f} },
+{ 0x1122,	16,	{0xff, 0x22, 0x7f, 0xff, 0x22, 0x7f, 0xff, 0x22, 0x74, 0x07, 0x25, 0x62, 0xf5, 0x62, 0xe4, 0x35} },
+{ 0x1132,	16,	{0x61, 0xf5, 0x61, 0x02, 0x0f, 0xc3, 0x20, 0x03, 0x0d, 0x90, 0x02, 0x4c, 0xe0, 0x60, 0x07, 0x90} },
+{ 0x1142,	8,	{0x7f, 0xae, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0x00} },
+{ 0x114a,	1,	{0x22} },
+{ 0x114b,	2,	{0xae, 0x07} },
+{ 0x114d,	16,	{0x7c, 0x02, 0xec, 0x14, 0x60, 0x15, 0x14, 0x70, 0x1e, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0} },
+{ 0x115d,	16,	{0xee, 0x25, 0xe0, 0x44, 0x40, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xa6, 0xed, 0xf0} },
+{ 0x116d,	16,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xfb, 0x30, 0xe0, 0xf8, 0xbc} },
+{ 0x117d,	16,	{0x02, 0x0a, 0x20, 0xe1, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22, 0xeb, 0x30, 0xe2, 0x0a} },
+{ 0x118d,	14,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06, 0x22, 0xdc, 0xb6, 0x7f, 0x08} },
+{ 0x119b,	1,	{0x22} },
+{ 0x119c,	16,	{0x7f, 0x05, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x02, 0x7d, 0xff, 0x12, 0x11, 0x4b, 0x7f, 0x05} },
+{ 0x11ac,	13,	{0x7e, 0x00, 0x12, 0x08, 0x92, 0x7f, 0x03, 0x7d, 0xff, 0x12, 0x11, 0x4b, 0x22} },
+{ 0x11b9,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc2, 0xa9, 0x90, 0x02, 0x9e, 0x74, 0x19, 0xf0, 0xd2, 0xa9} },
+{ 0x11c9,	15,	{0x53, 0x91, 0x7f, 0x90, 0x01, 0x62, 0xe4, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x11d8,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33} },
+{ 0x11e8,	7,	{0xd8, 0xfc, 0x42, 0x3a, 0x7f, 0x00, 0x22} },
+{ 0x11ef,	3,	{0x00, 0x02, 0x28} },
+{ 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} },
+{ 0x1230,	16,	{0x00, 0x00, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x00} },
+{ 0x1240,	16,	{0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} },
+{ 0x1250,	16,	{0x84, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x87, 0x02} },
+{ 0x1260,	16,	{0x40, 0x00, 0x00, 0x07, 0x05, 0x07, 0x02, 0x40, 0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x24, 0x03} },
+{ 0x1270,	16,	{0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x20, 0x00} },
+{ 0x1280,	16,	{0x54, 0x00, 0x65, 0x00, 0x63, 0x00, 0x68, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} },
+{ 0x1290,	16,	{0x2e, 0x00, 0x18, 0x03, 0x57, 0x00, 0x68, 0x00, 0x69, 0x00, 0x74, 0x00, 0x65, 0x00, 0x48, 0x00} },
+{ 0x12a0,	16,	{0x45, 0x00, 0x41, 0x00, 0x54, 0x00, 0x2d, 0x00, 0x34, 0x00, 0x1a, 0x03, 0x58, 0x00, 0x58, 0x00} },
+{ 0x12b0,	16,	{0x2d, 0x00, 0x58, 0x00, 0x58, 0x00, 0x2d, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00} },
+{ 0x12c0,	16,	{0x58, 0x00, 0x58, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} },
+{ 0x12d0,	16,	{0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} },
+{ 0x12e0,	16,	{0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} },
+{ 0x12f0,	16,	{0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} },
+{ 0x1300,	16,	{0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} },
+{ 0x1310,	2,	{0x00, 0x00} },
+{ 0x1312,	16,	{0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0xc0, 0xd0} },
+{ 0x1322,	16,	{0x75, 0x86, 0x00, 0x75, 0xd0, 0x18, 0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xf5, 0xf0, 0x70, 0x11} },
+{ 0x1332,	16,	{0xd0, 0xd0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0} },
+{ 0x1342,	16,	{0x32, 0x75, 0x86, 0x00, 0x10, 0xf0, 0x0b, 0x10, 0xf1, 0x12, 0x10, 0xf2, 0x19, 0x10, 0xf3, 0x20} },
+{ 0x1352,	16,	{0x80, 0xd4, 0xe5, 0x27, 0x70, 0x03, 0x75, 0x27, 0x14, 0x02, 0x13, 0x7c, 0xe5, 0x28, 0x70, 0x03} },
+{ 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} },
+{ 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} },
+{ 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} },
+{ 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} },
+{ 0x1442,	16,	{0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xef, 0x05} },
+{ 0x1452,	16,	{0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xb7, 0xf0, 0x05, 0x86, 0xa3, 0xe0, 0x54, 0xfe, 0xf0} },
+{ 0x1462,	16,	{0x02, 0x13, 0x43, 0x53, 0x2c, 0xfa, 0xe5, 0x22, 0x60, 0x08, 0x75, 0x22, 0x00, 0xd2, 0xe7, 0xfe} },
+{ 0x1472,	16,	{0x80, 0x0a, 0x90, 0x7f, 0xc7, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x14, 0xff, 0x90, 0x20, 0x50, 0x74} },
+{ 0x1482,	16,	{0x00, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0, 0x90} },
+{ 0x1492,	16,	{0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7e, 0x40, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84, 0xf0} },
+{ 0x14a2,	16,	{0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0, 0x24, 0x38, 0xf0, 0x05} },
+{ 0x14b2,	16,	{0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60, 0x30, 0x03, 0x03, 0x03} },
+{ 0x14c2,	16,	{0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} },
+{ 0x14d2,	16,	{0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11, 0x8b, 0x22, 0x90, 0x7f} },
+{ 0x14e2,	16,	{0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80, 0x1b, 0xe0, 0xde, 0xfd} },
+{ 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} },
+{ 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} },
+{ 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} },
+{ 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} },
+{ 0x15d2,	16,	{0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xdf, 0xef} },
+{ 0x15e2,	16,	{0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xb9, 0xf0, 0x05, 0x86, 0xa3, 0xe0, 0x54, 0xfe} },
+{ 0x15f2,	16,	{0xf0, 0x02, 0x13, 0x43, 0x53, 0x2d, 0xfa, 0xe5, 0x23, 0x60, 0x08, 0x75, 0x23, 0x00, 0xd2, 0xe7} },
+{ 0x1602,	16,	{0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xc9, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x16, 0x90, 0x90, 0x20, 0x50} },
+{ 0x1612,	16,	{0x74, 0x01, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x40, 0xf0} },
+{ 0x1622,	16,	{0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0xc0, 0x05, 0x86, 0xe5, 0x85, 0xf0, 0xa3, 0xe5, 0x84} },
+{ 0x1632,	16,	{0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0, 0x24, 0x38, 0xf0} },
+{ 0x1642,	16,	{0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60, 0x30, 0x03, 0x03} },
+{ 0x1652,	16,	{0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0} },
+{ 0x1662,	16,	{0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11, 0x8b, 0x23, 0x90} },
+{ 0x1672,	16,	{0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80, 0x1b, 0xe0, 0xde} },
+{ 0x1682,	14,	{0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} },
+{ 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} },
+{ 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} },
+{ 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} },
+{ 0x1760,	16,	{0x05, 0xfd, 0x8d, 0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3, 0x05} },
+{ 0x1770,	16,	{0x86, 0xdf, 0xef, 0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xbb, 0xf0, 0x05, 0x86, 0xa3} },
+{ 0x1780,	16,	{0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x53, 0x2e, 0xfa, 0xe5, 0x24, 0x60, 0x08, 0x75, 0x24} },
+{ 0x1790,	16,	{0x00, 0xd2, 0xe7, 0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xcb, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x18, 0x21} },
+{ 0x17a0,	16,	{0x90, 0x20, 0x50, 0x74, 0x02, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2, 0xe0} },
+{ 0x17b0,	16,	{0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7d, 0x40, 0x05, 0x86, 0xe5, 0x85, 0xf0} },
+{ 0x17c0,	16,	{0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86, 0xe0} },
+{ 0x17d0,	16,	{0x24, 0x38, 0xf0, 0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78, 0x60} },
+{ 0x17e0,	16,	{0x30, 0x03, 0x03, 0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0, 0xe0} },
+{ 0x17f0,	16,	{0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70, 0x11} },
+{ 0x1800,	16,	{0x8b, 0x24, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0, 0x80} },
+{ 0x1810,	16,	{0x1b, 0xe0, 0xde, 0xfd, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00} },
+{ 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} },
+{ 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} },
+{ 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} },
+{ 0x18f0,	16,	{0x24, 0x05, 0xfd, 0x8d, 0x84, 0xe0, 0x8e, 0x84, 0x30, 0xe0, 0x09, 0xe0, 0x05, 0x86, 0xf0, 0xa3} },
+{ 0x1900,	16,	{0x05, 0x86, 0xdf, 0xef, 0x05, 0x86, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0x7f, 0xbd, 0xf0, 0x05, 0x86} },
+{ 0x1910,	16,	{0xa3, 0xe0, 0x54, 0xfe, 0xf0, 0x02, 0x13, 0x43, 0x53, 0x2f, 0xfa, 0xe5, 0x25, 0x60, 0x08, 0x75} },
+{ 0x1920,	16,	{0x25, 0x00, 0xd2, 0xe7, 0xfe, 0x80, 0x0a, 0x90, 0x7f, 0xcd, 0xe0, 0xfe, 0x70, 0x03, 0x02, 0x19} },
+{ 0x1930,	16,	{0xb2, 0x90, 0x20, 0x50, 0x74, 0x03, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xe2} },
+{ 0x1940,	16,	{0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xe3, 0x05, 0x86, 0x90, 0x7c, 0xc0, 0x05, 0x86, 0xe5, 0x85} },
+{ 0x1950,	16,	{0xf0, 0xa3, 0xe5, 0x84, 0xf0, 0x05, 0x86, 0x90, 0x7f, 0xe5, 0xee, 0x30, 0xe7, 0x08, 0x05, 0x86} },
+{ 0x1960,	16,	{0xe0, 0x24, 0x38, 0xf0, 0x05, 0x86, 0xee, 0x54, 0x7f, 0xfe, 0x54, 0x07, 0xfb, 0xee, 0x54, 0x78} },
+{ 0x1970,	16,	{0x60, 0x30, 0x03, 0x03, 0x03, 0x30, 0xe3, 0x04, 0x74, 0x07, 0x7b, 0x08, 0xfd, 0xfc, 0xe0, 0xe0} },
+{ 0x1980,	16,	{0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xdd, 0xf6, 0xeb, 0xfe, 0x60, 0x19, 0xec, 0x64, 0x07, 0x70} },
+{ 0x1990,	16,	{0x11, 0x8b, 0x25, 0x90, 0x7f, 0xe2, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x20, 0x58, 0x74, 0x00, 0xf0} },
+{ 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,	{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, 0x69, 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, 0x9a, 0xa4, 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,	{0x9a, 0x8e, 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, 0x69, 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, 0x69, 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,	{0x8e, 0x5f, 0x8f, 0x60, 0x8c, 0x61, 0x8d, 0x62, 0xaf, 0x03, 0x1b, 0xef, 0x60, 0x24, 0x05, 0x60} },
+{ 0x1b1c,	16,	{0xe5, 0x60, 0xae, 0x5f, 0x70, 0x02, 0x05, 0x5f, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05} },
+{ 0x1b2c,	16,	{0x62, 0xe5, 0x62, 0xac, 0x61, 0x70, 0x02, 0x05, 0x61, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0} },
+{ 0x1b3c,	3,	{0x80, 0xd6, 0x22} },
+{ 0x8000,	4,	{0x8e, 0x69, 0x8f, 0x6a} },
+{ 0x8004,	16,	{0x75, 0x6b, 0x03, 0xe5, 0x6a, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x69, 0xf5, 0x83, 0xe0, 0xfe} },
+{ 0x8014,	16,	{0xa3, 0xe0, 0x4e, 0x70, 0x03, 0x02, 0x81, 0x0e, 0xe5, 0x6b, 0x60, 0x4e, 0x14, 0x60, 0x38, 0x14} },
+{ 0x8024,	16,	{0x60, 0x20, 0x14, 0x60, 0x03, 0x02, 0x80, 0xb2, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0x85} },
+{ 0x8034,	16,	{0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90, 0x7f, 0xa6, 0xf0} },
+{ 0x8044,	16,	{0x80, 0x6c, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xe0, 0xc3, 0x94, 0x20, 0x40, 0x09, 0xa3, 0xa3} },
+{ 0x8054,	16,	{0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x57, 0x15, 0x6b, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3} },
+{ 0x8064,	16,	{0xa3, 0xe0, 0xa3, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x80, 0x44, 0xe5, 0x6a, 0x24, 0x06, 0xf5, 0x82} },
+{ 0x8074,	16,	{0xe4, 0x35, 0x69, 0xf5, 0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5} },
+{ 0x8084,	16,	{0x83, 0xe0, 0x90, 0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe5, 0x6a, 0x24} },
+{ 0x8094,	16,	{0x04, 0xf5, 0x82, 0xe4, 0x35, 0x69, 0xf5, 0x83, 0x74, 0xff, 0xf5, 0xf0, 0x12, 0x9a, 0x8e, 0x85} },
+{ 0x80a4,	16,	{0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xa3, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0x8e, 0x90, 0x7f} },
+{ 0x80b4,	16,	{0xa5, 0xe0, 0xf5, 0x6c, 0x30, 0xe0, 0xf7, 0x30, 0xe2, 0x07, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x06} },
+{ 0x80c4,	16,	{0x22, 0xe5, 0x6c, 0x20, 0xe1, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x07, 0x22} },
+{ 0x80d4,	16,	{0xe5, 0x6b, 0x70, 0x31, 0x7f, 0x01, 0x7e, 0x00, 0x12, 0x08, 0x92, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x80e4,	16,	{0x80, 0xf0, 0x85, 0x6a, 0x82, 0x85, 0x69, 0x83, 0xa3, 0xe0, 0xff, 0x25, 0xe0, 0x44, 0xa0, 0x90} },
+{ 0x80f4,	16,	{0x7f, 0xa6, 0xf0, 0x90, 0x7f, 0xa5, 0xe0, 0xf5, 0x6c, 0x30, 0xe0, 0xf7, 0x30, 0xe1, 0xd5, 0x75} },
+{ 0x8104,	12,	{0x6b, 0x03, 0x02, 0x80, 0x07, 0x15, 0x6b, 0x02, 0x80, 0x07, 0x7f, 0x08} },
+{ 0x8110,	1,	{0x22} },
+{ 0x8111,	2,	{0xac, 0x07} },
+{ 0x8113,	16,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xec, 0x25, 0xe0, 0x44, 0x41, 0x90, 0x7f, 0xa6, 0xf0} },
+{ 0x8123,	16,	{0x7b, 0x3c, 0xaf, 0x03, 0x1b, 0xef, 0x70, 0x16, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90} },
+{ 0x8133,	16,	{0x7f, 0xa6, 0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x60, 0xd4, 0x80, 0xf8, 0x90, 0x7f} },
+{ 0x8143,	16,	{0xa5, 0xe0, 0xfd, 0x30, 0xe0, 0xdc, 0x20, 0xe1, 0x09, 0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f} },
+{ 0x8153,	16,	{0xf9, 0x22, 0xed, 0x30, 0xe2, 0x0c, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f} },
+{ 0x8163,	16,	{0xfa, 0x22, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0x7b, 0x1e} },
+{ 0x8173,	16,	{0xaf, 0x03, 0x1b, 0xef, 0x70, 0x16, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6} },
+{ 0x8183,	16,	{0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x60, 0x86, 0x80, 0xf8, 0x90, 0x7f, 0xa5, 0xe0} },
+{ 0x8193,	16,	{0xfd, 0x20, 0xe0, 0xdc, 0x7b, 0x3c, 0xaf, 0x03, 0x1b, 0xef, 0x70, 0x19, 0x90, 0x7f, 0xa5, 0xe0} },
+{ 0x81a3,	16,	{0x44, 0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0x7d, 0x32, 0xaf, 0x05, 0x1d, 0xef, 0x70, 0x03} },
+{ 0x81b3,	16,	{0x02, 0x81, 0x13, 0x80, 0xf5, 0x90, 0x7f, 0xa5, 0xe0, 0xfd, 0x30, 0xe0, 0xd9, 0x30, 0xe2, 0x09} },
+{ 0x81c3,	16,	{0xe0, 0x44, 0x40, 0xf0, 0x7e, 0xff, 0x7f, 0xfa, 0x22, 0xc2, 0xaf, 0x90, 0x7f, 0xa5, 0xe0, 0x44} },
+{ 0x81d3,	12,	{0x40, 0xf0, 0x90, 0x7f, 0xa6, 0xe0, 0xfd, 0xd2, 0xaf, 0xff, 0x7e, 0x00} },
+{ 0x81df,	1,	{0x22} },
+{ 0x81e0,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xf5} },
+{ 0x81f0,	16,	{0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf9, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0} },
+{ 0x8200,	16,	{0x44, 0x10, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0xe4, 0xf0, 0x8b, 0x82, 0x8a, 0x83} },
+{ 0x8210,	16,	{0xa3, 0xf0, 0xed, 0x60, 0x29, 0x74, 0x01, 0x7e, 0x00, 0xa8, 0x07, 0x08, 0x80, 0x05, 0xc3, 0x33} },
+{ 0x8220,	16,	{0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0xe4, 0xef, 0x55, 0x3b, 0x60, 0x0a, 0x8b, 0x82, 0x8a, 0x83} },
+{ 0x8230,	16,	{0xa3, 0x74, 0x01, 0xf0, 0x80, 0x08, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0x74, 0xad, 0xf0, 0x8b, 0x82} },
+{ 0x8240,	16,	{0x8a, 0x83, 0xa3, 0xa3, 0xa3, 0x74, 0xbf, 0xf0, 0x8b, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xe0, 0x54} },
+{ 0x8250,	15,	{0xef, 0xf0, 0xae, 0x02, 0xaf, 0x03, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe9, 0xf0} },
+{ 0x825f,	1,	{0x22} },
+{ 0x8260,	4,	{0x8f, 0x68, 0x8d, 0x69} },
+{ 0x8264,	16,	{0xe4, 0xf5, 0x6a, 0x74, 0x3c, 0x2f, 0xf8, 0x76, 0x08, 0xe5, 0x68, 0x75, 0xf0, 0x0d, 0xa4, 0x24} },
+{ 0x8274,	16,	{0xa0, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe} },
+{ 0x8284,	16,	{0xa3, 0xe0, 0xff, 0x7b, 0x80, 0x7a, 0x25, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x50} },
+{ 0x8294,	16,	{0x3c, 0xe5, 0x68, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0xa0, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} },
+{ 0x82a4,	16,	{0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x7b, 0x00, 0x7a, 0x96, 0x78} },
+{ 0x82b4,	16,	{0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x40, 0x0c, 0x75, 0x6a, 0x40, 0x74, 0x3c, 0x25, 0x68, 0xf8, 0x76} },
+{ 0x82c4,	16,	{0x10, 0x80, 0x0a, 0x75, 0x6a, 0x80, 0x74, 0x3c, 0x25, 0x68, 0xf8, 0x76, 0x38, 0xe5, 0x6a, 0x45} },
+{ 0x82d4,	16,	{0x69, 0x44, 0x01, 0xff, 0xe5, 0x68, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x82e4,	5,	{0x20, 0xf5, 0x83, 0xef, 0xf0} },
+{ 0x82e9,	1,	{0x22} },
+{ 0x82ea,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x5f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} },
+{ 0x82fa,	16,	{0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xf5, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5} },
+{ 0x830a,	16,	{0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x44, 0x03, 0xf0, 0xaf, 0x5f, 0x7d, 0x06, 0x12, 0x82} },
+{ 0x831a,	16,	{0x60, 0xaf, 0x5f, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0x85, 0x62, 0x82, 0x85, 0x61, 0x83, 0xa3, 0xa3} },
+{ 0x832a,	16,	{0xe0, 0x20, 0xe0, 0x28, 0xe0, 0xf5, 0x60, 0xe5, 0x62, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x61} },
+{ 0x833a,	16,	{0xf5, 0x83, 0xe0, 0xf5, 0x60, 0xe5, 0x62, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83} },
+{ 0x834a,	16,	{0xe0, 0xf5, 0x60, 0xaf, 0x5f, 0x7d, 0x06, 0x12, 0x82, 0x60, 0x80, 0xcc, 0x74, 0x96, 0x25, 0x5f} },
+{ 0x835a,	16,	{0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x5f, 0x25, 0xe0, 0xff, 0xc3, 0x74} },
+{ 0x836a,	16,	{0x0c, 0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82} },
+{ 0x837a,	16,	{0xfe, 0xe5, 0x5f, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xee, 0xf0} },
+{ 0x838a,	16,	{0xa3, 0xef, 0xf0, 0xaf, 0x5f, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc} },
+{ 0x839a,	4,	{0x42, 0x30, 0x7f, 0x00} },
+{ 0x839e,	1,	{0x22} },
+{ 0x839f,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x47, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} },
+{ 0x83af,	16,	{0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x49, 0x8f, 0x4a, 0x74, 0x96, 0x25, 0x47, 0xf5, 0x82, 0xe4} },
+{ 0x83bf,	16,	{0x34, 0x02, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x4a, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x49, 0xf5} },
+{ 0x83cf,	16,	{0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xaf, 0x47, 0xe4, 0xfd, 0x12, 0x81, 0xe0, 0xaf, 0x47, 0x7d, 0x06} },
+{ 0x83df,	16,	{0x12, 0x82, 0x60, 0xe5, 0x4a, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x49, 0xf5, 0x83, 0xe0, 0x30} },
+{ 0x83ef,	16,	{0xe0, 0x0b, 0x85, 0x4a, 0x82, 0x85, 0x49, 0x83, 0xe0, 0xf5, 0x48, 0x80, 0xe6, 0xaf, 0x47, 0x74} },
+{ 0x83ff,	16,	{0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x30, 0xe5, 0x47, 0x25} },
+{ 0x840f,	13,	{0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0xff} },
+{ 0x841c,	1,	{0x22} },
+{ 0x841d,	4,	{0x8e, 0x47, 0x8f, 0x48} },
+{ 0x8421,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x49, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82} },
+{ 0x8431,	16,	{0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x70, 0x23, 0x85, 0x48, 0x82, 0x8e, 0x83, 0xa3} },
+{ 0x8441,	16,	{0xe0, 0x30, 0xe0, 0x07, 0xaf, 0x49, 0x7d, 0x02, 0x12, 0x82, 0x60, 0x85, 0x48, 0x82, 0x85, 0x47} },
+{ 0x8451,	15,	{0x83, 0xa3, 0xe0, 0x30, 0xe1, 0x07, 0xaf, 0x49, 0x7d, 0x04, 0x12, 0x82, 0x60, 0x7f, 0x00} },
+{ 0x8460,	1,	{0x22} },
+{ 0x8461,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0xa3, 0xa3, 0xa3, 0xe0, 0xfc, 0xed} },
+{ 0x8471,	16,	{0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xc0, 0x83, 0xc0} },
+{ 0x8481,	16,	{0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0} },
+{ 0x8491,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0xe0, 0xfd, 0xec, 0x6d, 0xd0} },
+{ 0x84a1,	16,	{0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f} },
+{ 0x84b1,	16,	{0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82} },
+{ 0x84c1,	16,	{0x8e, 0x83, 0xa3, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0} },
+{ 0x84d1,	16,	{0xfc, 0xed, 0x6c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xc0, 0x83, 0xc0} },
+{ 0x84e1,	16,	{0x82, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xff, 0xed, 0x6f, 0xd0, 0x82, 0xd0} },
+{ 0x84f1,	3,	{0x83, 0xf0, 0x22} },
+{ 0x84f4,	4,	{0x8e, 0x5f, 0x8f, 0x60} },
+{ 0x84f8,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xff, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x8508,	16,	{0x1f, 0xad, 0x82, 0xf5, 0x66, 0x8d, 0x67, 0xaa, 0x5f, 0xa9, 0x60, 0x7b, 0x01, 0xc0, 0x03, 0xc0} },
+{ 0x8518,	16,	{0x01, 0xef, 0x75, 0xf0, 0x0d, 0xa4, 0x24, 0x92, 0xf9, 0x74, 0x02, 0x35, 0xf0, 0xa8, 0x01, 0xfc} },
+{ 0x8528,	16,	{0xad, 0x03, 0xd0, 0x01, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x0d, 0x12, 0x9a, 0x1f, 0x85, 0x60, 0x82} },
+{ 0x8538,	16,	{0x85, 0x5f, 0x83, 0xa3, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0x7f} },
+{ 0x8548,	16,	{0x00, 0x7e, 0x08, 0x7d, 0x07, 0x7c, 0x00, 0x12, 0x9b, 0x2e, 0x8f, 0x64, 0x8e, 0x63, 0x8d, 0x62} },
+{ 0x8558,	16,	{0x8c, 0x61, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x9b, 0xc0, 0x70, 0x09} },
+{ 0x8568,	16,	{0x75, 0x64, 0x01, 0xf5, 0x63, 0xf5, 0x62, 0xf5, 0x61, 0x7f, 0xff, 0x7e, 0xff, 0x7d, 0x00, 0x7c} },
+{ 0x8578,	16,	{0x00, 0xab, 0x64, 0xaa, 0x63, 0xa9, 0x62, 0xa8, 0x61, 0xd3, 0x12, 0x9b, 0xc0, 0x40, 0x0c, 0x75} },
+{ 0x8588,	16,	{0x64, 0xff, 0x75, 0x63, 0xff, 0x75, 0x62, 0x00, 0x75, 0x61, 0x00, 0x85, 0x67, 0x82, 0x85, 0x66} },
+{ 0x8598,	16,	{0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xe5, 0x64} },
+{ 0x85a8,	16,	{0xf0, 0xaf, 0x64, 0xae, 0x63, 0xad, 0x62, 0xac, 0x61, 0x78, 0x08, 0x12, 0x9b, 0xd1, 0x85, 0x67} },
+{ 0x85b8,	16,	{0x82, 0x85, 0x66, 0x83, 0xa3, 0xef, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3} },
+{ 0x85c8,	16,	{0xe0, 0x54, 0x7f, 0xf0, 0xe4, 0xf5, 0x65, 0xe5, 0x60, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x5f} },
+{ 0x85d8,	16,	{0xf5, 0x83, 0xe0, 0xff, 0xb4, 0x62, 0x05, 0x43, 0x65, 0x0a, 0x80, 0x10, 0xef, 0xb4, 0x72, 0x05} },
+{ 0x85e8,	16,	{0x43, 0x65, 0x08, 0x80, 0x07, 0xef, 0xb4, 0x74, 0x03, 0x43, 0x65, 0x02, 0xe5, 0x60, 0x24, 0x0b} },
+{ 0x85f8,	16,	{0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0x30, 0xe3, 0x03, 0x43, 0x65, 0x80, 0xef} },
+{ 0x8608,	16,	{0x30, 0xe7, 0x12, 0x43, 0x65, 0x40, 0xe5, 0x67, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5} },
+{ 0x8618,	16,	{0x83, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x60, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83} },
+{ 0x8628,	16,	{0xe0, 0xff, 0x20, 0xe1, 0x03, 0x30, 0xe4, 0x27, 0x85, 0x60, 0x82, 0x85, 0x5f, 0x83, 0xe0, 0x14} },
+{ 0x8638,	16,	{0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x42, 0x3b, 0xe5, 0x67} },
+{ 0x8648,	16,	{0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x17, 0x85} },
+{ 0x8658,	16,	{0x60, 0x82, 0x85, 0x5f, 0x83, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3} },
+{ 0x8668,	16,	{0x33, 0xd8, 0xfc, 0xf4, 0x52, 0x3b, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3, 0x74} },
+{ 0x8678,	16,	{0xbf, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x65, 0xf0, 0xe5} },
+{ 0x8688,	16,	{0x60, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x04} },
+{ 0x8698,	16,	{0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24, 0x0a, 0xf5, 0x82, 0xe4} },
+{ 0x86a8,	16,	{0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5} },
+{ 0x86b8,	16,	{0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff} },
+{ 0x86c8,	16,	{0xe5, 0x67, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x60, 0x24} },
+{ 0x86d8,	16,	{0x09, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x67, 0x24, 0x07, 0xf5, 0x82} },
+{ 0x86e8,	16,	{0xe4, 0x35, 0x66, 0xf5, 0x83, 0xef, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3} },
+{ 0x86f8,	16,	{0xe4, 0xf0, 0x85, 0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xf0, 0x85, 0x60, 0x82, 0x85, 0x5f} },
+{ 0x8708,	16,	{0x83, 0xe0, 0x14, 0xff, 0x7d, 0x06, 0x12, 0x82, 0x60, 0x75, 0x65, 0x08, 0xe5, 0x60, 0x24, 0x0c} },
+{ 0x8718,	16,	{0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0x43, 0x65, 0x10, 0xe5, 0x67, 0x24} },
+{ 0x8728,	16,	{0x04, 0xf5, 0x82, 0xe4, 0x35, 0x66, 0xf5, 0x83, 0xe0, 0x54, 0x03, 0x45, 0x65, 0xf0, 0xe5, 0x60} },
+{ 0x8738,	16,	{0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x14, 0xff, 0x25, 0xe0, 0x25, 0xe0} },
+{ 0x8748,	16,	{0xff, 0xe5, 0x60, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x24, 0xfb, 0x4f} },
+{ 0x8758,	16,	{0xf5, 0x65, 0xe5, 0x60, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x5f, 0xf5, 0x83, 0xe0, 0x24, 0xd0} },
+{ 0x8768,	16,	{0x60, 0x15, 0x14, 0x60, 0x17, 0x24, 0xc2, 0x60, 0x09, 0x24, 0x0a, 0x70, 0x12, 0x43, 0x65, 0x18} },
+{ 0x8778,	16,	{0x80, 0x0d, 0x43, 0x65, 0x08, 0x80, 0x08, 0x43, 0x65, 0x38, 0x80, 0x03, 0x43, 0x65, 0x28, 0x85} },
+{ 0x8788,	13,	{0x67, 0x82, 0x85, 0x66, 0x83, 0xa3, 0xa3, 0xa3, 0xe5, 0x65, 0xf0, 0x7f, 0x00} },
+{ 0x8795,	1,	{0x22} },
+{ 0x8796,	4,	{0x8e, 0x47, 0x8f, 0x48} },
+{ 0x879a,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x14, 0xf5, 0x4a, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82} },
+{ 0x87aa,	16,	{0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x4d, 0x8f, 0x4e, 0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01} },
+{ 0x87ba,	16,	{0xf5, 0x4c, 0xe4, 0x3e, 0xf5, 0x4b, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x08, 0xf0, 0xe5, 0x4a, 0x04} },
+{ 0x87ca,	16,	{0x85, 0x4c, 0x82, 0x85, 0x4b, 0x83, 0xf0, 0xa3, 0xe4, 0xf0, 0xe5, 0x4e, 0x24, 0x06, 0xf5, 0x82} },
+{ 0x87da,	16,	{0xe4, 0x35, 0x4d, 0xf5, 0x83, 0xe0, 0x85, 0x4c, 0x82, 0x85, 0x4b, 0x83, 0xa3, 0xa3, 0xf0, 0xe5} },
+{ 0x87ea,	16,	{0x4e, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x4d, 0xf5, 0x83, 0xe0, 0x54, 0x1e, 0x85, 0x4c, 0x82} },
+{ 0x87fa,	16,	{0x85, 0x4b, 0x83, 0xa3, 0xa3, 0xa3, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x2b} },
+{ 0x880a,	16,	{0xf8, 0xe6, 0xff, 0xe5, 0x4c, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x4b, 0xf5, 0x83, 0xef, 0xf0} },
+{ 0x881a,	16,	{0xaf, 0x4a, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x49, 0x7f} },
+{ 0x882a,	16,	{0x02, 0x12, 0x81, 0x11, 0xc3, 0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xe5, 0x49, 0x5f, 0xff} },
+{ 0x883a,	16,	{0xe5, 0x4c, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x4b, 0xf5, 0x83, 0xef, 0xf0, 0x90, 0x7f, 0xc3} },
+{ 0x884a,	5,	{0x74, 0x07, 0xf0, 0x7f, 0x00} },
+{ 0x884f,	1,	{0x22} },
+{ 0x8850,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} },
+{ 0x8860,	16,	{0xaf, 0x82, 0xf5, 0x47, 0x8f, 0x48, 0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xfd, 0xe4, 0x3e} },
+{ 0x8870,	16,	{0xfc, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x0a, 0xf0, 0xe5, 0x48, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35} },
+{ 0x8880,	16,	{0x47, 0xf5, 0x83, 0xe0, 0x8d, 0x82, 0x8c, 0x83, 0xf0, 0x90, 0x7f, 0xc3, 0x74, 0x02, 0xf0, 0x7f} },
+{ 0x8890,	1,	{0x00} },
+{ 0x8891,	1,	{0x22} },
+{ 0x8892,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} },
+{ 0x88a2,	16,	{0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0f, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c} },
+{ 0x88b2,	16,	{0xf5, 0x83, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x11, 0xae, 0x04, 0xaf, 0x05, 0xef, 0x24, 0x04, 0xf5} },
+{ 0x88c2,	11,	{0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0xf0, 0x7f, 0x00} },
+{ 0x88cd,	1,	{0x22} },
+{ 0x88ce,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} },
+{ 0x88de,	16,	{0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0f, 0xed, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x3c} },
+{ 0x88ee,	16,	{0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x11, 0xae, 0x04, 0xaf, 0x05, 0xef, 0x24, 0x04, 0xf5} },
+{ 0x88fe,	11,	{0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x00} },
+{ 0x8909,	1,	{0x22} },
+{ 0x890a,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0xf8, 0xf5, 0x82, 0xe4, 0x34, 0x1f} },
+{ 0x891a,	16,	{0xad, 0x82, 0xfc, 0x8f, 0x82, 0xa3, 0xe0, 0x60, 0x0d, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3} },
+{ 0x892a,	16,	{0xe0, 0x44, 0x40, 0xf0, 0x80, 0x0f, 0xae, 0x04, 0xaf, 0x05, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3} },
+{ 0x893a,	7,	{0xa3, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x00} },
+{ 0x8941,	1,	{0x22} },
+{ 0x8942,	4,	{0x8e, 0x47, 0x8f, 0x48} },
+{ 0x8946,	16,	{0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xe0, 0xf5, 0x4b, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x24, 0xfe, 0x60} },
+{ 0x8956,	16,	{0x16, 0x14, 0x60, 0x1f, 0x14, 0x60, 0x28, 0x24, 0x03, 0x70, 0x2e, 0x7e, 0x7e, 0x7f, 0x80, 0x75} },
+{ 0x8966,	16,	{0x49, 0x7e, 0x75, 0x4a, 0x80, 0x80, 0x22, 0x7e, 0x7e, 0x7f, 0x00, 0x75, 0x49, 0x7e, 0x75, 0x4a} },
+{ 0x8976,	16,	{0x00, 0x80, 0x16, 0x7e, 0x7d, 0x7f, 0x80, 0x75, 0x49, 0x7d, 0x75, 0x4a, 0x80, 0x80, 0x0a, 0x7e} },
+{ 0x8986,	16,	{0x7d, 0x7f, 0x00, 0x75, 0x49, 0x7d, 0x75, 0x4a, 0x00, 0xe5, 0x4b, 0x70, 0x20, 0x85, 0x4a, 0x82} },
+{ 0x8996,	16,	{0x85, 0x49, 0x83, 0x74, 0xff, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x25, 0xe0, 0x24} },
+{ 0x89a6,	16,	{0xb5, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x80, 0x3a, 0xe5, 0x48, 0x24} },
+{ 0x89b6,	16,	{0x02, 0xff, 0xe4, 0x35, 0x47, 0xfe, 0xe5, 0x4b, 0x60, 0x10, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0x85} },
+{ 0x89c6,	16,	{0x4a, 0x82, 0x85, 0x49, 0x83, 0xf0, 0x15, 0x4b, 0x80, 0xec, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83} },
+{ 0x89d6,	16,	{0xa3, 0xe0, 0xff, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x25, 0xe0, 0x24, 0xb5, 0xf5, 0x82} },
+{ 0x89e6,	9,	{0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x7f, 0x00} },
+{ 0x89ef,	1,	{0x22} },
+{ 0x89f0,	16,	{0xef, 0x24, 0x01, 0xf5, 0x48, 0xe4, 0x3e, 0xf5, 0x47, 0x7c, 0x7b, 0x7d, 0x80, 0x7e, 0x7b, 0x7f} },
+{ 0x8a00,	16,	{0x80, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x07, 0xf0, 0xef, 0x24, 0x01, 0xff, 0xe4, 0x3e, 0x90, 0x01} },
+{ 0x8a10,	16,	{0x31, 0xf0, 0xa3, 0xef, 0xf0, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xfe} },
+{ 0x8a20,	16,	{0xa3, 0xe0, 0x8e, 0x49, 0xf5, 0x4a, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x9e, 0x60} },
+{ 0x8a30,	16,	{0x61, 0x24, 0xf9, 0x60, 0x0e, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8a, 0xdd, 0x24, 0x14, 0x60, 0x03} },
+{ 0x8a40,	16,	{0x02, 0x8b, 0x30, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3} },
+{ 0x8a50,	16,	{0xe4, 0x9f, 0xf5, 0x4c, 0x74, 0x01, 0x9e, 0xf5, 0x4b, 0xd3, 0xe5, 0x4c, 0x94, 0x40, 0xe5, 0x4b} },
+{ 0x8a60,	16,	{0x94, 0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5, 0x4a, 0x95, 0x4c, 0xe5} },
+{ 0x8a70,	16,	{0x49, 0x95, 0x4b, 0x50, 0x03, 0x02, 0x8b, 0x30, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82, 0x85} },
+{ 0x8a80,	16,	{0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a, 0x02} },
+{ 0x8a90,	16,	{0x8b, 0x30, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x74} },
+{ 0x8aa0,	16,	{0x30, 0x9f, 0xf5, 0x4c, 0xe4, 0x9e, 0xf5, 0x4b, 0xd3, 0xe5, 0x4c, 0x94, 0x40, 0xe5, 0x4b, 0x94} },
+{ 0x8ab0,	16,	{0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5, 0x4a, 0x95, 0x4c, 0xe5, 0x49} },
+{ 0x8ac0,	16,	{0x95, 0x4b, 0x40, 0x6c, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3} },
+{ 0x8ad0,	16,	{0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a, 0x80, 0x53, 0x85, 0x48, 0x82} },
+{ 0x8ae0,	16,	{0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0xe4, 0x9f, 0xf5, 0x4c, 0xe4, 0x9e} },
+{ 0x8af0,	16,	{0xf5, 0x4b, 0x45, 0x4c, 0x70, 0x07, 0xf5, 0x4b, 0x75, 0x4c, 0x40, 0x80, 0x11, 0xd3, 0xe5, 0x4c} },
+{ 0x8b00,	16,	{0x94, 0x40, 0xe5, 0x4b, 0x94, 0x00, 0x40, 0x06, 0x75, 0x4b, 0x00, 0x75, 0x4c, 0x40, 0xd3, 0xe5} },
+{ 0x8b10,	16,	{0x4a, 0x95, 0x4c, 0xe5, 0x49, 0x95, 0x4b, 0x40, 0x17, 0xae, 0x4b, 0xaf, 0x4c, 0x85, 0x48, 0x82} },
+{ 0x8b20,	16,	{0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xee, 0xf0, 0xfe, 0xa3, 0xef, 0xf0, 0x8e, 0x49, 0xf5, 0x4a} },
+{ 0x8b30,	16,	{0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xe0, 0x24, 0x9e, 0x70, 0x03, 0x02, 0x8b, 0xf0, 0x24, 0xf9} },
+{ 0x8b40,	16,	{0x60, 0x58, 0x24, 0xf1, 0x70, 0x03, 0x02, 0x8c, 0x40, 0x24, 0x14, 0x60, 0x03, 0x02, 0x8c, 0x84} },
+{ 0x8b50,	16,	{0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xd3, 0x94, 0xff, 0xee} },
+{ 0x8b60,	16,	{0x94, 0x00, 0x40, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2c, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a} },
+{ 0x8b70,	16,	{0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x70, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2c, 0xe0} },
+{ 0x8b80,	16,	{0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a} },
+{ 0x8b90,	16,	{0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83} },
+{ 0x8ba0,	16,	{0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x80, 0xee, 0x94, 0x00, 0x50, 0x03, 0x02, 0x8c} },
+{ 0x8bb0,	16,	{0x84, 0xd3, 0xef, 0x94, 0xff, 0xee, 0x94, 0x00, 0x40, 0x03, 0x02, 0x8c, 0x84, 0x90, 0x01, 0x2d} },
+{ 0x8bc0,	16,	{0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x70, 0x03, 0x02} },
+{ 0x8bd0,	16,	{0x8c, 0x84, 0x90, 0x01, 0x2d, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31} },
+{ 0x8be0,	16,	{0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd2} },
+{ 0x8bf0,	16,	{0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xc3, 0x94, 0x20, 0xee} },
+{ 0x8c00,	16,	{0x94, 0x00, 0x50, 0x03, 0x02, 0x8c, 0x84, 0xd3, 0xef, 0x94, 0x2f, 0xee, 0x94, 0x00, 0x50, 0x74} },
+{ 0x8c10,	16,	{0x90, 0x01, 0x2e, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e} },
+{ 0x8c20,	16,	{0x60, 0x62, 0x90, 0x01, 0x2e, 0xe0, 0xff, 0x04, 0xf0, 0xa8, 0x07, 0xe6, 0xff, 0x90, 0x01, 0x31} },
+{ 0x8c30,	16,	{0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xef, 0xf0, 0x80, 0xd5} },
+{ 0x8c40,	16,	{0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0x01, 0x2f, 0xcf, 0xf0} },
+{ 0x8c50,	16,	{0xa3, 0xef, 0xf0, 0xe5, 0x4a, 0x15, 0x4a, 0xae, 0x49, 0x70, 0x02, 0x15, 0x49, 0x4e, 0x60, 0x24} },
+{ 0x8c60,	16,	{0x90, 0x01, 0x2f, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0} },
+{ 0x8c70,	16,	{0xff, 0x90, 0x01, 0x31, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83} },
+{ 0x8c80,	16,	{0xef, 0xf0, 0x80, 0xcf, 0x85, 0x48, 0x82, 0x85, 0x47, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xa3, 0xe0} },
+{ 0x8c90,	6,	{0x90, 0x7f, 0xc3, 0xf0, 0x7f, 0x00} },
+{ 0x8c96,	1,	{0x22} },
+{ 0x8c97,	16,	{0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xfd, 0xe4, 0x3e, 0xfc, 0x8f, 0x82, 0x8e, 0x83, 0x74} },
+{ 0x8ca7,	16,	{0x0b, 0xf0, 0x90, 0x20, 0x70, 0xe0, 0x54, 0xf0, 0xff, 0xc4, 0x54, 0x0f, 0x8d, 0x82, 0x8c, 0x83} },
+{ 0x8cb7,	16,	{0xf0, 0x90, 0x11, 0xf0, 0xe4, 0x93, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xf0, 0x90, 0x11, 0xf1, 0xe4} },
+{ 0x8cc7,	16,	{0x93, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xf0, 0xe4, 0x90, 0x01, 0x33, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x8cd7,	16,	{0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xed, 0x24, 0x03, 0xfe, 0xe4, 0x3c, 0xa3} },
+{ 0x8ce7,	16,	{0xf0, 0xa3, 0xce, 0xf0, 0x7e, 0x01, 0x7f, 0x33, 0x12, 0x19, 0xc1, 0x90, 0x7f, 0xc3, 0x74, 0x14} },
+{ 0x8cf7,	3,	{0xf0, 0x7f, 0x00} },
+{ 0x8cfa,	1,	{0x22} },
+{ 0x8cfb,	4,	{0x8e, 0x40, 0x8f, 0x41} },
+{ 0x8cff,	16,	{0x85, 0x40, 0x43, 0x85, 0x41, 0x44, 0x85, 0x44, 0x82, 0x85, 0x43, 0x83, 0xe0, 0x14, 0xb4, 0x0f} },
+{ 0x8d0f,	16,	{0x00, 0x40, 0x03, 0x02, 0x8e, 0x32, 0x90, 0x8d, 0x1c, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x8d, 0x49} },
+{ 0x8d1f,	16,	{0x02, 0x8d, 0x5a, 0x02, 0x8d, 0x6b, 0x02, 0x8d, 0x8e, 0x02, 0x8d, 0x9f, 0x02, 0x8d, 0xb0, 0x02} },
+{ 0x8d2f,	16,	{0x8d, 0xc0, 0x02, 0x8d, 0xcb, 0x02, 0x8d, 0xdb, 0x02, 0x8d, 0xeb, 0x02, 0x8d, 0xfb, 0x02, 0x8e} },
+{ 0x8d3f,	16,	{0x02, 0x02, 0x8e, 0x32, 0x02, 0x8e, 0x12, 0x02, 0x8e, 0x22, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4} },
+{ 0x8d4f,	16,	{0x35, 0x43, 0xfe, 0x12, 0x82, 0xea, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5, 0x44, 0x24, 0x01, 0xff} },
+{ 0x8d5f,	16,	{0xe4, 0x35, 0x43, 0xfe, 0x12, 0x83, 0x9f, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5, 0x44, 0x24, 0x01} },
+{ 0x8d6f,	16,	{0xf5, 0x46, 0xe4, 0x35, 0x43, 0xf5, 0x45, 0xe5, 0x46, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x45, 0xfe} },
+{ 0x8d7f,	16,	{0x12, 0x84, 0x61, 0xaf, 0x46, 0xae, 0x45, 0x12, 0x84, 0xf4, 0x8f, 0x42, 0x02, 0x8e, 0x32, 0xe5} },
+{ 0x8d8f,	16,	{0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0x92, 0x8f, 0x42, 0x02, 0x8e, 0x32} },
+{ 0x8d9f,	16,	{0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0xce, 0x8f, 0x42, 0x02, 0x8e} },
+{ 0x8daf,	16,	{0x32, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x89, 0x0a, 0x8f, 0x42, 0x80} },
+{ 0x8dbf,	16,	{0x72, 0xaf, 0x41, 0xae, 0x40, 0x12, 0x89, 0xf0, 0x8f, 0x42, 0x80, 0x67, 0xe5, 0x44, 0x24, 0x01} },
+{ 0x8dcf,	16,	{0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x87, 0x96, 0x8f, 0x42, 0x80, 0x57, 0xe5, 0x44, 0x24, 0x01} },
+{ 0x8ddf,	16,	{0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x84, 0x1d, 0x8f, 0x42, 0x80, 0x47, 0xe5, 0x44, 0x24, 0x01} },
+{ 0x8def,	16,	{0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x88, 0x50, 0x8f, 0x42, 0x80, 0x37, 0x12, 0x8c, 0x97, 0x8f} },
+{ 0x8dff,	16,	{0x42, 0x80, 0x30, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x11, 0xd8, 0x8f} },
+{ 0x8e0f,	16,	{0x42, 0x80, 0x20, 0xe5, 0x44, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x43, 0xfe, 0x12, 0x89, 0x42, 0x8f} },
+{ 0x8e1f,	16,	{0x42, 0x80, 0x10, 0xaf, 0x41, 0xae, 0x40, 0x7c, 0x02, 0x7d, 0x4d, 0x7b, 0x40, 0x12, 0x1b, 0x0c} },
+{ 0x8e2f,	5,	{0xe4, 0xf5, 0x42, 0xaf, 0x42} },
+{ 0x8e34,	1,	{0x22} },
+{ 0x8e35,	8,	{0x8f, 0x61, 0x8e, 0x60, 0x8d, 0x5f, 0x8c, 0x5e} },
+{ 0x8e3d,	16,	{0x75, 0x68, 0x01, 0x75, 0x69, 0x3b, 0xe4, 0xf5, 0x67, 0xaf, 0x63, 0x15, 0x63, 0xef, 0x70, 0x03} },
+{ 0x8e4d,	16,	{0x02, 0x8e, 0xd3, 0xaf, 0x62, 0xe4, 0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xaf, 0x61} },
+{ 0x8e5d,	16,	{0xae, 0x60, 0xad, 0x5f, 0xac, 0x5e, 0x12, 0x9b, 0x2e, 0xaf, 0x03, 0x8f, 0x66, 0xaf, 0x61, 0xae} },
+{ 0x8e6d,	16,	{0x60, 0xad, 0x5f, 0xac, 0x5e, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xaf, 0x62, 0xe4} },
+{ 0x8e7d,	16,	{0xfc, 0xfd, 0xfe, 0xf8, 0xf9, 0xfa, 0xab, 0x07, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04} },
+{ 0x8e8d,	16,	{0x12, 0x9b, 0x2e, 0x8f, 0x61, 0x8e, 0x60, 0x8d, 0x5f, 0x8c, 0x5e, 0xe5, 0x66, 0x24, 0x30, 0xf5} },
+{ 0x8e9d,	16,	{0x66, 0xd3, 0x94, 0x39, 0x40, 0x06, 0x74, 0x07, 0x25, 0x66, 0xf5, 0x66, 0x05, 0x69, 0xe5, 0x69} },
+{ 0x8ead,	16,	{0xae, 0x68, 0x70, 0x02, 0x05, 0x68, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x05, 0x69, 0xe5} },
+{ 0x8ebd,	16,	{0x69, 0xae, 0x68, 0x70, 0x02, 0x05, 0x68, 0x14, 0xf5, 0x82, 0x8e, 0x83, 0xe5, 0x66, 0xf0, 0x05} },
+{ 0x8ecd,	16,	{0x67, 0x05, 0x67, 0x02, 0x8e, 0x46, 0xe5, 0x69, 0x15, 0x69, 0x70, 0x02, 0x15, 0x68, 0xaf, 0x67} },
+{ 0x8edd,	16,	{0x15, 0x67, 0xef, 0x60, 0x23, 0xe5, 0x69, 0x15, 0x69, 0xae, 0x68, 0x70, 0x02, 0x15, 0x68, 0xf5} },
+{ 0x8eed,	16,	{0x82, 0x8e, 0x83, 0xe0, 0xff, 0x05, 0x65, 0xe5, 0x65, 0xac, 0x64, 0x70, 0x02, 0x05, 0x64, 0x14} },
+{ 0x8efd,	8,	{0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x80, 0xd6} },
+{ 0x8f05,	1,	{0x22} },
+{ 0x8f06,	16,	{0xe4, 0x90, 0x01, 0x67, 0xf0, 0x7e, 0x01, 0x7f, 0x68, 0x90, 0x01, 0x5c, 0xee, 0xf0, 0xa3, 0xef} },
+{ 0x8f16,	10,	{0xf0, 0x90, 0x01, 0x60, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} },
+{ 0x8f20,	16,	{0xaa, 0x07, 0xa9, 0x05, 0x90, 0x01, 0x67, 0xe0, 0xc3, 0x94, 0x40, 0x50, 0x61, 0xac, 0x02, 0x74} },
+{ 0x8f30,	16,	{0x01, 0x7e, 0x00, 0xa8, 0x04, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff} },
+{ 0x8f40,	16,	{0xe4, 0xef, 0x55, 0x30, 0x60, 0x45, 0xea, 0x04, 0xff, 0x90, 0x01, 0x60, 0xe0, 0xfc, 0xa3, 0xe0} },
+{ 0x8f50,	16,	{0xfd, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0xa3, 0xe9, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3} },
+{ 0x8f60,	16,	{0xeb, 0xf0, 0x90, 0x01, 0x60, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9a, 0x8e, 0xfc, 0xd3, 0xe5, 0xf0} },
+{ 0x8f70,	16,	{0x94, 0x25, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0x60, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x68} },
+{ 0x8f80,	16,	{0xf0, 0xc2, 0xaf, 0x90, 0x01, 0x67, 0xe0, 0x04, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
+{ 0x8f90,	1,	{0x22} },
+{ 0x8f91,	16,	{0x90, 0x01, 0x67, 0xe0, 0xd3, 0x94, 0x00, 0x40, 0x55, 0x90, 0x01, 0x5c, 0xe0, 0xfc, 0xa3, 0xe0} },
+{ 0x8fa1,	16,	{0xaa, 0x04, 0xf9, 0x7b, 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0xaa, 0x06, 0xa9, 0x07, 0xa8} },
+{ 0x8fb1,	16,	{0x01, 0xac, 0x02, 0xad, 0x03, 0xd0, 0x01, 0xd0, 0x02, 0xd0, 0x03, 0x7e, 0x00, 0x7f, 0x03, 0x12} },
+{ 0x8fc1,	16,	{0x9a, 0x1f, 0x90, 0x01, 0x5c, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x9a, 0x8e, 0xfc, 0xd3, 0xe5, 0xf0} },
+{ 0x8fd1,	16,	{0x94, 0x25, 0xec, 0x94, 0x02, 0x40, 0x0a, 0x90, 0x01, 0x5c, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x68} },
+{ 0x8fe1,	16,	{0xf0, 0xc2, 0xaf, 0x90, 0x01, 0x67, 0xe0, 0x14, 0xf0, 0xd2, 0xaf, 0x7f, 0x01, 0x22, 0x7f, 0x00} },
+{ 0x8ff1,	1,	{0x22} },
+{ 0x8ff2,	16,	{0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x5e, 0x7e, 0x7b, 0x7f, 0x80, 0x75, 0x63, 0x7b, 0x75, 0x64} },
+{ 0x9002,	16,	{0x80, 0xe5, 0x64, 0x24, 0x01, 0xff, 0xe4, 0x35, 0x63, 0xa9, 0x07, 0x7b, 0x01, 0x8b, 0x65, 0xf5} },
+{ 0x9012,	16,	{0x66, 0x89, 0x67, 0xfe, 0x12, 0x8f, 0x91, 0xef, 0x60, 0x3b, 0xab, 0x65, 0xaa, 0x66, 0xa9, 0x67} },
+{ 0x9022,	16,	{0x12, 0x9a, 0x48, 0x14, 0xff, 0x90, 0x00, 0x01, 0x12, 0x9a, 0x61, 0xb4, 0x02, 0x16, 0xc2, 0xaf} },
+{ 0x9032,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x44} },
+{ 0x9042,	16,	{0x04, 0xf0, 0xd2, 0xaf, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83, 0x74, 0x0d, 0xf0, 0x90, 0x7f, 0xc3} },
+{ 0x9052,	5,	{0x74, 0x04, 0xf0, 0xd2, 0xaf} },
+{ 0x9057,	1,	{0x22} },
+{ 0x9058,	16,	{0x12, 0x8f, 0xf2, 0xe4, 0xf5, 0x5e, 0x74, 0x36, 0x25, 0x5e, 0xf8, 0xe6, 0x54, 0xf0, 0xf5, 0x5f} },
+{ 0x9068,	16,	{0x74, 0x63, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5, 0x83, 0xe0, 0x65, 0x5f, 0xff, 0xc4} },
+{ 0x9078,	16,	{0x54, 0x0f, 0xf5, 0x60, 0x60, 0x22, 0x74, 0x63, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x01, 0xf5} },
+{ 0x9088,	16,	{0x83, 0xe5, 0x5f, 0xf0, 0xaf, 0x5e, 0x7d, 0x01, 0xe5, 0x5f, 0x45, 0x60, 0xfb, 0x12, 0x8f, 0x20} },
+{ 0x9098,	16,	{0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2, 0x80, 0xec, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40} },
+{ 0x90a8,	16,	{0xb5, 0x12, 0x8f, 0xf2, 0xe5, 0x3a, 0x60, 0x48, 0xe4, 0xf5, 0x5e, 0xaf, 0x5e, 0x74, 0x01, 0xa8} },
+{ 0x90b8,	16,	{0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x55, 0x3a, 0x60, 0x29, 0xe5, 0x5e} },
+{ 0x90c8,	16,	{0x75, 0xf0, 0x08, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xf5, 0x83, 0xe0, 0x30, 0xe6} },
+{ 0x90d8,	16,	{0x16, 0xaf, 0x5e, 0x7d, 0x04, 0x7b, 0x80, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2} },
+{ 0x90e8,	16,	{0x80, 0xef, 0xe5, 0x5f, 0xf4, 0x52, 0x3a, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0xbb} },
+{ 0x90f8,	16,	{0x90, 0x02, 0x9e, 0xe0, 0x60, 0x03, 0x02, 0x91, 0xc5, 0x74, 0x19, 0xf0, 0x7f, 0x02, 0x12, 0x81} },
+{ 0x9108,	16,	{0x11, 0x8e, 0x61, 0x8f, 0x62, 0xc3, 0xe5, 0x61, 0x64, 0x80, 0x94, 0x80, 0x40, 0xee, 0x90, 0x01} },
+{ 0x9118,	16,	{0x5b, 0xe0, 0x65, 0x62, 0xf0, 0x60, 0x37, 0xe4, 0xf5, 0x5e, 0xaf, 0x5e, 0x74, 0x01, 0xa8, 0x07} },
+{ 0x9128,	16,	{0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x90, 0x01, 0x5b, 0xe0, 0x55, 0x5f, 0x60} },
+{ 0x9138,	16,	{0x14, 0xaf, 0x5e, 0x7d, 0x08, 0xe5, 0x5f, 0x55, 0x62, 0xfb, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05} },
+{ 0x9148,	16,	{0x12, 0x8f, 0xf2, 0x80, 0xec, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0xcc, 0x90, 0x01} },
+{ 0x9158,	16,	{0x5b, 0xe5, 0x62, 0xf0, 0xe4, 0xf5, 0x5e, 0xc2, 0xaf, 0x74, 0x32, 0x25, 0x5e, 0xf8, 0xe6, 0xf5} },
+{ 0x9168,	16,	{0x5f, 0xe4, 0xf6, 0xd2, 0xaf, 0x53, 0x5f, 0x1e, 0xe5, 0x5f, 0x60, 0x11, 0xaf, 0x5e, 0x7d, 0x02} },
+{ 0x9178,	16,	{0xab, 0x5f, 0x12, 0x8f, 0x20, 0xef, 0x70, 0x05, 0x12, 0x8f, 0xf2, 0x80, 0xef, 0x74, 0x2c, 0x25} },
+{ 0x9188,	16,	{0x5e, 0xf8, 0xe6, 0xf5, 0x5f, 0x74, 0x9a, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83} },
+{ 0x9198,	16,	{0xe0, 0x65, 0x5f, 0x60, 0x11, 0xaf, 0x5e, 0x7d, 0x04, 0xab, 0x5f, 0x12, 0x8f, 0x20, 0xef, 0x70} },
+{ 0x91a8,	16,	{0x05, 0x12, 0x8f, 0xf2, 0x80, 0xef, 0x74, 0x9a, 0x25, 0x5e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5} },
+{ 0x91b8,	16,	{0x83, 0xe5, 0x5f, 0xf0, 0x05, 0x5e, 0xe5, 0x5e, 0xc3, 0x94, 0x04, 0x40, 0x9a, 0x12, 0x8f, 0xf2} },
+{ 0x91c8,	1,	{0x22} },
+{ 0x91c9,	12,	{0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x6e, 0x02, 0x92, 0x10} },
+{ 0x91d5,	16,	{0x02, 0x05, 0x28, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
+{ 0x91e5,	16,	{0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
+{ 0x91f5,	16,	{0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
+{ 0x9205,	16,	{0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x92, 0x55, 0xe4, 0x7e} },
+{ 0x9215,	16,	{0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
+{ 0x9225,	16,	{0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
+{ 0x9235,	16,	{0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
+{ 0x9245,	16,	{0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
+{ 0x9255,	16,	{0x60, 0x24, 0x02, 0x28, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x81, 0x82, 0x84, 0x88} },
+{ 0x9265,	16,	{0x90, 0xa0, 0xc0, 0xc1, 0xc2, 0xc4, 0xc8, 0xd0, 0xe0, 0xe1, 0xe2, 0xe4, 0xe8, 0xf0, 0xf1, 0xf2} },
+{ 0x9275,	8,	{0xf4, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xfe, 0xff} },
+{ 0x927d,	1,	{0x00} },
+{ 0x927e,	11,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18} },
+{ 0x9289,	16,	{0x90, 0x20, 0x60, 0xe0, 0x54, 0x0f, 0xfe, 0x30, 0xe0, 0x05, 0x90, 0x20, 0x02, 0xe0, 0xff, 0xee} },
+{ 0x9299,	16,	{0x30, 0xe1, 0x05, 0x90, 0x20, 0x0a, 0xe0, 0xff, 0xee, 0x30, 0xe2, 0x05, 0x90, 0x20, 0x12, 0xe0} },
+{ 0x92a9,	16,	{0xff, 0xee, 0x30, 0xe3, 0x05, 0x90, 0x20, 0x1a, 0xe0, 0xff, 0x90, 0x01, 0x62, 0xe0, 0xb5, 0x1e} },
+{ 0x92b9,	10,	{0x04, 0xe4, 0xf0, 0x80, 0x05, 0x90, 0x01, 0x62, 0xee, 0xf0} },
+{ 0x92c3,	9,	{0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x92cc,	2,	{0xa9, 0x03} },
+{ 0x92ce,	16,	{0xef, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xab, 0x82, 0xfa, 0xe5} },
+{ 0x92de,	16,	{0x6c, 0x45, 0x6d, 0xf5, 0x6e, 0xe9, 0x60, 0x14, 0x8a, 0x83, 0xe5, 0x82, 0x24, 0x04, 0xf5, 0x82} },
+{ 0x92ee,	16,	{0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x4d, 0xf0, 0xe4, 0xfe, 0x80, 0x13, 0xeb, 0x24, 0x04, 0xf5} },
+{ 0x92fe,	16,	{0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0xff, 0xed, 0xf4, 0xfc, 0xef, 0x5c, 0xf0, 0xae, 0x6e, 0xeb} },
+{ 0x930e,	16,	{0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3a, 0xf5, 0x83, 0xe0, 0x55, 0x6e, 0xfc, 0xb5, 0x06, 0x03, 0xaf} },
+{ 0x931e,	16,	{0x05, 0x22, 0xe5, 0x6c, 0x5c, 0xfe, 0xe5, 0x6d, 0x5c, 0xfd, 0xe9, 0x60, 0x16, 0xee, 0x70, 0x04} },
+{ 0x932e,	16,	{0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xae, 0x07, 0xed, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f} },
+{ 0x933e,	16,	{0x00, 0xad, 0x07, 0xee, 0x60, 0x03, 0xaf, 0x6c, 0x22, 0xed, 0x60, 0x03, 0xaf, 0x6d, 0x22, 0x7f} },
+{ 0x934e,	1,	{0x00} },
+{ 0x934f,	1,	{0x22} },
+{ 0x9350,	16,	{0x7e, 0x7b, 0x7f, 0x80, 0xef, 0x24, 0x01, 0xf5, 0x66, 0xe4, 0x3e, 0xf5, 0x65, 0x75, 0x63, 0x02} },
+{ 0x9360,	16,	{0x75, 0x64, 0x4e, 0x8f, 0x82, 0x8e, 0x83, 0x74, 0x0f, 0xf0, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83} },
+{ 0x9370,	16,	{0xe0, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xf0, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83, 0xa3, 0xe0} },
+{ 0x9380,	16,	{0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xf0, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3} },
+{ 0x9390,	16,	{0x74, 0xff, 0xf0, 0xe5, 0x66, 0x24, 0x03, 0xf5, 0x68, 0xe4, 0x35, 0x65, 0xf5, 0x67, 0x85, 0x64} },
+{ 0x93a0,	16,	{0x82, 0x85, 0x63, 0x83, 0xe0, 0x14, 0xb4, 0x0b, 0x00, 0x40, 0x03, 0x02, 0x98, 0x43, 0x90, 0x93} },
+{ 0x93b0,	16,	{0xb5, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x93, 0xd6, 0x02, 0x94, 0x7c, 0x02, 0x95, 0xba, 0x02, 0x95} },
+{ 0x93c0,	16,	{0xda, 0x02, 0x95, 0xda, 0x02, 0x96, 0x7f, 0x02, 0x96, 0xbd, 0x02, 0x96, 0xe4, 0x02, 0x97, 0xa6} },
+{ 0x93d0,	16,	{0x02, 0x97, 0xda, 0x02, 0x98, 0x0b, 0xe4, 0xf5, 0x5e, 0xe5, 0x5e, 0x75, 0xf0, 0x08, 0xa4, 0x24} },
+{ 0x93e0,	16,	{0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xe4, 0xff, 0xe4, 0xfe} },
+{ 0x93f0,	16,	{0xef, 0x60, 0x10, 0x74, 0x28, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf4, 0xf5} },
+{ 0x9400,	16,	{0x5f, 0x80, 0x0d, 0x74, 0x28, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0xf5, 0x5f} },
+{ 0x9410,	16,	{0xe5, 0x62, 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83, 0xe5, 0x5f, 0xf0, 0xe0, 0xf5} },
+{ 0x9420,	16,	{0x60, 0x65, 0x5f, 0x60, 0x3d, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5} },
+{ 0x9430,	16,	{0x5e, 0x04, 0xfd, 0x05, 0x68, 0xe5, 0x68, 0xaa, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82} },
+{ 0x9440,	16,	{0x8a, 0x83, 0xed, 0xf0, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5} },
+{ 0x9450,	16,	{0x82, 0x8c, 0x83, 0xe5, 0x5f, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0xe5, 0x60, 0xf0, 0x02} },
+{ 0x9460,	16,	{0x98, 0x4e, 0x0e, 0xee, 0x64, 0x24, 0x70, 0x88, 0x0f, 0xef, 0x64, 0x02, 0x70, 0x80, 0x05, 0x5e} },
+{ 0x9470,	16,	{0xe5, 0x5e, 0x64, 0x04, 0x60, 0x03, 0x02, 0x93, 0xd9, 0x02, 0x98, 0x4e, 0x7e, 0x20, 0x7f, 0x00} },
+{ 0x9480,	16,	{0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe4, 0xf5, 0x5e, 0xaf, 0x62, 0xae, 0x61, 0xe4, 0xfd, 0x12} },
+{ 0x9490,	16,	{0x81, 0xe0, 0x74, 0x08, 0x25, 0x62, 0xf5, 0x62, 0xe4, 0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5} },
+{ 0x94a0,	16,	{0x5e, 0xd3, 0x94, 0x03, 0x40, 0xe3, 0x90, 0x00, 0x04, 0x74, 0x92, 0xf0, 0xa3, 0x74, 0x7e, 0xf0} },
+{ 0x94b0,	16,	{0xe4, 0xf5, 0x60, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xf5, 0x5e, 0xaf} },
+{ 0x94c0,	16,	{0x5e, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0xf5, 0x5f, 0x90, 0x01} },
+{ 0x94d0,	16,	{0x62, 0xf0, 0x90, 0x01, 0x5e, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x85, 0x62, 0x82, 0x85, 0x61} },
+{ 0x94e0,	16,	{0x83, 0xa3, 0x74, 0x02, 0xf0, 0x90, 0x01, 0x62, 0xe0, 0x65, 0x5f, 0x70, 0x39, 0x90, 0x01, 0x5e} },
+{ 0x94f0,	16,	{0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xee, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xf0} },
+{ 0x9500,	16,	{0xe5, 0x5e, 0x04, 0xff, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5} },
+{ 0x9510,	16,	{0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0x74, 0xff, 0xf0, 0xe4, 0x90} },
+{ 0x9520,	16,	{0x01, 0x62, 0xf0, 0x75, 0x60, 0xff, 0x90, 0x01, 0x62, 0xe0, 0xff, 0x60, 0x3c, 0x85, 0x66, 0x82} },
+{ 0x9530,	16,	{0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5e, 0x04, 0xfe, 0x05, 0x68, 0xe5, 0x68, 0xac} },
+{ 0x9540,	16,	{0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xee, 0xf0, 0x05, 0x68, 0xe5, 0x68} },
+{ 0x9550,	16,	{0xac, 0x67, 0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82} },
+{ 0x9560,	16,	{0x85, 0x67, 0x83, 0xe5, 0x5f, 0xf0, 0x75, 0x60, 0xff, 0xe5, 0x60, 0x70, 0x16, 0x74, 0x08, 0x25} },
+{ 0x9570,	16,	{0x62, 0xf5, 0x62, 0xe4, 0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5, 0x5e, 0x64, 0x04, 0x60, 0x03} },
+{ 0x9580,	16,	{0x02, 0x94, 0xbf, 0x7e, 0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe4, 0xf5, 0x5e} },
+{ 0x9590,	16,	{0xaf, 0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0x74, 0x08, 0x25, 0x62, 0xf5, 0x62, 0xe4} },
+{ 0x95a0,	16,	{0x35, 0x61, 0xf5, 0x61, 0x05, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x03, 0x40, 0xe3, 0x90, 0x00, 0x04} },
+{ 0x95b0,	16,	{0x74, 0x13, 0xf0, 0xa3, 0x74, 0x12, 0xf0, 0x02, 0x98, 0x4e, 0x85, 0x64, 0x82, 0x85, 0x63, 0x83} },
+{ 0x95c0,	16,	{0xa3, 0xe0, 0x14, 0xff, 0x74, 0x01, 0xa8, 0x07, 0x08, 0x80, 0x02, 0xc3, 0x33, 0xd8, 0xfc, 0x90} },
+{ 0x95d0,	16,	{0x02, 0x95, 0xf0, 0x90, 0x01, 0x62, 0xf0, 0x02, 0x98, 0x4e, 0x90, 0x01, 0x5e, 0x74, 0x03, 0xf0} },
+{ 0x95e0,	16,	{0xa3, 0x74, 0xe8, 0xf0, 0xe4, 0xf5, 0x60, 0x90, 0x02, 0x95, 0xe0, 0xff, 0x90, 0x01, 0x62, 0xe0} },
+{ 0x95f0,	16,	{0xb5, 0x07, 0x1e, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xea, 0x85, 0x66, 0x82} },
+{ 0x9600,	16,	{0x85, 0x65, 0x83, 0xa3, 0xa3, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0x74, 0xff, 0xf0, 0xf5} },
+{ 0x9610,	16,	{0x60, 0xe5, 0x60, 0x60, 0x03, 0x02, 0x98, 0x4e, 0x90, 0x01, 0x5e, 0xf0, 0xa3, 0x74, 0x96, 0xf0} },
+{ 0x9620,	16,	{0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70, 0xf6, 0x7f, 0x02, 0x12, 0x81, 0x11, 0xc3} },
+{ 0x9630,	16,	{0xee, 0x64, 0x80, 0x94, 0x80, 0x40, 0xf3, 0xef, 0x54, 0x0f, 0xf5, 0x60, 0x90, 0x02, 0x95, 0xe0} },
+{ 0x9640,	16,	{0x55, 0x60, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x8f, 0x5f, 0x85, 0x64, 0x82, 0x85} },
+{ 0x9650,	16,	{0x63, 0x83, 0xe0, 0xb4, 0x05, 0x0c, 0xe5, 0x5f, 0x70, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00} },
+{ 0x9660,	16,	{0x8f, 0x5f, 0xe5, 0x5f, 0x70, 0x03, 0x02, 0x98, 0x4e, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3} },
+{ 0x9670,	16,	{0xa3, 0xe4, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67, 0x83, 0xe5, 0x60, 0xf0, 0x02, 0x98, 0x4e, 0x7e} },
+{ 0x9680,	16,	{0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xaf, 0x62, 0xae, 0x61, 0xe4, 0xfd, 0x12} },
+{ 0x9690,	16,	{0x81, 0xe0, 0x85, 0x62, 0x82, 0x85, 0x61, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x44, 0x80, 0xf0, 0x85} },
+{ 0x96a0,	16,	{0x62, 0x82, 0x85, 0x61, 0x83, 0x74, 0x01, 0xf0, 0xa3, 0xe4, 0xf0, 0x85, 0x62, 0x82, 0x85, 0x61} },
+{ 0x96b0,	16,	{0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0xd2, 0x04, 0x02, 0x98, 0x4e, 0xc2, 0x04, 0x7e} },
+{ 0x96c0,	16,	{0x20, 0x7f, 0x00, 0x75, 0x61, 0x20, 0x75, 0x62, 0x00, 0xe5, 0x62, 0x24, 0x05, 0xf5, 0x82, 0xe4} },
+{ 0x96d0,	16,	{0x35, 0x61, 0xf5, 0x83, 0xe0, 0x30, 0xe6, 0xf1, 0xaf, 0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81} },
+{ 0x96e0,	16,	{0xe0, 0x02, 0x98, 0x4e, 0xe4, 0xf5, 0x60, 0xf5, 0x5e, 0xe5, 0x5e, 0x75, 0xf0, 0x08, 0xa4, 0x24} },
+{ 0x96f0,	16,	{0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xf5, 0x61, 0x8f, 0x62, 0xfe, 0xe4, 0xfd, 0x12} },
+{ 0x9700,	16,	{0x81, 0xe0, 0xe5, 0x62, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x61, 0xf5, 0x83, 0xe0, 0x54, 0xfc} },
+{ 0x9710,	16,	{0xf0, 0xaf, 0x5e, 0x7d, 0x01, 0x7b, 0x01, 0x75, 0x6c, 0x80, 0x75, 0x6d, 0x40, 0x12, 0x92, 0xcc} },
+{ 0x9720,	16,	{0x8f, 0x60, 0xe5, 0x60, 0x70, 0x11, 0xaf, 0x5e, 0x7d, 0x02, 0x7b, 0x01, 0x75, 0x6c, 0x10, 0x75} },
+{ 0x9730,	16,	{0x6d, 0x20, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xe5, 0x60, 0x70, 0x10, 0xaf, 0x5e, 0x7d, 0x01, 0xfb} },
+{ 0x9740,	16,	{0x75, 0x6c, 0x80, 0x75, 0x6d, 0x40, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xe5, 0x60, 0x70, 0x10, 0xaf} },
+{ 0x9750,	16,	{0x5e, 0x7d, 0x02, 0xfb, 0x75, 0x6c, 0x10, 0x75, 0x6d, 0x20, 0x12, 0x92, 0xcc, 0x8f, 0x60, 0xaf} },
+{ 0x9760,	16,	{0x62, 0xae, 0x61, 0x7d, 0x01, 0x12, 0x81, 0xe0, 0xe5, 0x60, 0x60, 0x2b, 0x85, 0x66, 0x82, 0x85} },
+{ 0x9770,	16,	{0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0xe5, 0x5e, 0x04, 0xff, 0x05, 0x68, 0xe5, 0x68, 0xac, 0x67} },
+{ 0x9780,	16,	{0x70, 0x02, 0x05, 0x67, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x85, 0x68, 0x82, 0x85, 0x67} },
+{ 0x9790,	16,	{0x83, 0xe5, 0x60, 0xf0, 0x02, 0x98, 0x4e, 0x05, 0x5e, 0xe5, 0x5e, 0xd3, 0x94, 0x03, 0x50, 0x03} },
+{ 0x97a0,	16,	{0x02, 0x96, 0xe9, 0x02, 0x98, 0x4e, 0xe4, 0x90, 0x02, 0xd3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3} },
+{ 0x97b0,	16,	{0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0x74, 0x98, 0xf0, 0xa3, 0x74, 0x6d, 0xf0, 0x7e} },
+{ 0x97c0,	16,	{0x02, 0x7f, 0xd3, 0x12, 0x80, 0x00, 0xef, 0x64, 0x08, 0x70, 0x03, 0x02, 0x98, 0x4e, 0x85, 0x66} },
+{ 0x97d0,	16,	{0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0x80, 0x74, 0xe4, 0x90, 0x02, 0xd3, 0xf0, 0xa3} },
+{ 0x97e0,	16,	{0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xa3, 0xe5, 0x67, 0xf0, 0xa3} },
+{ 0x97f0,	16,	{0xe5, 0x68, 0xf0, 0x7e, 0x02, 0x7f, 0xd3, 0x12, 0x19, 0xc1, 0xef, 0x64, 0x08, 0x60, 0x4f, 0x85} },
+{ 0x9800,	16,	{0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4, 0xf0, 0x80, 0x43, 0xe4, 0x90, 0x02, 0xd3, 0xf0} },
+{ 0x9810,	16,	{0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0xa3, 0x74, 0x10, 0xf0, 0xe5, 0x64, 0x24, 0x02} },
+{ 0x9820,	16,	{0x90, 0x02, 0xda, 0xf0, 0xe4, 0x35, 0x63, 0x90, 0x02, 0xd9, 0xf0, 0x7e, 0x02, 0x7f, 0xd3, 0x12} },
+{ 0x9830,	16,	{0x80, 0x00, 0xef, 0x64, 0x08, 0x60, 0x17, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0xe4} },
+{ 0x9840,	16,	{0xf0, 0x80, 0x0b, 0x85, 0x66, 0x82, 0x85, 0x65, 0x83, 0xa3, 0xa3, 0x74, 0x01, 0xf0, 0x90, 0x01} },
+{ 0x9850,	16,	{0x5e, 0xe4, 0xf0, 0xa3, 0x74, 0x0a, 0xf0, 0x90, 0x01, 0x5e, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x70} },
+{ 0x9860,	12,	{0xf6, 0x90, 0x7f, 0xc3, 0x74, 0x24, 0xf0, 0xe4, 0x90, 0x02, 0x4d, 0xf0} },
+{ 0x986c,	1,	{0x22} },
+{ 0x986d,	16,	{0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0} },
+{ 0x987d,	16,	{0xe4, 0xfd, 0x74, 0x01, 0x7e, 0x00, 0xa8, 0x05, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, 0xce} },
+{ 0x988d,	16,	{0xd8, 0xf9, 0xff, 0xe5, 0x3b, 0xfb, 0xe4, 0xef, 0x5b, 0x70, 0x03, 0x02, 0x99, 0x45, 0xed, 0x75} },
+{ 0x989d,	16,	{0xf0, 0x08, 0xa4, 0x24, 0x00, 0xf5, 0x82, 0xe4, 0x34, 0x20, 0xaf, 0x82, 0xfe, 0xf5, 0x83, 0xe5} },
+{ 0x98ad,	16,	{0x82, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0xe0, 0x54, 0x60, 0x64, 0x60, 0x60} },
+{ 0x98bd,	16,	{0x03, 0x02, 0x99, 0x45, 0xef, 0x24, 0x06, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0xfc, 0x74} },
+{ 0x98cd,	16,	{0x36, 0x2d, 0xf8, 0xec, 0xf6, 0x30, 0xe5, 0x70, 0x74, 0x96, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x02} },
+{ 0x98dd,	16,	{0xf5, 0x83, 0xe0, 0x60, 0x63, 0xed, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5} },
+{ 0x98ed,	16,	{0x83, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x9a, 0xa4, 0x85, 0xf0, 0x82, 0xf5, 0x83, 0xe0, 0x8f, 0x82} },
+{ 0x98fd,	16,	{0x8e, 0x83, 0xf0, 0x74, 0x96, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x02, 0xf5, 0x83, 0xe0, 0x14, 0xf0} },
+{ 0x990d,	16,	{0x70, 0x36, 0xed, 0x25, 0xe0, 0x24, 0xc7, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0} },
+{ 0x991d,	16,	{0xed, 0x25, 0xe0, 0xff, 0xc3, 0x74, 0x0c, 0x9f, 0x75, 0xf0, 0x40, 0xa4, 0x24, 0x40, 0xf5, 0x82} },
+{ 0x992d,	16,	{0xe5, 0xf0, 0x34, 0x7b, 0xaf, 0x82, 0xfe, 0xed, 0x25, 0xe0, 0x24, 0x8d, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x993d,	16,	{0x02, 0xf5, 0x83, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x0d, 0xed, 0x64, 0x04, 0x60, 0x03, 0x02, 0x98} },
+{ 0x994d,	1,	{0x7f} },
+{ 0x994e,	1,	{0x22} },
+{ 0x994f,	16,	{0xe7, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e} },
+{ 0x995f,	16,	{0x88, 0x82, 0x8c, 0x83, 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08} },
+{ 0x996f,	16,	{0xdf, 0xfa, 0x80, 0x78, 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83} },
+{ 0x997f,	16,	{0xe3, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x64, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf6, 0x08} },
+{ 0x998f,	16,	{0xdf, 0xfa, 0x80, 0x58, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0xa3, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x4c} },
+{ 0x999f,	16,	{0x80, 0xd2, 0x80, 0xfa, 0x80, 0xc6, 0x80, 0xd4, 0x80, 0x69, 0x80, 0xf2, 0x80, 0x33, 0x80, 0x10} },
+{ 0x99af,	16,	{0x80, 0xa6, 0x80, 0xea, 0x80, 0x9a, 0x80, 0xa8, 0x80, 0xda, 0x80, 0xe2, 0x80, 0xca, 0x80, 0x33} },
+{ 0x99bf,	16,	{0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83} },
+{ 0x99cf,	16,	{0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xe9, 0xde, 0xe7, 0x80} },
+{ 0x99df,	16,	{0x0d, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf6, 0x08, 0xdf, 0xf9, 0xec, 0xfa, 0xa9, 0xf0} },
+{ 0x99ef,	16,	{0xed, 0xfb, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xec, 0xfa, 0xe0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc} },
+{ 0x99ff,	16,	{0xc5, 0x83, 0xcc, 0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xcc, 0xc5, 0x83, 0xcc, 0xdf, 0xea, 0xde} },
+{ 0x9a0f,	16,	{0xe8, 0x80, 0xdb, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc} },
+{ 0x9a1f,	16,	{0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xc2, 0xf5, 0x82, 0xeb, 0x24, 0x02, 0xb4} },
+{ 0x9a2f,	16,	{0x04, 0x00, 0x50, 0xb8, 0x23, 0x23, 0x45, 0x82, 0xf5, 0x82, 0xef, 0x4e, 0x60, 0xae, 0xef, 0x60} },
+{ 0x9a3f,	9,	{0x01, 0x0e, 0xe5, 0x82, 0x23, 0x90, 0x99, 0x9f, 0x73} },
+{ 0x9a48,	16,	{0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
+{ 0x9a58,	9,	{0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x9a61,	16,	{0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
+{ 0x9a71,	16,	{0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
+{ 0x9a81,	13,	{0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x9a8e,	16,	{0xc5, 0xf0, 0xf8, 0xa3, 0xe0, 0x28, 0xf0, 0xc5, 0xf0, 0xf8, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02} },
+{ 0x9a9e,	6,	{0x15, 0x83, 0xe0, 0x38, 0xf0, 0x22} },
+{ 0x9aa4,	16,	{0xa3, 0xf8, 0xe0, 0xc5, 0xf0, 0x25, 0xf0, 0xf0, 0xe5, 0x82, 0x15, 0x82, 0x70, 0x02, 0x15, 0x83} },
+{ 0x9ab4,	6,	{0xe0, 0xc8, 0x38, 0xf0, 0xe8, 0x22} },
+{ 0x9aba,	16,	{0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} },
+{ 0x9aca,	16,	{0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} },
+{ 0x9ada,	16,	{0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} },
+{ 0x9aea,	8,	{0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} },
+{ 0x9af2,	16,	{0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc} },
+{ 0x9b02,	16,	{0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, 0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40} },
+{ 0x9b12,	16,	{0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, 0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6} },
+{ 0x9b22,	16,	{0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, 0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9} },
+{ 0x9b32,	16,	{0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, 0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb} },
+{ 0x9b42,	16,	{0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb} },
+{ 0x9b52,	16,	{0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, 0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9} },
+{ 0x9b62,	16,	{0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc} },
+{ 0x9b72,	16,	{0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, 0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a} },
+{ 0x9b82,	16,	{0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, 0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f} },
+{ 0x9b92,	16,	{0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, 0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07} },
+{ 0x9ba2,	16,	{0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, 0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8} },
+{ 0x9bb2,	14,	{0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, 0xfa, 0xe4, 0xc8, 0xf9, 0x22} },
+{ 0x9bc0,	16,	{0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} },
+{ 0x9bd0,	1,	{0x22} },
+{ 0x9bd1,	16,	{0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, 0xee, 0x13, 0xfe, 0xef, 0x13, 0xff} },
+{ 0x9be1,	3,	{0xd8, 0xf1, 0x22} },
+{ 0x9be4,	16,	{0x08, 0x08, 0x08, 0xe6, 0xcf, 0x2f, 0xf6, 0x18, 0xe6, 0xce, 0x3e, 0xf6, 0x18, 0xe6, 0xcd, 0x3d} },
+{ 0x9bf4,	7,	{0xf6, 0x18, 0xe6, 0xcc, 0x3c, 0xf6, 0x22} },
+{ 0x9bfb,	12,	{0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x22} },
+{ 0x9c07,	16,	{0xa8, 0x82, 0x85, 0x83, 0xf0, 0xd0, 0x83, 0xd0, 0x82, 0x12, 0x9c, 0x1e, 0x12, 0x9c, 0x1e, 0x12} },
+{ 0x9c17,	16,	{0x9c, 0x1e, 0x12, 0x9c, 0x1e, 0xe4, 0x73, 0xe4, 0x93, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83} },
+{ 0x9c27,	16,	{0xc8, 0xc5, 0x82, 0xc8, 0xf0, 0xa3, 0xc5, 0x83, 0xc5, 0xf0, 0xc5, 0x83, 0xc8, 0xc5, 0x82, 0xc8} },
+{ 0x9c37,	1,	{0x22} },
+{ 0xffff,	0,	{0x00} }
+};
+
+#ifdef DEBUG
+static const struct whiteheat_hex_record whiteheat_loader[] = {
+{ 0x0000,	3,	{0x02, 0x09, 0x8d} },
+{ 0x0033,	3,	{0x02, 0x0e, 0x70} },
+{ 0x0043,	3,	{0x02, 0x0b, 0x00} },
+{ 0x004b,	3,	{0x02, 0x05, 0xb3} },
+{ 0x0100,	16,	{0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x10, 0xff, 0xc4, 0x54, 0x0f, 0x44, 0x50, 0xf5, 0x0f, 0x13, 0xe4} },
+{ 0x0110,	16,	{0x33, 0xf5, 0x11, 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5e, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x03} },
+{ 0x0120,	16,	{0x7c, 0x90, 0x01, 0x28, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x01, 0xbc, 0x02, 0x01, 0xbc, 0x02, 0x01} },
+{ 0x0130,	16,	{0x91, 0x02, 0x01, 0x3d, 0x02, 0x01, 0x53, 0x02, 0x01, 0x6f, 0x02, 0x01, 0x9a, 0x90, 0x7f, 0x00} },
+{ 0x0140,	16,	{0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} },
+{ 0x0150,	16,	{0x02, 0x03, 0x7c, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x90, 0x7f, 0x00, 0xf0, 0x90} },
+{ 0x0160,	16,	{0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03, 0x7c, 0x12} },
+{ 0x0170,	16,	{0x0a, 0x89, 0x50, 0x07, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x00, 0x74, 0x0f} },
+{ 0x0180,	16,	{0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03} },
+{ 0x0190,	16,	{0x7c, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0x02, 0x03, 0x7c, 0x90, 0x7f, 0x00, 0x74, 0x07, 0xf0} },
+{ 0x01a0,	16,	{0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xe8, 0x7e} },
+{ 0x01b0,	16,	{0x03, 0x12, 0x0d, 0xd5, 0xd2, 0x06, 0x12, 0x0d, 0x0d, 0x02, 0x03, 0x7c, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x01c0,	16,	{0x75, 0x29, 0x00, 0xf5, 0x2a, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x29, 0x90, 0x7f, 0xee, 0xe0} },
+{ 0x01d0,	16,	{0x75, 0x2b, 0x00, 0xf5, 0x2c, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x2b, 0x90, 0x7f, 0xe8, 0xe0} },
+{ 0x01e0,	16,	{0x64, 0xc0, 0x60, 0x03, 0x02, 0x02, 0xc9, 0xe5, 0x2c, 0x45, 0x2b, 0x70, 0x03, 0x02, 0x03, 0x7c} },
+{ 0x01f0,	16,	{0xc3, 0xe5, 0x2c, 0x94, 0x40, 0xe5, 0x2b, 0x94, 0x00, 0x50, 0x08, 0x85, 0x2b, 0x2d, 0x85, 0x2c} },
+{ 0x0200,	16,	{0x2e, 0x80, 0x06, 0x75, 0x2d, 0x00, 0x75, 0x2e, 0x40, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70} },
+{ 0x0210,	16,	{0x34, 0xf5, 0x31, 0xf5, 0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5, 0x31, 0x95, 0x2d, 0x50, 0x5c} },
+{ 0x0220,	16,	{0xe5, 0x2a, 0x25, 0x32, 0xf5, 0x82, 0xe5, 0x31, 0x35, 0x29, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00} },
+{ 0x0230,	16,	{0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70} },
+{ 0x0240,	16,	{0x02, 0x05, 0x31, 0x80, 0xd0, 0xe4, 0xf5, 0x31, 0xf5, 0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5} },
+{ 0x0250,	16,	{0x31, 0x95, 0x2d, 0x50, 0x18, 0x74, 0x00, 0x25, 0x32, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} },
+{ 0x0260,	16,	{0x74, 0xcd, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70, 0x02, 0x05, 0x31, 0x80, 0xdd, 0xaf, 0x2a, 0xae} },
+{ 0x0270,	16,	{0x29, 0xad, 0x2e, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x0b, 0xf4, 0x90, 0x7f, 0xb5, 0xe5} },
+{ 0x0280,	16,	{0x2e, 0xf0, 0xe5, 0x2e, 0x25, 0x2a, 0xf5, 0x2a, 0xe5, 0x2d, 0x35, 0x29, 0xf5, 0x29, 0xc3, 0xe5} },
+{ 0x0290,	16,	{0x2c, 0x95, 0x2e, 0xf5, 0x2c, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0x90, 0x7f, 0x92, 0xe0, 0xff} },
+{ 0x02a0,	16,	{0xc4, 0x54, 0x0f, 0x75, 0x2f, 0x00, 0xf5, 0x30, 0xd3, 0x94, 0x00, 0xe5, 0x2f, 0x94, 0x00, 0x50} },
+{ 0x02b0,	16,	{0x0c, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xb4} },
+{ 0x02c0,	16,	{0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x60} },
+{ 0x02d0,	16,	{0x03, 0x02, 0x03, 0x7c, 0xe5, 0x2c, 0x45, 0x2b, 0x70, 0x03, 0x02, 0x03, 0x7c, 0xe4, 0x90, 0x7f} },
+{ 0x02e0,	16,	{0xc5, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x75, 0x2f, 0x00, 0xf5, 0x30, 0xd3} },
+{ 0x02f0,	16,	{0x94, 0x00, 0xe5, 0x2f, 0x94, 0x00, 0x50, 0x09, 0x90, 0x7f, 0xc4, 0xe0, 0x30, 0xe1, 0x09, 0x80} },
+{ 0x0300,	16,	{0xf7, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f, 0xc5, 0xe0, 0x75, 0x2d, 0x00, 0xf5} },
+{ 0x0310,	16,	{0x2e, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70, 0x38, 0x90, 0x20, 0x6b, 0xf0, 0xf5, 0x31, 0xf5} },
+{ 0x0320,	16,	{0x32, 0xc3, 0xe5, 0x32, 0x95, 0x2e, 0xe5, 0x31, 0x95, 0x2d, 0x50, 0x34, 0x74, 0xc0, 0x25, 0x32} },
+{ 0x0330,	16,	{0xf5, 0x82, 0xe4, 0x34, 0x7e, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x2a, 0x25, 0x32, 0xf5, 0x82, 0xe5} },
+{ 0x0340,	16,	{0x31, 0x35, 0x29, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x32, 0xe5, 0x32, 0x70, 0x02, 0x05, 0x31, 0x80} },
+{ 0x0350,	16,	{0xd0, 0xaf, 0x2a, 0xae, 0x29, 0xad, 0x2e, 0x7a, 0x7e, 0x79, 0xc0, 0x7b, 0xc0, 0x12, 0x0c, 0x80} },
+{ 0x0360,	16,	{0xe5, 0x2e, 0x25, 0x2a, 0xf5, 0x2a, 0xe5, 0x2d, 0x35, 0x29, 0xf5, 0x29, 0xc3, 0xe5, 0x2c, 0x95} },
+{ 0x0370,	13,	{0x2e, 0xf5, 0x2c, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0x02, 0x02, 0xd4, 0xc3} },
+{ 0x037d,	1,	{0x22} },
+{ 0x037e,	16,	{0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x56, 0x14, 0x70, 0x03, 0x02, 0x04, 0xd2, 0x24} },
+{ 0x038e,	16,	{0xfe, 0x70, 0x03, 0x02, 0x05, 0x46, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x50, 0x14, 0x70, 0x03} },
+{ 0x039e,	16,	{0x02, 0x04, 0x4a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3e, 0x14, 0x70, 0x03, 0x02, 0x04, 0x44, 0x24} },
+{ 0x03ae,	16,	{0x05, 0x60, 0x03, 0x02, 0x05, 0x9a, 0x12, 0x0e, 0x7b, 0x40, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f} },
+{ 0x03be,	16,	{0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02, 0x70, 0x69, 0x74, 0x11, 0x90} },
+{ 0x03ce,	16,	{0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x03de,	16,	{0xff, 0x12, 0x0b, 0x58, 0x8b, 0x26, 0x8a, 0x27, 0x89, 0x28, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02} },
+{ 0x03ee,	16,	{0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90} },
+{ 0x03fe,	16,	{0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x0c} },
+{ 0x040e,	16,	{0x3f, 0x8b, 0x26, 0x8a, 0x27, 0x89, 0x28, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f} },
+{ 0x041e,	16,	{0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0} },
+{ 0x042e,	16,	{0x44, 0x01, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xab} },
+{ 0x043e,	16,	{0x12, 0x0e, 0x52, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x60, 0x02, 0x05, 0xab, 0x12, 0x0a, 0xf7, 0x02} },
+{ 0x044e,	16,	{0x05, 0xab, 0x12, 0x08, 0xf1, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x7d, 0x40, 0x03, 0x02, 0x05, 0xab} },
+{ 0x045e,	16,	{0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} },
+{ 0x046e,	16,	{0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} },
+{ 0x047e,	16,	{0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0xe4, 0x90, 0x7f, 0x00} },
+{ 0x048e,	16,	{0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xec, 0xe0} },
+{ 0x049e,	16,	{0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} },
+{ 0x04ae,	16,	{0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} },
+{ 0x04be,	16,	{0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} },
+{ 0x04ce,	16,	{0xf0, 0x02, 0x05, 0xab, 0x12, 0x0e, 0x7f, 0x40, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xe8, 0xe0} },
+{ 0x04de,	16,	{0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xea, 0xe0, 0xb4} },
+{ 0x04ee,	16,	{0x01, 0x05, 0xc2, 0x00, 0x02, 0x05, 0xab, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05} },
+{ 0x04fe,	16,	{0xab, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} },
+{ 0x050e,	16,	{0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} },
+{ 0x051e,	16,	{0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f} },
+{ 0x052e,	16,	{0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x6e, 0x90} },
+{ 0x053e,	16,	{0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x65, 0x12, 0x0e, 0x81, 0x50, 0x60, 0x90, 0x7f, 0xe8} },
+{ 0x054e,	16,	{0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x54, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} },
+{ 0x055e,	16,	{0xd2, 0x00, 0x80, 0x49, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x40, 0x90, 0x7f, 0xea} },
+{ 0x056e,	16,	{0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} },
+{ 0x057e,	16,	{0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} },
+{ 0x058e,	16,	{0xf0, 0x80, 0x1a, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x11, 0xe4, 0x90, 0x20, 0x6a} },
+{ 0x059e,	16,	{0xf0, 0x12, 0x01, 0x00, 0x50, 0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4} },
+{ 0x05ae,	4,	{0xe0, 0x44, 0x02, 0xf0} },
+{ 0x05b2,	1,	{0x22} },
+{ 0x05b3,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
+{ 0x05c3,	16,	{0xd0, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0xa5} },
+{ 0x05d3,	16,	{0xe0, 0x30, 0xe2, 0x06, 0x75, 0x0d, 0x06, 0x02, 0x06, 0x7f, 0x90, 0x7f, 0xa5, 0xe0, 0x20, 0xe1} },
+{ 0x05e3,	16,	{0x0c, 0xe5, 0x0d, 0x64, 0x02, 0x60, 0x06, 0x75, 0x0d, 0x07, 0x02, 0x06, 0x7f, 0xaf, 0x0d, 0xef} },
+{ 0x05f3,	16,	{0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04, 0x60, 0x03, 0x02} },
+{ 0x0603,	16,	{0x06, 0x7f, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xaf, 0x0c, 0x05, 0x0c, 0x8f, 0x82, 0x75, 0x83} },
+{ 0x0613,	16,	{0x00, 0x12, 0x07, 0x85, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x0c, 0x65, 0x08, 0x70, 0x5e, 0x75, 0x0d} },
+{ 0x0623,	16,	{0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e} },
+{ 0x0633,	16,	{0x82, 0x75, 0x83, 0x00, 0x12, 0x07, 0xb2, 0x75, 0x0d, 0x02, 0x80, 0x40, 0xe5, 0x08, 0x24, 0xfe} },
+{ 0x0643,	16,	{0xb5, 0x0c, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x08, 0x14, 0xb5, 0x0c, 0x0a} },
+{ 0x0653,	16,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09} },
+{ 0x0663,	16,	{0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x07, 0xb2, 0x05, 0x0c} },
+{ 0x0673,	16,	{0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x53, 0x91, 0xdf, 0xd0} },
+{ 0x0683,	16,	{0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0} },
+{ 0x0693,	10,	{0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x069d,	16,	{0xc2, 0x04, 0xd2, 0x05, 0xe4, 0xf5, 0x25, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2, 0x01, 0x12} },
+{ 0x06ad,	16,	{0x0e, 0x74, 0xd2, 0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9} },
+{ 0x06bd,	16,	{0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90} },
+{ 0x06cd,	16,	{0x7f, 0x93, 0x74, 0x30, 0xf0, 0x12, 0x0a, 0x19, 0x75, 0x24, 0x48, 0x75, 0x23, 0x92, 0x75, 0x22} },
+{ 0x06dd,	16,	{0x00, 0x75, 0x21, 0x00, 0xe4, 0xff, 0xfe, 0x7e, 0x05, 0x90, 0x20, 0x68, 0x74, 0x01, 0xf0, 0xa3} },
+{ 0x06ed,	16,	{0xde, 0xfc, 0x7e, 0x00, 0x7f, 0x05, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae} },
+{ 0x06fd,	16,	{0xe0, 0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0x12, 0x0e, 0x68, 0x30, 0x01, 0x0a, 0xe4, 0x90, 0x20, 0x69} },
+{ 0x070d,	16,	{0xf0, 0x12, 0x03, 0x7e, 0xc2, 0x01, 0x30, 0x04, 0x1a, 0x12, 0x0e, 0x77, 0x50, 0x13, 0x12, 0x09} },
+{ 0x071d,	16,	{0x00, 0x30, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0xf3, 0x12, 0x0d, 0x8b, 0x12, 0x0e} },
+{ 0x072d,	16,	{0x79, 0xc2, 0x03, 0x7f, 0xff, 0x7e, 0xff, 0x7d, 0xff, 0x7c, 0xff, 0x78, 0x21, 0x12, 0x08, 0x1d} },
+{ 0x073d,	16,	{0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xc3, 0x12, 0x08, 0x0c, 0x70, 0x1b, 0x75, 0x24} },
+{ 0x074d,	16,	{0x48, 0x75, 0x23, 0x92, 0xf5, 0x22, 0xf5, 0x21, 0x63, 0x25, 0xff, 0x90, 0x20, 0x68, 0xe5, 0x25} },
+{ 0x075d,	14,	{0xf0, 0xa3, 0x74, 0x01, 0xf0, 0xa3, 0xf0, 0xa3, 0xf0, 0x12, 0x08, 0xff, 0x80, 0x9b} },
+{ 0x076b,	1,	{0x22} },
+{ 0x076c,	16,	{0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
+{ 0x077c,	9,	{0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x0785,	16,	{0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
+{ 0x0795,	16,	{0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
+{ 0x07a5,	13,	{0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x07b2,	16,	{0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0} },
+{ 0x07c2,	16,	{0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8} },
+{ 0x07d2,	2,	{0xf2, 0x22} },
+{ 0x07d4,	16,	{0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} },
+{ 0x07e4,	16,	{0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} },
+{ 0x07f4,	16,	{0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} },
+{ 0x0804,	8,	{0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} },
+{ 0x080c,	16,	{0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} },
+{ 0x081c,	1,	{0x22} },
+{ 0x081d,	16,	{0x08, 0x08, 0x08, 0xe6, 0x2f, 0xff, 0xf6, 0x18, 0xe6, 0x3e, 0xfe, 0xf6, 0x18, 0xe6, 0x3d, 0xfd} },
+{ 0x082d,	7,	{0xf6, 0x18, 0xe6, 0x3c, 0xfc, 0xf6, 0x22} },
+{ 0x0834,	4,	{0x8c, 0x34, 0x8d, 0x35} },
+{ 0x0838,	16,	{0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0xe4, 0xf5, 0x36, 0xf5, 0x37, 0xc3, 0xe5, 0x37, 0x95} },
+{ 0x0848,	16,	{0x35, 0xe5, 0x36, 0x95, 0x34, 0x50, 0x69, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5} },
+{ 0x0858,	16,	{0x83, 0x74, 0xff, 0xf0, 0xf4, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36} },
+{ 0x0868,	16,	{0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36} },
+{ 0x0878,	16,	{0x3e, 0xf5, 0x83, 0x74, 0xaa, 0xf0, 0x64, 0xaa, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x37, 0xf5} },
+{ 0x0888,	16,	{0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0x74, 0x55, 0xf0, 0x64, 0x55, 0x60, 0x02, 0xc3, 0x22, 0xad} },
+{ 0x0898,	16,	{0x37, 0xe5, 0x37, 0x2f, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xed, 0xf0, 0xfc, 0xac, 0x05} },
+{ 0x08a8,	16,	{0xed, 0x6c, 0x60, 0x02, 0xc3, 0x22, 0x05, 0x37, 0xe5, 0x37, 0x70, 0x02, 0x05, 0x36, 0x80, 0x8c} },
+{ 0x08b8,	16,	{0xe4, 0xf5, 0x36, 0xf5, 0x37, 0xc3, 0xe5, 0x37, 0x95, 0x35, 0xe5, 0x36, 0x95, 0x34, 0x50, 0x27} },
+{ 0x08c8,	16,	{0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xe0, 0x65, 0x37, 0x60, 0x02, 0xc3} },
+{ 0x08d8,	16,	{0x22, 0xef, 0x25, 0x37, 0xf5, 0x82, 0xe5, 0x36, 0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x37, 0xe5} },
+{ 0x08e8,	8,	{0x37, 0x70, 0x02, 0x05, 0x36, 0x80, 0xce, 0xd3} },
+{ 0x08f0,	1,	{0x22} },
+{ 0x08f1,	14,	{0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} },
+{ 0x08ff,	1,	{0x22} },
+{ 0x0900,	9,	{0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} },
+{ 0x097d,	16,	{0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} },
+{ 0x098d,	12,	{0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x3a, 0x02, 0x09, 0xd4} },
+{ 0x0999,	16,	{0x02, 0x06, 0x9d, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
+{ 0x09a9,	16,	{0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
+{ 0x09b9,	16,	{0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
+{ 0x09c9,	16,	{0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0e, 0x2d, 0xe4, 0x7e} },
+{ 0x09d9,	16,	{0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
+{ 0x09e9,	16,	{0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
+{ 0x09f9,	16,	{0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
+{ 0x0a09,	16,	{0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
+{ 0x0a19,	16,	{0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0x74, 0x89} },
+{ 0x0a29,	16,	{0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0xd5, 0x90, 0x7f} },
+{ 0x0a39,	16,	{0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x0a49,	16,	{0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05} },
+{ 0x0a59,	16,	{0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x0a69,	16,	{0x12, 0x0d, 0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d} },
+{ 0x0a79,	16,	{0xd5, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d, 0xd5, 0x22} },
+{ 0x0a89,	16,	{0x75, 0x33, 0x01, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x01, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x0e} },
+{ 0x0a99,	16,	{0x7d, 0x00, 0x7c, 0x01, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12} },
+{ 0x0aa9,	16,	{0x0e, 0x18, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x02, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x80, 0x7d} },
+{ 0x0ab9,	16,	{0x00, 0x7c, 0x80, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0e} },
+{ 0x0ac9,	16,	{0x18, 0xe5, 0x33, 0x60, 0x1b, 0x7f, 0x03, 0x12, 0x0e, 0x18, 0x7f, 0x00, 0x7e, 0x20, 0x7d, 0x40} },
+{ 0x0ad9,	16,	{0x7c, 0x5b, 0x12, 0x08, 0x34, 0xe4, 0x33, 0xf5, 0x33, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0e, 0x18} },
+{ 0x0ae9,	13,	{0xe5, 0x33, 0x60, 0x05, 0xe4, 0xff, 0x12, 0x0e, 0x18, 0xe5, 0x33, 0x24, 0xff} },
+{ 0x0af6,	1,	{0x22} },
+{ 0x0af7,	8,	{0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x10, 0xd3, 0x22} },
+{ 0x0aff,	1,	{0x32} },
+{ 0x0b00,	16,	{0x02, 0x0d, 0xa5, 0x00, 0x02, 0x0d, 0xec, 0x00, 0x02, 0x0d, 0x70, 0x00, 0x02, 0x0d, 0xbd, 0x00} },
+{ 0x0b10,	16,	{0x02, 0x0e, 0x02, 0x00, 0x02, 0x0a, 0xff, 0x00, 0x02, 0x0e, 0x83, 0x00, 0x02, 0x0e, 0x84, 0x00} },
+{ 0x0b20,	16,	{0x02, 0x0e, 0x85, 0x00, 0x02, 0x0e, 0x86, 0x00, 0x02, 0x0e, 0x87, 0x00, 0x02, 0x0e, 0x88, 0x00} },
+{ 0x0b30,	16,	{0x02, 0x0e, 0x89, 0x00, 0x02, 0x0e, 0x8a, 0x00, 0x02, 0x0e, 0x8b, 0x00, 0x02, 0x0e, 0x8c, 0x00} },
+{ 0x0b40,	16,	{0x02, 0x0e, 0x8d, 0x00, 0x02, 0x0e, 0x8e, 0x00, 0x02, 0x0e, 0x8f, 0x00, 0x02, 0x0e, 0x90, 0x00} },
+{ 0x0b50,	8,	{0x02, 0x0e, 0x91, 0x00, 0x02, 0x0e, 0x92, 0x00} },
+{ 0x0b58,	16,	{0xe4, 0xfe, 0x75, 0x2b, 0xff, 0x75, 0x2c, 0x11, 0x75, 0x2d, 0x12, 0xab, 0x2b, 0xaa, 0x2c, 0xa9} },
+{ 0x0b68,	16,	{0x2d, 0x90, 0x00, 0x01, 0x12, 0x07, 0x85, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} },
+{ 0x0b78,	16,	{0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x07, 0xd4, 0x85, 0xf0, 0x29, 0xf5, 0x2a, 0x62, 0x29} },
+{ 0x0b88,	16,	{0xe5, 0x29, 0x62, 0x2a, 0xe5, 0x2a, 0x62, 0x29, 0x29, 0xfd, 0xe5, 0x29, 0x3a, 0xa9, 0x05, 0x75} },
+{ 0x0b98,	14,	{0x2b, 0xff, 0xf5, 0x2c, 0x89, 0x2d, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x0ba6,	1,	{0x22} },
+{ 0x0ba7,	6,	{0xab, 0x07, 0xaa, 0x06, 0xac, 0x05} },
+{ 0x0bad,	16,	{0xe4, 0xfd, 0xe5, 0x11, 0x60, 0x11, 0xea, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x10, 0xf5, 0x82} },
+{ 0x0bbd,	16,	{0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05, 0x0d, 0x74, 0x10, 0x2e, 0xf5, 0x82} },
+{ 0x0bcd,	16,	{0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d, 0x74, 0x10, 0x2f, 0xf5, 0x82, 0xe4} },
+{ 0x0bdd,	16,	{0x34, 0x0f, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f, 0x7b, 0x10, 0x12, 0x0d, 0x51, 0x7f} },
+{ 0x0bed,	6,	{0x0a, 0x7e, 0x00, 0x12, 0x0d, 0xd5} },
+{ 0x0bf3,	1,	{0x22} },
+{ 0x0bf4,	10,	{0x8e, 0x33, 0x8f, 0x34, 0x8d, 0x35, 0x8a, 0x36, 0x8b, 0x37} },
+{ 0x0bfe,	16,	{0xe4, 0xfd, 0xf5, 0x38, 0xe5, 0x11, 0x60, 0x12, 0xe5, 0x33, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24} },
+{ 0x0c0e,	16,	{0x13, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x34, 0xae, 0x05, 0x0d, 0x74} },
+{ 0x0c1e,	16,	{0x13, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xe5, 0x34, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f} },
+{ 0x0c2e,	16,	{0x7b, 0x13, 0x12, 0x0d, 0x51, 0xaf, 0x0f, 0xad, 0x35, 0xab, 0x37, 0xaa, 0x36, 0x12, 0x0d, 0x32} },
+{ 0x0c3e,	1,	{0x22} },
+{ 0x0c3f,	2,	{0x8f, 0x29} },
+{ 0x0c41,	16,	{0xe4, 0xf5, 0x2a, 0x75, 0x2b, 0xff, 0x75, 0x2c, 0x11, 0x75, 0x2d, 0x32, 0xab, 0x2b, 0xaa, 0x2c} },
+{ 0x0c51,	16,	{0xa9, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x07, 0x85, 0xb4, 0x03, 0x1d, 0xaf, 0x2a, 0x05, 0x2a, 0xef} },
+{ 0x0c61,	16,	{0xb5, 0x29, 0x01, 0x22, 0x12, 0x07, 0x6c, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
+{ 0x0c71,	14,	{0x2b, 0xff, 0xf5, 0x2c, 0x89, 0x2d, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x0c7f,	1,	{0x22} },
+{ 0x0c80,	10,	{0x8e, 0x33, 0x8f, 0x34, 0x8d, 0x35, 0x8a, 0x36, 0x8b, 0x37} },
+{ 0x0c8a,	16,	{0xe4, 0xf5, 0x38, 0xe5, 0x38, 0xc3, 0x95, 0x35, 0x50, 0x20, 0x05, 0x34, 0xe5, 0x34, 0xae, 0x33} },
+{ 0x0c9a,	16,	{0x70, 0x02, 0x05, 0x33, 0x14, 0xff, 0xe5, 0x37, 0x25, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x36, 0xf5} },
+{ 0x0caa,	10,	{0x83, 0xe0, 0xfd, 0x12, 0x0b, 0xa7, 0x05, 0x38, 0x80, 0xd9} },
+{ 0x0cb4,	1,	{0x22} },
+{ 0x0cb5,	16,	{0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} },
+{ 0x0cc5,	16,	{0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a} },
+{ 0x0cd5,	13,	{0x0a, 0x89, 0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x03, 0xd3, 0x22, 0xc3, 0x22} },
+{ 0x0ce2,	16,	{0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} },
+{ 0x0cf2,	16,	{0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a, 0x0a, 0x89} },
+{ 0x0d02,	11,	{0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x01, 0xd3, 0x22, 0xc3, 0x22} },
+{ 0x0d0d,	16,	{0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x06, 0x04, 0xe0, 0x44} },
+{ 0x0d1d,	16,	{0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x0d, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
+{ 0x0d2d,	5,	{0xe0, 0x44, 0x04, 0xf0, 0x22} },
+{ 0x0d32,	16,	{0x12, 0x0c, 0xb5, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} },
+{ 0x0d42,	15,	{0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} },
+{ 0x0d51,	16,	{0x12, 0x0c, 0xe2, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} },
+{ 0x0d61,	15,	{0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} },
+{ 0x0d70,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0d80,	11,	{0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d8b,	16,	{0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12} },
+{ 0x0d9b,	10,	{0x0d, 0xd5, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} },
+{ 0x0da5,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} },
+{ 0x0db5,	8,	{0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dbd,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x03, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} },
+{ 0x0dcd,	8,	{0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dd5,	16,	{0x8e, 0x39, 0x8f, 0x3a, 0xe5, 0x3a, 0x15, 0x3a, 0xae, 0x39, 0x70, 0x02, 0x15, 0x39, 0x4e, 0x60} },
+{ 0x0de5,	7,	{0x05, 0x12, 0x0e, 0x41, 0x80, 0xee, 0x22} },
+{ 0x0dec,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0} },
+{ 0x0dfc,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0e02,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} },
+{ 0x0e12,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0e18,	16,	{0xae, 0x07, 0x7f, 0x21, 0x7d, 0x01, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xab, 0x82} },
+{ 0x0e28,	5,	{0xfa, 0x12, 0x0d, 0x51, 0x22} },
+{ 0x0e2d,	16,	{0x50, 0x0f, 0x00, 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6} },
+{ 0x0e3d,	3,	{0xa1, 0x86, 0x8e} },
+{ 0x0e40,	1,	{0x00} },
+{ 0x0e41,	16,	{0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
+{ 0x0e51,	1,	{0x22} },
+{ 0x0e52,	14,	{0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} },
+{ 0x0e60,	8,	{0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22} },
+{ 0x0e68,	8,	{0xe4, 0xf5, 0x0d, 0xd2, 0xe9, 0xd2, 0xaf, 0x22} },
+{ 0x0e70,	4,	{0x53, 0xd8, 0xef, 0x32} },
+{ 0x0e74,	3,	{0xd2, 0x00, 0x22} },
+{ 0x0e77,	2,	{0xd3, 0x22} },
+{ 0x0e79,	2,	{0xd3, 0x22} },
+{ 0x0e7b,	2,	{0xd3, 0x22} },
+{ 0x0e7d,	2,	{0xd3, 0x22} },
+{ 0x0e7f,	2,	{0xd3, 0x22} },
+{ 0x0e81,	2,	{0xd3, 0x22} },
+{ 0x0e83,	1,	{0x32} },
+{ 0x0e84,	1,	{0x32} },
+{ 0x0e85,	1,	{0x32} },
+{ 0x0e86,	1,	{0x32} },
+{ 0x0e87,	1,	{0x32} },
+{ 0x0e88,	1,	{0x32} },
+{ 0x0e89,	1,	{0x32} },
+{ 0x0e8a,	1,	{0x32} },
+{ 0x0e8b,	1,	{0x32} },
+{ 0x0e8c,	1,	{0x32} },
+{ 0x0e8d,	1,	{0x32} },
+{ 0x0e8e,	1,	{0x32} },
+{ 0x0e8f,	1,	{0x32} },
+{ 0x0e90,	1,	{0x32} },
+{ 0x0e91,	1,	{0x32} },
+{ 0x0e92,	1,	{0x32} },
+{ 0x1100,	16,	{0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x47, 0x05, 0x10, 0x27, 0x01, 0x00, 0x01, 0x02} },
+{ 0x1110,	16,	{0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x03, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02} },
+{ 0x1120,	16,	{0xff, 0x00, 0x00, 0x04, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} },
+{ 0x1130,	16,	{0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x41, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x68, 0x00} },
+{ 0x1140,	16,	{0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00} },
+{ 0x1150,	16,	{0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x28, 0x03, 0x46, 0x00} },
+{ 0x1160,	16,	{0x69, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00} },
+{ 0x1170,	16,	{0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x72, 0x00} },
+{ 0x1180,	16,	{0x6b, 0x00, 0x73, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} },
+{ 0x1190,	16,	{0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} },
+{ 0x11a0,	16,	{0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} },
+{ 0x11b0,	16,	{0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} },
+{ 0x11c0,	16,	{0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} },
+{ 0x11d0,	2,	{0x00, 0x00} },
+{ 0xffff,	0,	{0x00} }
+};
+
+#else
+
+static const struct whiteheat_hex_record whiteheat_loader[] = {
+{ 0x0000,	3,	{0x02, 0x09, 0x8d} },
+{ 0x0033,	3,	{0x02, 0x08, 0xfb} },
+{ 0x0043,	3,	{0x02, 0x0b, 0x00} },
+{ 0x004b,	3,	{0x02, 0x05, 0xaa} },
+{ 0x0100,	16,	{0x90, 0x7f, 0xa5, 0xe0, 0x54, 0x10, 0xff, 0xc4, 0x54, 0x0f, 0x44, 0x50, 0xf5, 0x0f, 0x13, 0xe4} },
+{ 0x0110,	16,	{0x33, 0xf5, 0x11, 0x90, 0x7f, 0xe9, 0xe0, 0x24, 0x5e, 0xb4, 0x07, 0x00, 0x40, 0x03, 0x02, 0x03} },
+{ 0x0120,	16,	{0x78, 0x90, 0x01, 0x28, 0xf8, 0x28, 0x28, 0x73, 0x02, 0x01, 0xbc, 0x02, 0x01, 0xbc, 0x02, 0x01} },
+{ 0x0130,	16,	{0x91, 0x02, 0x01, 0x3d, 0x02, 0x01, 0x53, 0x02, 0x01, 0x6f, 0x02, 0x01, 0x9a, 0x90, 0x7f, 0x00} },
+{ 0x0140,	16,	{0xe5, 0x11, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} },
+{ 0x0150,	16,	{0x02, 0x03, 0x78, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x90, 0x7f, 0x00, 0xf0, 0x90} },
+{ 0x0160,	16,	{0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03, 0x78, 0x12} },
+{ 0x0170,	16,	{0x0a, 0x89, 0x50, 0x07, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0x80, 0x06, 0x90, 0x7f, 0x00, 0x74, 0x0f} },
+{ 0x0180,	16,	{0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x03} },
+{ 0x0190,	16,	{0x78, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0f, 0x02, 0x03, 0x78, 0x90, 0x7f, 0x00, 0x74, 0x07, 0xf0} },
+{ 0x01a0,	16,	{0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x7f, 0xe8, 0x7e} },
+{ 0x01b0,	16,	{0x03, 0x12, 0x0d, 0x94, 0xd2, 0x06, 0x12, 0x0c, 0xcc, 0x02, 0x03, 0x78, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x01c0,	16,	{0x75, 0x28, 0x00, 0xf5, 0x29, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x28, 0x90, 0x7f, 0xee, 0xe0} },
+{ 0x01d0,	16,	{0x75, 0x2a, 0x00, 0xf5, 0x2b, 0xa3, 0xe0, 0xfe, 0xe4, 0xee, 0x42, 0x2a, 0x90, 0x7f, 0xe8, 0xe0} },
+{ 0x01e0,	16,	{0x64, 0xc0, 0x60, 0x03, 0x02, 0x02, 0xc9, 0xe5, 0x2b, 0x45, 0x2a, 0x70, 0x03, 0x02, 0x03, 0x78} },
+{ 0x01f0,	16,	{0xc3, 0xe5, 0x2b, 0x94, 0x40, 0xe5, 0x2a, 0x94, 0x00, 0x50, 0x08, 0x85, 0x2a, 0x2c, 0x85, 0x2b} },
+{ 0x0200,	16,	{0x2d, 0x80, 0x06, 0x75, 0x2c, 0x00, 0x75, 0x2d, 0x40, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70} },
+{ 0x0210,	16,	{0x34, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31, 0x95, 0x2d, 0xe5, 0x30, 0x95, 0x2c, 0x50, 0x5c} },
+{ 0x0220,	16,	{0xe5, 0x29, 0x25, 0x31, 0xf5, 0x82, 0xe5, 0x30, 0x35, 0x28, 0xf5, 0x83, 0xe0, 0xff, 0x74, 0x00} },
+{ 0x0230,	16,	{0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70} },
+{ 0x0240,	16,	{0x02, 0x05, 0x30, 0x80, 0xd0, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31, 0x95, 0x2d, 0xe5} },
+{ 0x0250,	16,	{0x30, 0x95, 0x2c, 0x50, 0x18, 0x74, 0x00, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83} },
+{ 0x0260,	16,	{0x74, 0xcd, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70, 0x02, 0x05, 0x30, 0x80, 0xdd, 0xaf, 0x29, 0xae} },
+{ 0x0270,	16,	{0x28, 0xad, 0x2d, 0x7a, 0x7f, 0x79, 0x00, 0x7b, 0x00, 0x12, 0x0b, 0xf4, 0x90, 0x7f, 0xb5, 0xe5} },
+{ 0x0280,	16,	{0x2d, 0xf0, 0xe5, 0x2d, 0x25, 0x29, 0xf5, 0x29, 0xe5, 0x2c, 0x35, 0x28, 0xf5, 0x28, 0xc3, 0xe5} },
+{ 0x0290,	16,	{0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0xe5, 0x2a, 0x95, 0x2c, 0xf5, 0x2a, 0x90, 0x7f, 0x92, 0xe0, 0xff} },
+{ 0x02a0,	16,	{0xc4, 0x54, 0x0f, 0x75, 0x2e, 0x00, 0xf5, 0x2f, 0xd3, 0x94, 0x00, 0xe5, 0x2e, 0x94, 0x00, 0x50} },
+{ 0x02b0,	16,	{0x0c, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe1, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xb4} },
+{ 0x02c0,	16,	{0xe0, 0x20, 0xe2, 0x03, 0x02, 0x01, 0xe7, 0x80, 0xf4, 0x90, 0x7f, 0xe8, 0xe0, 0x64, 0x40, 0x60} },
+{ 0x02d0,	16,	{0x03, 0x02, 0x03, 0x78, 0xe5, 0x2b, 0x45, 0x2a, 0x70, 0x03, 0x02, 0x03, 0x78, 0xe4, 0x90, 0x7f} },
+{ 0x02e0,	16,	{0xc5, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0xff, 0xc4, 0x54, 0x0f, 0x75, 0x2e, 0x00, 0xf5, 0x2f, 0xd3} },
+{ 0x02f0,	16,	{0x94, 0x00, 0xe5, 0x2e, 0x94, 0x00, 0x50, 0x09, 0x90, 0x7f, 0xc4, 0xe0, 0x30, 0xe1, 0x09, 0x80} },
+{ 0x0300,	16,	{0xf7, 0x90, 0x7f, 0xb4, 0xe0, 0x20, 0xe3, 0xf9, 0x90, 0x7f, 0xc5, 0xe0, 0x75, 0x2c, 0x00, 0xf5} },
+{ 0x0310,	16,	{0x2d, 0x90, 0x7f, 0xe9, 0xe0, 0x64, 0xa3, 0x70, 0x34, 0xf5, 0x30, 0xf5, 0x31, 0xc3, 0xe5, 0x31} },
+{ 0x0320,	16,	{0x95, 0x2d, 0xe5, 0x30, 0x95, 0x2c, 0x50, 0x34, 0x74, 0xc0, 0x25, 0x31, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x0330,	1,	{0x7e} },
+{ 0x0331,	16,	{0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x29, 0x25, 0x31, 0xf5, 0x82, 0xe5, 0x30, 0x35, 0x28, 0xf5, 0x83} },
+{ 0x0341,	16,	{0xef, 0xf0, 0x05, 0x31, 0xe5, 0x31, 0x70, 0x02, 0x05, 0x30, 0x80, 0xd0, 0xaf, 0x29, 0xae, 0x28} },
+{ 0x0351,	16,	{0xad, 0x2d, 0x7a, 0x7e, 0x79, 0xc0, 0x7b, 0xc0, 0x12, 0x0c, 0x3f, 0xe5, 0x2d, 0x25, 0x29, 0xf5} },
+{ 0x0361,	16,	{0x29, 0xe5, 0x2c, 0x35, 0x28, 0xf5, 0x28, 0xc3, 0xe5, 0x2b, 0x95, 0x2d, 0xf5, 0x2b, 0xe5, 0x2a} },
+{ 0x0371,	9,	{0x95, 0x2c, 0xf5, 0x2a, 0x02, 0x02, 0xd4, 0xc3, 0x22} },
+{ 0x037a,	16,	{0x90, 0x7f, 0xe9, 0xe0, 0x70, 0x03, 0x02, 0x04, 0x52, 0x14, 0x70, 0x03, 0x02, 0x04, 0xce, 0x24} },
+{ 0x038a,	16,	{0xfe, 0x70, 0x03, 0x02, 0x05, 0x42, 0x24, 0xfb, 0x70, 0x03, 0x02, 0x04, 0x4c, 0x14, 0x70, 0x03} },
+{ 0x039a,	16,	{0x02, 0x04, 0x46, 0x14, 0x70, 0x03, 0x02, 0x04, 0x3a, 0x14, 0x70, 0x03, 0x02, 0x04, 0x40, 0x24} },
+{ 0x03aa,	16,	{0x05, 0x60, 0x03, 0x02, 0x05, 0x96, 0x12, 0x0e, 0x44, 0x40, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f} },
+{ 0x03ba,	16,	{0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x16, 0x14, 0x60, 0x40, 0x24, 0x02, 0x70, 0x69, 0x74, 0x11, 0x90} },
+{ 0x03ca,	16,	{0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0} },
+{ 0x03da,	16,	{0xff, 0x12, 0x0b, 0x58, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02} },
+{ 0x03ea,	16,	{0xee, 0x90, 0x7f, 0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90} },
+{ 0x03fa,	16,	{0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x08} },
+{ 0x040a,	16,	{0xba, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0xea, 0x49, 0x60, 0x11, 0xae, 0x02, 0xee, 0x90, 0x7f} },
+{ 0x041a,	16,	{0xd4, 0xf0, 0xaf, 0x01, 0xef, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0} },
+{ 0x042a,	16,	{0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05, 0xa2} },
+{ 0x043a,	16,	{0x12, 0x0e, 0x1f, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x2d, 0x02, 0x05, 0xa2, 0x12, 0x0a, 0xf7, 0x02} },
+{ 0x044a,	16,	{0x05, 0xa2, 0x12, 0x0e, 0x11, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x46, 0x40, 0x03, 0x02, 0x05, 0xa2} },
+{ 0x045a,	16,	{0x90, 0x7f, 0xe8, 0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2} },
+{ 0x046a,	16,	{0x00, 0xe4, 0x33, 0xff, 0x25, 0xe0, 0xff, 0xa2, 0x02, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0} },
+{ 0x047a,	16,	{0xe4, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0xe4, 0x90, 0x7f, 0x00} },
+{ 0x048a,	16,	{0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xec, 0xe0} },
+{ 0x049a,	16,	{0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} },
+{ 0x04aa,	16,	{0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3} },
+{ 0x04ba,	16,	{0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} },
+{ 0x04ca,	16,	{0xf0, 0x02, 0x05, 0xa2, 0x12, 0x0e, 0x48, 0x40, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xe8, 0xe0} },
+{ 0x04da,	16,	{0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xea, 0xe0, 0xb4} },
+{ 0x04ea,	16,	{0x01, 0x05, 0xc2, 0x00, 0x02, 0x05, 0xa2, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x05} },
+{ 0x04fa,	16,	{0xa2, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4} },
+{ 0x050a,	16,	{0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f} },
+{ 0x051a,	16,	{0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff, 0x13, 0x13, 0x13, 0x54, 0x1f} },
+{ 0x052a,	16,	{0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x69, 0x90} },
+{ 0x053a,	16,	{0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x60, 0x12, 0x0e, 0x4a, 0x50, 0x5b, 0x90, 0x7f, 0xe8} },
+{ 0x054a,	16,	{0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4f, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} },
+{ 0x055a,	16,	{0xd2, 0x00, 0x80, 0x44, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x3b, 0x90, 0x7f, 0xea} },
+{ 0x056a,	16,	{0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} },
+{ 0x057a,	16,	{0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} },
+{ 0x058a,	16,	{0xf0, 0x80, 0x15, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x0c, 0x12, 0x01, 0x00, 0x50} },
+{ 0x059a,	16,	{0x07, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x22} },
+{ 0x05aa,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xc0} },
+{ 0x05ba,	16,	{0xd0, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x06, 0xc0, 0x07, 0x90, 0x7f, 0xa5} },
+{ 0x05ca,	16,	{0xe0, 0x30, 0xe2, 0x06, 0x75, 0x0d, 0x06, 0x02, 0x06, 0x76, 0x90, 0x7f, 0xa5, 0xe0, 0x20, 0xe1} },
+{ 0x05da,	16,	{0x0c, 0xe5, 0x0d, 0x64, 0x02, 0x60, 0x06, 0x75, 0x0d, 0x07, 0x02, 0x06, 0x76, 0xaf, 0x0d, 0xef} },
+{ 0x05ea,	16,	{0x24, 0xfe, 0x60, 0x48, 0x14, 0x60, 0x2c, 0x24, 0xfe, 0x60, 0x77, 0x24, 0x04, 0x60, 0x03, 0x02} },
+{ 0x05fa,	16,	{0x06, 0x76, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xaf, 0x0c, 0x05, 0x0c, 0x8f, 0x82, 0x75, 0x83} },
+{ 0x060a,	16,	{0x00, 0x12, 0x08, 0x22, 0x90, 0x7f, 0xa6, 0xf0, 0xe5, 0x0c, 0x65, 0x08, 0x70, 0x5e, 0x75, 0x0d} },
+{ 0x061a,	16,	{0x05, 0x80, 0x59, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09, 0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e} },
+{ 0x062a,	16,	{0x82, 0x75, 0x83, 0x00, 0x12, 0x08, 0x4f, 0x75, 0x0d, 0x02, 0x80, 0x40, 0xe5, 0x08, 0x24, 0xfe} },
+{ 0x063a,	16,	{0xb5, 0x0c, 0x07, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x20, 0xf0, 0xe5, 0x08, 0x14, 0xb5, 0x0c, 0x0a} },
+{ 0x064a,	16,	{0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x90, 0x7f, 0xa6, 0xe0, 0xab, 0x09} },
+{ 0x065a,	16,	{0xaa, 0x0a, 0xa9, 0x0b, 0xae, 0x0c, 0x8e, 0x82, 0x75, 0x83, 0x00, 0x12, 0x08, 0x4f, 0x05, 0x0c} },
+{ 0x066a,	16,	{0x80, 0x0a, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x40, 0xf0, 0xe4, 0xf5, 0x0d, 0x53, 0x91, 0xdf, 0xd0} },
+{ 0x067a,	16,	{0x07, 0xd0, 0x06, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x86, 0xd0} },
+{ 0x068a,	10,	{0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0694,	16,	{0x8c, 0x33, 0x8d, 0x34, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x36} },
+{ 0x06a4,	16,	{0xc3, 0xe5, 0x36, 0x95, 0x34, 0xe5, 0x35, 0x95, 0x33, 0x50, 0x69, 0xef, 0x25, 0x36, 0xf5, 0x82} },
+{ 0x06b4,	16,	{0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0xff, 0xf0, 0xf4, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36} },
+{ 0x06c4,	16,	{0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe4, 0xf0, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36} },
+{ 0x06d4,	16,	{0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0xaa, 0xf0, 0x64, 0xaa, 0x60, 0x02, 0xc3, 0x22} },
+{ 0x06e4,	16,	{0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0x74, 0x55, 0xf0, 0x64, 0x55, 0x60} },
+{ 0x06f4,	16,	{0x02, 0xc3, 0x22, 0xad, 0x36, 0xe5, 0x36, 0x2f, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xed} },
+{ 0x0704,	16,	{0xf0, 0xfc, 0xac, 0x05, 0xed, 0x6c, 0x60, 0x02, 0xc3, 0x22, 0x05, 0x36, 0xe5, 0x36, 0x70, 0x02} },
+{ 0x0714,	16,	{0x05, 0x35, 0x80, 0x8c, 0xe4, 0xf5, 0x35, 0xf5, 0x36, 0xc3, 0xe5, 0x36, 0x95, 0x34, 0xe5, 0x35} },
+{ 0x0724,	16,	{0x95, 0x33, 0x50, 0x27, 0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe0, 0x65} },
+{ 0x0734,	16,	{0x36, 0x60, 0x02, 0xc3, 0x22, 0xef, 0x25, 0x36, 0xf5, 0x82, 0xe5, 0x35, 0x3e, 0xf5, 0x83, 0xe4} },
+{ 0x0744,	13,	{0xf0, 0x05, 0x36, 0xe5, 0x36, 0x70, 0x02, 0x05, 0x35, 0x80, 0xce, 0xd3, 0x22} },
+{ 0x0751,	16,	{0xc2, 0x04, 0xd2, 0x05, 0xc2, 0x03, 0xc2, 0x00, 0xc2, 0x02, 0xc2, 0x01, 0x12, 0x0e, 0x3d, 0xd2} },
+{ 0x0761,	16,	{0xe8, 0x43, 0xd8, 0x20, 0x90, 0x7f, 0xab, 0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f} },
+{ 0x0771,	16,	{0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0x95, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x7f, 0x93, 0x74} },
+{ 0x0781,	16,	{0x30, 0xf0, 0x12, 0x0a, 0x19, 0x90, 0x7f, 0xaf, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0xe0} },
+{ 0x0791,	16,	{0x44, 0x0d, 0xf0, 0xd2, 0xaf, 0x12, 0x0e, 0x35, 0x20, 0x01, 0x42, 0x75, 0x24, 0x00, 0x75, 0x23} },
+{ 0x07a1,	16,	{0x00, 0x75, 0x22, 0x00, 0x75, 0x21, 0x00, 0x7f, 0x48, 0x7e, 0x92, 0x7d, 0x00, 0x7c, 0x00, 0xab} },
+{ 0x07b1,	16,	{0x24, 0xaa, 0x23, 0xa9, 0x22, 0xa8, 0x21, 0xc3, 0x12, 0x08, 0xa9, 0x50, 0xdb, 0x20, 0x01, 0xd8} },
+{ 0x07c1,	16,	{0x7a, 0x00, 0x79, 0x00, 0x78, 0x00, 0xe5, 0x24, 0x24, 0x01, 0xf5, 0x24, 0xea, 0x35, 0x23, 0xf5} },
+{ 0x07d1,	16,	{0x23, 0xe9, 0x35, 0x22, 0xf5, 0x22, 0xe8, 0x35, 0x21, 0xf5, 0x21, 0x80, 0xca, 0x30, 0x01, 0x05} },
+{ 0x07e1,	16,	{0x12, 0x03, 0x7a, 0xc2, 0x01, 0x30, 0x04, 0x1a, 0x12, 0x0e, 0x40, 0x50, 0x13, 0x12, 0x09, 0x00} },
+{ 0x07f1,	16,	{0x30, 0x00, 0x07, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0xf3, 0x12, 0x0d, 0x4a, 0x12, 0x0e, 0x42} },
+{ 0x0801,	8,	{0xc2, 0x03, 0x12, 0x08, 0xff, 0x80, 0xd6, 0x22} },
+{ 0x0809,	16,	{0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} },
+{ 0x0819,	9,	{0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x0822,	16,	{0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} },
+{ 0x0832,	16,	{0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} },
+{ 0x0842,	13,	{0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} },
+{ 0x084f,	16,	{0xf8, 0xbb, 0x01, 0x0d, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe8, 0xf0} },
+{ 0x085f,	16,	{0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xc8, 0xf6, 0x22, 0xbb, 0xfe, 0x05, 0xe9, 0x25, 0x82, 0xc8} },
+{ 0x086f,	2,	{0xf2, 0x22} },
+{ 0x0871,	16,	{0xbb, 0x01, 0x10, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0xf5, 0xf0} },
+{ 0x0881,	16,	{0xa3, 0xe0, 0x22, 0x50, 0x09, 0xe9, 0x25, 0x82, 0xf8, 0x86, 0xf0, 0x08, 0xe6, 0x22, 0xbb, 0xfe} },
+{ 0x0891,	16,	{0x0a, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0xf5, 0xf0, 0x08, 0xe2, 0x22, 0xe5, 0x83, 0x2a, 0xf5, 0x83} },
+{ 0x08a1,	8,	{0xe9, 0x93, 0xf5, 0xf0, 0xa3, 0xe9, 0x93, 0x22} },
+{ 0x08a9,	16,	{0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, 0xf0, 0xe8, 0x9c, 0x45, 0xf0} },
+{ 0x08b9,	1,	{0x22} },
+{ 0x08ba,	2,	{0x8f, 0x28} },
+{ 0x08bc,	16,	{0xe4, 0xf5, 0x29, 0x75, 0x2a, 0xff, 0x75, 0x2b, 0x11, 0x75, 0x2c, 0x32, 0xab, 0x2a, 0xaa, 0x2b} },
+{ 0x08cc,	16,	{0xa9, 0x2c, 0x90, 0x00, 0x01, 0x12, 0x08, 0x22, 0xb4, 0x03, 0x1d, 0xaf, 0x29, 0x05, 0x29, 0xef} },
+{ 0x08dc,	16,	{0xb5, 0x28, 0x01, 0x22, 0x12, 0x08, 0x09, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} },
+{ 0x08ec,	14,	{0x2a, 0xff, 0xf5, 0x2b, 0x89, 0x2c, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x08fa,	1,	{0x22} },
+{ 0x08fb,	4,	{0x53, 0xd8, 0xef, 0x32} },
+{ 0x08ff,	1,	{0x22} },
+{ 0x0900,	9,	{0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x74} },
+{ 0x097d,	16,	{0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} },
+{ 0x098d,	12,	{0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x39, 0x02, 0x09, 0xd4} },
+{ 0x0999,	16,	{0x02, 0x07, 0x51, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} },
+{ 0x09a9,	16,	{0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} },
+{ 0x09b9,	16,	{0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} },
+{ 0x09c9,	16,	{0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x0d, 0xec, 0xe4, 0x7e} },
+{ 0x09d9,	16,	{0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} },
+{ 0x09e9,	16,	{0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} },
+{ 0x09f9,	16,	{0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} },
+{ 0x0a09,	16,	{0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} },
+{ 0x0a19,	16,	{0xe4, 0x90, 0x7f, 0x9c, 0xf0, 0x7f, 0x0a, 0xfe, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0x74, 0x89} },
+{ 0x0a29,	16,	{0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xcf, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x0d, 0x94, 0x90, 0x7f} },
+{ 0x0a39,	16,	{0x96, 0xe0, 0x54, 0xfe, 0xf0, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x0a49,	16,	{0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0x05} },
+{ 0x0a59,	16,	{0x7e, 0x00, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x05, 0x7e, 0x00} },
+{ 0x0a69,	16,	{0x12, 0x0d, 0x94, 0x90, 0x7f, 0x96, 0xe0, 0x54, 0xbf, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d} },
+{ 0x0a79,	16,	{0x94, 0x90, 0x7f, 0x96, 0xe0, 0x44, 0x40, 0xf0, 0x7f, 0x32, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x22} },
+{ 0x0a89,	16,	{0x75, 0x32, 0x01, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x01, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x0e} },
+{ 0x0a99,	16,	{0x7d, 0x00, 0x7c, 0x01, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12} },
+{ 0x0aa9,	16,	{0x0d, 0xd7, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x02, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x80, 0x7d} },
+{ 0x0ab9,	16,	{0x00, 0x7c, 0x80, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0d} },
+{ 0x0ac9,	16,	{0xd7, 0xe5, 0x32, 0x60, 0x1b, 0x7f, 0x03, 0x12, 0x0d, 0xd7, 0x7f, 0x00, 0x7e, 0x20, 0x7d, 0x40} },
+{ 0x0ad9,	16,	{0x7c, 0x5b, 0x12, 0x06, 0x94, 0xe4, 0x33, 0xf5, 0x32, 0x70, 0x05, 0x7f, 0x0f, 0x12, 0x0d, 0xd7} },
+{ 0x0ae9,	14,	{0xe5, 0x32, 0x60, 0x05, 0xe4, 0xff, 0x12, 0x0d, 0xd7, 0xe5, 0x32, 0x24, 0xff, 0x22} },
+{ 0x0af7,	8,	{0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x10, 0xd3, 0x22} },
+{ 0x0aff,	1,	{0x32} },
+{ 0x0b00,	16,	{0x02, 0x0d, 0x64, 0x00, 0x02, 0x0d, 0xab, 0x00, 0x02, 0x0d, 0x2f, 0x00, 0x02, 0x0d, 0x7c, 0x00} },
+{ 0x0b10,	16,	{0x02, 0x0d, 0xc1, 0x00, 0x02, 0x0a, 0xff, 0x00, 0x02, 0x0e, 0x4c, 0x00, 0x02, 0x0e, 0x4d, 0x00} },
+{ 0x0b20,	16,	{0x02, 0x0e, 0x4e, 0x00, 0x02, 0x0e, 0x4f, 0x00, 0x02, 0x0e, 0x50, 0x00, 0x02, 0x0e, 0x51, 0x00} },
+{ 0x0b30,	16,	{0x02, 0x0e, 0x52, 0x00, 0x02, 0x0e, 0x53, 0x00, 0x02, 0x0e, 0x54, 0x00, 0x02, 0x0e, 0x55, 0x00} },
+{ 0x0b40,	16,	{0x02, 0x0e, 0x56, 0x00, 0x02, 0x0e, 0x57, 0x00, 0x02, 0x0e, 0x58, 0x00, 0x02, 0x0e, 0x59, 0x00} },
+{ 0x0b50,	8,	{0x02, 0x0e, 0x5a, 0x00, 0x02, 0x0e, 0x5b, 0x00} },
+{ 0x0b58,	16,	{0xe4, 0xfe, 0x75, 0x2a, 0xff, 0x75, 0x2b, 0x11, 0x75, 0x2c, 0x12, 0xab, 0x2a, 0xaa, 0x2b, 0xa9} },
+{ 0x0b68,	16,	{0x2c, 0x90, 0x00, 0x01, 0x12, 0x08, 0x22, 0x64, 0x02, 0x70, 0x2d, 0xad, 0x06, 0x0e, 0xed, 0xb5} },
+{ 0x0b78,	16,	{0x07, 0x01, 0x22, 0x90, 0x00, 0x02, 0x12, 0x08, 0x71, 0x85, 0xf0, 0x28, 0xf5, 0x29, 0x62, 0x28} },
+{ 0x0b88,	16,	{0xe5, 0x28, 0x62, 0x29, 0xe5, 0x29, 0x62, 0x28, 0x29, 0xfd, 0xe5, 0x28, 0x3a, 0xa9, 0x05, 0x75} },
+{ 0x0b98,	14,	{0x2a, 0xff, 0xf5, 0x2b, 0x89, 0x2c, 0x80, 0xc3, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} },
+{ 0x0ba6,	1,	{0x22} },
+{ 0x0ba7,	16,	{0xab, 0x07, 0xaa, 0x06, 0xac, 0x05, 0xe4, 0xfd, 0xe5, 0x11, 0x60, 0x11, 0xea, 0xff, 0xae, 0x05} },
+{ 0x0bb7,	16,	{0x0d, 0xee, 0x24, 0x10, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xef, 0xf0, 0xeb, 0xae, 0x05} },
+{ 0x0bc7,	16,	{0x0d, 0x74, 0x10, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xeb, 0xf0, 0xaf, 0x05, 0x0d} },
+{ 0x0bd7,	16,	{0x74, 0x10, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xf5, 0x83, 0xec, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f} },
+{ 0x0be7,	13,	{0x7b, 0x10, 0x12, 0x0d, 0x10, 0x7f, 0x0a, 0x7e, 0x00, 0x12, 0x0d, 0x94, 0x22} },
+{ 0x0bf4,	16,	{0x8e, 0x32, 0x8f, 0x33, 0x8d, 0x34, 0x8a, 0x35, 0x8b, 0x36, 0xe4, 0xfd, 0xf5, 0x37, 0xe5, 0x11} },
+{ 0x0c04,	16,	{0x60, 0x12, 0xe5, 0x32, 0xff, 0xae, 0x05, 0x0d, 0xee, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x34, 0x0f} },
+{ 0x0c14,	16,	{0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x33, 0xae, 0x05, 0x0d, 0x74, 0x13, 0x2e, 0xf5, 0x82, 0xe4, 0x34} },
+{ 0x0c24,	16,	{0x0f, 0xf5, 0x83, 0xe5, 0x33, 0xf0, 0xaf, 0x0f, 0x7a, 0x0f, 0x7b, 0x13, 0x12, 0x0d, 0x10, 0xaf} },
+{ 0x0c34,	11,	{0x0f, 0xad, 0x34, 0xab, 0x36, 0xaa, 0x35, 0x12, 0x0c, 0xf1, 0x22} },
+{ 0x0c3f,	16,	{0x8e, 0x32, 0x8f, 0x33, 0x8d, 0x34, 0x8a, 0x35, 0x8b, 0x36, 0xe4, 0xf5, 0x37, 0xe5, 0x37, 0xc3} },
+{ 0x0c4f,	16,	{0x95, 0x34, 0x50, 0x20, 0x05, 0x33, 0xe5, 0x33, 0xae, 0x32, 0x70, 0x02, 0x05, 0x32, 0x14, 0xff} },
+{ 0x0c5f,	16,	{0xe5, 0x36, 0x25, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x35, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x0b, 0xa7} },
+{ 0x0c6f,	5,	{0x05, 0x37, 0x80, 0xd9, 0x22} },
+{ 0x0c74,	16,	{0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x25, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} },
+{ 0x0c84,	16,	{0x44, 0x01, 0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a} },
+{ 0x0c94,	13,	{0x0a, 0x89, 0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x03, 0xd3, 0x22, 0xc3, 0x22} },
+{ 0x0ca1,	16,	{0xa9, 0x07, 0xe5, 0x0d, 0x70, 0x23, 0x90, 0x7f, 0xa5, 0xe0, 0x44, 0x80, 0xf0, 0xe9, 0x25, 0xe0} },
+{ 0x0cb1,	16,	{0x90, 0x7f, 0xa6, 0xf0, 0x8d, 0x08, 0xaf, 0x03, 0xa9, 0x07, 0x75, 0x09, 0x01, 0x8a, 0x0a, 0x89} },
+{ 0x0cc1,	11,	{0x0b, 0xe4, 0xf5, 0x0c, 0x75, 0x0d, 0x01, 0xd3, 0x22, 0xc3, 0x22} },
+{ 0x0ccc,	16,	{0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x06, 0x04, 0xe0, 0x44} },
+{ 0x0cdc,	16,	{0x02, 0xf0, 0x7f, 0xd0, 0x7e, 0x07, 0x12, 0x0d, 0x94, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} },
+{ 0x0cec,	5,	{0xe0, 0x44, 0x04, 0xf0, 0x22} },
+{ 0x0cf1,	16,	{0x12, 0x0c, 0x74, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} },
+{ 0x0d01,	15,	{0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} },
+{ 0x0d10,	16,	{0x12, 0x0c, 0xa1, 0xe5, 0x0d, 0x24, 0xfa, 0x60, 0x10, 0x14, 0x60, 0x07, 0x24, 0x07, 0x70, 0xf3} },
+{ 0x0d20,	15,	{0x7f, 0x08, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x07, 0x22, 0xe4, 0xf5, 0x0d, 0x7f, 0x06, 0x22} },
+{ 0x0d2f,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} },
+{ 0x0d3f,	11,	{0xab, 0x74, 0x04, 0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d4a,	16,	{0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x12, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x14, 0x7e, 0x00, 0x12} },
+{ 0x0d5a,	10,	{0x0d, 0x94, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} },
+{ 0x0d64,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01} },
+{ 0x0d74,	8,	{0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d7c,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xd2, 0x03, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} },
+{ 0x0d8c,	8,	{0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0d94,	16,	{0x8e, 0x38, 0x8f, 0x39, 0xe5, 0x39, 0x15, 0x39, 0xae, 0x38, 0x70, 0x02, 0x15, 0x38, 0x4e, 0x60} },
+{ 0x0da4,	7,	{0x05, 0x12, 0x0e, 0x00, 0x80, 0xee, 0x22} },
+{ 0x0dab,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x02, 0xf0, 0xd0} },
+{ 0x0dbb,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dc1,	16,	{0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x10, 0xf0, 0xd0} },
+{ 0x0dd1,	6,	{0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} },
+{ 0x0dd7,	16,	{0xae, 0x07, 0x7f, 0x21, 0x7d, 0x01, 0x74, 0x00, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x0f, 0xab, 0x82} },
+{ 0x0de7,	5,	{0xfa, 0x12, 0x0d, 0x10, 0x22} },
+{ 0x0dec,	16,	{0x50, 0x0f, 0x00, 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6} },
+{ 0x0dfc,	3,	{0xa1, 0x86, 0x8e} },
+{ 0x0dff,	1,	{0x00} },
+{ 0x0e00,	16,	{0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} },
+{ 0x0e10,	1,	{0x22} },
+{ 0x0e11,	14,	{0x90, 0x7f, 0x00, 0xe5, 0x10, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} },
+{ 0x0e1f,	14,	{0x90, 0x7f, 0x00, 0xe5, 0x0e, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0xd3, 0x22} },
+{ 0x0e2d,	8,	{0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0e, 0xd3, 0x22} },
+{ 0x0e35,	8,	{0xe4, 0xf5, 0x0d, 0xd2, 0xe9, 0xd2, 0xaf, 0x22} },
+{ 0x0e3d,	3,	{0xd2, 0x00, 0x22} },
+{ 0x0e40,	2,	{0xd3, 0x22} },
+{ 0x0e42,	2,	{0xd3, 0x22} },
+{ 0x0e44,	2,	{0xd3, 0x22} },
+{ 0x0e46,	2,	{0xd3, 0x22} },
+{ 0x0e48,	2,	{0xd3, 0x22} },
+{ 0x0e4a,	2,	{0xd3, 0x22} },
+{ 0x0e4c,	1,	{0x32} },
+{ 0x0e4d,	1,	{0x32} },
+{ 0x0e4e,	1,	{0x32} },
+{ 0x0e4f,	1,	{0x32} },
+{ 0x0e50,	1,	{0x32} },
+{ 0x0e51,	1,	{0x32} },
+{ 0x0e52,	1,	{0x32} },
+{ 0x0e53,	1,	{0x32} },
+{ 0x0e54,	1,	{0x32} },
+{ 0x0e55,	1,	{0x32} },
+{ 0x0e56,	1,	{0x32} },
+{ 0x0e57,	1,	{0x32} },
+{ 0x0e58,	1,	{0x32} },
+{ 0x0e59,	1,	{0x32} },
+{ 0x0e5a,	1,	{0x32} },
+{ 0x0e5b,	1,	{0x32} },
+{ 0x1100,	16,	{0x12, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x47, 0x05, 0x10, 0x27, 0x01, 0x00, 0x01, 0x02} },
+{ 0x1110,	16,	{0x00, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x03, 0xa0, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02} },
+{ 0x1120,	16,	{0xff, 0x00, 0x00, 0x04, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} },
+{ 0x1130,	16,	{0x00, 0x00, 0x04, 0x03, 0x09, 0x04, 0x26, 0x03, 0x41, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x68, 0x00} },
+{ 0x1140,	16,	{0x6f, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x68, 0x00, 0x69, 0x00, 0x70, 0x00, 0x73, 0x00} },
+{ 0x1150,	16,	{0x2c, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x28, 0x03, 0x46, 0x00} },
+{ 0x1160,	16,	{0x69, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x77, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00} },
+{ 0x1170,	16,	{0x46, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x57, 0x00, 0x6f, 0x00, 0x72, 0x00} },
+{ 0x1180,	16,	{0x6b, 0x00, 0x73, 0x00, 0x2a, 0x03, 0x43, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x69, 0x00} },
+{ 0x1190,	16,	{0x67, 0x00, 0x75, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00} },
+{ 0x11a0,	16,	{0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x22, 0x03} },
+{ 0x11b0,	16,	{0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00} },
+{ 0x11c0,	16,	{0x65, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00} },
+{ 0x11d0,	2,	{0x00, 0x00} },
+{ 0xffff,	0,	{0x00} }
+};
+#endif
diff -u --recursive --new-file v2.3.39/linux/drivers/usb/wmforce.c linux/drivers/usb/wmforce.c
--- v2.3.39/linux/drivers/usb/wmforce.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/wmforce.c	Thu Jan 20 09:48:48 2000
@@ -0,0 +1,165 @@
+/*
+ *  wmforce.c  Version 0.1
+ *
+ *  Copyright (c) 1999 Vojtech Pavlik
+ *
+ *  USB Logitech WingMan Force tablet support
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * 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
+ * 
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include "usb.h"
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
+
+#define USB_VENDOR_ID_LOGITECH		0x046d
+#define USB_DEVICE_ID_LOGITECH_WMFORCE	0xc281
+
+struct wmforce {
+	signed char data[8];
+	struct input_dev dev;
+	struct urb irq;
+};
+
+static struct {
+        __s32 x;
+        __s32 y;
+} wmforce_hat_to_axis[16] = {{ 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
+
+static void wmforce_irq(struct urb *urb)
+{
+	struct wmforce *wmforce = urb->context;
+	unsigned char *data = wmforce->data;
+	struct input_dev *dev = &wmforce->dev;
+
+	if (urb->status) return;
+
+	if (data[0] != 1) {
+		if (data[0] != 2)
+			warn("received unknown report #%d", data[0]);
+		return;
+	}
+
+	input_report_abs(dev, ABS_X, (__s16) (((__s16)data[2] << 8) | data[1]));
+	input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[4] << 8) | data[3]));
+	input_report_abs(dev, ABS_THROTTLE, data[5]);
+	input_report_abs(dev, ABS_HAT0X, wmforce_hat_to_axis[data[7] >> 4].x);
+	input_report_abs(dev, ABS_HAT0Y, wmforce_hat_to_axis[data[7] >> 4].y);
+
+	input_report_key(dev, BTN_TRIGGER, !!(data[6] & 0x01));
+	input_report_key(dev, BTN_TOP,     !!(data[6] & 0x02));
+	input_report_key(dev, BTN_THUMB,   !!(data[6] & 0x04));
+	input_report_key(dev, BTN_TOP2,    !!(data[6] & 0x08));
+	input_report_key(dev, BTN_BASE,    !!(data[6] & 0x10));
+	input_report_key(dev, BTN_BASE2,   !!(data[6] & 0x20));
+	input_report_key(dev, BTN_BASE3,   !!(data[6] & 0x40));
+	input_report_key(dev, BTN_BASE4,   !!(data[6] & 0x80));
+	input_report_key(dev, BTN_BASE5,   !!(data[7] & 0x01));
+}
+
+static void *wmforce_probe(struct usb_device *dev, unsigned int ifnum)
+{
+	struct usb_endpoint_descriptor *endpoint;
+	struct wmforce *wmforce;
+	int i;
+
+	if (dev->descriptor.idVendor != USB_VENDOR_ID_LOGITECH ||
+	    dev->descriptor.idProduct != USB_DEVICE_ID_LOGITECH_WMFORCE)
+		return NULL;
+
+	endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
+
+	if (!(wmforce = kmalloc(sizeof(struct wmforce), GFP_KERNEL))) return NULL;
+	memset(wmforce, 0, sizeof(struct wmforce));
+
+	wmforce->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	wmforce->dev.keybit[LONG(BTN_JOYSTICK)] = BIT(BTN_TRIGGER) | BIT(BTN_TOP) | BIT(BTN_THUMB) | BIT(BTN_TOP2) |
+					BIT(BTN_BASE) | BIT(BTN_BASE2) | BIT(BTN_BASE3) | BIT(BTN_BASE4) | BIT(BTN_BASE5);
+	wmforce->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_THROTTLE) | BIT(ABS_HAT0X) | BIT(ABS_HAT0Y);
+
+	for (i = ABS_X; i <= ABS_Y; i++) {
+		wmforce->dev.absmax[i] =  1920;
+		wmforce->dev.absmin[i] = -1920;
+		wmforce->dev.absfuzz[i] = 0;
+		wmforce->dev.absflat[i] = 128;
+	}
+
+	wmforce->dev.absmax[ABS_THROTTLE] = 0;
+	wmforce->dev.absmin[ABS_THROTTLE] = 255;
+	wmforce->dev.absfuzz[ABS_THROTTLE] = 0;
+	wmforce->dev.absflat[ABS_THROTTLE] = 0;
+
+	for (i = ABS_HAT0X; i <= ABS_HAT0Y; i++) {
+		wmforce->dev.absmax[i] =  1;
+		wmforce->dev.absmin[i] = -1;
+		wmforce->dev.absfuzz[i] = 0;
+		wmforce->dev.absflat[i] = 0;
+	}
+
+	FILL_INT_URB(&wmforce->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+			wmforce->data, 8, wmforce_irq, wmforce, endpoint->bInterval);
+
+	if (usb_submit_urb(&wmforce->irq)) {
+		kfree(wmforce);
+		return NULL;
+	}
+
+	input_register_device(&wmforce->dev);
+
+	printk(KERN_INFO "input%d: Logitech WingMan Force USB\n", wmforce->dev.number);
+
+	return wmforce;
+}
+
+static void wmforce_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct wmforce *wmforce = ptr;
+	usb_unlink_urb(&wmforce->irq);
+	input_unregister_device(&wmforce->dev);
+	kfree(wmforce);
+}
+
+static struct usb_driver wmforce_driver = {
+	name:		"wmforce",
+	probe:		wmforce_probe,
+	disconnect:	wmforce_disconnect,
+};
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	usb_deregister(&wmforce_driver);
+}
+
+int init_module(void)
+#else
+int wmforce_init(void)
+#endif
+{
+	usb_register(&wmforce_driver);
+	return 0;
+}
diff -u --recursive --new-file v2.3.39/linux/drivers/video/dummycon.c linux/drivers/video/dummycon.c
--- v2.3.39/linux/drivers/video/dummycon.c	Wed Dec 15 10:43:16 1999
+++ linux/drivers/video/dummycon.c	Wed Jan 12 11:51:49 2000
@@ -25,7 +25,7 @@
 #define DUMMY_ROWS	25
 #endif
 
-static const char *__init dummycon_startup(void)
+static const char *dummycon_startup(void)
 {
     return "dummy device";
 }
diff -u --recursive --new-file v2.3.39/linux/fs/cramfs/README linux/fs/cramfs/README
--- v2.3.39/linux/fs/cramfs/README	Wed Dec 31 16:00:00 1969
+++ linux/fs/cramfs/README	Tue Jan 11 10:24:58 2000
@@ -0,0 +1,166 @@
+Notes on Filesystem Layout
+--------------------------
+
+These notes describe what mkcramfs generates.  Kernel requirements are
+a bit looser, e.g. it doesn't care if the <file_data> items are
+swapped around (though it does care that directory entries (inodes) in
+a given directory are contiguous, as this is used by readdir).
+
+All data is in host-endian format; neither mkcramfs nor the kernel
+ever do swabbing.  (See section `Block Size' below.)
+
+<filesystem>:
+	<superblock>
+	<directory_structure>
+	<data>
+
+<superblock>: struct cramfs_super (see cramfs.h).
+
+<directory_structure>:
+	For each file:
+		struct cramfs_inode (see cramfs.h).
+		Filename.  Not generally null-terminated, but it is
+		 null-padded to a multiple of 4 bytes.
+
+The order of inode traversal is described as "width-first" (not to be
+confused with breadth-first); i.e. like depth-first but listing all of
+a directory's entries before recursing down its subdirectories: the
+same order as `ls -AUR' (but without the /^\..*:$/ directory header
+lines); put another way, the same order as `find -type d -exec
+ls -AU1 {} \;'.
+
+<data>:
+	One <file_data> for each file that's either a symlink or a
+	 regular file of non-zero st_size.
+
+<file_data>:
+	nblocks * <block_pointer>
+	 (where nblocks = (st_size - 1) / blksize + 1)
+	nblocks * <block>
+	padding to multiple of 4 bytes
+
+The i'th <block_pointer> for a file stores the byte offset of the
+*end* of the i'th <block> (i.e. one past the last byte, which is the
+same as the start of the (i+1)'th <block> if there is one).  The first
+<block> immediately follows the last <block_pointer> for the file.
+<block_pointer>s are each 32 bits long.
+
+The order of <file_data>'s is a depth-first descent of the directory
+tree, i.e. the same order as `find -size +0 \( -type f -o -type l \)
+-print'.
+
+
+<block>: The i'th <block> is the output of zlib's compress function
+applied to the i'th blksize-sized chunk of the input data.
+(For the last <block> of the file, the input may of course be smaller.)
+Each <block> may be a different size.  (See <block_pointer> above.)
+<block>s are merely byte-aligned, not generally u32-aligned.
+
+
+Holes
+-----
+
+This kernel supports cramfs holes (i.e. [efficient representation of]
+blocks in uncompressed data consisting entirely of NUL bytes), but by
+default mkcramfs doesn't test for & create holes, since cramfs in
+kernels up to at least 2.3.39 didn't support holes.  Compile mkcramfs
+with -DDO_HOLES if you want it to create files that can have holes in
+them.
+
+
+Tools
+-----
+
+If you're hacking on cramfs, you might find useful some tools for
+testing cramfs at <http://cvs.bofh.asn.au/cramfs/>, including a
+rudimentary fsck for cramfs.
+
+
+Future Development
+==================
+
+Block Size
+----------
+
+(Block size in cramfs refers to the size of input data that is
+compressed at a time.  It's intended to be somewhere around
+PAGE_CACHE_SIZE for cramfs_readpage's convenience.)
+
+The superblock ought to indicate the block size that the fs was
+written for, since comments in <linux/pagemap.h> indicate that
+PAGE_CACHE_SIZE may grow in future (if I interpret the comment
+correctly).
+
+Currently, mkcramfs #define's PAGE_CACHE_SIZE as 4096 and uses that
+for blksize, whereas Linux-2.3.39 uses its PAGE_CACHE_SIZE, which in
+turn is defined as PAGE_SIZE (which can be as large as 32KB on arm).
+This discrepancy is a bug, though it's not clear which should be
+changed.
+
+One option is to change mkcramfs to take its PAGE_CACHE_SIZE from
+<asm/page.h>.  Personally I don't like this option, but it does
+require the least amount of change: just change `#define
+PAGE_CACHE_SIZE (4096)' to `#include <asm/page.h>'.  The disadvantage
+is that the generated cramfs cannot always be shared between different
+kernels, not even necessarily kernels of the same architecture if
+PAGE_CACHE_SIZE is subject to change between kernel versions.
+
+
+The remaining options try to make cramfs more sharable.
+
+One part of that is addressing endianness.  The two options here are
+`always use little-endian' (like ext2fs) or `writer chooses
+endianness; kernel adapts at runtime'.  Little-endian wins because of
+code simplicity and little CPU overhead even on big-endian machines.
+
+The cost of swabbing is changing the code to use the le32_to_cpu
+etc. macros as used by ext2fs.  We don't need to swab the compressed
+data, only the superblock, inodes and block pointers.
+
+
+The other part of making cramfs more sharable is choosing a block
+size.  The options are:
+
+  1. Always 4096 bytes.
+
+  2. Writer chooses blocksize; kernel adapts but rejects blocksize >
+     PAGE_CACHE_SIZE.
+
+  3. Writer chooses blocksize; kernel adapts even to blocksize >
+     PAGE_CACHE_SIZE.
+
+It's easy enough to change the kernel to use a smaller value than
+PAGE_CACHE_SIZE: just make cramfs_readpage read multiple blocks.
+
+The cost of option 1 is that kernels with a larger PAGE_CACHE_SIZE
+value don't get as good compression as they can.
+
+The cost of option 2 relative to option 1 is that the code uses
+variables instead of #define'd constants.  The gain is that people
+with kernels having larger PAGE_CACHE_SIZE can make use of that if
+they don't mind their cramfs being inaccessible to kernels with
+smaller PAGE_CACHE_SIZE values.
+
+Option 3 is easy to implement if we don't mind being CPU-inefficient:
+e.g. get readpage to decompress to a buffer of size MAX_BLKSIZE (which
+must be no larger than 32KB) and discard what it doesn't need.
+Getting readpage to read into all the covered pages is harder.
+
+The main advantage of option 3 over 1, 2, is better compression.  The
+cost is greater complexity.  Probably not worth it, but I hope someone
+will disagree.  (If it is implemented, then I'll re-use that code in
+e2compr.)
+
+
+Another cost of 2 and 3 over 1 is making mkcramfs use a different
+block size, but that just means adding and parsing a -b option.
+
+
+Inode Size
+----------
+
+Given that cramfs will probably be used for CDs etc. as well as just
+silicon ROMs, it might make sense to expand the inode a little from
+its current 12 bytes.  Inodes other than the root inode are followed
+by filename, so the expansion doesn't even have to be a multiple of 4
+bytes.
diff -u --recursive --new-file v2.3.39/linux/fs/cramfs/cramfs.h linux/fs/cramfs/cramfs.h
--- v2.3.39/linux/fs/cramfs/cramfs.h	Wed Dec 29 13:13:20 1999
+++ linux/fs/cramfs/cramfs.h	Tue Jan 11 10:24:58 2000
@@ -5,17 +5,20 @@
 #define CRAMFS_SIGNATURE	"Compressed ROMFS"
 
 /*
- * Reasonably terse representation of the inode
- * data.. When the mode of the inode indicates
- * a special device node, the "offset" bits will
- * encode i_rdev. In other cases, "offset" points
- * to the ROM image for the actual file data
- * (whether that data be directory or compressed
- * file data depends on the inode type again)
+ * Reasonably terse representation of the inode data.
  */
 struct cramfs_inode {
 	u32 mode:16, uid:16;
+	/* SIZE for device files is i_rdev */
 	u32 size:24, gid:8;
+	/* NAMELEN is the length of the file name, divided by 4 and
+           rounded up.  (cramfs doesn't support hard links.) */
+	/* OFFSET: For symlinks and non-empty regular files, this
+	   contains the offset (divided by 4) of the file data in
+	   compressed form (starting with an array of block pointers;
+	   see README).  For non-empty directories it is the offset
+	   (divided by 4) of the inode of the first file in that
+	   directory.  For anything else, offset is zero. */
 	u32 namelen:6, offset:26;
 };
 
@@ -24,7 +27,8 @@
  */
 struct cramfs_super {
 	u32 magic;		/* 0x28cd3d45 - random number */
-	u32 size;		/* > offset, < 2**26 */
+	u32 size;		/* Not used.  mkcramfs currently
+                                   writes a constant 1<<16 here. */
 	u32 flags;		/* 0 */
 	u32 future;		/* 0 */
 	u8 signature[16];	/* "Compressed ROMFS" */
@@ -32,6 +36,13 @@
 	u8 name[16];		/* user-defined name */
 	struct cramfs_inode root;	/* Root inode data */
 };
+
+/*
+ * Valid values in super.flags.  Currently we refuse to mount
+ * if (flags & ~CRAMFS_SUPPORTED_FLAGS).  Maybe that should be
+ * changed to test super.future instead.
+ */
+#define CRAMFS_SUPPORTED_FLAGS (0xff)
 
 /* Uncompression interfaces to the underlying zlib */
 int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen);
diff -u --recursive --new-file v2.3.39/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c
--- v2.3.39/linux/fs/cramfs/inode.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/cramfs/inode.c	Tue Jan 11 10:24:58 2000
@@ -27,7 +27,10 @@
 static struct inode_operations cramfs_dir_inode_operations;
 static struct inode_operations cramfs_symlink_inode_operations;
 
+/* These two macros may change in future, to provide better st_ino
+   semantics. */
 #define CRAMINO(x)	((x)->offset?(x)->offset<<2:1)
+#define OFFSET(x)	((x)->i_ino)
 
 static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inode * cramfs_inode)
 {
@@ -41,6 +44,12 @@
 		inode->i_ino = CRAMINO(cramfs_inode);
 		inode->i_sb = sb;
 		inode->i_dev = sb->s_dev;
+		inode->i_nlink = 1; /* arguably wrong for directories,
+				       but it's the best we can do
+				       without reading the directory
+				       contents.  1 yields the right
+				       result in GNU find, even
+				       without -noleaf option. */
 		insert_inode_hash(inode);
 		if (S_ISREG(inode->i_mode))
 			inode->i_op = &cramfs_file_inode_operations;
@@ -62,45 +71,75 @@
  * up the accesses should be fairly regular and cached in the
  * page cache and dentry tree anyway..
  *
- * This also acts as a way to guarantee contiguous areas of
- * up to 2*PAGE_CACHE_SIZE, so that the caller doesn't need
- * to worry about end-of-buffer issues even when decompressing
- * a full page cache.
+ * This also acts as a way to guarantee contiguous areas of up to
+ * BLKS_PER_BUF*PAGE_CACHE_SIZE, so that the caller doesn't need to
+ * worry about end-of-buffer issues even when decompressing a full
+ * page cache.
  */
 #define READ_BUFFERS (2)
-static unsigned char read_buffers[READ_BUFFERS][PAGE_CACHE_SIZE*4];
-static int buffer_blocknr[READ_BUFFERS];
-static int last_buffer = 0;
+/* NEXT_BUFFER(): Loop over [0..(READ_BUFFERS-1)]. */
+#define NEXT_BUFFER(_ix) ((_ix) ^ 1)
 
-static void *cramfs_read(struct super_block *sb, unsigned int offset)
+/*
+ * BLKS_PER_BUF_SHIFT must be at least 1 to allow for "compressed"
+ * data that takes up more space than the original.  1 is guaranteed
+ * to suffice, though.  Larger values provide more read-ahead and
+ * proportionally less wastage at the end of the buffer.
+ */
+#define BLKS_PER_BUF_SHIFT (2)
+#define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT)
+static unsigned char read_buffers[READ_BUFFERS][BLKS_PER_BUF][PAGE_CACHE_SIZE];
+static unsigned buffer_blocknr[READ_BUFFERS];
+static int next_buffer = 0;
+
+/*
+ * Returns a pointer to a buffer containing at least LEN bytes of
+ * filesystem starting at byte offset OFFSET into the filesystem.
+ */
+static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
 {
-	struct buffer_head * bh_array[4];
-	int i, blocknr, buffer;
+	struct buffer_head * bh_array[BLKS_PER_BUF];
+	unsigned i, blocknr, last_blocknr, buffer;
 
+	if (!len)
+		return NULL;
 	blocknr = offset >> PAGE_CACHE_SHIFT;
-	offset &= PAGE_CACHE_SIZE-1;
+	last_blocknr = (offset + len - 1) >> PAGE_CACHE_SHIFT;
+	if (last_blocknr - blocknr >= BLKS_PER_BUF)
+		goto eek; resume:
+	offset &= PAGE_CACHE_SIZE - 1;
 	for (i = 0; i < READ_BUFFERS; i++) {
-		if (blocknr == buffer_blocknr[i])
-			return read_buffers[i] + offset;
+		if ((blocknr >= buffer_blocknr[i]) &&
+		    (last_blocknr - buffer_blocknr[i] < BLKS_PER_BUF))
+			return &read_buffers[i][blocknr - buffer_blocknr[i]][offset];
 	}
 
-	/* Ok, read in four buffers completely first */
-	for (i = 0; i < 4; i++)
+	/* Ok, read in BLKS_PER_BUF pages completely first. */
+	for (i = 0; i < BLKS_PER_BUF; i++)
 		bh_array[i] = bread(sb->s_dev, blocknr + i, PAGE_CACHE_SIZE);
 
-	/* Ok, copy them to the staging area without sleeping.. */
-	buffer = last_buffer;
-	last_buffer = buffer ^ 1;
+	/* Ok, copy them to the staging area without sleeping. */
+	buffer = next_buffer;
+	next_buffer = NEXT_BUFFER(buffer);
 	buffer_blocknr[buffer] = blocknr;
-	for (i = 0; i < 4; i++) {
+	for (i = 0; i < BLKS_PER_BUF; i++) {
 		struct buffer_head * bh = bh_array[i];
 		if (bh) {
-			memcpy(read_buffers[buffer] + i*PAGE_CACHE_SIZE, bh->b_data, PAGE_CACHE_SIZE);
+			memcpy(read_buffers[buffer][i], bh->b_data, PAGE_CACHE_SIZE);
 			bforget(bh);
-		}
-		blocknr++;
+		} else
+			memset(read_buffers[buffer][i], 0, PAGE_CACHE_SIZE);
 	}
-	return read_buffers[buffer] + offset;
+	return read_buffers[buffer][0] + offset;
+
+ eek:
+	printk(KERN_ERR
+	       "cramfs (device %s): requested chunk (%u:+%u) bigger than buffer\n",
+	       bdevname(sb->s_dev), offset, len);
+	/* TODO: return EIO to process or kill the current process
+           instead of resuming. */
+	*((int *)0) = 0; /* XXX: doesn't work on all archs */
+	goto resume;
 }
 			
 
@@ -121,7 +160,7 @@
 		buffer_blocknr[i] = -1;
 
 	/* Read the first block and get the superblock from it */
-	memcpy(&super, cramfs_read(sb, 0), sizeof(super));
+	memcpy(&super, cramfs_read(sb, 0, sizeof(super)), sizeof(super));
 
 	/* Do sanity checks on the superblock */
 	if (super.magic != CRAMFS_MAGIC) {
@@ -132,21 +171,23 @@
 		printk("wrong signature\n");
 		goto out;
 	}
-
-	/* Check that the root inode is in a sane state */
-	root_offset = super.root.offset << 2;
-	if (root_offset < sizeof(struct cramfs_super)) {
-		printk("root offset too small\n");
-		goto out;
-	}
-	if (root_offset >= super.size) {
-		printk("root offset too large (%lu %u)\n", root_offset, super.size);
+	if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) {
+		printk("unsupported filesystem features\n");
 		goto out;
 	}
+
+	/* Check that the root inode is in a sane state */
 	if (!S_ISDIR(super.root.mode)) {
 		printk("root is not a directory\n");
 		goto out;
 	}
+	root_offset = super.root.offset << 2;
+	if (root_offset == 0)
+		printk(KERN_INFO "cramfs: note: empty filesystem");
+	else if (root_offset != sizeof(struct cramfs_super)) {
+		printk("bad root offset %lu\n", root_offset);
+		goto out;
+	}
 
 	/* Set it all up.. */
 	sb->s_op	= &cramfs_ops;
@@ -168,19 +209,20 @@
 {
 	struct statfs tmp;
 
-	memset(&tmp, 0, sizeof(tmp));
+	/* Unsupported fields set to -1 as per man page. */
+	memset(&tmp, 0xff, sizeof(tmp));
+
 	tmp.f_type = CRAMFS_MAGIC;
 	tmp.f_bsize = PAGE_CACHE_SIZE;
-	tmp.f_blocks = 0;
+	tmp.f_bfree = 0;
+	tmp.f_bavail = 0;
+	tmp.f_ffree = 0;
 	tmp.f_namelen = 255;
 	return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
 }
 
 /*
- * Read a cramfs directory entry..
- *
- * Remember: the inode number is the byte offset of the start
- * of the directory..
+ * Read a cramfs directory entry.
  */
 static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
@@ -189,7 +231,7 @@
 	unsigned int offset;
 	int copied;
 
-	/* Offset within the thing.. */
+	/* Offset within the thing. */
 	offset = filp->f_pos;
 	if (offset >= inode->i_size)
 		return 0;
@@ -204,7 +246,7 @@
 		char *name;
 		int namelen, error;
 
-		de = cramfs_read(sb, offset + inode->i_ino);
+		de = cramfs_read(sb, OFFSET(inode) + offset, sizeof(*de)+256);
 		name = (char *)(de+1);
 
 		/*
@@ -244,7 +286,7 @@
 		char *name;
 		int namelen;
 
-		de = cramfs_read(dir->i_sb, offset + dir->i_ino);
+		de = cramfs_read(dir->i_sb, OFFSET(dir) + offset, sizeof(*de)+256);
 		name = (char *)(de+1);
 		namelen = de->namelen << 2;
 		offset += sizeof(*de) + namelen;
@@ -274,27 +316,29 @@
 static int cramfs_readpage(struct dentry *dentry, struct page * page)
 {
 	struct inode *inode = dentry->d_inode;
-	unsigned long maxblock, bytes;
+	u32 maxblock, bytes_filled;
 
 	maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	bytes = 0;
+	bytes_filled = 0;
 	if (page->index < maxblock) {
 		struct super_block *sb = inode->i_sb;
-		unsigned long block_offset = inode->i_ino + page->index*4;
-		unsigned long start_offset = inode->i_ino + maxblock*4;
-		unsigned long end_offset;
+		u32 blkptr_offset = OFFSET(inode) + page->index*4;
+		u32 start_offset, compr_len;
 
-		end_offset = *(u32 *) cramfs_read(sb, block_offset);
+		start_offset = OFFSET(inode) + maxblock*4;
 		if (page->index)
-			start_offset = *(u32 *) cramfs_read(sb, block_offset-4);
-
-		bytes = inode->i_size & (PAGE_CACHE_SIZE - 1);
-		if (page->index < maxblock)
-			bytes = PAGE_CACHE_SIZE;
-
-		cramfs_uncompress_block((void *) page_address(page), PAGE_CACHE_SIZE, cramfs_read(sb, start_offset), end_offset - start_offset);
+			start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4);
+		compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4)
+			     - start_offset);
+		if (compr_len == 0)
+			; /* hole */
+		else
+			bytes_filled = cramfs_uncompress_block((void *) page_address(page),
+				 PAGE_CACHE_SIZE,
+				 cramfs_read(sb, start_offset, compr_len),
+				 compr_len);
 	}
-	memset((void *) (page_address(page) + bytes), 0, PAGE_CACHE_SIZE - bytes);
+	memset((void *) (page_address(page) + bytes_filled), 0, PAGE_CACHE_SIZE - bytes_filled);
 	SetPageUptodate(page);
 	UnlockPage(page);
 	return 0;
diff -u --recursive --new-file v2.3.39/linux/fs/cramfs/uncompress.c linux/fs/cramfs/uncompress.c
--- v2.3.39/linux/fs/cramfs/uncompress.c	Wed Dec 29 13:13:20 1999
+++ linux/fs/cramfs/uncompress.c	Tue Jan 11 10:24:58 2000
@@ -22,6 +22,7 @@
 static z_stream stream;
 static int initialized = 0;
 
+/* Returns length of decompressed data. */
 int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen)
 {
 	int err;
@@ -32,14 +33,22 @@
 	stream.next_out = dst;
 	stream.avail_out = dstlen;
 
-	inflateReset(&stream);
+	err = inflateReset(&stream);
+	if (err != Z_OK) {
+		printk("inflateReset error %d\n", err);
+		inflateEnd(&stream);
+		inflateInit(&stream);
+	}
 
 	err = inflate(&stream, Z_FINISH);
-	if (err != Z_STREAM_END) {
-		printk("Error %d while decompressing!\n", err);
-		printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
-	}
+	if (err != Z_STREAM_END)
+		goto err;
 	return stream.total_out;
+
+err:
+	printk("Error %d while decompressing!\n", err);
+	printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen);
+	return 0;
 }
 
 int cramfs_uncompress_init(void)
diff -u --recursive --new-file v2.3.39/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.3.39/linux/fs/ext2/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/ext2/file.c	Tue Jan 11 14:19:17 2000
@@ -28,7 +28,7 @@
 #define MIN(a,b) (((a)<(b))?(a):(b))
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
-static long long ext2_file_lseek(struct file *, long long, int);
+static loff_t ext2_file_lseek(struct file *, loff_t, int);
 static int ext2_open_file (struct inode *, struct file *);
 
 #define EXT2_MAX_SIZE(bits)							\
@@ -45,9 +45,9 @@
 /*
  * Make sure the offset never goes beyond the 32-bit mark..
  */
-static long long ext2_file_lseek(
+static loff_t ext2_file_lseek(
 	struct file *file,
-	long long offset,
+	loff_t offset,
 	int origin)
 {
 	struct inode *inode = file->f_dentry->d_inode;
diff -u --recursive --new-file v2.3.39/linux/fs/ext2/inode.c linux/fs/ext2/inode.c
--- v2.3.39/linux/fs/ext2/inode.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/ext2/inode.c	Thu Jan 20 10:48:35 2000
@@ -899,28 +899,28 @@
 	flags = iattr->ia_attr_flags;
 	if (flags & ATTR_FLAG_SYNCRONOUS) {
 		inode->i_flags |= MS_SYNCHRONOUS;
-		inode->u.ext2_i.i_flags = EXT2_SYNC_FL;
+		inode->u.ext2_i.i_flags |= EXT2_SYNC_FL;
 	} else {
 		inode->i_flags &= ~MS_SYNCHRONOUS;
 		inode->u.ext2_i.i_flags &= ~EXT2_SYNC_FL;
 	}
 	if (flags & ATTR_FLAG_NOATIME) {
 		inode->i_flags |= MS_NOATIME;
-		inode->u.ext2_i.i_flags = EXT2_NOATIME_FL;
+		inode->u.ext2_i.i_flags |= EXT2_NOATIME_FL;
 	} else {
 		inode->i_flags &= ~MS_NOATIME;
 		inode->u.ext2_i.i_flags &= ~EXT2_NOATIME_FL;
 	}
 	if (flags & ATTR_FLAG_APPEND) {
 		inode->i_flags |= S_APPEND;
-		inode->u.ext2_i.i_flags = EXT2_APPEND_FL;
+		inode->u.ext2_i.i_flags |= EXT2_APPEND_FL;
 	} else {
 		inode->i_flags &= ~S_APPEND;
 		inode->u.ext2_i.i_flags &= ~EXT2_APPEND_FL;
 	}
 	if (flags & ATTR_FLAG_IMMUTABLE) {
 		inode->i_flags |= S_IMMUTABLE;
-		inode->u.ext2_i.i_flags = EXT2_IMMUTABLE_FL;
+		inode->u.ext2_i.i_flags |= EXT2_IMMUTABLE_FL;
 	} else {
 		inode->i_flags &= ~S_IMMUTABLE;
 		inode->u.ext2_i.i_flags &= ~EXT2_IMMUTABLE_FL;
diff -u --recursive --new-file v2.3.39/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.3.39/linux/fs/ext2/namei.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/ext2/namei.c	Thu Jan 20 10:48:35 2000
@@ -832,6 +832,13 @@
 	new_dir->i_version = ++event;
 
 	/*
+	 * Like most other Unix systems, set the ctime for inodes on a
+	 * rename.
+	 */
+	old_inode->i_ctime = CURRENT_TIME;
+	mark_inode_dirty(old_inode);
+
+	/*
 	 * ok, that's it
 	 */
 	new_de->inode = le32_to_cpu(old_inode->i_ino);
diff -u --recursive --new-file v2.3.39/linux/fs/fat/dir.c linux/fs/fat/dir.c
--- v2.3.39/linux/fs/fat/dir.c	Mon Dec 20 18:48:22 1999
+++ linux/fs/fat/dir.c	Thu Jan 20 10:48:35 2000
@@ -289,11 +289,11 @@
 	}
 
 Found:
-	fat_brelse(sb, bh);
 	res = long_slots + 1;
 	*spos = cpos - sizeof(struct msdos_dir_entry);
 	*lpos = cpos - res*sizeof(struct msdos_dir_entry);
 EODir:
+	fat_brelse(sb, bh);
 	if (unicode) {
 		free_page((unsigned long) unicode);
 	}
diff -u --recursive --new-file v2.3.39/linux/fs/hfs/ChangeLog linux/fs/hfs/ChangeLog
--- v2.3.39/linux/fs/hfs/ChangeLog	Wed May 12 13:26:20 1999
+++ linux/fs/hfs/ChangeLog	Thu Jan 13 11:55:38 2000
@@ -1,3 +1,7 @@
+2000-01-02  a sun  <asun@asun.cobalt.com>
+
+	* file.c (hfs_get_block): added hfs_get_block for regular files. 
+
 1999-04-12  a sun  <asun@hecate.darksunrising.blah>
 
 	* file_hdr.c (hdr_read): added rootinfo behaviour for DID header.
diff -u --recursive --new-file v2.3.39/linux/fs/hfs/extent.c linux/fs/hfs/extent.c
--- v2.3.39/linux/fs/hfs/extent.c	Wed Dec 23 14:10:36 1998
+++ linux/fs/hfs/extent.c	Thu Jan 13 11:54:37 2000
@@ -523,7 +523,7 @@
  * Try to add enough allocation blocks to 'fork'
  * so that it is 'ablock' allocation blocks long. 
  */
-static void grow_fork(struct hfs_fork *fork, int ablocks)
+static int grow_fork(struct hfs_fork *fork, int ablocks)
 {
 	struct hfs_cat_entry *entry = fork->entry;
 	struct hfs_mdb *mdb = entry->mdb;
@@ -535,8 +535,8 @@
 
 	blocks = fork->psize;
 	need = ablocks - blocks/ablksz;
-	if (need < 1) {
-		return;
+	if (need < 1) { /* no need to grow the fork */
+		return 0;
 	}
 
 	/* round up to clumpsize */
@@ -550,7 +550,7 @@
 	/* find last extent record and try to extend it */
 	if (!(ext = find_ext(fork, blocks/ablksz - 1))) {
 		/* somehow we couldn't find the end of the file! */
-		return;
+		return -1;
 	}
 
 	/* determine which is the last used extent in the record */
@@ -574,7 +574,7 @@
 		unlock_bitmap(mdb);
 		if (err) {
 			relse_ext(ext);
-			return;
+			return -1;
 		}
 	
 		zero_blocks(mdb, start, len);
@@ -600,7 +600,7 @@
 		unlock_bitmap(mdb);
 		if (!len || err) {
 			relse_ext(ext);
-			return;
+			return -1;
 		}
 		zero_blocks(mdb, start, len);
 
@@ -617,7 +617,7 @@
 				lock_bitmap(mdb);
 				hfs_clear_vbm_bits(mdb, start, len);
 				unlock_bitmap(mdb);
-				return;
+				return -1;
 			}
 		}
 		blocks = (fork->psize += len * ablksz);
@@ -625,7 +625,7 @@
 	}
 	set_cache(fork, ext);
 	relse_ext(ext);
-	return;
+	return 0;
 }
 
 /*================ Global functions ================*/
@@ -738,11 +738,8 @@
 	ablock = block / ablksz;
 	
 	if (block >= fork->psize) {
-		if (create) {
-			grow_fork(fork, ablock + 1);
-		} else {
+		if (!create || (grow_fork(fork, ablock + 1) < 0))
 			return 0;
-		}
 	}
 
 #if defined(DEBUG_EXTENTS) || defined(DEBUG_ALL)
diff -u --recursive --new-file v2.3.39/linux/fs/hfs/file.c linux/fs/hfs/file.c
--- v2.3.39/linux/fs/hfs/file.c	Fri Jan  7 19:13:22 2000
+++ linux/fs/hfs/file.c	Thu Jan 13 11:54:37 2000
@@ -28,7 +28,7 @@
 static hfs_rwret_t hfs_file_write(struct file *, const char *, hfs_rwarg_t,
 				  loff_t *);
 static void hfs_file_truncate(struct inode *);
-static int hfs_bmap(struct inode *, int);
+static int hfs_get_block(struct inode *, long, struct buffer_head *, int);
 
 /*================ Global variables ================*/
 
@@ -61,7 +61,7 @@
 	NULL,			/* rename */
 	NULL,			/* readlink */
 	NULL,			/* follow_link */
-	hfs_bmap,		/* get_block */
+	hfs_get_block,		/* get_block */
 	block_read_full_page,	/* readpage */
 	NULL,			/* writepage */
 	hfs_file_truncate,	/* truncate */
@@ -124,19 +124,37 @@
 }
 
 /*
- * hfs_bmap()
+ * hfs_get_block
  *
- * This is the bmap() field in the inode_operations structure for
+ * This is the hfs_get_block() field in the inode_operations structure for
  * "regular" (non-header) files.  The purpose is to translate an inode
  * and a block number within the corresponding file into a physical
  * block number.  This function just calls hfs_extent_map() to do the
- * real work.
+ * real work and then stuffs the appropriate info into the buffer_head.
  */
-static int hfs_bmap(struct inode * inode, int block)
+int hfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_result, int create)
 {
-	return hfs_extent_map(HFS_I(inode)->fork, block, 0);
+	unsigned long phys;
+
+	phys = hfs_extent_map(HFS_I(inode)->fork, iblock, create);
+	if (phys) {
+		bh_result->b_dev = inode->i_dev;
+		bh_result->b_blocknr = phys;
+		bh_result->b_state |= (1UL << BH_Mapped);
+		if (create)
+			bh_result->b_state |= (1UL << BH_New);
+		return 0;
+	}
+
+	if (!create)
+		return 0;
+
+	/* we tried to add stuff, but we couldn't. send back an out-of-space
+	 * error. */
+	return -ENOSPC;
 }
 
+
 /*
  * hfs_file_read()
  *
@@ -146,8 +164,7 @@
  * 'filp->offset' bytes into the file.	The data is transfered to
  * user-space at the address 'buf'.  Returns the number of bytes
  * successfully transfered.  This function checks the arguments, does
- * some setup and then calls hfs_do_read() to do the actual transfer.
- */
+ * some setup and then calls hfs_do_read() to do the actual transfer.  */
 static hfs_rwret_t hfs_file_read(struct file * filp, char * buf, 
 				 hfs_rwarg_t count, loff_t *ppos)
 {
diff -u --recursive --new-file v2.3.39/linux/fs/hfs/hfs_btree.h linux/fs/hfs/hfs_btree.h
--- v2.3.39/linux/fs/hfs/hfs_btree.h	Sat Feb 28 13:23:45 1998
+++ linux/fs/hfs/hfs_btree.h	Thu Jan 13 11:54:37 2000
@@ -34,6 +34,20 @@
 #define ndMapNode	0x02	/* Holds part of the bitmap of used nodes */
 #define ndLeafNode	0xFF	/* A leaf (ndNHeight==1) node */
 
+/*
+ * Legal values for the bthAtrb field of a (struct BTHdrRec)
+ *
+ * Reference: TN 1150
+ */
+#define bthBadClose     0x00000001  /* b-tree not closed properly. not
+                                       used by hfsplus. */
+#define bthBigKeys      0x00000002  /* key length is u16 instead of u8.
+				       used by hfsplus. */
+#define bthVarIndxKeys  0x00000004  /* variable key length instead of
+                                       max key length. use din catalog
+                                       b-tree but not in extents
+                                       b-tree (hfsplus). */
+
 /*================ Function-like macros ================*/
 
 /* Access the cache slot which should contain the desired node */
@@ -70,7 +84,12 @@
 	hfs_word_t  bthKeyLen;	/* (F) The length of a key in an index node */
 	hfs_lword_t bthNNodes;	/* (V) The total number of nodes */
 	hfs_lword_t bthFree;	/* (V) The number of unused nodes */
-	hfs_byte_t  bthResv[76];	/* Reserved */
+        hfs_word_t  bthResv1;   /* reserved */
+        hfs_lword_t bthClpSiz;  /* (F) clump size. not usually used. */
+        hfs_byte_t  bthType;    /* (F) BTree type */
+        hfs_byte_t  bthResv2;   /* reserved */
+        hfs_lword_t bthAtrb;    /* (F) attributes */
+        hfs_lword_t bthResv3[16]; /* Reserved */
 };
 
 /*
@@ -129,6 +148,8 @@
 					this node in-core (set for
 					root and head) */
 	hfs_u32		    node;    /* Node number */
+	hfs_u16             nodeSize; /* node size */
+        hfs_u16             keyLen;  /* key length */
 	/* locking related fields: */
 	hfs_wait_queue	    wqueue;  /* Wait queue for write access */
 	hfs_wait_queue	    rqueue;  /* Wait queue for read or reserve
@@ -176,6 +197,7 @@
 	int			lock;
 	hfs_wait_queue		wait;
 	int			dirt;
+	int                     keySize;   
 	/* Fields from the BTHdrRec in native byte-order: */
 	hfs_u32			bthRoot;
 	hfs_u32			bthNRecs;
diff -u --recursive --new-file v2.3.39/linux/fs/hfs/inode.c linux/fs/hfs/inode.c
--- v2.3.39/linux/fs/hfs/inode.c	Wed May 12 13:26:20 1999
+++ linux/fs/hfs/inode.c	Thu Jan 13 11:54:37 2000
@@ -44,14 +44,18 @@
 	}
 
 	if (fork == HFS_FK_DATA) {
+#if 0 /* XXX: disable crlf translations for now */
 		hfs_u32 type = hfs_get_nl(entry->info.file.finfo.fdType);
 
-		fk = &entry->u.file.data_fork;
 		HFS_I(inode)->convert =
 			((HFS_SB(inode->i_sb)->s_conv == 't') ||
 			 ((HFS_SB(inode->i_sb)->s_conv == 'a') &&
 			  ((type == htonl(0x54455854)) ||   /* "TEXT" */
 			   (type == htonl(0x7474726f)))));  /* "ttro" */
+#else
+		HFS_I(inode)->convert = 0;
+#endif
+		fk = &entry->u.file.data_fork;
 	} else {
 		fk = &entry->u.file.rsrc_fork;
 		HFS_I(inode)->convert = 0;
diff -u --recursive --new-file v2.3.39/linux/fs/lockd/mon.c linux/fs/lockd/mon.c
--- v2.3.39/linux/fs/lockd/mon.c	Sun Nov  7 16:37:34 1999
+++ linux/fs/lockd/mon.c	Thu Jan 20 10:48:35 2000
@@ -143,7 +143,7 @@
 	char	buffer[20];
 	u32	addr = ntohl(argp->addr);
 
-	dprintk("nsm: xdr_encode_mon(%08lx, %ld, %ld, %ld)\n",
+	dprintk("nsm: xdr_encode_mon(%08x, %d, %d, %d)\n",
 			htonl(argp->addr), htonl(argp->proc),
 			htonl(argp->vers), htonl(argp->proc));
 
diff -u --recursive --new-file v2.3.39/linux/fs/lockd/svcproc.c linux/fs/lockd/svcproc.c
--- v2.3.39/linux/fs/lockd/svcproc.c	Wed Feb 17 09:44:33 1999
+++ linux/fs/lockd/svcproc.c	Thu Jan 20 10:48:35 2000
@@ -43,7 +43,7 @@
 	/* Obtain handle for client host */
 	if (rqstp->rq_client == NULL) {
 		printk(KERN_NOTICE
-			"lockd: unauthenticated request from (%08lx:%d)\n",
+			"lockd: unauthenticated request from (%08x:%d)\n",
 			ntohl(rqstp->rq_addr.sin_addr.s_addr),
 			ntohs(rqstp->rq_addr.sin_port));
 		return nlm_lck_denied_nolocks;
@@ -110,7 +110,7 @@
 	/* Now check for conflicting locks */
 	resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock);
 
-	dprintk("lockd: TEST          status %ld\n", ntohl(resp->status));
+	dprintk("lockd: TEST          status %d\n", ntohl(resp->status));
 	nlm_release_host(host);
 	nlm_release_file(file);
 	return rpc_success;
@@ -153,7 +153,7 @@
 	resp->status = nlmsvc_lock(rqstp, file, &argp->lock,
 					argp->block, &argp->cookie);
 
-	dprintk("lockd: LOCK          status %ld\n", ntohl(resp->status));
+	dprintk("lockd: LOCK          status %d\n", ntohl(resp->status));
 	nlm_release_host(host);
 	nlm_release_file(file);
 	return rpc_success;
@@ -183,7 +183,7 @@
 	/* Try to cancel request. */
 	resp->status = nlmsvc_cancel_blocked(file, &argp->lock);
 
-	dprintk("lockd: CANCEL        status %ld\n", ntohl(resp->status));
+	dprintk("lockd: CANCEL        status %d\n", ntohl(resp->status));
 	nlm_release_host(host);
 	nlm_release_file(file);
 	return rpc_success;
@@ -216,7 +216,7 @@
 	/* Now try to remove the lock */
 	resp->status = nlmsvc_unlock(file, &argp->lock);
 
-	dprintk("lockd: UNLOCK        status %ld\n", ntohl(resp->status));
+	dprintk("lockd: UNLOCK        status %d\n", ntohl(resp->status));
 	nlm_release_host(host);
 	nlm_release_file(file);
 	return rpc_success;
@@ -234,7 +234,7 @@
 
 	dprintk("lockd: GRANTED       called\n");
 	resp->status = nlmclnt_grant(&argp->lock);
-	dprintk("lockd: GRANTED       status %ld\n", ntohl(resp->status));
+	dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
 	return rpc_success;
 }
 
@@ -340,7 +340,7 @@
 	/* Now try to create the share */
 	resp->status = nlmsvc_share_file(host, file, argp);
 
-	dprintk("lockd: SHARE         status %ld\n", ntohl(resp->status));
+	dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
 	nlm_release_host(host);
 	nlm_release_file(file);
 	return rpc_success;
@@ -373,7 +373,7 @@
 	/* Now try to lock the file */
 	resp->status = nlmsvc_unshare_file(host, file, argp);
 
-	dprintk("lockd: UNSHARE       status %ld\n", ntohl(resp->status));
+	dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
 	nlm_release_host(host);
 	nlm_release_file(file);
 	return rpc_success;
@@ -424,7 +424,7 @@
 	if (saddr.sin_addr.s_addr != htonl(INADDR_LOOPBACK)
 	 || ntohs(saddr.sin_port) >= 1024) {
 		printk(KERN_WARNING
-			"lockd: rejected NSM callback from %08lx:%d\n",
+			"lockd: rejected NSM callback from %08x:%d\n",
 			ntohl(rqstp->rq_addr.sin_addr.s_addr),
 			ntohs(rqstp->rq_addr.sin_port));
 		return rpc_system_err;
diff -u --recursive --new-file v2.3.39/linux/fs/lockd/svcsubs.c linux/fs/lockd/svcsubs.c
--- v2.3.39/linux/fs/lockd/svcsubs.c	Tue Jun  1 23:25:47 1999
+++ linux/fs/lockd/svcsubs.c	Thu Jan 20 10:48:35 2000
@@ -86,7 +86,7 @@
 	 * the file.
 	 */
 	if ((nfserr = nlmsvc_ops->fopen(rqstp, fh, &file->f_file)) != 0) {
-		dprintk("lockd: open failed (nfserr %ld)\n", ntohl(nfserr));
+		dprintk("lockd: open failed (nfserr %d)\n", ntohl(nfserr));
 		goto out_free;
 	}
 
diff -u --recursive --new-file v2.3.39/linux/fs/lockd/xdr.c linux/fs/lockd/xdr.c
--- v2.3.39/linux/fs/lockd/xdr.c	Sat Feb  6 12:46:21 1999
+++ linux/fs/lockd/xdr.c	Tue Jan 11 14:19:17 2000
@@ -95,8 +95,8 @@
 
 	if ((len = ntohl(*p++)) != sizeof(*f)) {
 		printk(KERN_NOTICE
-			"lockd: bad fhandle size %x (should be %d)\n",
-			len, sizeof(*f));
+			"lockd: bad fhandle size %u (should be %lu)\n",
+			len, (unsigned long) sizeof(*f));
 		return NULL;
 	}
 	memcpy(f, p, sizeof(*f));
diff -u --recursive --new-file v2.3.39/linux/fs/namei.c linux/fs/namei.c
--- v2.3.39/linux/fs/namei.c	Tue Jan  4 13:57:18 2000
+++ linux/fs/namei.c	Wed Jan 12 11:51:49 2000
@@ -780,16 +780,14 @@
 	char * tmp;
 	struct dentry * dentry;
 
-	lock_kernel();
-	error = -EPERM;
 	if (S_ISDIR(mode) || (!S_ISFIFO(mode) && !capable(CAP_MKNOD)))
-		goto out;
+		return -EPERM;
 	tmp = getname(filename);
-	error = PTR_ERR(tmp);
 	if (IS_ERR(tmp))
-		goto out;
+		return PTR_ERR(tmp);
 
 	error = -EINVAL;
+	lock_kernel();
 	switch (mode & S_IFMT) {
 	case 0:
 		mode |= S_IFREG;	/* fallthrough */
@@ -815,10 +813,9 @@
 		}
 		break;
 	}
+	unlock_kernel();
 	putname(tmp);
 
-out:
-	unlock_kernel();
 	return error;
 }
 
@@ -870,14 +867,14 @@
 	int error;
 	char * tmp;
 
-	lock_kernel();
 	tmp = getname(pathname);
-	error = PTR_ERR(tmp);
-	if (!IS_ERR(tmp)) {
-		error = do_mkdir(tmp,mode);
-		putname(tmp);
-	}
+	if(IS_ERR(tmp))
+		return PTR_ERR(tmp);
+	lock_kernel();
+	error = do_mkdir(tmp,mode);
 	unlock_kernel();
+	putname(tmp);
+
 	return error;
 }
 
@@ -965,14 +962,15 @@
 	int error;
 	char * tmp;
 
-	lock_kernel();
 	tmp = getname(pathname);
-	error = PTR_ERR(tmp);
-	if (!IS_ERR(tmp)) {
-		error = do_rmdir(tmp);
-		putname(tmp);
-	}
+	if(IS_ERR(tmp))
+		return PTR_ERR(tmp);
+	lock_kernel();
+	error = do_rmdir(tmp);
 	unlock_kernel();
+
+	putname(tmp);
+
 	return error;
 }
 
@@ -1018,14 +1016,14 @@
 	int error;
 	char * tmp;
 
-	lock_kernel();
 	tmp = getname(pathname);
-	error = PTR_ERR(tmp);
-	if (!IS_ERR(tmp)) {
-		error = do_unlink(tmp);
-		putname(tmp);
-	}
+	if(IS_ERR(tmp))
+		return PTR_ERR(tmp);
+	lock_kernel();
+	error = do_unlink(tmp);
 	unlock_kernel();
+	putname(tmp);
+
 	return error;
 }
 
@@ -1068,21 +1066,20 @@
 {
 	int error;
 	char * from;
+	char * to;
 
-	lock_kernel();
 	from = getname(oldname);
-	error = PTR_ERR(from);
-	if (!IS_ERR(from)) {
-		char * to;
-		to = getname(newname);
-		error = PTR_ERR(to);
-		if (!IS_ERR(to)) {
-			error = do_symlink(from,to);
-			putname(to);
-		}
-		putname(from);
+	if(IS_ERR(from))
+		return PTR_ERR(from);
+	to = getname(newname);
+	error = PTR_ERR(to);
+	if (!IS_ERR(to)) {
+		lock_kernel();
+		error = do_symlink(from,to);
+		unlock_kernel();
+		putname(to);
 	}
-	unlock_kernel();
+	putname(from);
 	return error;
 }
 
@@ -1156,21 +1153,21 @@
 {
 	int error;
 	char * from;
+		char * to;
 
-	lock_kernel();
 	from = getname(oldname);
-	error = PTR_ERR(from);
-	if (!IS_ERR(from)) {
-		char * to;
-		to = getname(newname);
-		error = PTR_ERR(to);
-		if (!IS_ERR(to)) {
-			error = do_link(from,to);
-			putname(to);
-		}
-		putname(from);
+	if(IS_ERR(from))
+		return PTR_ERR(from);
+	to = getname(newname);
+	error = PTR_ERR(to);
+	if (!IS_ERR(to)) {
+		lock_kernel();
+		error = do_link(from,to);
+		unlock_kernel();
+		putname(to);
 	}
-	unlock_kernel();
+	putname(from);
+
 	return error;
 }
 
@@ -1327,21 +1324,20 @@
 {
 	int error;
 	char * from;
+	char * to;
 
-	lock_kernel();
 	from = getname(oldname);
-	error = PTR_ERR(from);
-	if (!IS_ERR(from)) {
-		char * to;
-		to = getname(newname);
-		error = PTR_ERR(to);
-		if (!IS_ERR(to)) {
-			error = do_rename(from,to);
-			putname(to);
-		}
-		putname(from);
+	if(IS_ERR(from))
+		return PTR_ERR(from);
+	to = getname(newname);
+	error = PTR_ERR(to);
+	if (!IS_ERR(to)) {
+		lock_kernel();
+		error = do_rename(from,to);
+		unlock_kernel();
+		putname(to);
 	}
-	unlock_kernel();
+	putname(from);
 	return error;
 }
 
diff -u --recursive --new-file v2.3.39/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.3.39/linux/fs/ncpfs/inode.c	Wed Dec  8 14:11:27 1999
+++ linux/fs/ncpfs/inode.c	Sun Jan 16 10:47:19 2000
@@ -258,7 +258,7 @@
 struct super_block *
 ncp_read_super(struct super_block *sb, void *raw_data, int silent)
 {
-	struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
+	struct ncp_mount_data_kernel data;
 	struct ncp_server *server;
 	struct file *ncp_filp;
 	struct inode *root_inode;
@@ -270,11 +270,50 @@
 	struct ncp_entry_info finfo;
 
 	MOD_INC_USE_COUNT;
-	if (data == NULL)
+	if (raw_data == NULL)
 		goto out_no_data;
-	if (data->version != NCP_MOUNT_VERSION)
-		goto out_bad_mount;
-	ncp_filp = fget(data->ncp_fd);
+	switch (*(int*)raw_data) {
+		case NCP_MOUNT_VERSION:
+			{
+				struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;
+
+				data.flags = md->flags;
+				data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
+				data.mounted_uid = md->mounted_uid;
+				data.wdog_pid = md->wdog_pid;
+				data.ncp_fd = md->ncp_fd;
+				data.time_out = md->time_out;
+				data.retry_count = md->retry_count;
+				data.uid = md->uid;
+				data.gid = md->gid;
+				data.file_mode = md->file_mode;
+				data.dir_mode = md->dir_mode;
+				memcpy(data.mounted_vol, md->mounted_vol,
+					NCP_VOLNAME_LEN+1);
+			}
+			break;
+		case NCP_MOUNT_VERSION_V4:
+			{
+				struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;
+
+				data.flags = md->flags;
+				data.int_flags = 0;
+				data.mounted_uid = md->mounted_uid;
+				data.wdog_pid = md->wdog_pid;
+				data.ncp_fd = md->ncp_fd;
+				data.time_out = md->time_out;
+				data.retry_count = md->retry_count;
+				data.uid = md->uid;
+				data.gid = md->gid;
+				data.file_mode = md->file_mode;
+				data.dir_mode = md->dir_mode;
+				data.mounted_vol[0] = 0;
+			}
+			break;
+		default:
+			goto out_bad_mount;
+	}
+	ncp_filp = fget(data.ncp_fd);
 	if (!ncp_filp)
 		goto out_bad_file;
 	if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
@@ -310,7 +349,7 @@
 /*	server->priv.len = 0;			*/
 /*	server->priv.data = NULL;		*/
 
-	server->m = *data;
+	server->m = data;
 	/* Althought anything producing this is buggy, it happens
 	   now because of PATH_MAX changes.. */
 	if (server->m.time_out < 1) {
diff -u --recursive --new-file v2.3.39/linux/fs/ncpfs/ioctl.c linux/fs/ncpfs/ioctl.c
--- v2.3.39/linux/fs/ncpfs/ioctl.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/ncpfs/ioctl.c	Sun Jan 16 10:52:45 2000
@@ -32,25 +32,8 @@
 	struct ncp_server *server = NCP_SERVER(inode);
 	int result;
 	struct ncp_ioctl_request request;
-	struct ncp_fs_info info;
 	char* bouncebuffer;
 
-#ifdef NCP_IOC_GETMOUNTUID_INT
-	/* remove after ncpfs-2.0.13/2.2.0 gets released */
-	if ((NCP_IOC_GETMOUNTUID != NCP_IOC_GETMOUNTUID_INT) &&
-             (cmd == NCP_IOC_GETMOUNTUID_INT)) {
-		int tmp = server->m.mounted_uid;
-
-		if (   (permission(inode, MAY_READ) != 0)
-		    && (current->uid != server->m.mounted_uid))
-		{
-			return -EACCES;
-		}
-		if (put_user(tmp, (unsigned int*) arg)) return -EFAULT;
-		return 0;
-	}
-#endif	/* NCP_IOC_GETMOUNTUID_INT */
-
 	switch (cmd) {
 	case NCP_IOC_NCPREQUEST:
 
@@ -67,10 +50,6 @@
 		  NCP_PACKET_SIZE - sizeof(struct ncp_request_header))) {
 			return -EINVAL;
 		}
-		if ((result = verify_area(VERIFY_WRITE, (char *) request.data,
-					  NCP_PACKET_SIZE)) != 0) {
-			return result;
-		}
 		bouncebuffer = kmalloc(NCP_PACKET_SIZE, GFP_NFS);
 		if (!bouncebuffer)
 			return -ENOMEM;
@@ -108,53 +87,82 @@
 		    && (current->uid != server->m.mounted_uid)) {
 			return -EACCES;
 		}
-		if (server->root_setuped) return -EBUSY;
+		if (!(server->m.int_flags & NCP_IMOUNT_LOGGEDIN_POSSIBLE))
+			return -EINVAL;
+		if (server->root_setuped)
+			return -EBUSY;
 		server->root_setuped = 1;
 		return ncp_conn_logged_in(inode->i_sb);
 
 	case NCP_IOC_GET_FS_INFO:
+		{
+			struct ncp_fs_info info;
 
-		if ((permission(inode, MAY_WRITE) != 0)
-		    && (current->uid != server->m.mounted_uid)) {
-			return -EACCES;
-		}
-		if ((result = verify_area(VERIFY_WRITE, (char *) arg,
-					  sizeof(info))) != 0) {
-			return result;
-		}
-		copy_from_user(&info, (struct ncp_fs_info *) arg, sizeof(info));
+			if ((permission(inode, MAY_WRITE) != 0)
+			    && (current->uid != server->m.mounted_uid)) {
+				return -EACCES;
+			}
+			if (copy_from_user(&info, (struct ncp_fs_info *) arg, 
+				sizeof(info)))
+				return -EFAULT;
 
-		if (info.version != NCP_GET_FS_INFO_VERSION) {
-			DPRINTK("info.version invalid: %d\n", info.version);
-			return -EINVAL;
+			if (info.version != NCP_GET_FS_INFO_VERSION) {
+				DPRINTK("info.version invalid: %d\n", info.version);
+				return -EINVAL;
+			}
+			/* TODO: info.addr = server->m.serv_addr; */
+			info.mounted_uid	= NEW_TO_OLD_UID(server->m.mounted_uid);
+			info.connection		= server->connection;
+			info.buffer_size	= server->buffer_size;
+			info.volume_number	= NCP_FINFO(inode)->volNumber;
+			info.directory_id	= NCP_FINFO(inode)->DosDirNum;
+
+			if (copy_to_user((struct ncp_fs_info *) arg, &info, 
+				sizeof(info))) return -EFAULT;
+			return 0;
 		}
-		/* TODO: info.addr = server->m.serv_addr; */
-		info.mounted_uid	= NEW_TO_OLD_UID(server->m.mounted_uid);
-		info.connection		= server->connection;
-		info.buffer_size	= server->buffer_size;
-		info.volume_number	= NCP_FINFO(inode)->volNumber;
-		info.directory_id	= NCP_FINFO(inode)->DosDirNum;
 
-		copy_to_user((struct ncp_fs_info *) arg, &info, sizeof(info));
-		return 0;
+	case NCP_IOC_GET_FS_INFO_V2:
+		{
+			struct ncp_fs_info_v2 info2;
 
-	case NCP_IOC_GETMOUNTUID:
+			if ((permission(inode, MAY_WRITE) != 0)
+			    && (current->uid != server->m.mounted_uid)) {
+				return -EACCES;
+			}
+			if (copy_from_user(&info2, (struct ncp_fs_info_v2 *) arg, 
+				sizeof(info2)))
+				return -EFAULT;
 
-		if ((permission(inode, MAY_READ) != 0)
-		    && (current->uid != server->m.mounted_uid)) {
-			return -EACCES;
+			if (info2.version != NCP_GET_FS_INFO_VERSION_V2) {
+				DPRINTK("info.version invalid: %d\n", info2.version);
+				return -EINVAL;
+			}
+			info2.mounted_uid   = server->m.mounted_uid;
+			info2.connection    = server->connection;
+			info2.buffer_size   = server->buffer_size;
+			info2.volume_number = NCP_FINFO(inode)->volNumber;
+			info2.directory_id  = NCP_FINFO(inode)->DosDirNum;
+			info2.dummy1 = info2.dummy2 = info2.dummy3 = 0;
+
+			if (copy_to_user((struct ncp_fs_info_v2 *) arg, &info2, 
+				sizeof(info2))) return -EFAULT;
+			return 0;
 		}
-		put_user(high2lowuid(server->m.mounted_uid), (old_uid_t *) arg);
-		return 0;
 
-	case NCP_IOC_GETMOUNTUID32:
+	case NCP_IOC_GETMOUNTUID2:
+		{
+			unsigned long tmp = server->m.mounted_uid;
 
-		if ((permission(inode, MAY_READ) != 0)
-		    && (current->uid != server->m.mounted_uid)) {
-			return -EACCES;
+			if (   (permission(inode, MAY_READ) != 0)
+			    && (current->uid != server->m.mounted_uid))
+			{
+				return -EACCES;
+			}
+			if (put_user(tmp, (unsigned long*) arg)) 
+				return -EFAULT;
+			return 0;
 		}
-		put_user(server->m.mounted_uid, (uid_t *) arg);
-		return 0;
 
 #ifdef CONFIG_NCPFS_MOUNT_SUBDIR
 	case NCP_IOC_GETROOT:
@@ -377,11 +385,6 @@
 			struct ncp_objectname_ioctl user;
 			int outl;
 
-			if ((result = verify_area(VERIFY_WRITE,
-					   (struct ncp_objectname_ioctl*)arg,
-					   sizeof(user))) != 0) {
-				return result;
-			}
 			if (copy_from_user(&user, 
 					   (struct ncp_objectname_ioctl*)arg,
 					   sizeof(user))) return -EFAULT;
@@ -452,11 +455,6 @@
 			struct ncp_privatedata_ioctl user;
 			int outl;
 
-			if ((result = verify_area(VERIFY_WRITE,
-					   (struct ncp_privatedata_ioctl*)arg,
-					   sizeof(user))) != 0) {
-				return result;
-			}
 			if (copy_from_user(&user, 
 					   (struct ncp_privatedata_ioctl*)arg,
 					   sizeof(user))) return -EFAULT;
@@ -635,7 +633,19 @@
 			return 0;
 		}
 
-	default:
-		return -EINVAL;
 	}
+/* #ifdef CONFIG_UID16 */
+	/* NCP_IOC_GETMOUNTUID may be same as NCP_IOC_GETMOUNTUID2,
+           so we have this out of switch */
+	if (cmd == NCP_IOC_GETMOUNTUID) {
+		if ((permission(inode, MAY_READ) != 0)
+		    && (current->uid != server->m.mounted_uid)) {
+			return -EACCES;
+		}
+		if (put_user(NEW_TO_OLD_UID(server->m.mounted_uid), (__kernel_uid_t *) arg))
+			return -EFAULT;
+		return 0;
+	}
+/* #endif */
+	return -EINVAL;
 }
diff -u --recursive --new-file v2.3.39/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.3.39/linux/fs/nfs/inode.c	Wed Dec  8 14:11:27 1999
+++ linux/fs/nfs/inode.c	Tue Jan 11 14:19:17 2000
@@ -681,7 +681,7 @@
 	if (attr->ia_valid & ATTR_SIZE) {
 		if (attr->ia_size != fattr.size)
 			printk("nfs_notify_change: attr=%Ld, fattr=%d??\n",
-				attr->ia_size, fattr.size);
+			       (long long) attr->ia_size, fattr.size);
 		inode->i_size  = attr->ia_size;
 		inode->i_mtime = fattr.mtime.seconds;
 	}
diff -u --recursive --new-file v2.3.39/linux/fs/nfsd/export.c linux/fs/nfsd/export.c
--- v2.3.39/linux/fs/nfsd/export.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/nfsd/export.c	Thu Jan 20 10:48:35 2000
@@ -221,7 +221,7 @@
 
 	dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
 			nxp->ex_client, nxp->ex_path,
-			nxp->ex_dev, nxp->ex_ino, nxp->ex_flags);
+			nxp->ex_dev, (long) nxp->ex_ino, nxp->ex_flags);
 	dev = to_kdev_t(nxp->ex_dev);
 	ino = nxp->ex_ino;
 
@@ -453,11 +453,11 @@
 		ino = dentry->d_inode->i_ino;
 	
 		dprintk("nfsd: exp_rootfh(%s [%p] %s:%x/%ld)\n",
-		         path, dentry, clp->cl_ident, dev, ino);
+		         path, dentry, clp->cl_ident, dev, (long) ino);
 		exp = exp_parent(clp, dev, dentry);
 	} else {
 		dprintk("nfsd: exp_rootfh(%s:%x/%ld)\n",
-		         clp->cl_ident, dev, ino);
+		         clp->cl_ident, dev, (long) ino);
 		if ((exp = exp_get(clp, dev, ino)))
 			if (!(dentry = dget(exp->ex_dentry))) {
 				printk("exp_rootfh: Aieee, NULL dentry\n");
@@ -478,7 +478,7 @@
 		printk("exp_rootfh: Aieee, ino/dev mismatch\n");
 		printk("exp_rootfh: arg[dev(%x):ino(%ld)]"
 		       " inode[dev(%x):ino(%ld)]\n",
-		       dev, ino, inode->i_dev, inode->i_ino);
+		       dev, (long) ino, inode->i_dev, (long) inode->i_ino);
 	}
 
 	/*
@@ -667,7 +667,7 @@
 							if (first++) len += sprintf(buffer+len, "%s", " ");
 							if (tmp->h_client != clp)
 								len += sprintf(buffer+len, "(");
-							len += sprintf(buffer+len, "%ld.%ld.%ld.%ld",
+							len += sprintf(buffer+len, "%d.%d.%d.%d",
 									htonl(addr.s_addr) >> 24 & 0xff,
 									htonl(addr.s_addr) >> 16 & 0xff,
 									htonl(addr.s_addr) >>  8 & 0xff,
diff -u --recursive --new-file v2.3.39/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.3.39/linux/fs/nfsd/nfsctl.c	Tue Dec  7 09:32:48 1999
+++ linux/fs/nfsd/nfsctl.c	Thu Jan 20 10:48:35 2000
@@ -262,7 +262,7 @@
 int
 init_module(void)
 {
-	printk("Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
+	printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
 	do_nfsservctl = handle_sys_nfsservctl;
 	return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- v2.3.39/linux/fs/nfsd/nfsfh.c	Tue Nov 23 22:42:21 1999
+++ linux/fs/nfsd/nfsfh.c	Tue Jan 11 14:19:17 2000
@@ -614,7 +614,7 @@
 	struct dentry *parent = dentry->d_parent;
 
 	dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)\n",
-		exp->ex_dev, exp->ex_ino,
+		exp->ex_dev, (long) exp->ex_ino,
 		parent->d_name.name, dentry->d_name.name,
 		(inode ? inode->i_ino : 0));
 
diff -u --recursive --new-file v2.3.39/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- v2.3.39/linux/fs/nfsd/nfsproc.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/nfsd/nfsproc.c	Thu Jan 20 10:48:35 2000
@@ -143,7 +143,7 @@
 
 	if ((avail << 2) < argp->count) {
 		printk(KERN_NOTICE
-			"oversized read request from %08lx:%d (%d bytes)\n",
+			"oversized read request from %08x:%d (%d bytes)\n",
 				ntohl(rqstp->rq_addr.sin_addr.s_addr),
 				ntohs(rqstp->rq_addr.sin_port),
 				argp->count);
diff -u --recursive --new-file v2.3.39/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.3.39/linux/fs/nfsd/vfs.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/nfsd/vfs.c	Thu Jan 20 10:48:35 2000
@@ -1590,7 +1590,7 @@
 	*p++ = htonl(eof);		/* end of directory */
 	*countp = (caddr_t) p - (caddr_t) buffer;
 
-	dprintk("nfsd: readdir result %d bytes, eof %d offset %ld\n",
+	dprintk("nfsd: readdir result %d bytes, eof %d offset %d\n",
 				*countp, eof,
 				cd.offset? ntohl(*cd.offset) : -1);
 	err = 0;
diff -u --recursive --new-file v2.3.39/linux/fs/ntfs/inode.c linux/fs/ntfs/inode.c
--- v2.3.39/linux/fs/ntfs/inode.c	Sat Apr 24 17:51:48 1999
+++ linux/fs/ntfs/inode.c	Thu Jan 20 10:48:35 2000
@@ -612,7 +612,7 @@
 		return 0;
 
 	for(rnum=0;rnum<data->d.r.len && 
-		    vcn>data->d.r.runlist[rnum].len;rnum++)
+		    vcn>=data->d.r.runlist[rnum].len;rnum++)
 		vcn-=data->d.r.runlist[rnum].len;
 	
 	return data->d.r.runlist[rnum].cluster+vcn;
diff -u --recursive --new-file v2.3.39/linux/fs/partitions/check.c linux/fs/partitions/check.c
--- v2.3.39/linux/fs/partitions/check.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/partitions/check.c	Tue Jan 18 18:54:21 2000
@@ -234,7 +234,7 @@
 }
 #endif
 
-void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
+static void check_partition(struct gendisk *hd, kdev_t dev, int first_part_minor)
 {
 	static int first_time = 1;
 	unsigned long first_sector;
@@ -272,13 +272,27 @@
  * Much of the cleanup from the old partition tables should have already been
  * done
  */
-void resetup_one_dev(struct gendisk *dev, int drive)
+
+void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
+	struct block_device_operations *ops, long size)
+{
+	unsigned first = (unsigned)dev;
+	if (!gdev)
+		return;
+	grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
+}
+
+void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
 {
 	int i;
 	int first_minor	= drive << dev->minor_shift;
 	int end_minor	= first_minor + dev->max_p;
 
 	blk_size[dev->major] = NULL;
+	dev->part[first_minor].nr_sects = size;
+	/* No Such Agen^Wdevice or no minors to use for partitions */
+	if (!size || minors == 1)
+		return;
 	check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
 
  	/*
@@ -292,30 +306,9 @@
 	}
 }
 
-static inline void setup_dev(struct gendisk *dev)
-{
-	int i, drive;
-	int end_minor	= dev->max_nr * dev->max_p;
-
-	blk_size[dev->major] = NULL;
-	for (i = 0; i < end_minor; i++) {
-		dev->part[i].start_sect = 0;
-		dev->part[i].nr_sects = 0;
-		dev->sizes[i] = 0;
-	}
-	dev->init(dev);	
-	for (drive = 0 ; drive < dev->nr_real ; drive++)
-		resetup_one_dev(dev, drive);
-}
-
 int __init partition_setup(void)
 {
-	struct gendisk *p;
-
 	device_init();
-
-	for (p = gendisk_head ; p ; p=p->next)
-		setup_dev(p);
 
 #ifdef CONFIG_BLK_DEV_RAM
 #ifdef CONFIG_BLK_DEV_INITRD
diff -u --recursive --new-file v2.3.39/linux/fs/partitions/msdos.c linux/fs/partitions/msdos.c
--- v2.3.39/linux/fs/partitions/msdos.c	Mon Oct 11 15:38:15 1999
+++ linux/fs/partitions/msdos.c	Fri Jan 14 14:52:14 2000
@@ -163,25 +163,37 @@
 	bforget(bh);
 }
 
+static inline struct buffer_head *
+get_partition_table_block(struct gendisk *hd, int minor, int blocknr) {
+	kdev_t dev = MKDEV(hd->major, minor);
+	return bread(dev, blocknr, get_ptable_blocksize(dev));
+}
+
 #ifdef CONFIG_SOLARIS_X86_PARTITION
+
+/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
+   indicates linux swap.  Be careful before believing this is Solaris. */
+
 static void
-solaris_x86_partition(struct gendisk *hd, kdev_t dev, long offset) {
+solaris_x86_partition(struct gendisk *hd, int minor) {
+	long offset = hd->part[minor].start_sect;
 
 	struct buffer_head *bh;
 	struct solaris_x86_vtoc *v;
 	struct solaris_x86_slice *s;
 	int i;
+	char buf[40];
 
-	if(!(bh = bread(dev, 0, get_ptable_blocksize(dev))))
+	if(!(bh = get_partition_table_block(hd, minor, 0)))
 		return;
 	v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
 	if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
 		brelse(bh);
 		return;
 	}
-	printk(" <solaris:");
+	printk(" %s: <solaris:", disk_name(hd, minor, buf));
 	if(v->v_version != 1) {
-		printk("  cannot handle version %ld vtoc>", v->v_version);
+		printk("  cannot handle version %ld vtoc>\n", v->v_version);
 		brelse(bh);
 		return;
 	}
@@ -199,21 +211,21 @@
 		current_minor++;
 	}
 	brelse(bh);
-	printk(" >");
+	printk(" >\n");
 }
 #endif
 
 #ifdef CONFIG_BSD_DISKLABEL
-static void check_and_add_bsd_partition(struct gendisk *hd,
-					struct bsd_partition *bsd_p, kdev_t dev)
-{
+static void
+check_and_add_bsd_partition(struct gendisk *hd,
+			    struct bsd_partition *bsd_p, int minor) {
 	struct hd_struct *lin_p;
 		/* check relative position of partitions.  */
-	for (lin_p = hd->part + 1 + MINOR(dev);
-	     lin_p - hd->part - MINOR(dev) < current_minor; lin_p++) {
+	for (lin_p = hd->part + 1 + minor;
+	     lin_p - hd->part - minor < current_minor; lin_p++) {
 			/* no relationship -> try again */
-		if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset 
-			|| lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
+		if (lin_p->start_sect + lin_p->nr_sects <= bsd_p->p_offset ||
+		    lin_p->start_sect >= bsd_p->p_offset + bsd_p->p_size)
 			continue;	
 			/* equal -> no need to add */
 		if (lin_p->start_sect == bsd_p->p_offset && 
@@ -244,26 +256,32 @@
 	add_gd_partition(hd, current_minor, bsd_p->p_offset, bsd_p->p_size);
 	current_minor++;
 }
+
 /* 
  * Create devices for BSD partitions listed in a disklabel, under a
  * dos-like partition. See extended_partition() for more information.
  */
-static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev, 
-   int max_partitions)
-{
+static void bsd_disklabel_partition(struct gendisk *hd, int minor, int type) {
 	struct buffer_head *bh;
 	struct bsd_disklabel *l;
 	struct bsd_partition *p;
+	int max_partitions;
 	int mask = (1 << hd->minor_shift) - 1;
+	char buf[40];
 
-	if (!(bh = bread(dev,0,get_ptable_blocksize(dev))))
+	if (!(bh = get_partition_table_block(hd, minor, 0)))
 		return;
 	l = (struct bsd_disklabel *) (bh->b_data+512);
 	if (l->d_magic != BSD_DISKMAGIC) {
 		brelse(bh);
 		return;
 	}
+	printk(" %s:", disk_name(hd, minor, buf));
+	printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
+	       (type == NETBSD_PARTITION) ? " <netbsd:" : " <bsd:");
 
+	max_partitions = ((type == OPENBSD_PARTITION) ? OPENBSD_MAXPARTITIONS
+			                              : BSD_MAXPARTITIONS);
 	if (l->d_npartitions < max_partitions)
 		max_partitions = l->d_npartitions;
 	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
@@ -271,12 +289,13 @@
 			break;
 
 		if (p->p_fstype != BSD_FS_UNUSED) 
-			check_and_add_bsd_partition(hd, p, dev);
+			check_and_add_bsd_partition(hd, p, minor);
 	}
 
 	/* Use bforget(), as we have changed the disk setup */
 	bforget(bh);
 
+	printk(" >\n");
 }
 #endif
 
@@ -285,14 +304,14 @@
  * Create devices for Unixware partitions listed in a disklabel, under a
  * dos-like partition. See extended_partition() for more information.
  */
-static void unixware_partition(struct gendisk *hd, kdev_t dev)
-{
+static void unixware_partition(struct gendisk *hd, int minor) {
 	struct buffer_head *bh;
 	struct unixware_disklabel *l;
 	struct unixware_slice *p;
 	int mask = (1 << hd->minor_shift) - 1;
+	char buf[40];
 
-	if (!(bh = bread(dev, 14, get_ptable_blocksize(dev))))
+	if (!(bh = get_partition_table_block(hd, minor, 14)))
 		return;
 	l = (struct unixware_disklabel *) (bh->b_data+512);
 	if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
@@ -300,7 +319,7 @@
 		brelse(bh);
 		return;
 	}
-	printk(" <unixware:");
+	printk(" %s: <unixware:", disk_name(hd, minor, buf));
 	p = &l->vtoc.v_slice[1];
 	/* I omit the 0th slice as it is the same as whole disk. */
 	while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
@@ -308,30 +327,26 @@
 			break;
 
 		if (p->s_label != UNIXWARE_FS_UNUSED) {
-			add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
+			add_gd_partition(hd, current_minor, START_SECT(p),
+					 NR_SECTS(p));
 			current_minor++;
 		}
 		p++;
 	}
 	/* Use bforget, as we have changed the disk setup */
 	bforget(bh);
-	printk(" >");
+	printk(" >\n");
 }
 #endif
 
-int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int first_part_minor)
-{
+int msdos_partition(struct gendisk *hd, kdev_t dev,
+		    unsigned long first_sector, int first_part_minor) {
 	int i, minor = current_minor = first_part_minor;
 	struct buffer_head *bh;
 	struct partition *p;
 	unsigned char *data;
 	int mask = (1 << hd->minor_shift) - 1;
 	int sector_size = get_hardsect_size(dev) / 512;
-#ifdef CONFIG_BSD_DISKLABEL
-	/* no bsd disklabel as a default */
-	kdev_t bsd_kdev = 0;
-	int bsd_maxpart = BSD_MAXPARTITIONS;
-#endif
 #ifdef CONFIG_BLK_DEV_IDE
 	int tested_for_xlate = 0;
 
@@ -345,7 +360,7 @@
 #ifdef CONFIG_BLK_DEV_IDE
 check_table:
 #endif
-	/* Use bforget(), because we have potentially changed the disk geometry */
+	/* Use bforget(), because we may have changed the disk geometry */
 	if (*(unsigned short *)  (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
 		bforget(bh);
 		return 0;
@@ -410,11 +425,16 @@
 	}
 #endif	/* CONFIG_BLK_DEV_IDE */
 
+	/* Look for partitions in two passes:
+	   First find the primary partitions, and the DOS-type extended partitions.
+	   On the second pass look inside *BSD and Unixware and Solaris partitions. */
+
 	current_minor += 4;  /* first "extra" minor (for extended partitions) */
 	for (i=1 ; i<=4 ; minor++,i++,p++) {
 		if (!NR_SECTS(p))
 			continue;
-		add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size, NR_SECTS(p)*sector_size);
+		add_gd_partition(hd, minor, first_sector+START_SECT(p)*sector_size,
+				 NR_SECTS(p)*sector_size);
 		if (is_extended_partition(p)) {
 			printk(" <");
 			/*
@@ -432,44 +452,8 @@
 			if (hd->part[minor].nr_sects > 2)
 				hd->part[minor].nr_sects = 2;
 		}
-#ifdef CONFIG_BSD_DISKLABEL
-			/* tag first disklabel for late recognition */
-		if (SYS_IND(p) == BSD_PARTITION || SYS_IND(p) == NETBSD_PARTITION) {
-			printk("!");
-			if (!bsd_kdev)
-				bsd_kdev = MKDEV(hd->major, minor);
-		} else if (SYS_IND(p) == OPENBSD_PARTITION) {
-			printk("!");
-			if (!bsd_kdev) {
-				bsd_kdev = MKDEV(hd->major, minor);
-				bsd_maxpart = OPENBSD_MAXPARTITIONS;
-			}
-		}
-#endif
-#ifdef CONFIG_UNIXWARE_DISKLABEL
-		if (SYS_IND(p) == UNIXWARE_PARTITION)
-			unixware_partition(hd, MKDEV(hd->major, minor));
-#endif
-#ifdef CONFIG_SOLARIS_X86_PARTITION
-
-		/* james@bpgc.com: Solaris has a nasty indicator: 0x82
-		 * which also means linux swap.  For that reason, all
-		 * of the prints are done inside the
-		 * solaris_x86_partition routine */
-
-		if(SYS_IND(p) == SOLARIS_X86_PARTITION) {
-			solaris_x86_partition(hd, MKDEV(hd->major, minor),
-					      first_sector+START_SECT(p));
-		}
-#endif
-	}
-#ifdef CONFIG_BSD_DISKLABEL
-	if (bsd_kdev) {
-		printk(" <");
-		bsd_disklabel_partition(hd, bsd_kdev, bsd_maxpart);
-		printk(" >");
 	}
-#endif
+
 	/*
 	 *  Check for old-style Disk Manager partition table
 	 */
@@ -485,6 +469,29 @@
 		}
 	}
 	printk("\n");
+
+	/* second pass - output for each on a separate line */
+	minor -= 4;
+	p = (struct partition *) (0x1be + data);
+	for (i=1 ; i<=4 ; minor++,i++,p++) {
+		if (!NR_SECTS(p))
+			continue;
+#ifdef CONFIG_BSD_DISKLABEL
+		if (SYS_IND(p) == BSD_PARTITION ||
+		    SYS_IND(p) == NETBSD_PARTITION ||
+		    SYS_IND(p) == OPENBSD_PARTITION)
+			bsd_disklabel_partition(hd, minor, SYS_IND(p));
+#endif
+#ifdef CONFIG_UNIXWARE_DISKLABEL
+		if (SYS_IND(p) == UNIXWARE_PARTITION)
+			unixware_partition(hd, minor);
+#endif
+#ifdef CONFIG_SOLARIS_X86_PARTITION
+		if(SYS_IND(p) == SOLARIS_X86_PARTITION)
+			solaris_x86_partition(hd, minor);
+#endif
+	}
+
 	bforget(bh);
 	return 1;
 }
diff -u --recursive --new-file v2.3.39/linux/fs/proc/generic.c linux/fs/proc/generic.c
--- v2.3.39/linux/fs/proc/generic.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/proc/generic.c	Tue Jan 11 14:19:17 2000
@@ -20,7 +20,7 @@
 			      size_t nbytes, loff_t *ppos);
 static ssize_t proc_file_write(struct file * file, const char * buffer,
 			       size_t count, loff_t *ppos);
-static long long proc_file_lseek(struct file *, long long, int);
+static loff_t proc_file_lseek(struct file *, loff_t, int);
 
 int proc_match(int len, const char *name,struct proc_dir_entry * de)
 {
@@ -139,8 +139,8 @@
 }
 
 
-static long long
-proc_file_lseek(struct file * file, long long offset, int orig)
+static loff_t
+proc_file_lseek(struct file * file, loff_t offset, int orig)
 {
     switch (orig) {
     case 0:
diff -u --recursive --new-file v2.3.39/linux/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c
--- v2.3.39/linux/fs/smbfs/ioctl.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/smbfs/ioctl.c	Sat Jan 15 22:08:29 2000
@@ -28,7 +28,7 @@
 	switch (cmd)
 	{
 	case SMB_IOC_GETMOUNTUID:
-		result = put_user(high2lowuid(server->mnt->mounted_uid), (old_uid_t *) arg);
+		result = put_user(NEW_TO_OLD_UID(server->mnt->mounted_uid), (uid16_t *) arg);
 		break;
 	case SMB_IOC_GETMOUNTUID32:
 		result = put_user(server->mnt->mounted_uid, (uid_t *) arg);
diff -u --recursive --new-file v2.3.39/linux/fs/super.c linux/fs/super.c
--- v2.3.39/linux/fs/super.c	Thu Jan  6 12:57:48 2000
+++ linux/fs/super.c	Sun Jan 16 10:47:19 2000
@@ -932,7 +932,6 @@
 /*
  * Alters the mount flags of a mounted file system. Only the mount point
  * is used as a reference - file system type and the device are ignored.
- * FS-specific mount options can't be altered by remounting.
  */
 
 static int do_remount_sb(struct super_block *sb, int flags, char *data)
@@ -1174,7 +1173,7 @@
 #endif
 
 	bdev = bdget(kdev_t_to_nr(ROOT_DEV));
-	if (!bdget)
+	if (!bdev)
 		panic(__FUNCTION__ ": unable to allocate root device");
 	mode = FMODE_READ;
 	if (!(root_mountflags & MS_RDONLY))
diff -u --recursive --new-file v2.3.39/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.3.39/linux/fs/ufs/super.c	Tue Jan  4 13:57:19 2000
+++ linux/fs/ufs/super.c	Tue Jan 11 11:41:25 2000
@@ -452,8 +452,14 @@
 	MOD_INC_USE_COUNT;
 	lock_super (sb);
 
+	UFSD(("flag %u\n", (int)(sb->s_flags & MS_RDONLY)))
+	
 #ifndef CONFIG_UFS_FS_WRITE
-	sb->s_flags |= MS_RDONLY;
+	if (!(sb->s_flags & MS_RDONLY)) {
+		printk("ufs was compiled with read-only support, "
+		"can't be mounted as read-write\n");
+		goto failed;
+	}
 #endif
 	/*
 	 * Set default mount options
@@ -632,12 +638,14 @@
 	uspi->s_fmask = SWAB32(usb1->fs_fmask);
 	uspi->s_fshift = SWAB32(usb1->fs_fshift);
 
-	if (uspi->s_bsize != 4096 && uspi->s_bsize != 8192) {
-		printk("ufs_read_super: fs_bsize %u != {4096, 8192}\n", uspi->s_bsize);
+	if (uspi->s_bsize != 4096 && uspi->s_bsize != 8192 
+	  && uspi->s_bsize != 32768) {
+		printk("ufs_read_super: fs_bsize %u != {4096, 8192, 32768}\n", uspi->s_bsize);
 		goto failed;
 	}
-	if (uspi->s_fsize != 512 && uspi->s_fsize != 1024 && uspi->s_fsize != 2048) {
-		printk("ufs_read_super: fs_fsize %u != {512, 1024, 2048}\n", uspi->s_fsize);
+	if (uspi->s_fsize != 512 && uspi->s_fsize != 1024 
+	  && uspi->s_fsize != 2048 && uspi->s_fsize != 4096) {
+		printk("ufs_read_super: fs_fsize %u != {512, 1024, 2048. 4096}\n", uspi->s_fsize);
 		goto failed;
 	}
 	if (uspi->s_fsize != block_size || uspi->s_sbsize != super_block_size) {
@@ -869,10 +877,15 @@
 		printk("ufstype can't be changed during remount\n");
 		return -EINVAL;
 	}
-	sb->u.ufs_sb.s_mount_opt = new_mount_opt;
 
-	if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
+	if ((*mount_flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) {
+		sb->u.ufs_sb.s_mount_opt = new_mount_opt;
 		return 0;
+	}
+	
+	/*
+	 * fs was mouted as rw, remounting ro
+	 */
 	if (*mount_flags & MS_RDONLY) {
 		ufs_put_cylinder_structures(sb);
 		usb1->fs_time = SWAB32(CURRENT_TIME);
@@ -883,18 +896,29 @@
 		sb->s_dirt = 0;
 		sb->s_flags |= MS_RDONLY;
 	}
+	/*
+	 * fs was mounted as ro, remounting rw
+	 */
 	else {
+#ifndef CONFIG_UFS_FS_WRITE
+		printk("ufs was compiled with read-only support, "
+		"can't be mounted as read-write\n");
+		return -EINVAL;
+#else
 		if (ufstype != UFS_MOUNT_UFSTYPE_SUN && 
-		    ufstype != UFS_MOUNT_UFSTYPE_44BSD) {
+		    ufstype != UFS_MOUNT_UFSTYPE_44BSD &&
+		    ufstype != UFS_MOUNT_UFSTYPE_SUNx86) {
 			printk("this ufstype is read-only supported\n");
-			return 0;
+			return -EINVAL;
 		}
 		if (!ufs_read_cylinder_structures (sb)) {
 			printk("failed during remounting\n");
-			return 0;
+			return -EPERM;
 		}
 		sb->s_flags &= ~MS_RDONLY;
+#endif
 	}
+	sb->u.ufs_sb.s_mount_opt = new_mount_opt;
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-alpha/core_cia.h linux/include/asm-alpha/core_cia.h
--- v2.3.39/linux/include/asm-alpha/core_cia.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-alpha/core_cia.h	Tue Jan 11 14:18:38 2000
@@ -218,32 +218,12 @@
  * Data structure for handling CIA machine checks.
  */
 
-/* EV5-specific info.  */
-struct el_CIA_procdata {
-	unsigned long shadow[8];	/* PALmode shadow registers */
-	unsigned long paltemp[24];	/* PAL temporary registers */
-	/* EV5-specific fields */
-	unsigned long exc_addr;		/* Address of excepting instruction. */
-	unsigned long exc_sum;		/* Summary of arithmetic traps. */
-	unsigned long exc_mask;		/* Exception mask (from exc_sum). */
-	unsigned long exc_base;		/* PALbase at time of exception. */
-	unsigned long isr;		/* Interrupt summary register. */
-	unsigned long icsr;		/* Ibox control register. */
-	unsigned long ic_perr_stat;
-	unsigned long dc_perr_stat;
-	unsigned long va;		/* Effective VA of fault or miss. */
-	unsigned long mm_stat;
-	unsigned long sc_addr;
-	unsigned long sc_stat;
-	unsigned long bc_tag_addr;
-	unsigned long ei_addr;
-	unsigned long fill_syn;
-	unsigned long ei_stat;
-	unsigned long ld_lock;
-};
-
 /* System-specific info.  */
 struct el_CIA_sysdata_mcheck {
+#if 0
+	/* ??? Where did this come from.  It appears to bear no
+	   relation to the cia logout written in the milo sources.
+	   Who knows what happens in the srm console... */
 	unsigned long      coma_gcr;
 	unsigned long      coma_edsr;
 	unsigned long      coma_ter;
@@ -285,6 +265,19 @@
 	unsigned long      epic_data5;
 	unsigned long      epic_data6;
 	unsigned long      epic_data7;
+#else
+	unsigned long	cpu_err0;
+	unsigned long	cpu_err1;
+	unsigned long	cia_err;
+	unsigned long	cia_stat;
+	unsigned long	err_mask;
+	unsigned long	cia_syn;
+	unsigned long	mem_err0;
+	unsigned long	mem_err1;
+	unsigned long	pci_err0;
+	unsigned long	pci_err1;
+	unsigned long	pci_err2;
+#endif
 };
 
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-alpha/core_pyxis.h linux/include/asm-alpha/core_pyxis.h
--- v2.3.39/linux/include/asm-alpha/core_pyxis.h	Tue Sep  7 12:14:07 1999
+++ linux/include/asm-alpha/core_pyxis.h	Tue Jan 11 14:18:38 2000
@@ -203,6 +203,10 @@
  * Data structure for handling PYXIS machine checks:
  */
 struct el_PYXIS_sysdata_mcheck {
+#if 0
+	/* ??? Where did this come from.  It appears to bear no
+	   relation to the pyxis logout written in the milo sources.
+	   Who knows what happens in the srm console... */
     u_long      coma_gcr;
     u_long      coma_edsr;
     u_long      coma_ter;
@@ -244,6 +248,19 @@
     u_long      epic_data5;
     u_long      epic_data6;
     u_long      epic_data7;
+#else
+	unsigned long	cpu_err0;
+	unsigned long	cpu_err1;
+	unsigned long	cia_err;
+	unsigned long	cia_stat;
+	unsigned long	err_mask;
+	unsigned long	cia_syn;
+	unsigned long	mem_err0;
+	unsigned long	mem_err1;
+	unsigned long	pci_err0;
+	unsigned long	pci_err1;
+	unsigned long	pci_err2;
+#endif
 };
 
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-alpha/pci.h linux/include/asm-alpha/pci.h
--- v2.3.39/linux/include/asm-alpha/pci.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-alpha/pci.h	Tue Jan 11 14:22:31 2000
@@ -1,6 +1,8 @@
 #ifndef __ALPHA_PCI_H
 #define __ALPHA_PCI_H
 
+#include <asm/machvec.h>
+
 /*
  * The following structure is used to manage multiple PCI busses.
  */
@@ -26,6 +28,9 @@
    bus numbers.  */
 
 #define pcibios_assign_all_busses()	1
+
+#define PCIBIOS_MIN_IO		alpha_mv.min_io_address
+#define PCIBIOS_MIN_MEM		alpha_mv.min_mem_address
 
 #endif /* __ALPHA_PCI_H */
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-alpha/posix_types.h linux/include/asm-alpha/posix_types.h
--- v2.3.39/linux/include/asm-alpha/posix_types.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-alpha/posix_types.h	Sat Jan 15 22:08:28 2000
@@ -28,12 +28,15 @@
 typedef unsigned long	__kernel_sigset_t;	/* at least 32 bits */
 typedef unsigned short	__kernel_uid16_t;
 typedef unsigned short	__kernel_gid16_t;
-typedef unsigned int	__kernel_uid32_t;
-typedef unsigned int	__kernel_gid32_t;
 
 typedef struct {
 	int	val[2];
 } __kernel_fsid_t;
+
+typedef __kernel_uid_t __kernel_old_uid_t;
+typedef __kernel_gid_t __kernel_old_gid_t;
+typedef __kernel_uid_t __kernel_uid32_t;
+typedef __kernel_gid_t __kernel_gid32_t;
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-arc/serial.h linux/include/asm-arm/arch-arc/serial.h
--- v2.3.39/linux/include/asm-arm/arch-arc/serial.h	Tue Nov 23 22:42:21 1999
+++ linux/include/asm-arm/arch-arc/serial.h	Thu Jan 13 13:30:31 2000
@@ -28,13 +28,13 @@
 #if defined(CONFIG_ARCH_A5K)
      /* UART CLK        PORT  IRQ     FLAGS        */
 
-#define STD_SERIAL_PORT_DEFNS
+#define STD_SERIAL_PORT_DEFNS						\
 	{ 0, BASE_BAUD, 0x3F8, 10, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0x2F8, 10, STD_COM_FLAGS },	/* ttyS1 */
 
 #else
 
-#define STD_SERIAL_PORT_DEFNS
+#define STD_SERIAL_PORT_DEFNS						\
 	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS0 */	\
 	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS1 */
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-arc/system.h linux/include/asm-arm/arch-arc/system.h
--- v2.3.39/linux/include/asm-arm/arch-arc/system.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-arc/system.h	Thu Jan 13 13:30:31 2000
@@ -20,7 +20,8 @@
 
 #endif
 
-#define arch_do_idle() do { } while (0)
+#define arch_do_idle()		do { } while (0)
+#define arch_power_off()	do { } while (0)
 
 extern __inline__ void arch_reset(char mode)
 {
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-cl7500/system.h linux/include/asm-arm/arch-cl7500/system.h
--- v2.3.39/linux/include/asm-arm/arch-cl7500/system.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-arm/arch-cl7500/system.h	Thu Jan 13 13:30:31 2000
@@ -24,4 +24,6 @@
 #define arch_do_idle()				\
 	outb(0, IOMD_SUSMODE)
 
+#define arch_power_off()	do { } while (0)
+
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-ebsa110/system.h linux/include/asm-arm/arch-ebsa110/system.h
--- v2.3.39/linux/include/asm-arm/arch-ebsa110/system.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-arm/arch-ebsa110/system.h	Thu Jan 13 13:30:31 2000
@@ -7,6 +7,7 @@
 #define __ASM_ARCH_SYSTEM_H
 
 #define arch_do_idle()		cpu_do_idle()
+#define arch_power_off()	do { } while (0)
 
 extern __inline__ void arch_reset(char mode)
 {
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-ebsa285/io.h linux/include/asm-arm/arch-ebsa285/io.h
--- v2.3.39/linux/include/asm-arm/arch-ebsa285/io.h	Tue Dec 14 01:27:24 1999
+++ linux/include/asm-arm/arch-ebsa285/io.h	Thu Jan 13 13:30:31 2000
@@ -16,7 +16,7 @@
  * Translation of various region addresses to virtual addresses
  */
 #define __io_pci(a)		(PCIO_BASE + (a))
-#if 0
+#if 1
 #define __mem_pci(a)		((unsigned long)(a))
 #define __mem_isa(a)		(PCIMEM_BASE + (unsigned long)(a))
 #else
@@ -91,7 +91,7 @@
 #define __arch_ioremap(off,size,nocache)			\
 ({								\
 	unsigned long _off = (off), _size = (size);		\
-	void *_ret = NULL;					\
+	void *_ret = (void *)0;					\
 	if (valid_ioaddr(_off, _size))				\
 		_ret = __ioremap(io_to_phys(_off), _size, 0);	\
 	_ret;							\
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h
--- v2.3.39/linux/include/asm-arm/arch-ebsa285/irq.h	Thu Nov 18 20:25:37 1999
+++ linux/include/asm-arm/arch-ebsa285/irq.h	Thu Jan 13 13:30:31 2000
@@ -44,8 +44,19 @@
 static inline int fixup_irq(unsigned int irq)
 {
 #ifdef CONFIG_HOST_FOOTBRIDGE
-	if (irq == isa_irq)
+	if (irq == isa_irq) {
 		irq = *(unsigned char *)PCIIACK_BASE;
+
+		/*
+		 * The NetWinder appears to randomly give wrong interrupt
+		 * numbers from time to time.  When it does, map them to
+		 * the unused IRQ 13
+		 */
+		if (irq >= NR_IRQS) {
+			printk(KERN_ERR "Strange interrupt %d?\n", irq);
+			irq = _ISA_IRQ(13);
+		}
+	}
 #endif
 
 	return irq;
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-ebsa285/system.h linux/include/asm-arm/arch-ebsa285/system.h
--- v2.3.39/linux/include/asm-arm/arch-ebsa285/system.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-arm/arch-ebsa285/system.h	Thu Jan 13 13:30:31 2000
@@ -9,6 +9,7 @@
 #include <asm/leds.h>
 
 #define arch_do_idle()		cpu_do_idle()
+#define arch_power_off()	do { } while (0)
 
 extern __inline__ void arch_reset(char mode)
 {
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-nexuspci/system.h linux/include/asm-arm/arch-nexuspci/system.h
--- v2.3.39/linux/include/asm-arm/arch-nexuspci/system.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-nexuspci/system.h	Thu Jan 13 13:30:31 2000
@@ -8,5 +8,6 @@
 
 #define arch_do_idle()		do { } while (0)
 #define arch_reset(mode)	do { } while (0)
+#define arch_power_off()	do { } while (0)
 
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-rpc/system.h linux/include/asm-arm/arch-rpc/system.h
--- v2.3.39/linux/include/asm-arm/arch-rpc/system.h	Mon Nov  1 13:56:27 1999
+++ linux/include/asm-arm/arch-rpc/system.h	Thu Jan 13 13:30:31 2000
@@ -7,7 +7,8 @@
 #include <asm/iomd.h>
 #include <asm/io.h>
 
-#define arch_do_idle() cpu_do_idle()
+#define arch_do_idle()		cpu_do_idle()
+#define arch_power_off()	do { } while (0)
 
 extern __inline__ void arch_reset(char mode)
 {
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-sa1100/hardware.h linux/include/asm-arm/arch-sa1100/hardware.h
--- v2.3.39/linux/include/asm-arm/arch-sa1100/hardware.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-sa1100/hardware.h	Thu Jan 13 13:30:31 2000
@@ -1,7 +1,7 @@
 /*
  * linux/include/asm-arm/arch-brutus/hardware.h
  *
- * Copyright (C) 1998 Nicolas Pitre <nico@visuaide.com>
+ * Copyright (C) 1998 Nicolas Pitre <nico@cam.org>
  *
  * This file contains the hardware definitions for SA1100 architecture
  */
@@ -12,7 +12,7 @@
 /* Flushing areas */
 #define FLUSH_BASE_PHYS		0xe0000000	/* SA1100 zero bank */
 #define FLUSH_BASE		0xdf000000
-#define FLUSH_BASE_MINICACHE	0xde000000
+#define FLUSH_BASE_MINICACHE	0xdf800000
 
 /*
  * PCMCIA IO is mapped to 0xe0000000.  We are likely to use in*()/out*()
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-sa1100/ide.h linux/include/asm-arm/arch-sa1100/ide.h
--- v2.3.39/linux/include/asm-arm/arch-sa1100/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-sa1100/ide.h	Mon Jan 17 22:22:52 2000
@@ -0,0 +1,98 @@
+/*
+ * linux/include/asm-arm/arch-sa1100/ide.h
+ *
+ * Copyright (c) 1998 Hugo Fiennes & Nicolas Pitre
+ *
+ */
+
+#include <linux/config.h>
+
+#ifdef CONFIG_BLK_DEV_IDE
+
+#include <asm/irq.h>
+#include <asm/arch/hardware.h>
+
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+{
+	ide_ioreg_t reg;
+	int i;
+
+	memset(hw, 0, sizeof(*hw));
+
+#ifdef CONFIG_SA1100_EMPEG
+/* The Empeg board has the first two address lines unused */
+#define IO_SHIFT 2
+#else
+#define IO_SHIFT 0
+#endif
+
+	reg = (ide_ioreg_t) (data_port << IO_SHIFT);
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += (1 << IO_SHIFT);
+	}
+	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) (ctrl_port << IO_SHIFT);
+	hw->irq = irq;
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void
+ide_init_default_hwifs(void)
+{
+	hw_regs_t hw;
+
+#if defined( CONFIG_SA1100_EMPEG )
+	/* First, do the SA1100 setup */
+
+	/* PCMCIA IO space */
+	MECR=0x21062106;
+
+        /* Issue 3 is much neater than issue 2 */
+	GPDR&=~(EMPEG_IDE1IRQ|EMPEG_IDE2IRQ);
+
+	/* Interrupts on rising edge: lines are inverted before they get to
+           the SA */
+	GRER&=~(EMPEG_IDE1IRQ|EMPEG_IDE2IRQ);
+	GFER|=(EMPEG_IDE1IRQ|EMPEG_IDE2IRQ);
+
+	/* Take hard drives out of reset */
+	GPSR=(EMPEG_IDERESET);
+
+	/* Clear GEDR */
+	GEDR=0xffffffff;
+
+	/* Sonja and her successors have two IDE ports. */
+	/* MAC 23/4/1999, swap these round so that the left hand
+	   hard disk is hda when viewed from the front. This
+	   doesn't match the silkscreen however. */
+	ide_init_hwif_ports(&hw,0x10,0x1e,EMPEG_IRQ_IDE2);
+	ide_register_hw(&hw, NULL);
+	ide_init_hwif_ports(&hw,0x00,0x0e,EMPEG_IRQ_IDE1);
+	ide_register_hw(&hw, NULL);
+
+#elif defined( CONFIG_SA1100_VICTOR )
+	/* Enable appropriate GPIOs as interrupt lines */
+	GPDR &= ~GPIO_GPIO7;
+	GRER |= GPIO_GPIO7;
+	GFER &= ~GPIO_GPIO7;
+	GEDR = GPIO_GPIO7;
+	/* set the pcmcia interface timing */
+	MECR = 0x00060006;
+
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_GPIO7);
+	ide_register_hw(&hw, NULL);
+#else
+#error Missing IDE interface definition in include/asm/arch/ide.h
+#endif
+}
+
+#endif
+
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-sa1100/memory.h linux/include/asm-arm/arch-sa1100/memory.h
--- v2.3.39/linux/include/asm-arm/arch-sa1100/memory.h	Mon Nov  1 13:56:27 1999
+++ linux/include/asm-arm/arch-sa1100/memory.h	Thu Jan 13 13:30:31 2000
@@ -1,7 +1,7 @@
 /*
  * linux/include/asm-arm/arch-sa1100/memory.h
  *
- * Copyright (c) 1999 Nicolas Pitre <nico@visuaide.com>
+ * Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
  */
 
 #ifndef __ASM_ARCH_MEMORY_H
@@ -12,23 +12,27 @@
  * Task size: 3GB
  */
 #define TASK_SIZE	(0xc0000000UL)
+#define TASK_SIZE_26	(0x04000000UL)
 
 /*
  * Page offset: 3GB
  */
 #define PAGE_OFFSET	(0xc0000000UL)
-#define PHYS_OFFSET	(0x00000000UL)
+
+/*
+ * Physical DRAM offset is 0xc0000000 on the SA1100
+ */
+#define PHYS_OFFSET	(0xc0000000UL)
+
 
 #define __virt_to_phys__is_a_macro
 #define __phys_to_virt__is_a_macro
 
 /*
  * The following gives a maximum memory size of 128MB (32MB in each bank).
- *
- * Does this still need to be optimised for one bank machines?
  */
-#define __virt_to_phys(x)	(((x) & 0xe0ffffff) | ((x) & 0x06000000) << 2)
-#define __phys_to_virt(x)	(((x) & 0xe7ffffff) | ((x) & 0x30000000) >> 2)
+#define __virt_to_phys(x)	(((x) & 0xf9ffffff) | ((x) & 0x06000000) << 2)
+#define __phys_to_virt(x)	(((x) & 0xe7ffffff) | ((x) & 0x18000000) >> 2)
 
 /*
  * Virtual view <-> DMA view memory address translations
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-sa1100/param.h linux/include/asm-arm/arch-sa1100/param.h
--- v2.3.39/linux/include/asm-arm/arch-sa1100/param.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/arch-sa1100/param.h	Thu Jan 13 13:30:31 2000
@@ -1,3 +1,3 @@
 /*
- * linux/include/asm-arm/arch-ebsa110/param.h
+ * linux/include/asm-arm/arch-sa1100/param.h
  */
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-sa1100/serial.h linux/include/asm-arm/arch-sa1100/serial.h
--- v2.3.39/linux/include/asm-arm/arch-sa1100/serial.h	Tue Nov 23 22:42:21 1999
+++ linux/include/asm-arm/arch-sa1100/serial.h	Thu Jan 13 13:30:31 2000
@@ -1,6 +1,6 @@
 /*
  * include/asm-arm/arch-sa1100/serial.h
- * (C) 1999 Nicolas Pitre <nico@visuaide.com>
+ * (C) 1999 Nicolas Pitre <nico@cam.org>
  *
  * All this is intended to be used with a 16550-like UART on the SA1100's 
  * PCMCIA bus.  It has nothing to do with the SA1100's internal serial ports.
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-sa1100/system.h linux/include/asm-arm/arch-sa1100/system.h
--- v2.3.39/linux/include/asm-arm/arch-sa1100/system.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-arm/arch-sa1100/system.h	Thu Jan 13 13:30:31 2000
@@ -1,7 +1,7 @@
 /*
  * linux/include/asm-arm/arch-sa1100/system.h
  *
- * Copyright (c) 1999 Nicolas Pitre <nico@visuaide.com>
+ * Copyright (c) 1999 Nicolas Pitre <nico@cam.org>
  */
 #include <linux/config.h>
 
@@ -25,6 +25,9 @@
 #endif
 
 
+#if 0
+#define arch_do_idle()          cpu_do_idle()
+#else
 /* Enter SA1100 idle mode (see data sheet sec 9.5).
  * It seems that the wait-on-interrupt just hang the CPU forever if it's
  * on the end of a cache line.  Workaround: we force an explicit alignment
@@ -41,3 +44,7 @@
 "	mcr	p15, 0, %0, c15, c1, 2	@ Reenable clock switching \n" \
 	: : "r" (&ICIP) : "cc" ); \
 	} while (0)
+#endif
+
+#define arch_power_off()	do { } while (0)
+
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/arch-sa1100/uncompress.h linux/include/asm-arm/arch-sa1100/uncompress.h
--- v2.3.39/linux/include/asm-arm/arch-sa1100/uncompress.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-sa1100/uncompress.h	Mon Jan 17 22:22:52 2000
@@ -0,0 +1,52 @@
+/*
+ * linux/include/asm-arm/arch-brutus/uncompress.h
+ *
+ * (C) 1999 Nicolas Pitre <nico@cam.org>
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_SA1100_EMPEG) || \
+    defined(CONFIG_SA1100_VICTOR) || \
+    defined(CONFIG_SA1100_LART)
+
+#include "hardware.h"
+#include "serial_reg.h"
+
+static volatile unsigned long* serial_port = (unsigned long*)_Ser3UTCR0;
+
+/*
+ * The following code assumes the serial port has already been
+ * initialized by the bootloader or such...
+ */
+
+static void puts( const char *s )
+{
+    int i;
+
+    for (i = 0; *s; i++, s++) {
+	/* wait for space in the UART's transmiter */
+	while( !(serial_port[UTSR1] & UTSR1_TNF) );
+
+	/* send the character out. */
+	serial_port[UART_TX] = *s;
+
+	/* if a LF, also do CR... */
+	if (*s == 10) {
+	    while( !(serial_port[UTSR1] & UTSR1_TNF) );
+	    serial_port[UART_TX] = 13;
+	}
+    }
+}
+
+#else
+
+#define puts( x )
+
+#endif
+
+
+/* Nothing to do for these */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/checksum.h linux/include/asm-arm/checksum.h
--- v2.3.39/linux/include/asm-arm/checksum.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/checksum.h	Thu Jan 13 13:30:31 2000
@@ -4,7 +4,7 @@
  * IP checksum routines
  *
  * Copyright (C) Original authors of ../asm-i386/checksum.h
- * Copyright (C) 1996,1997,1998 Russell King
+ * Copyright (C) 1996-1999 Russell King
  */
 #ifndef __ASM_ARM_CHECKSUM_H
 #define __ASM_ARM_CHECKSUM_H
@@ -37,37 +37,25 @@
 unsigned int
 csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *err_ptr);
 
-#if 0
-/*
- * This combination is currently not used, but possible:
- */
-unsigned int
-csum_partial_copy_to_user(const char *src, char *dst, int len, int sum, int *err_ptr);
-#endif
-
 /*
  * These are the old (and unsafe) way of doing checksums, a warning message will be
  * printed if they are used and an exception occurs.
  *
  * these functions should go away after some time.
  */
-#define csum_partial_copy_fromuser csum_partial_copy
-unsigned int
-csum_partial_copy(const char *src, char *dst, int len, int sum);
+#define csum_partial_copy(src,dst,len,sum)	csum_partial_copy_nocheck(src,dst,len,sum)
 
 /*
  *	This is a version of ip_compute_csum() optimized for IP headers,
  *	which always checksum on 4 octet boundaries.
- *
- *	Converted and optimised for ARM by R. M. King.
  */
 static inline unsigned short
 ip_fast_csum(unsigned char * iph, unsigned int ihl)
 {
 	unsigned int sum, tmp1;
 
-    __asm__ __volatile__(
-	"sub	%2, %2, #5		@ ip_fast_csum 
+	__asm__ __volatile__(
+	"sub	%2, %2, #5		@ ip_fast_csum
 	ldr	%0, [%1], #4
 	ldr	%3, [%1], #4
 	adds	%0, %0, %3
@@ -86,10 +74,10 @@
 	mvn	%0, %0
 	mov	%0, %0, lsr #16
 	"
-	: "=&r" (sum), "=&r" (iph), "=&r" (ihl), "=&r" (tmp1)
+	: "=r" (sum), "=r" (iph), "=r" (ihl), "=r" (tmp1)
 	: "1" (iph), "2" (ihl)
 	: "cc");
-	return(sum);
+	return sum;
 }
 
 /*
@@ -130,7 +118,17 @@
 csum_tcpudp_magic(unsigned long saddr, unsigned long daddr, unsigned short len,
 		  unsigned int proto, unsigned int sum)
 {
-	return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
+	__asm__(
+	"adds	%0, %1, %2		@ csum_tcpudp_magic
+	adcs	%0, %0, %3
+	adcs	%0, %0, %4
+	adcs	%0, %0, %5
+	adds	%0, %0, %0, lsl #16
+	addcs	%0, %0, #0x10000"
+	: "=&r"(sum)
+	: "r" (sum), "r" (daddr), "r" (saddr), "r" (ntohs(len) << 16), "Ir" (proto << 8)
+	: "cc");
+	return (~sum) >> 16;
 }
 
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/div64.h linux/include/asm-arm/div64.h
--- v2.3.39/linux/include/asm-arm/div64.h	Tue Nov 23 22:42:21 1999
+++ linux/include/asm-arm/div64.h	Thu Jan 13 13:30:31 2000
@@ -1,32 +1,13 @@
 #ifndef __ASM_ARM_DIV64
 #define __ASM_ARM_DIV64
 
-/*
- * unsigned long long division.  Yuck Yuck!  What is Linux coming to?
- * This is 100% disgusting
- */
-#define do_div(n,base)							\
-({									\
-	unsigned long __low, __low2, __high, __rem;			\
-	__low  = (n) & 0xffffffff;					\
-	__high = (n) >> 32;						\
-	if (__high) {							\
-		__rem   = __high % (unsigned long)base;			\
-		__high  = __high / (unsigned long)base;			\
-		__low2  = __low >> 16;					\
-		__low2 += __rem << 16;					\
-		__rem   = __low2 % (unsigned long)base;			\
-		__low2  = __low2 / (unsigned long)base;			\
-		__low   = __low & 0xffff;				\
-		__low  += __rem << 16;					\
-		__rem   = __low  % (unsigned long)base;			\
-		__low   = __low  / (unsigned long)base;			\
-		n = __low  + (__low2 << 16) + (__high << 32);		\
-	} else {							\
-		__rem = __low % (unsigned long)base;			\
-		n = (__low / (unsigned long)base);			\
-	}								\
-	__rem;								\
+/* We're not 64-bit, but... */
+#define do_div(n,base)						\
+({								\
+	int __res;						\
+	__res = ((unsigned long)n) % (unsigned int)base;	\
+	n = ((unsigned long)n) / (unsigned int)base;		\
+	__res;							\
 })
 
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/io.h linux/include/asm-arm/io.h
--- v2.3.39/linux/include/asm-arm/io.h	Tue Dec 14 01:27:24 1999
+++ linux/include/asm-arm/io.h	Thu Jan 13 13:30:31 2000
@@ -42,10 +42,6 @@
 
 #ifdef __KERNEL__
 
-#ifndef NULL
-#define NULL	((void *) 0)
-#endif
-
 #include <asm/arch/memory.h>
 
 extern __inline__ unsigned long virt_to_phys(volatile void *x)
@@ -86,6 +82,14 @@
 extern void _memcpy_toio(unsigned long, const void *, unsigned long);
 extern void _memset_io(unsigned long, int, unsigned long);
 
+#define __raw_writeb(val,addr)		__arch_putb(val,addr)
+#define __raw_writew(val,addr)		__arch_putw(val,addr)
+#define __raw_writel(val,addr)		__arch_putl(val,addr)
+
+#define __raw_readb(addr)		__arch_getb(addr)
+#define __raw_readw(addr)		__arch_getw(addr)
+#define __raw_readl(addr)		__arch_getl(addr)
+
 /*
  * If this architecture has PCI memory IO, then define the read/write
  * macros.
@@ -151,11 +155,11 @@
 #define isa_writew(val,addr)		__arch_putw(val,__mem_isa(addr))
 #define isa_writel(val,addr)		__arch_putl(val,__mem_isa(addr))
 #define isa_memset_io(a,b,c)		_memset_io(__mem_isa(a),(b),(c))
-#define isa_memcpy_fromio(a,b,c)	_memcpy_fromio((a),__mem_isa((b)),(c))
+#define isa_memcpy_fromio(a,b,c)	_memcpy_fromio((a),__mem_isa(b),(c))
 #define isa_memcpy_toio(a,b,c)		_memcpy_toio(__mem_isa((a)),(b),(c))
 
 #define isa_eth_io_copy_and_sum(a,b,c,d) \
-				eth_copy_and_sum((a),__mem_isa((b),(c),(d))
+				eth_copy_and_sum((a),__mem_isa(b),(c),(d))
 
 static inline int
 isa_check_signature(unsigned long io_addr, const unsigned char *signature,
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/iomd.h linux/include/asm-arm/iomd.h
--- v2.3.39/linux/include/asm-arm/iomd.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/iomd.h	Thu Jan 13 13:30:31 2000
@@ -11,7 +11,7 @@
 #define IOMD_KARTRX	__IOMD(0x004)
 #define IOMD_KCTRL	__IOMD(0x008)
 
-#ifdef CONFIG_ARCH_CL7500
+#ifdef CONFIG_ARCH_CLPS7500
 #define IOMD_IOLINES	__IOMD(0x00C)
 #endif
 
@@ -20,6 +20,10 @@
 #define IOMD_IRQCLRA	__IOMD(0x014)
 #define IOMD_IRQMASKA	__IOMD(0x018)
 
+#ifdef CONFIG_ARCH_CLPS7500
+#define IOMD_SUSMODE	__IOMD(0x01C)
+#endif
+
 #define IOMD_IRQSTATB	__IOMD(0x020)
 #define IOMD_IRQREQB	__IOMD(0x024)
 #define IOMD_IRQMASKB	__IOMD(0x028)
@@ -28,6 +32,10 @@
 #define IOMD_FIQREQ	__IOMD(0x034)
 #define IOMD_FIQMASK	__IOMD(0x038)
 
+#ifdef CONFIG_ARCH_CLPS7500
+#define IOMD_CLKCTL	__IOMD(0x03C)
+#endif
+
 #define IOMD_T0CNTL	__IOMD(0x040)
 #define IOMD_T0LTCHL	__IOMD(0x040)
 #define IOMD_T0CNTH	__IOMD(0x044)
@@ -42,7 +50,7 @@
 #define IOMD_T1GO	__IOMD(0x058)
 #define IOMD_T1LATCH	__IOMD(0x05c)
 
-#ifdef CONFIG_ARCH_CL7500
+#ifdef CONFIG_ARCH_CLPS7500
 #define IOMD_IRQSTATC	__IOMD(0x060)
 #define IOMD_IRQREQC	__IOMD(0x064)
 #define IOMD_IRQMASKC	__IOMD(0x068)
@@ -59,7 +67,7 @@
 #ifdef CONFIG_ARCH_RPC
 #define IOMD_DRAMCR	__IOMD(0x088)
 #endif
-#define IOMD_VREFCR	__IOMD(0x08C)
+#define IOMD_REFCR	__IOMD(0x08C)
 
 #define IOMD_FSIZE	__IOMD(0x090)
 #define IOMD_ID0	__IOMD(0x094)
@@ -71,7 +79,7 @@
 #define IOMD_MOUSEY	__IOMD(0x0A4)
 #endif
 
-#ifdef CONFIG_ARCH_CL7500
+#ifdef CONFIG_ARCH_CLPS7500
 #define IOMD_MSEDAT	__IOMD(0x0A8)
 #define IOMD_MSECTL	__IOMD(0x0Ac)
 #endif
@@ -84,7 +92,7 @@
 #ifdef CONFIG_ARCH_RPC
 #define IOMD_DMAEXT	__IOMD(0x0CC)
 #endif
-#ifdef CONFIG_ARCH_CL7500
+#ifdef CONFIG_ARCH_CLPS7500
 #define IOMD_ASTCR	__IOMD(0x0CC)
 #define IOMD_DRAMCR	__IOMD(0x0D0)
 #define IOMD_SELFREF	__IOMD(0x0D4)
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/page.h linux/include/asm-arm/page.h
--- v2.3.39/linux/include/asm-arm/page.h	Tue Nov 23 22:42:21 1999
+++ linux/include/asm-arm/page.h	Thu Jan 13 13:30:31 2000
@@ -69,9 +69,9 @@
 
 #include <asm/arch/memory.h>
 
-#define __pa(x)			((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)
-#define __va(x)			((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
-#define MAP_NR(addr)		(((unsigned long)(addr) - PAGE_OFFSET) >> PAGE_SHIFT)
+#define __pa(x)			__virt_to_phys((unsigned long)(x))
+#define __va(x)			((void *)__phys_to_virt((unsigned long)(x)))
+#define MAP_NR(addr)		((__pa(addr) - PHYS_OFFSET) >> PAGE_SHIFT)
 
 #endif
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/posix_types.h linux/include/asm-arm/posix_types.h
--- v2.3.39/linux/include/asm-arm/posix_types.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-arm/posix_types.h	Sat Jan 15 22:08:28 2000
@@ -37,11 +37,8 @@
 typedef unsigned int		__kernel_uid32_t;
 typedef unsigned int		__kernel_gid32_t;
 
-#ifdef __KERNEL__
-#define UID16_COMPAT_NEEDED
 typedef unsigned short		__kernel_old_uid_t;
 typedef unsigned short		__kernel_old_gid_t;
-#endif /* __KERNEL__ */
 
 #ifdef __GNUC__
 typedef long long		__kernel_loff_t;
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/proc-armv/uncompress.h linux/include/asm-arm/proc-armv/uncompress.h
--- v2.3.39/linux/include/asm-arm/proc-armv/uncompress.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/proc-armv/uncompress.h	Thu Jan 13 13:30:31 2000
@@ -11,7 +11,7 @@
 	eor	r0, r0, #0x44 << 24
 	eor	r0, r0, #0x01 << 16
 	eor	r0, r0, #0xA1 << 8
-	movs	r0, r0, lsr #4
+	movs	r0, r0, lsr #5
 	mcreq	p15, 0, r0, c7, c5, 0		@ flush I cache
 	mrceq	p15, 0, r0, c1, c0
 	orreq	r0, r0, #1 << 12
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/proc-fns.h linux/include/asm-arm/proc-fns.h
--- v2.3.39/linux/include/asm-arm/proc-fns.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/proc-fns.h	Thu Jan 13 13:30:31 2000
@@ -47,6 +47,14 @@
 #   define CPU_NAME sa110
 #  endif
 # endif
+# ifdef CONFIG_CPU_SA1100
+#  ifdef CPU_NAME
+#   undef  MULTI_CPU
+#   define MULTI_CPU
+#  else
+#   define CPU_NAME sa1100
+#  endif
+# endif
 #endif
 
 #ifndef MULTI_CPU
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/sigcontext.h linux/include/asm-arm/sigcontext.h
--- v2.3.39/linux/include/asm-arm/sigcontext.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/sigcontext.h	Thu Jan 13 13:30:31 2000
@@ -27,6 +27,7 @@
 	unsigned long arm_lr;
 	unsigned long arm_pc;
 	unsigned long arm_cpsr;
+	unsigned long fault_address;
 };
 
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/stat.h linux/include/asm-arm/stat.h
--- v2.3.39/linux/include/asm-arm/stat.h	Mon Dec 20 18:48:22 1999
+++ linux/include/asm-arm/stat.h	Thu Jan 13 13:30:31 2000
@@ -38,5 +38,40 @@
 	unsigned long  __unused5;
 };
 
-/* Someone please add a glibc/arm compatible stat64 struct here. */
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+	unsigned short	st_dev;
+	unsigned char	__pad0[10];
+
+	unsigned long	st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned long	st_uid;
+	unsigned long	st_gid;
+
+	unsigned short	st_rdev;
+	unsigned char	__pad3[10];
+
+	long long	st_size;
+	unsigned long	st_blksize;
+
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long	__pad4;		/* future possible st_blocks high bits */
+
+	unsigned long	st_atime;
+	unsigned long	__pad5;
+
+	unsigned long	st_mtime;
+	unsigned long	__pad6;
+
+	unsigned long	st_ctime;
+	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
+
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/string.h linux/include/asm-arm/string.h
--- v2.3.39/linux/include/asm-arm/string.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/string.h	Thu Jan 13 13:30:31 2000
@@ -19,7 +19,6 @@
 #define __HAVE_ARCH_MEMSET
 
 extern void __memzero(void *ptr, __kernel_size_t n);
-extern void __memset(void *ptr, int v, __kernel_size_t n);
 
 #define memset(p,v,n)							\
 	({								\
@@ -27,7 +26,7 @@
 			if (__builtin_constant_p((v)) && (v) == 0)	\
 				__memzero((p),(n));			\
 			else						\
-				__memset((p),(v),(n));			\
+				memset((p),(v),(n));			\
 		}							\
 		(p);							\
 	})
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/system.h linux/include/asm-arm/system.h
--- v2.3.39/linux/include/asm-arm/system.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-arm/system.h	Thu Jan 13 13:30:31 2000
@@ -42,6 +42,7 @@
 #define MACH_TYPE_LACIE_NAS	13
 #define MACH_TYPE_CLPS7500	14
 #define MACH_TYPE_SHARK		15
+#define MACH_TYPE_SA1100	16
 
 /*
  * Sort out a definition for machine_arch_type
@@ -122,6 +123,18 @@
 # define machine_is_co285()	(machine_arch_type == MACH_TYPE_CO285)
 #else
 # define machine_is_co285()	(0)
+#endif
+
+#ifdef CONFIG_ARCH_SA1100
+# ifdef machine_arch_type
+#  undef machine_arch_type
+#  define machine_arch_type	__machine_arch_type
+# else
+#  define machine_arch_type	MACH_TYPE_SA1100
+# endif
+# define machine_is_sa1100()	(machine_arch_type == MACH_TYPE_SA1100
+#else
+# define machine_is_sa1100()	(0)
 #endif
 
 #ifndef machine_arch_type
diff -u --recursive --new-file v2.3.39/linux/include/asm-arm/unistd.h linux/include/asm-arm/unistd.h
--- v2.3.39/linux/include/asm-arm/unistd.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-arm/unistd.h	Thu Jan 13 13:30:31 2000
@@ -7,7 +7,6 @@
  * This file contains the system call numbers.
  */
 
-#define __NR_setup			(__NR_SYSCALL_BASE+  0)	/* used only by init, to get system going */
 #define __NR_exit			(__NR_SYSCALL_BASE+  1)
 #define __NR_fork			(__NR_SYSCALL_BASE+  2)
 #define __NR_read			(__NR_SYSCALL_BASE+  3)
@@ -25,7 +24,7 @@
 #define __NR_chmod			(__NR_SYSCALL_BASE+ 15)
 #define __NR_lchown			(__NR_SYSCALL_BASE+ 16)
 #define __NR_break			(__NR_SYSCALL_BASE+ 17)
-#define __NR_oldstat			(__NR_SYSCALL_BASE+ 18)
+
 #define __NR_lseek			(__NR_SYSCALL_BASE+ 19)
 #define __NR_getpid			(__NR_SYSCALL_BASE+ 20)
 #define __NR_mount			(__NR_SYSCALL_BASE+ 21)
@@ -35,7 +34,7 @@
 #define __NR_stime			(__NR_SYSCALL_BASE+ 25)
 #define __NR_ptrace			(__NR_SYSCALL_BASE+ 26)
 #define __NR_alarm			(__NR_SYSCALL_BASE+ 27)
-#define __NR_oldfstat			(__NR_SYSCALL_BASE+ 28)
+
 #define __NR_pause			(__NR_SYSCALL_BASE+ 29)
 #define __NR_utime			(__NR_SYSCALL_BASE+ 30)
 #define __NR_stty			(__NR_SYSCALL_BASE+ 31)
@@ -83,7 +82,7 @@
 #define __NR_sigpending			(__NR_SYSCALL_BASE+ 73)
 #define __NR_sethostname		(__NR_SYSCALL_BASE+ 74)
 #define __NR_setrlimit			(__NR_SYSCALL_BASE+ 75)
-#define __NR_old_getrlimit		(__NR_SYSCALL_BASE+ 76)
+#define __NR_old_getrlimit		(__NR_SYSCALL_BASE+ 76)	/* Back compat 2GB limited rlimit */
 #define __NR_getrusage			(__NR_SYSCALL_BASE+ 77)
 #define __NR_gettimeofday		(__NR_SYSCALL_BASE+ 78)
 #define __NR_settimeofday		(__NR_SYSCALL_BASE+ 79)
@@ -91,7 +90,7 @@
 #define __NR_setgroups			(__NR_SYSCALL_BASE+ 81)
 #define __NR_select			(__NR_SYSCALL_BASE+ 82)
 #define __NR_symlink			(__NR_SYSCALL_BASE+ 83)
-#define __NR_oldlstat			(__NR_SYSCALL_BASE+ 84)
+
 #define __NR_readlink			(__NR_SYSCALL_BASE+ 85)
 #define __NR_uselib			(__NR_SYSCALL_BASE+ 86)
 #define __NR_swapon			(__NR_SYSCALL_BASE+ 87)
@@ -198,7 +197,7 @@
 					/* 188 reserved */
 					/* 189 reserved */
 #define __NR_vfork			(__NR_SYSCALL_BASE+190)
-#define __NR_getrlimit			(__NR_SYSCALL_BASE+191)
+#define __NR_getrlimit			(__NR_SYSCALL_BASE+191)	/* SuS compliant getrlimit */
 #define __NR_mmap2			(__NR_SYSCALL_BASE+192)
 #define __NR_truncate64			(__NR_SYSCALL_BASE+193)
 #define __NR_ftruncate64		(__NR_SYSCALL_BASE+194)
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/apic.h linux/include/asm-i386/apic.h
--- v2.3.39/linux/include/asm-i386/apic.h	Sat Oct  9 11:47:50 1999
+++ linux/include/asm-i386/apic.h	Thu Jan 20 16:05:28 2000
@@ -1,358 +1,65 @@
 #ifndef __ASM_APIC_H
 #define __ASM_APIC_H
 
-/*
- * Constants for various Intel APICs. (local APIC, IOAPIC, etc.)
- *
- * Alan Cox <Alan.Cox@linux.org>, 1995.
- */
-#define		APIC_PHYS_BASE	0xfee00000 /* IA s/w dev Vol 3, Section 7.4 */
- 
-#define		APIC_ID		0x20
-#define			GET_APIC_ID(x)		(((x)>>24)&0x0F)
-#define		APIC_LVR	0x30
-#define			GET_APIC_VERSION(x)	((x)&0xFF)
-#define			GET_APIC_MAXLVT(x)	(((x)>>16)&0x0F)
-#define			APIC_INTEGRATED(x)	((x)&0xF0)
-#define		APIC_TASKPRI	0x80
-#define			APIC_TPRI_MASK		0xFF
-#define		APIC_ARBPRI	0x90
-#define			APIC_ARBPRI_MASK	0xFF
-#define		APIC_PROCPRI	0xA0
-#define		APIC_EOI	0xB0
-#define			APIC_EIO_ACK		0x0		/* Write this to the EOI register */
-#define		APIC_RRR	0xC0
-#define		APIC_LDR	0xD0
-#define			APIC_LDR_MASK		(0xFF<<24)
-#define			GET_APIC_LOGICAL_ID(x)	(((x)>>24)&0xFF)
-#define			SET_APIC_LOGICAL_ID(x)	(((x)<<24))
-#define			APIC_ALL_CPUS		0xFF
-#define		APIC_DFR	0xE0
-#define			GET_APIC_DFR(x)		(((x)>>28)&0x0F)
-#define			SET_APIC_DFR(x)		((x)<<28)
-#define		APIC_SPIV	0xF0
-#define		APIC_ISR	0x100
-#define		APIC_TMR	0x180
-#define 	APIC_IRR	0x200
-#define 	APIC_ESR	0x280
-#define			APIC_ESR_SEND_CS	0x00001
-#define			APIC_ESR_RECV_CS	0x00002
-#define			APIC_ESR_SEND_ACC	0x00004
-#define			APIC_ESR_RECV_ACC	0x00008
-#define			APIC_ESR_SENDILL	0x00020
-#define			APIC_ESR_RECVILL	0x00040
-#define			APIC_ESR_ILLREGA	0x00080
-#define		APIC_ICR	0x300
-#define			APIC_DEST_SELF		0x40000
-#define			APIC_DEST_ALLINC	0x80000
-#define			APIC_DEST_ALLBUT	0xC0000
-#define			APIC_DEST_RR_MASK	0x30000
-#define			APIC_DEST_RR_INVALID	0x00000
-#define			APIC_DEST_RR_INPROG	0x10000
-#define			APIC_DEST_RR_VALID	0x20000
-#define			APIC_DEST_LEVELTRIG	0x08000
-#define			APIC_DEST_ASSERT	0x04000
-#define			APIC_DEST_BUSY		0x01000
-#define			APIC_DEST_LOGICAL	0x00800
-#define			APIC_DEST_DM_FIXED	0x00000
-#define			APIC_DEST_DM_LOWEST	0x00100
-#define			APIC_DEST_DM_SMI	0x00200
-#define			APIC_DEST_DM_REMRD	0x00300
-#define			APIC_DEST_DM_NMI	0x00400
-#define			APIC_DEST_DM_INIT	0x00500
-#define			APIC_DEST_DM_STARTUP	0x00600
-#define			APIC_DEST_VECTOR_MASK	0x000FF
-#define		APIC_ICR2	0x310
-#define			GET_APIC_DEST_FIELD(x)	(((x)>>24)&0xFF)
-#define			SET_APIC_DEST_FIELD(x)	((x)<<24)
-#define		APIC_LVTT	0x320
-#define		APIC_LVTPC	0x340
-#define		APIC_LVT0	0x350
-#define			APIC_LVT_TIMER_BASE_MASK	(0x3<<18)
-#define			GET_APIC_TIMER_BASE(x)		(((x)>>18)&0x3)
-#define			SET_APIC_TIMER_BASE(x)		(((x)<<18))
-#define			APIC_TIMER_BASE_CLKIN		0x0
-#define			APIC_TIMER_BASE_TMBASE		0x1
-#define			APIC_TIMER_BASE_DIV		0x2
-#define			APIC_LVT_TIMER_PERIODIC		(1<<17)
-#define			APIC_LVT_MASKED			(1<<16)
-#define			APIC_LVT_LEVEL_TRIGGER		(1<<15)
-#define			APIC_LVT_REMOTE_IRR		(1<<14)
-#define			APIC_INPUT_POLARITY		(1<<13)
-#define			APIC_SEND_PENDING		(1<<12)
-#define			GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7)
-#define			SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8))
-#define				APIC_MODE_FIXED		0x0
-#define				APIC_MODE_NMI		0x4
-#define				APIC_MODE_EXINT		0x7
-#define 	APIC_LVT1	0x360
-#define		APIC_LVTERR	0x370
-#define		APIC_TMICT	0x380
-#define		APIC_TMCCT	0x390
-#define		APIC_TDCR	0x3E0
-#define			APIC_TDR_DIV_TMBASE	(1<<2)
-#define			APIC_TDR_DIV_1		0xB
-#define			APIC_TDR_DIV_2		0x0
-#define			APIC_TDR_DIV_4		0x1
-#define			APIC_TDR_DIV_8		0x2
-#define			APIC_TDR_DIV_16		0x3
-#define			APIC_TDR_DIV_32		0x8
-#define			APIC_TDR_DIV_64		0x9
-#define			APIC_TDR_DIV_128	0xA
+#include <linux/config.h>
+#include <asm/apicdef.h>
+
+#define APIC_DEBUG 1
 
-#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
+#ifdef CONFIG_X86_LOCAL_APIC
 
-#define MAX_IO_APICS 8
+#if APIC_DEBUG
+#define Dprintk(x...) printk(##x)
+#else
+#define Dprintk(x...)
+#endif
 
 /*
- * the local APIC register structure, memory mapped. Not terribly well
- * tested, but we might eventually use this one in the future - the
- * problem why we cannot use it right now is the P5 APIC, it has an
- * errata which cannot take 8-bit reads and writes, only 32-bit ones ...
+ * Basic functions accessing APICs.
  */
-#define u32 unsigned int
-
-#define lapic ((volatile struct local_apic *)APIC_BASE)
-
-struct local_apic {
-
-/*000*/	struct { u32 __reserved[4]; } __reserved_01;
-
-/*010*/	struct { u32 __reserved[4]; } __reserved_02;
-
-/*020*/	struct { /* APIC ID Register */
-		u32   __reserved_1	: 24,
-			phys_apic_id	:  4,
-			__reserved_2	:  4;
-		u32 __reserved[3];
-	} id;
-
-/*030*/	const
-	struct { /* APIC Version Register */
-		u32   version		:  8,
-			__reserved_1	:  8,
-			max_lvt		:  8,
-			__reserved_2	:  8;
-		u32 __reserved[3];
-	} version;
-
-/*040*/	struct { u32 __reserved[4]; } __reserved_03;
-
-/*050*/	struct { u32 __reserved[4]; } __reserved_04;
-
-/*060*/	struct { u32 __reserved[4]; } __reserved_05;
-
-/*070*/	struct { u32 __reserved[4]; } __reserved_06;
-
-/*080*/	struct { /* Task Priority Register */
-		u32   priority	:  8,
-			__reserved_1	: 24;
-		u32 __reserved_2[3];
-	} tpr;
-
-/*090*/	const
-	struct { /* Arbitration Priority Register */
-		u32   priority	:  8,
-			__reserved_1	: 24;
-		u32 __reserved_2[3];
-	} apr;
-
-/*0A0*/	const
-	struct { /* Processor Priority Register */
-		u32   priority	:  8,
-			__reserved_1	: 24;
-		u32 __reserved_2[3];
-	} ppr;
-
-/*0B0*/	struct { /* End Of Interrupt Register */
-		u32   eoi;
-		u32 __reserved[3];
-	} eoi;
-
-/*0C0*/	struct { u32 __reserved[4]; } __reserved_07;
-
-/*0D0*/	struct { /* Logical Destination Register */
-		u32   __reserved_1	: 24,
-			logical_dest	:  8;
-		u32 __reserved_2[3];
-	} ldr;
-
-/*0E0*/	struct { /* Destination Format Register */
-		u32   __reserved_1	: 28,
-			model		:  4;
-		u32 __reserved_2[3];
-	} dfr;
-
-/*0F0*/	struct { /* Spurious Interrupt Vector Register */
-		u32	spurious_vector	:  8,
-			apic_enabled	:  1,
-			focus_cpu	:  1,
-			__reserved_2	: 22;
-		u32 __reserved_3[3];
-	} svr;
-
-/*100*/	struct { /* In Service Register */
-/*170*/		u32 bitfield;
-		u32 __reserved[3];
-	} isr [8];
-
-/*180*/	struct { /* Trigger Mode Register */
-/*1F0*/		u32 bitfield;
-		u32 __reserved[3];
-	} tmr [8];
-
-/*200*/	struct { /* Interrupt Request Register */
-/*270*/		u32 bitfield;
-		u32 __reserved[3];
-	} irr [8];
-
-/*280*/	union { /* Error Status Register */
-		struct {
-			u32   send_cs_error			:  1,
-				receive_cs_error		:  1,
-				send_accept_error		:  1,
-				receive_accept_error		:  1,
-				__reserved_1			:  1,
-				send_illegal_vector		:  1,
-				receive_illegal_vector		:  1,
-				illegal_register_address	:  1,
-				__reserved_2			: 24;
-			u32 __reserved_3[3];
-		} error_bits;
-		struct {
-			u32 errors;
-			u32 __reserved_3[3];
-		} all_errors;
-	} esr;
-
-/*290*/	struct { u32 __reserved[4]; } __reserved_08;
-
-/*2A0*/	struct { u32 __reserved[4]; } __reserved_09;
-
-/*2B0*/	struct { u32 __reserved[4]; } __reserved_10;
-
-/*2C0*/	struct { u32 __reserved[4]; } __reserved_11;
-
-/*2D0*/	struct { u32 __reserved[4]; } __reserved_12;
-
-/*2E0*/	struct { u32 __reserved[4]; } __reserved_13;
-
-/*2F0*/	struct { u32 __reserved[4]; } __reserved_14;
-
-/*300*/	struct { /* Interrupt Command Register 1 */
-		u32   vector			:  8,
-			delivery_mode		:  3,
-			destination_mode	:  1,
-			delivery_status		:  1,
-			__reserved_1		:  1,
-			level			:  1,
-			trigger			:  1,
-			__reserved_2		:  2,
-			shorthand		:  2,
-			__reserved_3		:  12;
-		u32 __reserved_4[3];
-	} icr1;
-
-/*310*/	struct { /* Interrupt Command Register 2 */
-		union {
-			u32   __reserved_1	: 24,
-				phys_dest	:  4,
-				__reserved_2	:  4;
-			u32   __reserved_3	: 24,
-				logical_dest	:  8;
-		} dest;
-		u32 __reserved_4[3];
-	} icr2;
-
-/*320*/	struct { /* LVT - Timer */
-		u32   vector		:  8,
-			__reserved_1	:  4,
-			delivery_status	:  1,
-			__reserved_2	:  3,
-			mask		:  1,
-			timer_mode	:  1,
-			__reserved_3	: 14;
-		u32 __reserved_4[3];
-	} lvt_timer;
-
-/*330*/	struct { u32 __reserved[4]; } __reserved_15;
-
-/*340*/	struct { /* LVT - Performance Counter */
-		u32   vector		:  8,
-			delivery_mode	:  3,
-			__reserved_1	:  1,
-			delivery_status	:  1,
-			__reserved_2	:  3,
-			mask		:  1,
-			__reserved_3	: 15;
-		u32 __reserved_4[3];
-	} lvt_pc;
-
-/*350*/	struct { /* LVT - LINT0 */
-		u32   vector		:  8,
-			delivery_mode	:  3,
-			__reserved_1	:  1,
-			delivery_status	:  1,
-			polarity	:  1,
-			remote_irr	:  1,
-			trigger		:  1,
-			mask		:  1,
-			__reserved_2	: 15;
-		u32 __reserved_3[3];
-	} lvt_lint0;
-
-/*360*/	struct { /* LVT - LINT1 */
-		u32   vector		:  8,
-			delivery_mode	:  3,
-			__reserved_1	:  1,
-			delivery_status	:  1,
-			polarity	:  1,
-			remote_irr	:  1,
-			trigger		:  1,
-			mask		:  1,
-			__reserved_2	: 15;
-		u32 __reserved_3[3];
-	} lvt_lint1;
-
-/*370*/	struct { /* LVT - Error */
-		u32   vector		:  8,
-			__reserved_1	:  4,
-			delivery_status	:  1,
-			__reserved_2	:  3,
-			mask		:  1,
-			__reserved_3	: 15;
-		u32 __reserved_4[3];
-	} lvt_error;
-
-/*380*/	struct { /* Timer Initial Count Register */
-		u32   initial_count;
-		u32 __reserved_2[3];
-	} timer_icr;
-
-/*390*/	const
-	struct { /* Timer Current Count Register */
-		u32   curr_count;
-		u32 __reserved_2[3];
-	} timer_ccr;
-
-/*3A0*/	struct { u32 __reserved[4]; } __reserved_16;
-
-/*3B0*/	struct { u32 __reserved[4]; } __reserved_17;
-
-/*3C0*/	struct { u32 __reserved[4]; } __reserved_18;
-
-/*3D0*/	struct { u32 __reserved[4]; } __reserved_19;
-
-/*3E0*/	struct { /* Timer Divide Configuration Register */
-		u32   divisor		:  4,
-			__reserved_1	: 28;
-		u32 __reserved_2[3];
-	} timer_dcr;
-
-/*3F0*/	struct { u32 __reserved[4]; } __reserved_20;
-
-} __attribute__ ((packed));
 
-#undef u32
+extern __inline void apic_write(unsigned long reg, unsigned long v)
+{
+	*((volatile unsigned long *)(APIC_BASE+reg))=v;
+}
+
+extern __inline unsigned long apic_read(unsigned long reg)
+{
+	return *((volatile unsigned long *)(APIC_BASE+reg));
+}
+
+extern unsigned int apic_timer_irqs [NR_CPUS];
+
+#ifdef CONFIG_X86_GOOD_APIC
+# define FORCE_READ_AROUND_WRITE 0
+# define apic_readaround(x)
+#else
+# define FORCE_READ_AROUND_WRITE 1
+# define apic_readaround(x) apic_read(x)
+#endif
+
+#define apic_write_around(x,y) \
+		do { apic_readaround(x); apic_write(x,y); } while (0)
+
+extern inline void ack_APIC_irq(void)
+{
+        /* Clear the IPI */
+
+	apic_readaround(APIC_EOI);
+	/*
+	 * on P6+ cores (CONFIG_X86_GOOD_APIC) ack_APIC_irq() actually
+	 * gets compiled as a single instruction ... yummie.
+	 */
+        apic_write(APIC_EOI, 0); /* Docs say use 0 for future compatibility */
+}
+
+extern int get_maxlvt(void);
+extern void disable_local_APIC (void);
+extern void cache_APIC_registers (void);
+extern void setup_local_APIC (void);
+extern void init_apic_mappings(void);
+extern void smp_local_timer_interrupt(struct pt_regs * regs);
+extern void setup_APIC_clocks(void);
+#endif
 
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/apicdef.h linux/include/asm-i386/apicdef.h
--- v2.3.39/linux/include/asm-i386/apicdef.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/apicdef.h	Thu Jan 20 09:51:42 2000
@@ -0,0 +1,359 @@
+#ifndef __ASM_APICDEF_H
+#define __ASM_APICDEF_H
+
+/*
+ * Constants for various Intel APICs. (local APIC, IOAPIC, etc.)
+ *
+ * Alan Cox <Alan.Cox@linux.org>, 1995.
+ * Ingo Molnar <mingo@redhat.com>, 1999, 2000
+ */
+#define		APIC_PHYS_BASE	0xfee00000 /* IA s/w dev Vol 3, Section 7.4 */
+ 
+#define		APIC_ID		0x20
+#define			GET_APIC_ID(x)		(((x)>>24)&0x0F)
+#define		APIC_LVR	0x30
+#define			GET_APIC_VERSION(x)	((x)&0xFF)
+#define			GET_APIC_MAXLVT(x)	(((x)>>16)&0x0F)
+#define			APIC_INTEGRATED(x)	((x)&0xF0)
+#define		APIC_TASKPRI	0x80
+#define			APIC_TPRI_MASK		0xFF
+#define		APIC_ARBPRI	0x90
+#define			APIC_ARBPRI_MASK	0xFF
+#define		APIC_PROCPRI	0xA0
+#define		APIC_EOI	0xB0
+#define			APIC_EIO_ACK		0x0		/* Write this to the EOI register */
+#define		APIC_RRR	0xC0
+#define		APIC_LDR	0xD0
+#define			APIC_LDR_MASK		(0xFF<<24)
+#define			GET_APIC_LOGICAL_ID(x)	(((x)>>24)&0xFF)
+#define			SET_APIC_LOGICAL_ID(x)	(((x)<<24))
+#define			APIC_ALL_CPUS		0xFF
+#define		APIC_DFR	0xE0
+#define			GET_APIC_DFR(x)		(((x)>>28)&0x0F)
+#define			SET_APIC_DFR(x)		((x)<<28)
+#define		APIC_SPIV	0xF0
+#define		APIC_ISR	0x100
+#define		APIC_TMR	0x180
+#define 	APIC_IRR	0x200
+#define 	APIC_ESR	0x280
+#define			APIC_ESR_SEND_CS	0x00001
+#define			APIC_ESR_RECV_CS	0x00002
+#define			APIC_ESR_SEND_ACC	0x00004
+#define			APIC_ESR_RECV_ACC	0x00008
+#define			APIC_ESR_SENDILL	0x00020
+#define			APIC_ESR_RECVILL	0x00040
+#define			APIC_ESR_ILLREGA	0x00080
+#define		APIC_ICR	0x300
+#define			APIC_DEST_SELF		0x40000
+#define			APIC_DEST_ALLINC	0x80000
+#define			APIC_DEST_ALLBUT	0xC0000
+#define			APIC_DEST_RR_MASK	0x30000
+#define			APIC_DEST_RR_INVALID	0x00000
+#define			APIC_DEST_RR_INPROG	0x10000
+#define			APIC_DEST_RR_VALID	0x20000
+#define			APIC_DEST_LEVELTRIG	0x08000
+#define			APIC_DEST_ASSERT	0x04000
+#define			APIC_DEST_BUSY		0x01000
+#define			APIC_DEST_LOGICAL	0x00800
+#define			APIC_DEST_DM_FIXED	0x00000
+#define			APIC_DEST_DM_LOWEST	0x00100
+#define			APIC_DEST_DM_SMI	0x00200
+#define			APIC_DEST_DM_REMRD	0x00300
+#define			APIC_DEST_DM_NMI	0x00400
+#define			APIC_DEST_DM_INIT	0x00500
+#define			APIC_DEST_DM_STARTUP	0x00600
+#define			APIC_DEST_VECTOR_MASK	0x000FF
+#define		APIC_ICR2	0x310
+#define			GET_APIC_DEST_FIELD(x)	(((x)>>24)&0xFF)
+#define			SET_APIC_DEST_FIELD(x)	((x)<<24)
+#define		APIC_LVTT	0x320
+#define		APIC_LVTPC	0x340
+#define		APIC_LVT0	0x350
+#define			APIC_LVT_TIMER_BASE_MASK	(0x3<<18)
+#define			GET_APIC_TIMER_BASE(x)		(((x)>>18)&0x3)
+#define			SET_APIC_TIMER_BASE(x)		(((x)<<18))
+#define			APIC_TIMER_BASE_CLKIN		0x0
+#define			APIC_TIMER_BASE_TMBASE		0x1
+#define			APIC_TIMER_BASE_DIV		0x2
+#define			APIC_LVT_TIMER_PERIODIC		(1<<17)
+#define			APIC_LVT_MASKED			(1<<16)
+#define			APIC_LVT_LEVEL_TRIGGER		(1<<15)
+#define			APIC_LVT_REMOTE_IRR		(1<<14)
+#define			APIC_INPUT_POLARITY		(1<<13)
+#define			APIC_SEND_PENDING		(1<<12)
+#define			GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7)
+#define			SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8))
+#define				APIC_MODE_FIXED		0x0
+#define				APIC_MODE_NMI		0x4
+#define				APIC_MODE_EXINT		0x7
+#define 	APIC_LVT1	0x360
+#define		APIC_LVTERR	0x370
+#define		APIC_TMICT	0x380
+#define		APIC_TMCCT	0x390
+#define		APIC_TDCR	0x3E0
+#define			APIC_TDR_DIV_TMBASE	(1<<2)
+#define			APIC_TDR_DIV_1		0xB
+#define			APIC_TDR_DIV_2		0x0
+#define			APIC_TDR_DIV_4		0x1
+#define			APIC_TDR_DIV_8		0x2
+#define			APIC_TDR_DIV_16		0x3
+#define			APIC_TDR_DIV_32		0x8
+#define			APIC_TDR_DIV_64		0x9
+#define			APIC_TDR_DIV_128	0xA
+
+#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
+
+#define MAX_IO_APICS 8
+
+/*
+ * the local APIC register structure, memory mapped. Not terribly well
+ * tested, but we might eventually use this one in the future - the
+ * problem why we cannot use it right now is the P5 APIC, it has an
+ * errata which cannot take 8-bit reads and writes, only 32-bit ones ...
+ */
+#define u32 unsigned int
+
+#define lapic ((volatile struct local_apic *)APIC_BASE)
+
+struct local_apic {
+
+/*000*/	struct { u32 __reserved[4]; } __reserved_01;
+
+/*010*/	struct { u32 __reserved[4]; } __reserved_02;
+
+/*020*/	struct { /* APIC ID Register */
+		u32   __reserved_1	: 24,
+			phys_apic_id	:  4,
+			__reserved_2	:  4;
+		u32 __reserved[3];
+	} id;
+
+/*030*/	const
+	struct { /* APIC Version Register */
+		u32   version		:  8,
+			__reserved_1	:  8,
+			max_lvt		:  8,
+			__reserved_2	:  8;
+		u32 __reserved[3];
+	} version;
+
+/*040*/	struct { u32 __reserved[4]; } __reserved_03;
+
+/*050*/	struct { u32 __reserved[4]; } __reserved_04;
+
+/*060*/	struct { u32 __reserved[4]; } __reserved_05;
+
+/*070*/	struct { u32 __reserved[4]; } __reserved_06;
+
+/*080*/	struct { /* Task Priority Register */
+		u32   priority	:  8,
+			__reserved_1	: 24;
+		u32 __reserved_2[3];
+	} tpr;
+
+/*090*/	const
+	struct { /* Arbitration Priority Register */
+		u32   priority	:  8,
+			__reserved_1	: 24;
+		u32 __reserved_2[3];
+	} apr;
+
+/*0A0*/	const
+	struct { /* Processor Priority Register */
+		u32   priority	:  8,
+			__reserved_1	: 24;
+		u32 __reserved_2[3];
+	} ppr;
+
+/*0B0*/	struct { /* End Of Interrupt Register */
+		u32   eoi;
+		u32 __reserved[3];
+	} eoi;
+
+/*0C0*/	struct { u32 __reserved[4]; } __reserved_07;
+
+/*0D0*/	struct { /* Logical Destination Register */
+		u32   __reserved_1	: 24,
+			logical_dest	:  8;
+		u32 __reserved_2[3];
+	} ldr;
+
+/*0E0*/	struct { /* Destination Format Register */
+		u32   __reserved_1	: 28,
+			model		:  4;
+		u32 __reserved_2[3];
+	} dfr;
+
+/*0F0*/	struct { /* Spurious Interrupt Vector Register */
+		u32	spurious_vector	:  8,
+			apic_enabled	:  1,
+			focus_cpu	:  1,
+			__reserved_2	: 22;
+		u32 __reserved_3[3];
+	} svr;
+
+/*100*/	struct { /* In Service Register */
+/*170*/		u32 bitfield;
+		u32 __reserved[3];
+	} isr [8];
+
+/*180*/	struct { /* Trigger Mode Register */
+/*1F0*/		u32 bitfield;
+		u32 __reserved[3];
+	} tmr [8];
+
+/*200*/	struct { /* Interrupt Request Register */
+/*270*/		u32 bitfield;
+		u32 __reserved[3];
+	} irr [8];
+
+/*280*/	union { /* Error Status Register */
+		struct {
+			u32   send_cs_error			:  1,
+				receive_cs_error		:  1,
+				send_accept_error		:  1,
+				receive_accept_error		:  1,
+				__reserved_1			:  1,
+				send_illegal_vector		:  1,
+				receive_illegal_vector		:  1,
+				illegal_register_address	:  1,
+				__reserved_2			: 24;
+			u32 __reserved_3[3];
+		} error_bits;
+		struct {
+			u32 errors;
+			u32 __reserved_3[3];
+		} all_errors;
+	} esr;
+
+/*290*/	struct { u32 __reserved[4]; } __reserved_08;
+
+/*2A0*/	struct { u32 __reserved[4]; } __reserved_09;
+
+/*2B0*/	struct { u32 __reserved[4]; } __reserved_10;
+
+/*2C0*/	struct { u32 __reserved[4]; } __reserved_11;
+
+/*2D0*/	struct { u32 __reserved[4]; } __reserved_12;
+
+/*2E0*/	struct { u32 __reserved[4]; } __reserved_13;
+
+/*2F0*/	struct { u32 __reserved[4]; } __reserved_14;
+
+/*300*/	struct { /* Interrupt Command Register 1 */
+		u32   vector			:  8,
+			delivery_mode		:  3,
+			destination_mode	:  1,
+			delivery_status		:  1,
+			__reserved_1		:  1,
+			level			:  1,
+			trigger			:  1,
+			__reserved_2		:  2,
+			shorthand		:  2,
+			__reserved_3		:  12;
+		u32 __reserved_4[3];
+	} icr1;
+
+/*310*/	struct { /* Interrupt Command Register 2 */
+		union {
+			u32   __reserved_1	: 24,
+				phys_dest	:  4,
+				__reserved_2	:  4;
+			u32   __reserved_3	: 24,
+				logical_dest	:  8;
+		} dest;
+		u32 __reserved_4[3];
+	} icr2;
+
+/*320*/	struct { /* LVT - Timer */
+		u32   vector		:  8,
+			__reserved_1	:  4,
+			delivery_status	:  1,
+			__reserved_2	:  3,
+			mask		:  1,
+			timer_mode	:  1,
+			__reserved_3	: 14;
+		u32 __reserved_4[3];
+	} lvt_timer;
+
+/*330*/	struct { u32 __reserved[4]; } __reserved_15;
+
+/*340*/	struct { /* LVT - Performance Counter */
+		u32   vector		:  8,
+			delivery_mode	:  3,
+			__reserved_1	:  1,
+			delivery_status	:  1,
+			__reserved_2	:  3,
+			mask		:  1,
+			__reserved_3	: 15;
+		u32 __reserved_4[3];
+	} lvt_pc;
+
+/*350*/	struct { /* LVT - LINT0 */
+		u32   vector		:  8,
+			delivery_mode	:  3,
+			__reserved_1	:  1,
+			delivery_status	:  1,
+			polarity	:  1,
+			remote_irr	:  1,
+			trigger		:  1,
+			mask		:  1,
+			__reserved_2	: 15;
+		u32 __reserved_3[3];
+	} lvt_lint0;
+
+/*360*/	struct { /* LVT - LINT1 */
+		u32   vector		:  8,
+			delivery_mode	:  3,
+			__reserved_1	:  1,
+			delivery_status	:  1,
+			polarity	:  1,
+			remote_irr	:  1,
+			trigger		:  1,
+			mask		:  1,
+			__reserved_2	: 15;
+		u32 __reserved_3[3];
+	} lvt_lint1;
+
+/*370*/	struct { /* LVT - Error */
+		u32   vector		:  8,
+			__reserved_1	:  4,
+			delivery_status	:  1,
+			__reserved_2	:  3,
+			mask		:  1,
+			__reserved_3	: 15;
+		u32 __reserved_4[3];
+	} lvt_error;
+
+/*380*/	struct { /* Timer Initial Count Register */
+		u32   initial_count;
+		u32 __reserved_2[3];
+	} timer_icr;
+
+/*390*/	const
+	struct { /* Timer Current Count Register */
+		u32   curr_count;
+		u32 __reserved_2[3];
+	} timer_ccr;
+
+/*3A0*/	struct { u32 __reserved[4]; } __reserved_16;
+
+/*3B0*/	struct { u32 __reserved[4]; } __reserved_17;
+
+/*3C0*/	struct { u32 __reserved[4]; } __reserved_18;
+
+/*3D0*/	struct { u32 __reserved[4]; } __reserved_19;
+
+/*3E0*/	struct { /* Timer Divide Configuration Register */
+		u32   divisor		:  4,
+			__reserved_1	: 28;
+		u32 __reserved_2[3];
+	} timer_dcr;
+
+/*3F0*/	struct { u32 __reserved[4]; } __reserved_20;
+
+} __attribute__ ((packed));
+
+#undef u32
+
+#endif
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/bugs.h linux/include/asm-i386/bugs.h
--- v2.3.39/linux/include/asm-i386/bugs.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-i386/bugs.h	Thu Jan 20 16:05:26 2000
@@ -398,8 +398,16 @@
  * If we configured ourselves for a TSC, we'd better have one!
  */
 #ifdef CONFIG_X86_TSC
-	if (!(boot_cpu_data.x86_capability & X86_FEATURE_TSC))
-		panic("Kernel compiled for Pentium+, requires TSC");
+	if (!cpu_has_tsc)
+		panic("Kernel compiled for Pentium+, requires TSC feature!");
+#endif
+
+/*
+ * If we configured ourselves for PGE, we'd better have it.
+ */
+#ifdef CONFIG_X86_PGE
+	if (!cpu_has_pge)
+		panic("Kernel compiled for PPro+, requires PGE feature!");
 #endif
 
 /*
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/fixmap.h linux/include/asm-i386/fixmap.h
--- v2.3.39/linux/include/asm-i386/fixmap.h	Fri Oct 22 13:21:53 1999
+++ linux/include/asm-i386/fixmap.h	Thu Jan 20 16:05:28 2000
@@ -15,7 +15,7 @@
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <asm/apic.h>
+#include <asm/apicdef.h>
 #include <asm/page.h>
 #ifdef CONFIG_HIGHMEM
 #include <linux/threads.h>
@@ -68,8 +68,16 @@
 	__end_of_fixed_addresses
 };
 
-extern void set_fixmap (enum fixed_addresses idx, unsigned long phys);
+extern void __set_fixmap (enum fixed_addresses idx,
+					unsigned long phys, pgprot_t flags);
 
+#define set_fixmap(idx, phys) \
+		__set_fixmap(idx, phys, PAGE_KERNEL)
+/*
+ * Some hardware wants to get fixmapped without caching.
+ */
+#define set_fixmap_nocache(idx, phys) \
+		__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
 /*
  * used by vmalloc.c.
  *
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h
--- v2.3.39/linux/include/asm-i386/hardirq.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-i386/hardirq.h	Thu Jan 20 16:05:30 2000
@@ -25,6 +25,7 @@
 #else
 
 #include <asm/atomic.h>
+#include <asm/smp.h>
 
 extern unsigned char global_irq_holder;
 extern unsigned volatile int global_irq_lock;
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/hw_irq.h linux/include/asm-i386/hw_irq.h
--- v2.3.39/linux/include/asm-i386/hw_irq.h	Mon Dec 20 18:48:22 1999
+++ linux/include/asm-i386/hw_irq.h	Thu Jan 20 16:07:57 2000
@@ -89,26 +89,8 @@
 
 extern char _stext, _etext;
 
-#define MAX_IRQ_SOURCES 128
-#define MAX_MP_BUSSES 32
-enum mp_bustype {
-	MP_BUS_ISA,
-	MP_BUS_EISA,
-	MP_BUS_PCI
-};
-extern int mp_bus_id_to_type [MAX_MP_BUSSES];
-extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
-
-
-#ifdef __SMP__
 #define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs))
 
-#else
-
-#define IO_APIC_IRQ(x)	(0)
-
-#endif
-
 #define __STR(x) #x
 #define STR(x) __STR(x)
 
@@ -134,8 +116,6 @@
 	"movl %esp, %ebx\n\t" \
 	"andl $-8192, %ebx\n\t"
 
-#ifdef __SMP__
-
 /*
  *	SMP has a few special interrupts for IPI messages
  */
@@ -170,8 +150,6 @@
 	"call "SYMBOL_NAME_STR(smp_##x)"\n\t" \
 	"addl $4,%esp\n\t" \
 	"jmp ret_from_intr\n");
-
-#endif /* __SMP__ */
 
 #define BUILD_COMMON_IRQ() \
 asmlinkage void call_do_IRQ(void); \
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/io_apic.h linux/include/asm-i386/io_apic.h
--- v2.3.39/linux/include/asm-i386/io_apic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/io_apic.h	Thu Jan 20 09:51:42 2000
@@ -0,0 +1,134 @@
+#ifndef __ASM_IO_APIC_H
+#define __ASM_IO_APIC_H
+
+#include <asm/types.h>
+
+/*
+ * Intel IO-APIC support for SMP and UP systems.
+ *
+ * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar
+ */
+
+#define IO_APIC_BASE(idx) \
+		((volatile int *)__fix_to_virt(FIX_IO_APIC_BASE_0 + idx))
+
+/*
+ * The structure of the IO-APIC:
+ */
+struct IO_APIC_reg_00 {
+	__u32	__reserved_2	: 24,
+		ID		:  4,
+		__reserved_1	:  4;
+} __attribute__ ((packed));
+
+struct IO_APIC_reg_01 {
+	__u32	version		:  8,
+		__reserved_2	:  8,
+		entries		:  8,
+		__reserved_1	:  8;
+} __attribute__ ((packed));
+
+struct IO_APIC_reg_02 {
+	__u32	__reserved_2	: 24,
+		arbitration	:  4,
+		__reserved_1	:  4;
+} __attribute__ ((packed));
+
+/*
+ * # of IO-APICs and # of IRQ routing registers
+ */
+extern int nr_ioapics;
+extern int nr_ioapic_registers[MAX_IO_APICS];
+
+enum ioapic_irq_destination_types {
+	dest_Fixed = 0,
+	dest_LowestPrio = 1,
+	dest_SMI = 2,
+	dest__reserved_1 = 3,
+	dest_NMI = 4,
+	dest_INIT = 5,
+	dest__reserved_2 = 6,
+	dest_ExtINT = 7
+};
+
+struct IO_APIC_route_entry {
+	__u32	vector		:  8,
+		delivery_mode	:  3,	/* 000: FIXED
+					 * 001: lowest prio
+					 * 111: ExtINT
+					 */
+		dest_mode	:  1,	/* 0: physical, 1: logical */
+		delivery_status	:  1,
+		polarity	:  1,
+		irr		:  1,
+		trigger		:  1,	/* 0: edge, 1: level */
+		mask		:  1,	/* 0: enabled, 1: disabled */
+		__reserved_2	: 15;
+
+	union {		struct { __u32
+					__reserved_1	: 24,
+					physical_dest	:  4,
+					__reserved_2	:  4;
+			} physical;
+
+			struct { __u32
+					__reserved_1	: 24,
+					logical_dest	:  8;
+			} logical;
+	} dest;
+
+} __attribute__ ((packed));
+
+/*
+ * MP-BIOS irq configuration table structures:
+ */
+
+/* I/O APIC entries */
+extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS];
+
+/* # of MP IRQ source entries */
+extern int mp_irq_entries;
+
+/* MP IRQ source entries */
+extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
+
+/* non-0 if default (table-less) MP configuration */
+extern int mpc_default_type;
+
+static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
+{
+	*IO_APIC_BASE(apic) = reg;
+	return *(IO_APIC_BASE(apic)+4);
+}
+
+static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
+{
+	*IO_APIC_BASE(apic) = reg;
+	*(IO_APIC_BASE(apic)+4) = value;
+}
+
+/*
+ * Re-write a value: to be used for read-modify-write
+ * cycles where the read already set up the index register.
+ */
+static inline void io_apic_modify(unsigned int apic, unsigned int value)
+{
+	*(IO_APIC_BASE(apic)+4) = value;
+}
+
+/*
+ * Synchronize the IO-APIC and the CPU by doing
+ * a dummy read from the IO-APIC
+ */
+static inline void io_apic_sync(unsigned int apic)
+{
+	(void) *(IO_APIC_BASE(apic)+4);
+}
+
+extern int nmi_watchdog;
+/* 1 if "noapic" boot option passed */
+extern int skip_ioapic_setup;
+extern void IO_APIC_init_uniprocessor (void);
+
+#endif
+
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/mpspec.h linux/include/asm-i386/mpspec.h
--- v2.3.39/linux/include/asm-i386/mpspec.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/mpspec.h	Thu Jan 20 09:51:42 2000
@@ -0,0 +1,168 @@
+#ifndef __ASM_MPSPEC_H
+#define __ASM_MPSPEC_H
+
+/*
+ * Structure definitions for SMP machines following the
+ * Intel Multiprocessing Specification 1.1 and 1.4.
+ */
+
+/*
+ * This tag identifies where the SMP configuration
+ * information is. 
+ */
+ 
+#define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_')
+
+struct intel_mp_floating
+{
+	char mpf_signature[4];		/* "_MP_" 			*/
+	unsigned long mpf_physptr;	/* Configuration table address	*/
+	unsigned char mpf_length;	/* Our length (paragraphs)	*/
+	unsigned char mpf_specification;/* Specification version	*/
+	unsigned char mpf_checksum;	/* Checksum (makes sum 0)	*/
+	unsigned char mpf_feature1;	/* Standard or configuration ? 	*/
+	unsigned char mpf_feature2;	/* Bit7 set for IMCR|PIC	*/
+	unsigned char mpf_feature3;	/* Unused (0)			*/
+	unsigned char mpf_feature4;	/* Unused (0)			*/
+	unsigned char mpf_feature5;	/* Unused (0)			*/
+};
+
+struct mp_config_table
+{
+	char mpc_signature[4];
+#define MPC_SIGNATURE "PCMP"
+	unsigned short mpc_length;	/* Size of table */
+	char  mpc_spec;			/* 0x01 */
+	char  mpc_checksum;
+	char  mpc_oem[8];
+	char  mpc_productid[12];
+	unsigned long mpc_oemptr;	/* 0 if not present */
+	unsigned short mpc_oemsize;	/* 0 if not present */
+	unsigned short mpc_oemcount;
+	unsigned long mpc_lapic;	/* APIC address */
+	unsigned long reserved;
+};
+
+/* Followed by entries */
+
+#define	MP_PROCESSOR	0
+#define	MP_BUS		1
+#define	MP_IOAPIC	2
+#define	MP_INTSRC	3
+#define	MP_LINTSRC	4
+
+struct mpc_config_processor
+{
+	unsigned char mpc_type;
+	unsigned char mpc_apicid;	/* Local APIC number */
+	unsigned char mpc_apicver;	/* Its versions */
+	unsigned char mpc_cpuflag;
+#define CPU_ENABLED		1	/* Processor is available */
+#define CPU_BOOTPROCESSOR	2	/* Processor is the BP */
+	unsigned long mpc_cpufeature;		
+#define CPU_STEPPING_MASK 0x0F
+#define CPU_MODEL_MASK	0xF0
+#define CPU_FAMILY_MASK	0xF00
+	unsigned long mpc_featureflag;	/* CPUID feature value */
+	unsigned long mpc_reserved[2];
+};
+
+struct mpc_config_bus
+{
+	unsigned char mpc_type;
+	unsigned char mpc_busid;
+	unsigned char mpc_bustype[6] __attribute((packed));
+};
+
+#define BUSTYPE_EISA	"EISA"
+#define BUSTYPE_ISA	"ISA"
+#define BUSTYPE_INTERN	"INTERN"	/* Internal BUS */
+#define BUSTYPE_MCA	"MCA"
+#define BUSTYPE_VL	"VL"		/* Local bus */
+#define BUSTYPE_PCI	"PCI"
+#define BUSTYPE_PCMCIA	"PCMCIA"
+
+struct mpc_config_ioapic
+{
+	unsigned char mpc_type;
+	unsigned char mpc_apicid;
+	unsigned char mpc_apicver;
+	unsigned char mpc_flags;
+#define MPC_APIC_USABLE		0x01
+	unsigned long mpc_apicaddr;
+};
+
+struct mpc_config_intsrc
+{
+	unsigned char mpc_type;
+	unsigned char mpc_irqtype;
+	unsigned short mpc_irqflag;
+	unsigned char mpc_srcbus;
+	unsigned char mpc_srcbusirq;
+	unsigned char mpc_dstapic;
+	unsigned char mpc_dstirq;
+};
+
+enum mp_irq_source_types {
+	mp_INT = 0,
+	mp_NMI = 1,
+	mp_SMI = 2,
+	mp_ExtINT = 3
+};
+
+#define MP_IRQDIR_DEFAULT	0
+#define MP_IRQDIR_HIGH		1
+#define MP_IRQDIR_LOW		3
+
+
+struct mpc_config_lintsrc
+{
+	unsigned char mpc_type;
+	unsigned char mpc_irqtype;
+	unsigned short mpc_irqflag;
+	unsigned char mpc_srcbusid;
+	unsigned char mpc_srcbusirq;
+	unsigned char mpc_destapic;	
+#define MP_APIC_ALL	0xFF
+	unsigned char mpc_destapiclint;
+};
+
+/*
+ *	Default configurations
+ *
+ *	1	2 CPU ISA 82489DX
+ *	2	2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining
+ *	3	2 CPU EISA 82489DX
+ *	4	2 CPU MCA 82489DX
+ *	5	2 CPU ISA+PCI
+ *	6	2 CPU EISA+PCI
+ *	7	2 CPU MCA+PCI
+ */
+
+#define MAX_IRQ_SOURCES 128
+#define MAX_MP_BUSSES 32
+enum mp_bustype {
+	MP_BUS_ISA,
+	MP_BUS_EISA,
+	MP_BUS_PCI
+};
+extern int mp_bus_id_to_type [MAX_MP_BUSSES];
+extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
+
+extern unsigned int boot_cpu_id;
+extern unsigned long phys_cpu_present_map;
+extern int smp_found_config;
+extern void init_smp_config(void);
+extern int nr_ioapics;
+extern int apic_version [NR_CPUS];
+extern int mp_bus_id_to_type [MAX_MP_BUSSES];
+extern int mp_irq_entries;
+extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
+extern int mpc_default_type;
+extern int mp_bus_id_to_pci_bus [MAX_MP_BUSSES];
+extern int mp_current_pci_id;
+extern unsigned long mp_lapic_addr;
+extern int pic_mode;
+
+#endif
+
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/pci.h linux/include/asm-i386/pci.h
--- v2.3.39/linux/include/asm-i386/pci.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-i386/pci.h	Tue Jan 11 14:22:31 2000
@@ -7,5 +7,8 @@
 
 #define pcibios_assign_all_busses()	0
 
+#define PCIBIOS_MIN_IO		0x1000
+#define PCIBIOS_MIN_MEM		0x10000000
+
 #endif /* __i386_PCI_H */
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/pgalloc.h linux/include/asm-i386/pgalloc.h
--- v2.3.39/linux/include/asm-i386/pgalloc.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-i386/pgalloc.h	Thu Jan 20 16:05:31 2000
@@ -195,7 +195,7 @@
 #ifndef __SMP__
 
 #define flush_tlb() __flush_tlb()
-#define flush_tlb_all() __flush_tlb()
+#define flush_tlb_all() __flush_tlb_all()
 #define local_flush_tlb() __flush_tlb()
 
 static inline void flush_tlb_mm(struct mm_struct *mm)
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/pgtable.h linux/include/asm-i386/pgtable.h
--- v2.3.39/linux/include/asm-i386/pgtable.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-i386/pgtable.h	Thu Jan 20 16:05:30 2000
@@ -27,8 +27,49 @@
 #define flush_page_to_ram(page)			do { } while (0)
 #define flush_icache_range(start, end)		do { } while (0)
 
-#define __flush_tlb() \
-do { unsigned long tmpreg; __asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3":"=r" (tmpreg) : :"memory"); } while (0)
+#define __flush_tlb()							\
+	do {								\
+		__asm__ __volatile__					\
+			("movl %0, %%cr3;"				\
+				:					\
+				: "r" __pa(current->active_mm->pgd)	\
+				: "memory"				\
+		);							\
+	} while (0)
+
+/*
+ * Global pages have to be flushed a bit differently. Not a real
+ * performance problem because this does not happen often.
+ */
+#define __flush_tlb_global()						\
+	do {								\
+		__asm__ __volatile__(					\
+			"movl %0, %%cr4; # turn off PGE \n"		\
+			"mov %2, %%cr3;  # flush TLB \n"		\
+			"mov %1, %%cr4;  # turn PGE back on \n"		\
+			:						\
+			: "r" (mmu_cr4_features),			\
+			  "r" (mmu_cr4_features & ~X86_CR4_PGE),	\
+			  "r" (__pa(current->active_mm->pgd))		\
+			: "memory");					\
+	} while (0)
+
+extern unsigned long pgkern_mask;
+
+/*
+ * Do not check the PGE bit unnecesserily if this is a PPro+ kernel.
+ */
+#ifdef CONFIG_X86_PGE
+# define __flush_tlb_all() __flush_tlb_global()
+#else
+# define __flush_tlb_all()						\
+	do {								\
+		if (cpu_has_pge)					\
+			__flush_tlb_global();				\
+		else							\
+			__flush_tlb();					\
+	} while (0)
+#endif
 
 #ifndef CONFIG_X86_INVLPG
 #define __flush_tlb_one(addr) __flush_tlb()
@@ -116,12 +157,37 @@
 #define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
-#define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
-#define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED)
+
+#define __PAGE_KERNEL \
+	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+#define __PAGE_KERNEL_NOCACHE \
+	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED)
+#define __PAGE_KERNEL_RO \
+	(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED)
+
+#ifdef CONFIG_X86_PGE
+# define MAKE_GLOBAL(x) __pgprot((x) | _PAGE_GLOBAL)
+#else
+# define MAKE_GLOBAL(x)						\
+	({							\
+		pgprot_t __ret;					\
+								\
+		if (cpu_has_pge)				\
+			__ret = __pgprot((x) | _PAGE_GLOBAL);	\
+		else						\
+			__ret = __pgprot(x);			\
+		__ret;						\
+	})
+#endif
+
+#define PAGE_KERNEL MAKE_GLOBAL(__PAGE_KERNEL)
+#define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO)
+#define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
 
 /*
- * The i386 can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
+ * The i386 can't do page protection for execute, and considers that
+ * the same are read. Also, write permissions imply read permissions.
+ * This is the closest we can get..
  */
 #define __P000	PAGE_NONE
 #define __P001	PAGE_READONLY
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/posix_types.h linux/include/asm-i386/posix_types.h
--- v2.3.39/linux/include/asm-i386/posix_types.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-i386/posix_types.h	Mon Jan 17 22:22:52 2000
@@ -29,11 +29,8 @@
 typedef unsigned int	__kernel_uid32_t;
 typedef unsigned int	__kernel_gid32_t;
 
-#ifdef __KERNEL__
-#define UID16_COMPAT_NEEDED
 typedef unsigned short	__kernel_old_uid_t;
 typedef unsigned short	__kernel_old_gid_t;
-#endif /* __KERNEL__ */
 
 #ifdef __GNUC__
 typedef long long	__kernel_loff_t;
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/processor.h linux/include/asm-i386/processor.h
--- v2.3.39/linux/include/asm-i386/processor.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-i386/processor.h	Thu Jan 20 16:05:28 2000
@@ -115,7 +115,7 @@
 #define cpu_has_pae \
 		(boot_cpu_data.x86_capability & X86_FEATURE_PAE)
 #define cpu_has_tsc \
-		(cpu_data[smp_processor_id()].x86_capability & X86_FEATURE_TSC)
+		(boot_cpu_data.x86_capability & X86_FEATURE_TSC)
 
 extern char ignore_irq13;
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v2.3.39/linux/include/asm-i386/smp.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-i386/smp.h	Thu Jan 20 16:05:30 2000
@@ -4,228 +4,64 @@
 /*
  * We need the APIC definitions automatically as part of 'smp.h'
  */
+#ifndef ASSEMBLY
 #include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/ptrace.h>
+#endif
+
 #ifdef CONFIG_X86_LOCAL_APIC
 #ifndef ASSEMBLY
 #include <asm/fixmap.h>
-#include <asm/apic.h>
 #include <asm/bitops.h>
+#include <asm/mpspec.h>
+#include <asm/io_apic.h>
+#include <asm/apic.h>
 #endif
 #endif
 
-#ifdef __SMP__
+#ifdef CONFIG_SMP
 #ifndef ASSEMBLY
 
-#include <linux/threads.h>
-#include <linux/ptrace.h>
-
 /*
- *	Support definitions for SMP machines following the intel multiprocessing
- *	specification
- */
-
-/*
- *	This tag identifies where the SMP configuration
- *	information is. 
+ * Private routines/data
  */
  
-#define SMP_MAGIC_IDENT	(('_'<<24)|('P'<<16)|('M'<<8)|'_')
-
-struct intel_mp_floating
-{
-	char mpf_signature[4];		/* "_MP_" 			*/
-	unsigned long mpf_physptr;	/* Configuration table address	*/
-	unsigned char mpf_length;	/* Our length (paragraphs)	*/
-	unsigned char mpf_specification;/* Specification version	*/
-	unsigned char mpf_checksum;	/* Checksum (makes sum 0)	*/
-	unsigned char mpf_feature1;	/* Standard or configuration ? 	*/
-	unsigned char mpf_feature2;	/* Bit7 set for IMCR|PIC	*/
-	unsigned char mpf_feature3;	/* Unused (0)			*/
-	unsigned char mpf_feature4;	/* Unused (0)			*/
-	unsigned char mpf_feature5;	/* Unused (0)			*/
-};
-
-struct mp_config_table
-{
-	char mpc_signature[4];
-#define MPC_SIGNATURE "PCMP"
-	unsigned short mpc_length;	/* Size of table */
-	char  mpc_spec;			/* 0x01 */
-	char  mpc_checksum;
-	char  mpc_oem[8];
-	char  mpc_productid[12];
-	unsigned long mpc_oemptr;	/* 0 if not present */
-	unsigned short mpc_oemsize;	/* 0 if not present */
-	unsigned short mpc_oemcount;
-	unsigned long mpc_lapic;	/* APIC address */
-	unsigned long reserved;
-};
-
-/* Followed by entries */
-
-#define	MP_PROCESSOR	0
-#define	MP_BUS		1
-#define	MP_IOAPIC	2
-#define	MP_INTSRC	3
-#define	MP_LINTSRC	4
-
-struct mpc_config_processor
-{
-	unsigned char mpc_type;
-	unsigned char mpc_apicid;	/* Local APIC number */
-	unsigned char mpc_apicver;	/* Its versions */
-	unsigned char mpc_cpuflag;
-#define CPU_ENABLED		1	/* Processor is available */
-#define CPU_BOOTPROCESSOR	2	/* Processor is the BP */
-	unsigned long mpc_cpufeature;		
-#define CPU_STEPPING_MASK 0x0F
-#define CPU_MODEL_MASK	0xF0
-#define CPU_FAMILY_MASK	0xF00
-	unsigned long mpc_featureflag;	/* CPUID feature value */
-	unsigned long mpc_reserved[2];
-};
-
-struct mpc_config_bus
-{
-	unsigned char mpc_type;
-	unsigned char mpc_busid;
-	unsigned char mpc_bustype[6] __attribute((packed));
-};
-
-#define BUSTYPE_EISA	"EISA"
-#define BUSTYPE_ISA	"ISA"
-#define BUSTYPE_INTERN	"INTERN"	/* Internal BUS */
-#define BUSTYPE_MCA	"MCA"
-#define BUSTYPE_VL	"VL"		/* Local bus */
-#define BUSTYPE_PCI	"PCI"
-#define BUSTYPE_PCMCIA	"PCMCIA"
-
-/* We don't understand the others */
-
-struct mpc_config_ioapic
-{
-	unsigned char mpc_type;
-	unsigned char mpc_apicid;
-	unsigned char mpc_apicver;
-	unsigned char mpc_flags;
-#define MPC_APIC_USABLE		0x01
-	unsigned long mpc_apicaddr;
-};
-
-struct mpc_config_intsrc
-{
-	unsigned char mpc_type;
-	unsigned char mpc_irqtype;
-	unsigned short mpc_irqflag;
-	unsigned char mpc_srcbus;
-	unsigned char mpc_srcbusirq;
-	unsigned char mpc_dstapic;
-	unsigned char mpc_dstirq;
-};
-
-enum mp_irq_source_types {
-	mp_INT = 0,
-	mp_NMI = 1,
-	mp_SMI = 2,
-	mp_ExtINT = 3
-};
-
-#define MP_IRQDIR_DEFAULT	0
-#define MP_IRQDIR_HIGH		1
-#define MP_IRQDIR_LOW		3
-
-
-struct mpc_config_lintsrc
-{
-	unsigned char mpc_type;
-	unsigned char mpc_irqtype;
-	unsigned short mpc_irqflag;
-	unsigned char mpc_srcbusid;
-	unsigned char mpc_srcbusirq;
-	unsigned char mpc_destapic;	
-#define MP_APIC_ALL	0xFF
-	unsigned char mpc_destapiclint;
-};
-
-
-/*
- *	Default configurations
- *
- *	1	2 CPU ISA 82489DX
- *	2	2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining
- *	3	2 CPU EISA 82489DX
- *	4	2 CPU MCA 82489DX
- *	5	2 CPU ISA+PCI
- *	6	2 CPU EISA+PCI
- *	7	2 CPU MCA+PCI
- */
-
-/*
- *	Private routines/data
- */
- 
-extern int smp_found_config;
-extern void init_smp_config(void);
-extern void init_smp_mappings(void);
 extern void smp_alloc_memory(void);
-extern unsigned long cpu_present_map;
+extern unsigned long phys_cpu_present_map;
 extern unsigned long cpu_online_map;
 extern volatile unsigned long smp_invalidate_needed;
 extern int pic_mode;
 extern void smp_flush_tlb(void);
-extern int get_maxlvt(void);
-extern void disable_local_APIC (void);
 extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
 extern void smp_send_reschedule(int cpu);
 extern void smp_invalidate_rcv(void);		/* Process an NMI */
-extern void smp_local_timer_interrupt(struct pt_regs * regs);
 extern void (*mtrr_hook) (void);
-extern void setup_APIC_clocks(void);
 extern void zap_low_mappings (void);
-extern volatile int cpu_number_map[NR_CPUS];
-extern volatile int __cpu_logical_map[NR_CPUS];
-extern inline int cpu_logical_map(int cpu)
-{
-	return __cpu_logical_map[cpu];
-}
 
-extern __inline void apic_write(unsigned long reg, unsigned long v)
+/*
+ * On x86 all CPUs are mapped 1:1 to the APIC space.
+ * This simplifies scheduling and IPI sending and
+ * compresses data structures.
+ */
+extern inline int cpu_logical_map(int cpu)
 {
-	*((volatile unsigned long *)(APIC_BASE+reg))=v;
+	return cpu;
 }
-
-extern __inline unsigned long apic_read(unsigned long reg)
+extern inline int cpu_number_map(int cpu)
 {
-	return *((volatile unsigned long *)(APIC_BASE+reg));
+	return cpu;
 }
 
-extern unsigned int apic_timer_irqs [NR_CPUS];
-
-#ifdef CONFIG_X86_GOOD_APIC
-# define FORCE_READ_AROUND_WRITE 0
-# define apic_readaround(x)
-#else
-# define FORCE_READ_AROUND_WRITE 1
-# define apic_readaround(x) apic_read(x)
-#endif
-
-#define apic_write_around(x,y) \
-		do { apic_readaround(x); apic_write(x,y); } while (0)
-
-extern inline void ack_APIC_irq(void)
-{
-        /* Clear the IPI */
-
-	apic_readaround(APIC_EOI);
-	/*
-	 * on P6+ cores (CONFIG_X86_GOOD_APIC) ack_APIC_irq() actually
-	 * gets compiled as a single instruction ... yummie.
-	 */
-        apic_write(APIC_EOI, 0); /* Docs say use 0 for future compatibility */
-}
+/*
+ * Some lowlevel functions might want to know about
+ * the real APIC ID <-> CPU # mapping.
+ */
+extern volatile int x86_apicid_to_cpu[NR_CPUS];
+extern volatile int x86_cpu_to_apicid[NR_CPUS];
 
 /*
- *	General functions that each host system must provide.
+ * General functions that each host system must provide.
  */
  
 extern void smp_boot_cpus(void);
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/smplock.h linux/include/asm-i386/smplock.h
--- v2.3.39/linux/include/asm-i386/smplock.h	Tue Dec  7 09:32:49 1999
+++ linux/include/asm-i386/smplock.h	Thu Jan 20 16:05:52 2000
@@ -5,6 +5,8 @@
  */
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/sched.h>
+#include <asm/current.h>
 
 extern spinlock_t kernel_flag;
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-i386/spinlock.h linux/include/asm-i386/spinlock.h
--- v2.3.39/linux/include/asm-i386/spinlock.h	Tue Dec 14 01:27:24 1999
+++ linux/include/asm-i386/spinlock.h	Thu Jan 20 16:05:28 2000
@@ -96,7 +96,7 @@
 		:"=m" (__dummy_lock(lock)));
 }
 
-#define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
+#define spin_trylock(lock) ({ !test_and_set_bit(0,(lock)); })
 
 /*
  * Read-write spinlocks, allowing multiple readers
diff -u --recursive --new-file v2.3.39/linux/include/asm-m68k/posix_types.h linux/include/asm-m68k/posix_types.h
--- v2.3.39/linux/include/asm-m68k/posix_types.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-m68k/posix_types.h	Sat Jan 15 22:08:28 2000
@@ -29,11 +29,8 @@
 typedef unsigned int	__kernel_uid32_t;
 typedef unsigned int	__kernel_gid32_t;
 
-#ifdef __KERNEL__
-#define UID16_COMPAT_NEEDED
 typedef unsigned short	__kernel_old_uid_t;
 typedef unsigned short	__kernel_old_gid_t;
-#endif /* __KERNEL__ */
 
 #ifdef __GNUC__
 typedef long long	__kernel_loff_t;
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- v2.3.39/linux/include/asm-ppc/io.h	Tue Dec  7 09:32:51 1999
+++ linux/include/asm-ppc/io.h	Thu Jan 20 09:55:23 2000
@@ -100,7 +100,7 @@
 extern void _insl_ns(volatile unsigned long *port, void *buf, int nl);
 extern void _outsl_ns(volatile unsigned long *port, const void *buf, int nl);
 
-#define IO_SPACE_LIMIT 0xffff
+#define IO_SPACE_LIMIT ~0
 
 #define memset_io(a,b,c)	memset((a),(b),(c))
 #define memcpy_fromio(a,b,c)	memcpy((a),(b),(c))
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/ipcbuf.h linux/include/asm-ppc/ipcbuf.h
--- v2.3.39/linux/include/asm-ppc/ipcbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/ipcbuf.h	Sat Jan 15 22:08:29 2000
@@ -0,0 +1,11 @@
+#ifndef __PPC_IPCBUF_H__
+#define __PPC_IPCBUF_H__
+
+/*
+ * The ipc64_perm structure for the PPC is identical to kern_ipc_perm
+ * as we have always had 32-bit UIDs and GIDs in the kernel.
+ */
+
+#define ipc64_perm	kern_ipc_perm
+
+#endif /* __PPC_IPCBUF_H__ */
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/msgbuf.h linux/include/asm-ppc/msgbuf.h
--- v2.3.39/linux/include/asm-ppc/msgbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/msgbuf.h	Sat Jan 15 22:08:29 2000
@@ -0,0 +1,26 @@
+#ifndef _PPC_MSGBUF_H
+#define _PPC_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for the PPC architecture.
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm msg_perm;
+	unsigned int	__unused0;
+	unsigned int	__unused1;
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	unsigned int	__unused2;
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	unsigned int	__unused3;
+	__kernel_time_t msg_ctime;	/* last change time */
+	unsigned long  msg_cbytes;	/* current number of bytes on queue */
+	unsigned long  msg_qnum;	/* number of messages in queue */
+	unsigned long  msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+#endif /* _PPC_MSGBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/pci.h linux/include/asm-ppc/pci.h
--- v2.3.39/linux/include/asm-ppc/pci.h	Fri Sep 10 23:57:37 1999
+++ linux/include/asm-ppc/pci.h	Thu Jan 13 18:03:58 2000
@@ -7,4 +7,7 @@
  */
 #define pcibios_assign_all_busses()	0
 
+#define PCIBIOS_MIN_IO		0x1000
+#define PCIBIOS_MIN_MEM		0x10000000
+
 #endif /* __PPC_PCI_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/posix_types.h linux/include/asm-ppc/posix_types.h
--- v2.3.39/linux/include/asm-ppc/posix_types.h	Thu Apr 29 12:39:01 1999
+++ linux/include/asm-ppc/posix_types.h	Sat Jan 15 22:08:29 2000
@@ -24,6 +24,13 @@
 typedef int		__kernel_daddr_t;
 typedef char *		__kernel_caddr_t;
 typedef short             __kernel_ipc_pid_t;
+typedef unsigned int	__kernel_uid16_t;
+typedef unsigned int	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+
+typedef unsigned int	__kernel_old_uid_t;
+typedef unsigned int	__kernel_old_gid_t;
 
 #ifdef __GNUC__
 typedef long long	__kernel_loff_t;
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- v2.3.39/linux/include/asm-ppc/processor.h	Tue Jan 11 22:31:44 2000
+++ linux/include/asm-ppc/processor.h	Thu Jan 13 18:03:58 2000
@@ -99,10 +99,10 @@
 #define	  DBCR_EDM	0x80000000
 #define	  DBCR_IDM	0x40000000
 #define	  DBCR_RST(x)	(((x) & 0x3) << 28)
-#define	    NONE       	0
-#define	    CORE       	1
-#define	    CHIP       	2
-#define	    SYSTEM	3
+#define	    DBCR_RST_NONE       	0
+#define	    DBCR_RST_CORE       	1
+#define	    DBCR_RST_CHIP       	2
+#define	    DBCR_RST_SYSTEM		3
 #define	  DBCR_IC	0x08000000	/* Instruction Completion Debug Evnt */
 #define	  DBCR_BT	0x04000000	/* Branch Taken Debug Event */
 #define	  DBCR_EDE	0x02000000	/* Exception Debug Event */
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/sembuf.h linux/include/asm-ppc/sembuf.h
--- v2.3.39/linux/include/asm-ppc/sembuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/sembuf.h	Sat Jan 15 22:08:29 2000
@@ -0,0 +1,20 @@
+#ifndef _PPC_SEMBUF_H
+#define _PPC_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for PPC architecture.
+ */
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+	unsigned int	__unused0;
+	unsigned int	__unused1;
+	__kernel_time_t	sem_otime;		/* last semop time */
+	unsigned int	__unused2;
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _PPC_SEMBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/shmbuf.h linux/include/asm-ppc/shmbuf.h
--- v2.3.39/linux/include/asm-ppc/shmbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/shmbuf.h	Sat Jan 15 22:08:29 2000
@@ -0,0 +1,37 @@
+#ifndef _PPC_SHMBUF_H
+#define _PPC_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for PPC architecture.
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	unsigned int		__unused0;
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	unsigned long		__unused1;
+	__kernel_time_t		shm_atime;	/* last attach time */
+	unsigned long		__unused2;
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	unsigned long		__unused3;
+	__kernel_time_t		shm_ctime;	/* last change time */
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused4;
+	unsigned long		__unused5;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _PPC_SHMBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-ppc/stat.h linux/include/asm-ppc/stat.h
--- v2.3.39/linux/include/asm-ppc/stat.h	Mon Dec 20 18:48:22 1999
+++ linux/include/asm-ppc/stat.h	Thu Jan 13 18:03:57 2000
@@ -38,39 +38,29 @@
 	unsigned long  	__unused5;
 };
 
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
+/* This matches struct stat64 in glibc2.1.
  */
 struct stat64 {
-	unsigned short	st_dev;
-	unsigned char	__pad0[10];
-
-	unsigned long	st_ino;
-	unsigned int	st_mode;
-	unsigned int	st_nlink;
-
-	unsigned long	st_uid;
-	unsigned long	st_gid;
-
-	unsigned short	st_rdev;
-	unsigned char	__pad3[10];
-
-	long long	st_size;
-	unsigned long	st_blksize;
-
-	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
-	unsigned long	__pad4;		/* future possible st_blocks high bits */
-
-	unsigned long	st_atime;
-	unsigned long	__pad5;
-
-	unsigned long	st_mtime;
-	unsigned long	__pad6;
-
-	unsigned long	st_ctime;
-	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
-
-	unsigned long	__unused1;
-	unsigned long	__unused2;
+	unsigned long long st_dev; 	/* Device.  */
+	unsigned short int __pad1;
+	unsigned long st_ino;		/* File serial number.  */
+	unsigned int st_mode;		/* File mode.  */
+	unsigned int st_nlink;		/* Link count.  */
+	unsigned int st_uid;		/* User ID of the file's owner.  */
+	unsigned int st_gid;		/* Group ID of the file's group. */
+	unsigned long long st_rdev; 	/* Device number, if device.  */
+	unsigned short int __pad2;
+	long long st_size;		/* Size of file, in bytes.  */
+	long st_blksize;		/* Optimal block size for I/O.  */
+
+	long long st_blocks;		/* Number 512-byte blocks allocated. */
+	long st_atime;			/* Time of last access.  */
+	unsigned long int __unused1;
+	long st_mtime;			/* Time of last modification.  */
+	unsigned long int __unused2;
+	long st_ctime;			/* Time of last status change.  */
+	unsigned long int __unused3;
+	unsigned long int __unused4;
+	unsigned long int __unused5;
 };
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/a.out.h linux/include/asm-sparc/a.out.h
--- v2.3.39/linux/include/asm-sparc/a.out.h	Tue Apr 14 17:44:23 1998
+++ linux/include/asm-sparc/a.out.h	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: a.out.h,v 1.12 1998/02/05 14:20:00 jj Exp $ */
+/* $Id: a.out.h,v 1.13 2000/01/09 10:46:53 anton Exp $ */
 #ifndef __SPARC_A_OUT_H__
 #define __SPARC_A_OUT_H__
 
@@ -89,30 +89,9 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
-#include <asm/btfixup.h>
+#include <asm/page.h>
 
-#ifdef CONFIG_SUN4
-
-#define STACK_TOP	(0xefffe000UL)
-
-#else
-
-extern unsigned long	stack_top;
-
-#  ifndef MODULE
-
-    BTFIXUPDEF_SETHI_INIT(stack_top,0xeffff000)
-
-#    define STACK_TOP	((unsigned long)BTFIXUP_SETHI(stack_top))
-
-#  else /* MODULE */
-
-#    define STACK_TOP	(stack_top)
-
-#  endif /* MODULE */
-
-#endif /* !CONFIG_SUN4 */
+#define STACK_TOP	(PAGE_OFFSET - PAGE_SIZE)
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/asm_offsets.h linux/include/asm-sparc/asm_offsets.h
--- v2.3.39/linux/include/asm-sparc/asm_offsets.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc/asm_offsets.h	Thu Jan 13 12:03:00 2000
@@ -18,168 +18,174 @@
 #define ASIZ_task_exec_domain	0x00000004
 #define AOFF_task_need_resched	0x00000014
 #define ASIZ_task_need_resched	0x00000004
-#define AOFF_task_counter	0x00000018
+#define AOFF_task_avg_slice	0x00000018
+#define ASIZ_task_avg_slice	0x00000004
+#define AOFF_task_lock_depth	0x0000001c
+#define ASIZ_task_lock_depth	0x00000004
+#define AOFF_task_counter	0x00000020
 #define ASIZ_task_counter	0x00000004
-#define AOFF_task_priority	0x0000001c
+#define AOFF_task_priority	0x00000024
 #define ASIZ_task_priority	0x00000004
-#define AOFF_task_avg_slice	0x00000020
-#define ASIZ_task_avg_slice	0x00000004
-#define AOFF_task_has_cpu	0x00000024
+#define AOFF_task_policy	0x00000028
+#define ASIZ_task_policy	0x00000004
+#define AOFF_task_mm	0x0000002c
+#define ASIZ_task_mm	0x00000004
+#define AOFF_task_active_mm	0x00000030
+#define ASIZ_task_active_mm	0x00000004
+#define AOFF_task_has_cpu	0x00000034
 #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x00000028
+#define AOFF_task_processor	0x00000038
 #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x0000002c
-#define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x00000030
-#define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_next_task	0x00000034
-#define ASIZ_task_next_task	0x00000004
-#define AOFF_task_prev_task	0x00000038
-#define ASIZ_task_prev_task	0x00000004
 #define AOFF_task_run_list	0x0000003c
 #define ASIZ_task_run_list	0x00000008
-#define AOFF_task_binfmt	0x00000044
+#define AOFF_task_next_task	0x00000044
+#define ASIZ_task_next_task	0x00000004
+#define AOFF_task_prev_task	0x00000048
+#define ASIZ_task_prev_task	0x00000004
+#define AOFF_task_last_processor	0x0000004c
+#define ASIZ_task_last_processor	0x00000004
+#define AOFF_task_binfmt	0x00000050
 #define ASIZ_task_binfmt	0x00000004
-#define AOFF_task_exit_code	0x00000048
+#define AOFF_task_exit_code	0x00000054
 #define ASIZ_task_exit_code	0x00000004
-#define AOFF_task_exit_signal	0x0000004c
+#define AOFF_task_exit_signal	0x00000058
 #define ASIZ_task_exit_signal	0x00000004
-#define AOFF_task_pdeath_signal	0x00000050
+#define AOFF_task_pdeath_signal	0x0000005c
 #define ASIZ_task_pdeath_signal	0x00000004
-#define AOFF_task_personality	0x00000054
+#define AOFF_task_personality	0x00000060
 #define ASIZ_task_personality	0x00000004
-#define AOFF_task_pid	0x0000005c
+#define AOFF_task_pid	0x00000068
 #define ASIZ_task_pid	0x00000004
-#define AOFF_task_pgrp	0x00000060
+#define AOFF_task_pgrp	0x0000006c
 #define ASIZ_task_pgrp	0x00000004
-#define AOFF_task_tty_old_pgrp	0x00000064
+#define AOFF_task_tty_old_pgrp	0x00000070
 #define ASIZ_task_tty_old_pgrp	0x00000004
-#define AOFF_task_session	0x00000068
+#define AOFF_task_session	0x00000074
 #define ASIZ_task_session	0x00000004
-#define AOFF_task_leader	0x0000006c
+#define AOFF_task_leader	0x00000078
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_p_opptr	0x00000070
+#define AOFF_task_p_opptr	0x0000007c
 #define ASIZ_task_p_opptr	0x00000004
-#define AOFF_task_p_pptr	0x00000074
+#define AOFF_task_p_pptr	0x00000080
 #define ASIZ_task_p_pptr	0x00000004
-#define AOFF_task_p_cptr	0x00000078
+#define AOFF_task_p_cptr	0x00000084
 #define ASIZ_task_p_cptr	0x00000004
-#define AOFF_task_p_ysptr	0x0000007c
+#define AOFF_task_p_ysptr	0x00000088
 #define ASIZ_task_p_ysptr	0x00000004
-#define AOFF_task_p_osptr	0x00000080
+#define AOFF_task_p_osptr	0x0000008c
 #define ASIZ_task_p_osptr	0x00000004
-#define AOFF_task_pidhash_next	0x00000084
+#define AOFF_task_pidhash_next	0x00000090
 #define ASIZ_task_pidhash_next	0x00000004
-#define AOFF_task_pidhash_pprev	0x00000088
+#define AOFF_task_pidhash_pprev	0x00000094
 #define ASIZ_task_pidhash_pprev	0x00000004
-#define AOFF_task_wait_chldexit	0x0000008c
+#define AOFF_task_wait_chldexit	0x00000098
 #define ASIZ_task_wait_chldexit	0x00000010
-#define AOFF_task_vfork_sem	0x0000009c
+#define AOFF_task_vfork_sem	0x000000a8
 #define ASIZ_task_vfork_sem	0x00000004
-#define AOFF_task_policy	0x000000a0
-#define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x000000a4
+#define AOFF_task_rt_priority	0x000000ac
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000a8
+#define AOFF_task_it_real_value	0x000000b0
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x000000ac
+#define AOFF_task_it_prof_value	0x000000b4
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x000000b0
+#define AOFF_task_it_virt_value	0x000000b8
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x000000b4
+#define AOFF_task_it_real_incr	0x000000bc
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x000000b8
+#define AOFF_task_it_prof_incr	0x000000c0
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x000000bc
+#define AOFF_task_it_virt_incr	0x000000c4
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x000000c0
+#define AOFF_task_real_timer	0x000000c8
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x000000d4
+#define AOFF_task_times	0x000000dc
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x000000e4
+#define AOFF_task_start_time	0x000000ec
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x000000e8
+#define AOFF_task_per_cpu_utime	0x000000f0
 #define ASIZ_task_per_cpu_utime	0x00000004
-#define AOFF_task_min_flt	0x000000f0
+#define AOFF_task_min_flt	0x000000f8
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x000000f4
+#define AOFF_task_maj_flt	0x000000fc
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x000000f8
+#define AOFF_task_nswap	0x00000100
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x000000fc
+#define AOFF_task_cmin_flt	0x00000104
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x00000100
+#define AOFF_task_cmaj_flt	0x00000108
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x00000104
+#define AOFF_task_cnswap	0x0000010c
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_uid	0x0000010a
-#define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x0000010c
-#define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x0000010e
-#define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x00000110
-#define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x00000112
-#define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x00000114
-#define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x00000116
-#define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x00000118
-#define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_ngroups	0x0000011c
+#define AOFF_task_uid	0x00000114
+#define ASIZ_task_uid	0x00000004
+#define AOFF_task_euid	0x00000118
+#define ASIZ_task_euid	0x00000004
+#define AOFF_task_suid	0x0000011c
+#define ASIZ_task_suid	0x00000004
+#define AOFF_task_fsuid	0x00000120
+#define ASIZ_task_fsuid	0x00000004
+#define AOFF_task_gid	0x00000124
+#define ASIZ_task_gid	0x00000004
+#define AOFF_task_egid	0x00000128
+#define ASIZ_task_egid	0x00000004
+#define AOFF_task_sgid	0x0000012c
+#define ASIZ_task_sgid	0x00000004
+#define AOFF_task_fsgid	0x00000130
+#define ASIZ_task_fsgid	0x00000004
+#define AOFF_task_ngroups	0x00000134
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000120
-#define ASIZ_task_groups	0x00000040
-#define AOFF_task_cap_effective	0x00000160
+#define AOFF_task_groups	0x00000138
+#define ASIZ_task_groups	0x00000080
+#define AOFF_task_cap_effective	0x000001b8
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x00000164
+#define AOFF_task_cap_inheritable	0x000001bc
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000168
+#define AOFF_task_cap_permitted	0x000001c0
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x0000016c
+#define AOFF_task_user	0x000001c4
 #define ASIZ_task_user	0x00000004
-#define AOFF_task_rlim	0x00000170
+#define AOFF_task_rlim	0x000001c8
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000001c0
+#define AOFF_task_used_math	0x00000218
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x000001c2
+#define AOFF_task_comm	0x0000021a
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000001d4
+#define AOFF_task_link_count	0x0000022c
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000001d8
+#define AOFF_task_tty	0x00000230
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000001dc
+#define AOFF_task_semundo	0x00000234
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000001e0
+#define AOFF_task_semsleeping	0x00000238
 #define ASIZ_task_semsleeping	0x00000004
-#define AOFF_task_thread	0x000001e8
+#define AOFF_task_thread	0x00000240
 #define ASIZ_task_thread	0x00000388
-#define AOFF_task_fs	0x00000570
+#define AOFF_task_fs	0x000005c8
 #define ASIZ_task_fs	0x00000004
-#define AOFF_task_files	0x00000574
+#define AOFF_task_files	0x000005cc
 #define ASIZ_task_files	0x00000004
-#define AOFF_task_mm	0x00000578
-#define ASIZ_task_mm	0x00000004
-#define AOFF_task_active_mm	0x0000057c
-#define ASIZ_task_active_mm	0x00000004
-#define AOFF_task_sigmask_lock	0x00000580
+#define AOFF_task_sigmask_lock	0x000005d0
 #define ASIZ_task_sigmask_lock	0x00000000
-#define AOFF_task_sig	0x00000580
+#define AOFF_task_sig	0x000005d0
 #define ASIZ_task_sig	0x00000004
-#define AOFF_task_signal	0x00000584
+#define AOFF_task_signal	0x000005d4
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x0000058c
+#define AOFF_task_blocked	0x000005dc
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000594
+#define AOFF_task_sigqueue	0x000005e4
 #define ASIZ_task_sigqueue	0x00000004
-#define AOFF_task_sigqueue_tail	0x00000598
+#define AOFF_task_sigqueue_tail	0x000005e8
 #define ASIZ_task_sigqueue_tail	0x00000004
-#define AOFF_task_sas_ss_sp	0x0000059c
+#define AOFF_task_sas_ss_sp	0x000005ec
 #define ASIZ_task_sas_ss_sp	0x00000004
-#define AOFF_task_sas_ss_size	0x000005a0
+#define AOFF_task_sas_ss_size	0x000005f0
 #define ASIZ_task_sas_ss_size	0x00000004
+#define AOFF_task_parent_exec_id	0x000005f4
+#define ASIZ_task_parent_exec_id	0x00000004
+#define AOFF_task_self_exec_id	0x000005f8
+#define ASIZ_task_self_exec_id	0x00000004
+#define AOFF_task_exit_sem	0x000005fc
+#define ASIZ_task_exit_sem	0x0000001c
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
 #define AOFF_mm_mmap_avl	0x00000004
@@ -280,6 +286,8 @@
 #define ASIZ_thread_core_exec	0x00000020
 #define AOFF_thread_new_signal	0x00000380
 #define ASIZ_thread_new_signal	0x00000004
+#define AOFF_thread_refcount	0x00000384
+#define ASIZ_thread_refcount	0x00000004
 
 #else /* CONFIG_SMP */
 
@@ -295,168 +303,174 @@
 #define ASIZ_task_exec_domain	0x00000004
 #define AOFF_task_need_resched	0x00000014
 #define ASIZ_task_need_resched	0x00000004
-#define AOFF_task_counter	0x00000018
+#define AOFF_task_avg_slice	0x00000018
+#define ASIZ_task_avg_slice	0x00000004
+#define AOFF_task_lock_depth	0x0000001c
+#define ASIZ_task_lock_depth	0x00000004
+#define AOFF_task_counter	0x00000020
 #define ASIZ_task_counter	0x00000004
-#define AOFF_task_priority	0x0000001c
+#define AOFF_task_priority	0x00000024
 #define ASIZ_task_priority	0x00000004
-#define AOFF_task_avg_slice	0x00000020
-#define ASIZ_task_avg_slice	0x00000004
-#define AOFF_task_has_cpu	0x00000024
+#define AOFF_task_policy	0x00000028
+#define ASIZ_task_policy	0x00000004
+#define AOFF_task_mm	0x0000002c
+#define ASIZ_task_mm	0x00000004
+#define AOFF_task_active_mm	0x00000030
+#define ASIZ_task_active_mm	0x00000004
+#define AOFF_task_has_cpu	0x00000034
 #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x00000028
+#define AOFF_task_processor	0x00000038
 #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x0000002c
-#define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x00000030
-#define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_next_task	0x00000034
-#define ASIZ_task_next_task	0x00000004
-#define AOFF_task_prev_task	0x00000038
-#define ASIZ_task_prev_task	0x00000004
 #define AOFF_task_run_list	0x0000003c
 #define ASIZ_task_run_list	0x00000008
-#define AOFF_task_binfmt	0x00000044
+#define AOFF_task_next_task	0x00000044
+#define ASIZ_task_next_task	0x00000004
+#define AOFF_task_prev_task	0x00000048
+#define ASIZ_task_prev_task	0x00000004
+#define AOFF_task_last_processor	0x0000004c
+#define ASIZ_task_last_processor	0x00000004
+#define AOFF_task_binfmt	0x00000050
 #define ASIZ_task_binfmt	0x00000004
-#define AOFF_task_exit_code	0x00000048
+#define AOFF_task_exit_code	0x00000054
 #define ASIZ_task_exit_code	0x00000004
-#define AOFF_task_exit_signal	0x0000004c
+#define AOFF_task_exit_signal	0x00000058
 #define ASIZ_task_exit_signal	0x00000004
-#define AOFF_task_pdeath_signal	0x00000050
+#define AOFF_task_pdeath_signal	0x0000005c
 #define ASIZ_task_pdeath_signal	0x00000004
-#define AOFF_task_personality	0x00000054
+#define AOFF_task_personality	0x00000060
 #define ASIZ_task_personality	0x00000004
-#define AOFF_task_pid	0x0000005c
+#define AOFF_task_pid	0x00000068
 #define ASIZ_task_pid	0x00000004
-#define AOFF_task_pgrp	0x00000060
+#define AOFF_task_pgrp	0x0000006c
 #define ASIZ_task_pgrp	0x00000004
-#define AOFF_task_tty_old_pgrp	0x00000064
+#define AOFF_task_tty_old_pgrp	0x00000070
 #define ASIZ_task_tty_old_pgrp	0x00000004
-#define AOFF_task_session	0x00000068
+#define AOFF_task_session	0x00000074
 #define ASIZ_task_session	0x00000004
-#define AOFF_task_leader	0x0000006c
+#define AOFF_task_leader	0x00000078
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_p_opptr	0x00000070
+#define AOFF_task_p_opptr	0x0000007c
 #define ASIZ_task_p_opptr	0x00000004
-#define AOFF_task_p_pptr	0x00000074
+#define AOFF_task_p_pptr	0x00000080
 #define ASIZ_task_p_pptr	0x00000004
-#define AOFF_task_p_cptr	0x00000078
+#define AOFF_task_p_cptr	0x00000084
 #define ASIZ_task_p_cptr	0x00000004
-#define AOFF_task_p_ysptr	0x0000007c
+#define AOFF_task_p_ysptr	0x00000088
 #define ASIZ_task_p_ysptr	0x00000004
-#define AOFF_task_p_osptr	0x00000080
+#define AOFF_task_p_osptr	0x0000008c
 #define ASIZ_task_p_osptr	0x00000004
-#define AOFF_task_pidhash_next	0x00000084
+#define AOFF_task_pidhash_next	0x00000090
 #define ASIZ_task_pidhash_next	0x00000004
-#define AOFF_task_pidhash_pprev	0x00000088
+#define AOFF_task_pidhash_pprev	0x00000094
 #define ASIZ_task_pidhash_pprev	0x00000004
-#define AOFF_task_wait_chldexit	0x0000008c
+#define AOFF_task_wait_chldexit	0x00000098
 #define ASIZ_task_wait_chldexit	0x00000018
-#define AOFF_task_vfork_sem	0x000000a4
+#define AOFF_task_vfork_sem	0x000000b0
 #define ASIZ_task_vfork_sem	0x00000004
-#define AOFF_task_policy	0x000000a8
-#define ASIZ_task_policy	0x00000004
-#define AOFF_task_rt_priority	0x000000ac
+#define AOFF_task_rt_priority	0x000000b4
 #define ASIZ_task_rt_priority	0x00000004
-#define AOFF_task_it_real_value	0x000000b0
+#define AOFF_task_it_real_value	0x000000b8
 #define ASIZ_task_it_real_value	0x00000004
-#define AOFF_task_it_prof_value	0x000000b4
+#define AOFF_task_it_prof_value	0x000000bc
 #define ASIZ_task_it_prof_value	0x00000004
-#define AOFF_task_it_virt_value	0x000000b8
+#define AOFF_task_it_virt_value	0x000000c0
 #define ASIZ_task_it_virt_value	0x00000004
-#define AOFF_task_it_real_incr	0x000000bc
+#define AOFF_task_it_real_incr	0x000000c4
 #define ASIZ_task_it_real_incr	0x00000004
-#define AOFF_task_it_prof_incr	0x000000c0
+#define AOFF_task_it_prof_incr	0x000000c8
 #define ASIZ_task_it_prof_incr	0x00000004
-#define AOFF_task_it_virt_incr	0x000000c4
+#define AOFF_task_it_virt_incr	0x000000cc
 #define ASIZ_task_it_virt_incr	0x00000004
-#define AOFF_task_real_timer	0x000000c8
+#define AOFF_task_real_timer	0x000000d0
 #define ASIZ_task_real_timer	0x00000014
-#define AOFF_task_times	0x000000dc
+#define AOFF_task_times	0x000000e4
 #define ASIZ_task_times	0x00000010
-#define AOFF_task_start_time	0x000000ec
+#define AOFF_task_start_time	0x000000f4
 #define ASIZ_task_start_time	0x00000004
-#define AOFF_task_per_cpu_utime	0x000000f0
+#define AOFF_task_per_cpu_utime	0x000000f8
 #define ASIZ_task_per_cpu_utime	0x00000080
-#define AOFF_task_min_flt	0x000001f0
+#define AOFF_task_min_flt	0x000001f8
 #define ASIZ_task_min_flt	0x00000004
-#define AOFF_task_maj_flt	0x000001f4
+#define AOFF_task_maj_flt	0x000001fc
 #define ASIZ_task_maj_flt	0x00000004
-#define AOFF_task_nswap	0x000001f8
+#define AOFF_task_nswap	0x00000200
 #define ASIZ_task_nswap	0x00000004
-#define AOFF_task_cmin_flt	0x000001fc
+#define AOFF_task_cmin_flt	0x00000204
 #define ASIZ_task_cmin_flt	0x00000004
-#define AOFF_task_cmaj_flt	0x00000200
+#define AOFF_task_cmaj_flt	0x00000208
 #define ASIZ_task_cmaj_flt	0x00000004
-#define AOFF_task_cnswap	0x00000204
+#define AOFF_task_cnswap	0x0000020c
 #define ASIZ_task_cnswap	0x00000004
-#define AOFF_task_uid	0x0000020a
-#define ASIZ_task_uid	0x00000002
-#define AOFF_task_euid	0x0000020c
-#define ASIZ_task_euid	0x00000002
-#define AOFF_task_suid	0x0000020e
-#define ASIZ_task_suid	0x00000002
-#define AOFF_task_fsuid	0x00000210
-#define ASIZ_task_fsuid	0x00000002
-#define AOFF_task_gid	0x00000212
-#define ASIZ_task_gid	0x00000002
-#define AOFF_task_egid	0x00000214
-#define ASIZ_task_egid	0x00000002
-#define AOFF_task_sgid	0x00000216
-#define ASIZ_task_sgid	0x00000002
-#define AOFF_task_fsgid	0x00000218
-#define ASIZ_task_fsgid	0x00000002
-#define AOFF_task_ngroups	0x0000021c
+#define AOFF_task_uid	0x00000214
+#define ASIZ_task_uid	0x00000004
+#define AOFF_task_euid	0x00000218
+#define ASIZ_task_euid	0x00000004
+#define AOFF_task_suid	0x0000021c
+#define ASIZ_task_suid	0x00000004
+#define AOFF_task_fsuid	0x00000220
+#define ASIZ_task_fsuid	0x00000004
+#define AOFF_task_gid	0x00000224
+#define ASIZ_task_gid	0x00000004
+#define AOFF_task_egid	0x00000228
+#define ASIZ_task_egid	0x00000004
+#define AOFF_task_sgid	0x0000022c
+#define ASIZ_task_sgid	0x00000004
+#define AOFF_task_fsgid	0x00000230
+#define ASIZ_task_fsgid	0x00000004
+#define AOFF_task_ngroups	0x00000234
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000220
-#define ASIZ_task_groups	0x00000040
-#define AOFF_task_cap_effective	0x00000260
+#define AOFF_task_groups	0x00000238
+#define ASIZ_task_groups	0x00000080
+#define AOFF_task_cap_effective	0x000002b8
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x00000264
+#define AOFF_task_cap_inheritable	0x000002bc
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000268
+#define AOFF_task_cap_permitted	0x000002c0
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x0000026c
+#define AOFF_task_user	0x000002c4
 #define ASIZ_task_user	0x00000004
-#define AOFF_task_rlim	0x00000270
+#define AOFF_task_rlim	0x000002c8
 #define ASIZ_task_rlim	0x00000050
-#define AOFF_task_used_math	0x000002c0
+#define AOFF_task_used_math	0x00000318
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x000002c2
+#define AOFF_task_comm	0x0000031a
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x000002d4
+#define AOFF_task_link_count	0x0000032c
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x000002d8
+#define AOFF_task_tty	0x00000330
 #define ASIZ_task_tty	0x00000004
-#define AOFF_task_semundo	0x000002dc
+#define AOFF_task_semundo	0x00000334
 #define ASIZ_task_semundo	0x00000004
-#define AOFF_task_semsleeping	0x000002e0
+#define AOFF_task_semsleeping	0x00000338
 #define ASIZ_task_semsleeping	0x00000004
-#define AOFF_task_thread	0x000002e8
+#define AOFF_task_thread	0x00000340
 #define ASIZ_task_thread	0x00000388
-#define AOFF_task_fs	0x00000670
+#define AOFF_task_fs	0x000006c8
 #define ASIZ_task_fs	0x00000004
-#define AOFF_task_files	0x00000674
+#define AOFF_task_files	0x000006cc
 #define ASIZ_task_files	0x00000004
-#define AOFF_task_mm	0x00000678
-#define ASIZ_task_mm	0x00000004
-#define AOFF_task_active_mm	0x0000067c
-#define ASIZ_task_active_mm	0x00000004
-#define AOFF_task_sigmask_lock	0x00000680
+#define AOFF_task_sigmask_lock	0x000006d0
 #define ASIZ_task_sigmask_lock	0x00000008
-#define AOFF_task_sig	0x00000688
+#define AOFF_task_sig	0x000006d8
 #define ASIZ_task_sig	0x00000004
-#define AOFF_task_signal	0x0000068c
+#define AOFF_task_signal	0x000006dc
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000694
+#define AOFF_task_blocked	0x000006e4
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x0000069c
+#define AOFF_task_sigqueue	0x000006ec
 #define ASIZ_task_sigqueue	0x00000004
-#define AOFF_task_sigqueue_tail	0x000006a0
+#define AOFF_task_sigqueue_tail	0x000006f0
 #define ASIZ_task_sigqueue_tail	0x00000004
-#define AOFF_task_sas_ss_sp	0x000006a4
+#define AOFF_task_sas_ss_sp	0x000006f4
 #define ASIZ_task_sas_ss_sp	0x00000004
-#define AOFF_task_sas_ss_size	0x000006a8
+#define AOFF_task_sas_ss_size	0x000006f8
 #define ASIZ_task_sas_ss_size	0x00000004
+#define AOFF_task_parent_exec_id	0x000006fc
+#define ASIZ_task_parent_exec_id	0x00000004
+#define AOFF_task_self_exec_id	0x00000700
+#define ASIZ_task_self_exec_id	0x00000004
+#define AOFF_task_exit_sem	0x00000704
+#define ASIZ_task_exit_sem	0x00000024
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
 #define AOFF_mm_mmap_avl	0x00000004
@@ -557,6 +571,8 @@
 #define ASIZ_thread_core_exec	0x00000020
 #define AOFF_thread_new_signal	0x00000380
 #define ASIZ_thread_new_signal	0x00000004
+#define AOFF_thread_refcount	0x00000384
+#define ASIZ_thread_refcount	0x00000004
 
 #endif /* CONFIG_SMP */
 
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/ipcbuf.h linux/include/asm-sparc/ipcbuf.h
--- v2.3.39/linux/include/asm-sparc/ipcbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/ipcbuf.h	Thu Jan 13 12:03:00 2000
@@ -0,0 +1,31 @@
+#ifndef _SPARC_IPCBUF_H
+#define _SPARC_IPCBUF_H
+
+/* 
+ * The ipc64_perm structure for sparc architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode
+ * - 32-bit seq
+ * - 2 miscellaneous 64-bit values (so that this structure matches
+ *				    sparc64 ipc64_perm)
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
+	unsigned short		__pad1;
+	__kernel_mode_t		mode;
+	unsigned short		__pad2;
+	unsigned short		seq;
+	unsigned long long	__unused1;
+	unsigned long long	__unused2;
+};
+
+#endif /* _SPARC_IPCBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/msgbuf.h linux/include/asm-sparc/msgbuf.h
--- v2.3.39/linux/include/asm-sparc/msgbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/msgbuf.h	Thu Jan 13 12:03:00 2000
@@ -0,0 +1,31 @@
+#ifndef _SPARC64_MSGBUF_H
+#define _SPARC64_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for sparc64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm msg_perm;
+	unsigned int   __pad1;
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	unsigned int   __pad2;
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	unsigned int   __pad3;
+	__kernel_time_t msg_ctime;	/* last change time */
+	unsigned long  msg_cbytes;	/* current number of bytes on queue */
+	unsigned long  msg_qnum;	/* number of messages in queue */
+	unsigned long  msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	unsigned long  __unused1;
+	unsigned long  __unused2;
+};
+
+#endif /* _SPARC64_MSGBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/pgalloc.h linux/include/asm-sparc/pgalloc.h
--- v2.3.39/linux/include/asm-sparc/pgalloc.h	Tue Jan  4 13:57:19 2000
+++ linux/include/asm-sparc/pgalloc.h	Sat Jan 15 22:08:29 2000
@@ -1,4 +1,4 @@
-/* $Id: pgalloc.h,v 1.1 1999/12/28 04:13:35 anton Exp $ */
+/* $Id: pgalloc.h,v 1.2 2000/01/15 00:51:42 anton Exp $ */
 #ifndef _SPARC_PGALLOC_H
 #define _SPARC_PGALLOC_H
 
@@ -30,10 +30,10 @@
 #define local_flush_tlb_range(mm,start,end) BTFIXUP_CALL(local_flush_tlb_range)(mm,start,end)
 #define local_flush_tlb_page(vma,addr) BTFIXUP_CALL(local_flush_tlb_page)(vma,addr)
 
-BTFIXUPDEF_CALL(void, local_flush_page_to_ram, struct page *)
+BTFIXUPDEF_CALL(void, local_flush_page_to_ram, unsigned long)
 BTFIXUPDEF_CALL(void, local_flush_sig_insns, struct mm_struct *, unsigned long)
 
-#define local_flush_page_to_ram(page) BTFIXUP_CALL(local_flush_page_to_ram)(page)
+#define local_flush_page_to_ram(addr) BTFIXUP_CALL(local_flush_page_to_ram)(addr)
 #define local_flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(local_flush_sig_insns)(mm,insn_addr)
 
 extern void smp_flush_cache_all(void);
@@ -49,7 +49,7 @@
 				  unsigned long start,
 				  unsigned long end);
 extern void smp_flush_tlb_page(struct vm_area_struct *mm, unsigned long page);
-extern void smp_flush_page_to_ram(struct page *page);
+extern void smp_flush_page_to_ram(unsigned long page);
 extern void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);
 #endif
 
@@ -74,11 +74,13 @@
 #define flush_tlb_range(mm,start,end) BTFIXUP_CALL(flush_tlb_range)(mm,start,end)
 #define flush_tlb_page(vma,addr) BTFIXUP_CALL(flush_tlb_page)(vma,addr)
 
-BTFIXUPDEF_CALL(void, flush_page_to_ram, struct page *)
+BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
 BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)
 
-#define flush_page_to_ram(page) BTFIXUP_CALL(flush_page_to_ram)(page)
+#define __flush_page_to_ram(addr) BTFIXUP_CALL(__flush_page_to_ram)(addr)
 #define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr)
+
+#define flush_page_to_ram(page)    __flush_page_to_ram(page_address(page))
 
 extern struct pgtable_cache_struct {
 	unsigned long *pgd_cache;
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/posix_types.h linux/include/asm-sparc/posix_types.h
--- v2.3.39/linux/include/asm-sparc/posix_types.h	Wed Mar 10 16:53:37 1999
+++ linux/include/asm-sparc/posix_types.h	Sat Jan 15 22:08:29 2000
@@ -7,13 +7,7 @@
  * assume GCC is being used.
  */
 
-/* When cross-compilation is no longer an issue, fix this. */
-#if defined(__svr4__) || defined(__ELF__)
 typedef unsigned int           __kernel_size_t;
-#else
-typedef long unsigned int      __kernel_size_t;
-#endif /* !(__svr4__ || __ELF__) */
-
 typedef int                    __kernel_ssize_t;
 typedef long int               __kernel_ptrdiff_t;
 typedef long                   __kernel_time_t;
@@ -31,6 +25,12 @@
 typedef long                   __kernel_daddr_t;
 typedef long                   __kernel_off_t;
 typedef char *                 __kernel_caddr_t;
+typedef unsigned short	       __kernel_uid16_t;
+typedef unsigned short	       __kernel_gid16_t;
+typedef unsigned int	       __kernel_uid32_t;
+typedef unsigned int	       __kernel_gid32_t;
+typedef unsigned short	       __kernel_old_uid_t;
+typedef unsigned short	       __kernel_old_gid_t;
 
 #ifdef __GNUC__
 typedef long long	__kernel_loff_t;
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h
--- v2.3.39/linux/include/asm-sparc/processor.h	Fri Jan  7 19:13:22 2000
+++ linux/include/asm-sparc/processor.h	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.75 2000/01/07 20:21:42 davem Exp $
+/* $Id: processor.h,v 1.76 2000/01/09 09:13:38 anton Exp $
  * include/asm-sparc/processor.h
  *
  * Copyright (C) 1994 David S. Miller (davem@caip.rutgers.edu)
@@ -22,6 +22,7 @@
 #include <asm/segment.h>
 #include <asm/btfixup.h>
 #include <asm/page.h>
+#include <asm/atomic.h>
 
 /*
  * Bus types
@@ -88,6 +89,7 @@
 	mm_segment_t current_ds;
 	struct exec core_exec;     /* just what it says. */
 	int new_signal;
+	atomic_t refcount;	/* used for sun4c only */
 };
 
 #define SPARC_FLAG_KTHREAD      0x1    /* task is a kernel thread */
@@ -201,11 +203,11 @@
 /* Allocation and freeing of basic task resources. */
 BTFIXUPDEF_CALL(struct task_struct *, alloc_task_struct, void)
 BTFIXUPDEF_CALL(void, free_task_struct, struct task_struct *)
+BTFIXUPDEF_CALL(void, get_task_struct, struct task_struct *)
 
 #define alloc_task_struct() BTFIXUP_CALL(alloc_task_struct)()
 #define free_task_struct(tsk) BTFIXUP_CALL(free_task_struct)(tsk)
-
-/* XXX Anton, here is where you implement get_task_struct et al. */
+#define get_task_struct(tsk) BTFIXUP_CALL(get_task_struct)(tsk)
 
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/sembuf.h linux/include/asm-sparc/sembuf.h
--- v2.3.39/linux/include/asm-sparc/sembuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/sembuf.h	Thu Jan 13 12:03:00 2000
@@ -0,0 +1,25 @@
+#ifndef _SPARC_SEMBUF_H
+#define _SPARC_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for sparc architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+	unsigned int	__pad1;
+	__kernel_time_t	sem_otime;		/* last semop time */
+	unsigned int	__pad2;
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
+#endif /* _SPARC64_SEMBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/shmbuf.h linux/include/asm-sparc/shmbuf.h
--- v2.3.39/linux/include/asm-sparc/shmbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc/shmbuf.h	Thu Jan 13 12:03:00 2000
@@ -0,0 +1,42 @@
+#ifndef _SPARC_SHMBUF_H
+#define _SPARC_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for sparc architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	unsigned int		__pad1;
+	__kernel_time_t		shm_atime;	/* last attach time */
+	unsigned int		__pad2;
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	unsigned int		__pad3;
+	__kernel_time_t		shm_ctime;	/* last change time */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _SPARC_SHMBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc/unistd.h linux/include/asm-sparc/unistd.h
--- v2.3.39/linux/include/asm-sparc/unistd.h	Fri Jan  7 19:13:22 2000
+++ linux/include/asm-sparc/unistd.h	Fri Jan 14 14:52:08 2000
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.60 2000/01/05 07:37:50 jj Exp $ */
+/* $Id: unistd.h,v 1.63 2000/01/12 11:47:40 anton Exp $ */
 #ifndef _SPARC_UNISTD_H
 #define _SPARC_UNISTD_H
 
@@ -46,11 +46,11 @@
 #define __NR_sigaltstack	 28 /* Common					   */
 #define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
 #define __NR_utime               30 /* Implemented via utimes() under SunOS        */
-/* #define __NR_stty             31    Implemented via ioctl() under SunOS         */
-/* #define __NR_gtty             32    Implemented via ioctl() under SunOS         */
+#define __NR_lchown32            31 /* Linux sparc32 specific                      */
+#define __NR_fchown32            32 /* Linux sparc32 specific                      */
 #define __NR_access              33 /* Common                                      */
 #define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
-/* #define __NR_ftime            35    Implemented via gettimeofday() in SunOS     */
+#define __NR_chown32             35 /* Linux sparc32 specific                      */
 #define __NR_sync                36 /* Common                                      */
 #define __NR_kill                37 /* Common                                      */
 #define __NR_stat                38 /* Common                                      */
@@ -59,7 +59,7 @@
 #define __NR_dup                 41 /* Common                                      */
 #define __NR_pipe                42 /* Common                                      */
 #define __NR_times               43 /* Implemented via getrusage() in SunOS        */
-/* #define __NR_profil           44    Common                                      */
+#define __NR_getuid32            44 /* Linux sparc32 specific                      */
 #define __NR_umount2             45 /* Linux Specific                              */
 #define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
 #define __NR_getgid              47 /* Common                                      */
@@ -68,7 +68,7 @@
 #define __NR_getegid             50 /* SunOS calls getgid()                        */
 #define __NR_acct                51 /* Common                                      */
 /* #define __NR_ni_syscall	 52    ENOSYS under SunOS			   */
-/* #define __NR_mctl             53    SunOS specific                              */
+#define __NR_getgid32            53 /* Linux sparc32 specific                      */
 #define __NR_ioctl               54 /* Common                                      */
 #define __NR_reboot              55 /* Common                                      */
 #define __NR_mmap2		 56 /* Linux sparc32 Specific			   */
@@ -84,32 +84,32 @@
 #define __NR_vfork               66 /* Common                                      */
 #define __NR_pread               67 /* Linux Specific                              */
 #define __NR_pwrite              68 /* Linux Specific                              */
-/* #define __NR_sbrk             69    SunOS Specific                              */
-/* #define __NR_sstk             70    SunOS Specific                              */
+#define __NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
+#define __NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
 #define __NR_mmap                71 /* Common                                      */
-/* #define __NR_vadvise          72    SunOS Specific                              */
+#define __NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */
 #define __NR_munmap              73 /* Common                                      */
 #define __NR_mprotect            74 /* Common                                      */
-/* #define __NR_madvise          75    SunOS Specific                              */
+#define __NR_madvise             75 /* Common                                      */
 #define __NR_vhangup             76 /* Common                                      */
 #define __NR_truncate64		 77 /* Linux sparc32 Specific			   */
-/* #define __NR_mincore          78    SunOS Specific                              */
+#define __NR_mincore             78 /* Common                                      */
 #define __NR_getgroups           79 /* Common                                      */
 #define __NR_setgroups           80 /* Common                                      */
 #define __NR_getpgrp             81 /* Common                                      */
-/* #define __NR_setpgrp          82    setpgid, same difference...                 */
+#define __NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */
 #define __NR_setitimer           83 /* Common                                      */
 #define __NR_ftruncate64	 84 /* Linux sparc32 Specific			   */
 #define __NR_swapon              85 /* Common                                      */
 #define __NR_getitimer           86 /* Common                                      */
-/* #define __NR_gethostname      87    SunOS Specific                              */
+#define __NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */
 #define __NR_sethostname         88 /* Common                                      */
-/* #define __NR_getdtablesize    89    SunOS Specific                              */
+#define __NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */
 #define __NR_dup2                90 /* Common                                      */
-/* #define __NR_getdopt          91    SunOS Specific                              */
+#define __NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */
 #define __NR_fcntl               92 /* Common                                      */
 #define __NR_select              93 /* Common                                      */
-/* #define __NR_setdopt          94    SunOS Specific                              */
+#define __NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */
 #define __NR_fsync               95 /* Common                                      */
 #define __NR_setpriority         96 /* Common                                      */
 #define __NR_socket              97 /* Common                                      */
@@ -123,14 +123,14 @@
 #define __NR_rt_sigtimedwait    105 /* Linux Specific                              */
 #define __NR_rt_sigqueueinfo    106 /* Linux Specific                              */
 #define __NR_rt_sigsuspend      107 /* Linux Specific                              */
-/* #define __NR_sigvec          108    SunOS Specific                              */
-/* #define __NR_sigblock        109    SunOS Specific                              */
-/* #define __NR_sigsetmask      110    SunOS Specific                              */
-/* #define __NR_sigpause        111    SunOS Specific                              */
-/* #define __NR_sigstack        112    SunOS Specific                              */
+#define __NR_setresuid32        108 /* Linux Specific, sigvec under SunOS	   */
+#define __NR_getresuid32        109 /* Linux Specific, sigblock under SunOS	   */
+#define __NR_setresgid32        110 /* Linux Specific, sigsetmask under SunOS	   */
+#define __NR_getresgid32        111 /* Linux Specific, sigpause under SunOS	   */
+#define __NR_setregid32         112 /* Linux sparc32, sigstack under SunOS         */
 #define __NR_recvmsg            113 /* Common                                      */
 #define __NR_sendmsg            114 /* Common                                      */
-/* #define __NR_vtrace          115    SunOS Specific                              */
+#define __NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */
 #define __NR_gettimeofday       116 /* Common                                      */
 #define __NR_getrusage          117 /* Common                                      */
 #define __NR_getsockopt         118 /* Common                                      */
@@ -225,7 +225,7 @@
 #define __NR_syslog             207 /* Linux Specific                              */
 /* #define __NR_olduname        208    Linux Specific                              */
 /* #define __NR_iopl            209    Linux Specific - i386 specific, unused      */
-#define __NR_idle               210 /* Linux Specific                              */
+/* #define __NR_idle            210    Linux Specific - was sys_idle, now unused   */
 /* #define __NR_vm86            211    Linux Specific - i386 specific, unused      */
 #define __NR_waitpid            212 /* Linux Specific                              */
 #define __NR_swapoff            213 /* Linux Specific                              */
@@ -416,7 +416,6 @@
  * some others too.
  */
 #define __NR__exit __NR_exit
-static __inline__ _syscall0(int,idle)
 static __inline__ _syscall0(int,pause)
 static __inline__ _syscall0(int,sync)
 static __inline__ _syscall0(pid_t,setsid)
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h
--- v2.3.39/linux/include/asm-sparc64/asm_offsets.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc64/asm_offsets.h	Thu Jan 13 12:03:00 2000
@@ -24,152 +24,152 @@
 #define ASIZ_task_exec_domain	0x00000008
 #define AOFF_task_need_resched	0x00000020
 #define ASIZ_task_need_resched	0x00000008
-#define AOFF_task_counter	0x00000028
+#define AOFF_task_avg_slice	0x00000028
+#define ASIZ_task_avg_slice	0x00000008
+#define AOFF_task_lock_depth	0x00000030
+#define ASIZ_task_lock_depth	0x00000004
+#define AOFF_task_counter	0x00000038
 #define ASIZ_task_counter	0x00000008
-#define AOFF_task_priority	0x00000030
+#define AOFF_task_priority	0x00000040
 #define ASIZ_task_priority	0x00000008
-#define AOFF_task_avg_slice	0x00000038
-#define ASIZ_task_avg_slice	0x00000008
-#define AOFF_task_has_cpu	0x00000040
+#define AOFF_task_policy	0x00000048
+#define ASIZ_task_policy	0x00000008
+#define AOFF_task_mm	0x00000050
+#define ASIZ_task_mm	0x00000008
+#define AOFF_task_active_mm	0x00000058
+#define ASIZ_task_active_mm	0x00000008
+#define AOFF_task_has_cpu	0x00000060
 #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x00000044
+#define AOFF_task_processor	0x00000064
 #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x00000048
-#define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x0000004c
-#define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_next_task	0x00000050
+#define AOFF_task_run_list	0x00000068
+#define ASIZ_task_run_list	0x00000010
+#define AOFF_task_next_task	0x00000078
 #define ASIZ_task_next_task	0x00000008
-#define AOFF_task_prev_task	0x00000058
+#define AOFF_task_prev_task	0x00000080
 #define ASIZ_task_prev_task	0x00000008
-#define AOFF_task_run_list	0x00000060
-#define ASIZ_task_run_list	0x00000010
-#define AOFF_task_binfmt	0x00000070
+#define AOFF_task_last_processor	0x00000088
+#define ASIZ_task_last_processor	0x00000004
+#define AOFF_task_binfmt	0x00000090
 #define ASIZ_task_binfmt	0x00000008
-#define AOFF_task_exit_code	0x00000078
+#define AOFF_task_exit_code	0x00000098
 #define ASIZ_task_exit_code	0x00000004
-#define AOFF_task_exit_signal	0x0000007c
+#define AOFF_task_exit_signal	0x0000009c
 #define ASIZ_task_exit_signal	0x00000004
-#define AOFF_task_pdeath_signal	0x00000080
+#define AOFF_task_pdeath_signal	0x000000a0
 #define ASIZ_task_pdeath_signal	0x00000004
-#define AOFF_task_personality	0x00000088
+#define AOFF_task_personality	0x000000a8
 #define ASIZ_task_personality	0x00000008
-#define AOFF_task_pid	0x00000094
+#define AOFF_task_pid	0x000000b4
 #define ASIZ_task_pid	0x00000004
-#define AOFF_task_pgrp	0x00000098
+#define AOFF_task_pgrp	0x000000b8
 #define ASIZ_task_pgrp	0x00000004
-#define AOFF_task_tty_old_pgrp	0x0000009c
+#define AOFF_task_tty_old_pgrp	0x000000bc
 #define ASIZ_task_tty_old_pgrp	0x00000004
-#define AOFF_task_session	0x000000a0
+#define AOFF_task_session	0x000000c0
 #define ASIZ_task_session	0x00000004
-#define AOFF_task_leader	0x000000a4
+#define AOFF_task_leader	0x000000c4
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_p_opptr	0x000000a8
+#define AOFF_task_p_opptr	0x000000c8
 #define ASIZ_task_p_opptr	0x00000008
-#define AOFF_task_p_pptr	0x000000b0
+#define AOFF_task_p_pptr	0x000000d0
 #define ASIZ_task_p_pptr	0x00000008
-#define AOFF_task_p_cptr	0x000000b8
+#define AOFF_task_p_cptr	0x000000d8
 #define ASIZ_task_p_cptr	0x00000008
-#define AOFF_task_p_ysptr	0x000000c0
+#define AOFF_task_p_ysptr	0x000000e0
 #define ASIZ_task_p_ysptr	0x00000008
-#define AOFF_task_p_osptr	0x000000c8
+#define AOFF_task_p_osptr	0x000000e8
 #define ASIZ_task_p_osptr	0x00000008
-#define AOFF_task_pidhash_next	0x000000d0
+#define AOFF_task_pidhash_next	0x000000f0
 #define ASIZ_task_pidhash_next	0x00000008
-#define AOFF_task_pidhash_pprev	0x000000d8
+#define AOFF_task_pidhash_pprev	0x000000f8
 #define ASIZ_task_pidhash_pprev	0x00000008
-#define AOFF_task_wait_chldexit	0x000000e0
+#define AOFF_task_wait_chldexit	0x00000100
 #define ASIZ_task_wait_chldexit	0x00000020
-#define AOFF_task_vfork_sem	0x00000100
+#define AOFF_task_vfork_sem	0x00000120
 #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000108
-#define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000110
+#define AOFF_task_rt_priority	0x00000128
 #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000118
+#define AOFF_task_it_real_value	0x00000130
 #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000120
+#define AOFF_task_it_prof_value	0x00000138
 #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000128
+#define AOFF_task_it_virt_value	0x00000140
 #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000130
+#define AOFF_task_it_real_incr	0x00000148
 #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000138
+#define AOFF_task_it_prof_incr	0x00000150
 #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000140
+#define AOFF_task_it_virt_incr	0x00000158
 #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000148
+#define AOFF_task_real_timer	0x00000160
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000170
+#define AOFF_task_times	0x00000188
 #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x00000190
+#define AOFF_task_start_time	0x000001a8
 #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x00000198
+#define AOFF_task_per_cpu_utime	0x000001b0
 #define ASIZ_task_per_cpu_utime	0x00000008
-#define AOFF_task_min_flt	0x000001a8
+#define AOFF_task_min_flt	0x000001c0
 #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x000001b0
+#define AOFF_task_maj_flt	0x000001c8
 #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000001b8
+#define AOFF_task_nswap	0x000001d0
 #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000001c0
+#define AOFF_task_cmin_flt	0x000001d8
 #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000001c8
+#define AOFF_task_cmaj_flt	0x000001e0
 #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000001d0
+#define AOFF_task_cnswap	0x000001e8
 #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000001dc
+#define AOFF_task_uid	0x000001f4
 #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000001e0
+#define AOFF_task_euid	0x000001f8
 #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000001e4
+#define AOFF_task_suid	0x000001fc
 #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000001e8
+#define AOFF_task_fsuid	0x00000200
 #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000001ec
+#define AOFF_task_gid	0x00000204
 #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000001f0
+#define AOFF_task_egid	0x00000208
 #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000001f4
+#define AOFF_task_sgid	0x0000020c
 #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x000001f8
+#define AOFF_task_fsgid	0x00000210
 #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x000001fc
+#define AOFF_task_ngroups	0x00000214
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000200
+#define AOFF_task_groups	0x00000218
 #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000280
+#define AOFF_task_cap_effective	0x00000298
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x00000284
+#define AOFF_task_cap_inheritable	0x0000029c
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000288
+#define AOFF_task_cap_permitted	0x000002a0
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000290
+#define AOFF_task_user	0x000002a8
 #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x00000298
+#define AOFF_task_rlim	0x000002b0
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000338
+#define AOFF_task_used_math	0x00000350
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x0000033a
+#define AOFF_task_comm	0x00000352
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x0000034c
+#define AOFF_task_link_count	0x00000364
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000350
+#define AOFF_task_tty	0x00000368
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000358
+#define AOFF_task_semundo	0x00000370
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000360
+#define AOFF_task_semsleeping	0x00000378
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_thread	0x00000370
+#define AOFF_task_thread	0x00000380
 #define ASIZ_task_thread	0x00000460
-#define AOFF_task_fs	0x000007d0
+#define AOFF_task_fs	0x000007e0
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000007d8
+#define AOFF_task_files	0x000007e8
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000007e0
-#define ASIZ_task_mm	0x00000008
-#define AOFF_task_active_mm	0x000007e8
-#define ASIZ_task_active_mm	0x00000008
 #define AOFF_task_sigmask_lock	0x000007f0
 #define ASIZ_task_sigmask_lock	0x00000000
 #define AOFF_task_sig	0x000007f0
@@ -318,175 +318,175 @@
 #define ASIZ_task_exec_domain	0x00000008
 #define AOFF_task_need_resched	0x00000020
 #define ASIZ_task_need_resched	0x00000008
-#define AOFF_task_counter	0x00000028
+#define AOFF_task_avg_slice	0x00000028
+#define ASIZ_task_avg_slice	0x00000008
+#define AOFF_task_lock_depth	0x00000030
+#define ASIZ_task_lock_depth	0x00000004
+#define AOFF_task_counter	0x00000038
 #define ASIZ_task_counter	0x00000008
-#define AOFF_task_priority	0x00000030
+#define AOFF_task_priority	0x00000040
 #define ASIZ_task_priority	0x00000008
-#define AOFF_task_avg_slice	0x00000038
-#define ASIZ_task_avg_slice	0x00000008
-#define AOFF_task_has_cpu	0x00000040
+#define AOFF_task_policy	0x00000048
+#define ASIZ_task_policy	0x00000008
+#define AOFF_task_mm	0x00000050
+#define ASIZ_task_mm	0x00000008
+#define AOFF_task_active_mm	0x00000058
+#define ASIZ_task_active_mm	0x00000008
+#define AOFF_task_has_cpu	0x00000060
 #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x00000044
+#define AOFF_task_processor	0x00000064
 #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x00000048
-#define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x0000004c
-#define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_next_task	0x00000050
+#define AOFF_task_run_list	0x00000068
+#define ASIZ_task_run_list	0x00000010
+#define AOFF_task_next_task	0x00000078
 #define ASIZ_task_next_task	0x00000008
-#define AOFF_task_prev_task	0x00000058
+#define AOFF_task_prev_task	0x00000080
 #define ASIZ_task_prev_task	0x00000008
-#define AOFF_task_run_list	0x00000060
-#define ASIZ_task_run_list	0x00000010
-#define AOFF_task_binfmt	0x00000070
+#define AOFF_task_last_processor	0x00000088
+#define ASIZ_task_last_processor	0x00000004
+#define AOFF_task_binfmt	0x00000090
 #define ASIZ_task_binfmt	0x00000008
-#define AOFF_task_exit_code	0x00000078
+#define AOFF_task_exit_code	0x00000098
 #define ASIZ_task_exit_code	0x00000004
-#define AOFF_task_exit_signal	0x0000007c
+#define AOFF_task_exit_signal	0x0000009c
 #define ASIZ_task_exit_signal	0x00000004
-#define AOFF_task_pdeath_signal	0x00000080
+#define AOFF_task_pdeath_signal	0x000000a0
 #define ASIZ_task_pdeath_signal	0x00000004
-#define AOFF_task_personality	0x00000088
+#define AOFF_task_personality	0x000000a8
 #define ASIZ_task_personality	0x00000008
-#define AOFF_task_pid	0x00000094
+#define AOFF_task_pid	0x000000b4
 #define ASIZ_task_pid	0x00000004
-#define AOFF_task_pgrp	0x00000098
+#define AOFF_task_pgrp	0x000000b8
 #define ASIZ_task_pgrp	0x00000004
-#define AOFF_task_tty_old_pgrp	0x0000009c
+#define AOFF_task_tty_old_pgrp	0x000000bc
 #define ASIZ_task_tty_old_pgrp	0x00000004
-#define AOFF_task_session	0x000000a0
+#define AOFF_task_session	0x000000c0
 #define ASIZ_task_session	0x00000004
-#define AOFF_task_leader	0x000000a4
+#define AOFF_task_leader	0x000000c4
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_p_opptr	0x000000a8
+#define AOFF_task_p_opptr	0x000000c8
 #define ASIZ_task_p_opptr	0x00000008
-#define AOFF_task_p_pptr	0x000000b0
+#define AOFF_task_p_pptr	0x000000d0
 #define ASIZ_task_p_pptr	0x00000008
-#define AOFF_task_p_cptr	0x000000b8
+#define AOFF_task_p_cptr	0x000000d8
 #define ASIZ_task_p_cptr	0x00000008
-#define AOFF_task_p_ysptr	0x000000c0
+#define AOFF_task_p_ysptr	0x000000e0
 #define ASIZ_task_p_ysptr	0x00000008
-#define AOFF_task_p_osptr	0x000000c8
+#define AOFF_task_p_osptr	0x000000e8
 #define ASIZ_task_p_osptr	0x00000008
-#define AOFF_task_pidhash_next	0x000000d0
+#define AOFF_task_pidhash_next	0x000000f0
 #define ASIZ_task_pidhash_next	0x00000008
-#define AOFF_task_pidhash_pprev	0x000000d8
+#define AOFF_task_pidhash_pprev	0x000000f8
 #define ASIZ_task_pidhash_pprev	0x00000008
-#define AOFF_task_wait_chldexit	0x000000e0
+#define AOFF_task_wait_chldexit	0x00000100
 #define ASIZ_task_wait_chldexit	0x00000028
-#define AOFF_task_vfork_sem	0x00000108
+#define AOFF_task_vfork_sem	0x00000128
 #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000110
-#define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000118
+#define AOFF_task_rt_priority	0x00000130
 #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000120
+#define AOFF_task_it_real_value	0x00000138
 #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000128
+#define AOFF_task_it_prof_value	0x00000140
 #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000130
+#define AOFF_task_it_virt_value	0x00000148
 #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000138
+#define AOFF_task_it_real_incr	0x00000150
 #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000140
+#define AOFF_task_it_prof_incr	0x00000158
 #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000148
+#define AOFF_task_it_virt_incr	0x00000160
 #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000150
+#define AOFF_task_real_timer	0x00000168
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000178
+#define AOFF_task_times	0x00000190
 #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x00000198
+#define AOFF_task_start_time	0x000001b0
 #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x000001a0
+#define AOFF_task_per_cpu_utime	0x000001b8
 #define ASIZ_task_per_cpu_utime	0x00000100
-#define AOFF_task_min_flt	0x000003a0
+#define AOFF_task_min_flt	0x000003b8
 #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x000003a8
+#define AOFF_task_maj_flt	0x000003c0
 #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000003b0
+#define AOFF_task_nswap	0x000003c8
 #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000003b8
+#define AOFF_task_cmin_flt	0x000003d0
 #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000003c0
+#define AOFF_task_cmaj_flt	0x000003d8
 #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000003c8
+#define AOFF_task_cnswap	0x000003e0
 #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000003d4
+#define AOFF_task_uid	0x000003ec
 #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000003d8
+#define AOFF_task_euid	0x000003f0
 #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000003dc
+#define AOFF_task_suid	0x000003f4
 #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000003e0
+#define AOFF_task_fsuid	0x000003f8
 #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000003e4
+#define AOFF_task_gid	0x000003fc
 #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000003e8
+#define AOFF_task_egid	0x00000400
 #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000003ec
+#define AOFF_task_sgid	0x00000404
 #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x000003f0
+#define AOFF_task_fsgid	0x00000408
 #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x000003f4
+#define AOFF_task_ngroups	0x0000040c
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x000003f8
+#define AOFF_task_groups	0x00000410
 #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000478
+#define AOFF_task_cap_effective	0x00000490
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x0000047c
+#define AOFF_task_cap_inheritable	0x00000494
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000480
+#define AOFF_task_cap_permitted	0x00000498
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000488
+#define AOFF_task_user	0x000004a0
 #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x00000490
+#define AOFF_task_rlim	0x000004a8
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000530
+#define AOFF_task_used_math	0x00000548
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x00000532
+#define AOFF_task_comm	0x0000054a
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x00000544
+#define AOFF_task_link_count	0x0000055c
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000548
+#define AOFF_task_tty	0x00000560
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000550
+#define AOFF_task_semundo	0x00000568
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000558
+#define AOFF_task_semsleeping	0x00000570
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_thread	0x00000560
+#define AOFF_task_thread	0x00000580
 #define ASIZ_task_thread	0x00000460
-#define AOFF_task_fs	0x000009c0
+#define AOFF_task_fs	0x000009e0
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000009c8
+#define AOFF_task_files	0x000009e8
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000009d0
-#define ASIZ_task_mm	0x00000008
-#define AOFF_task_active_mm	0x000009d8
-#define ASIZ_task_active_mm	0x00000008
-#define AOFF_task_sigmask_lock	0x000009e0
+#define AOFF_task_sigmask_lock	0x000009f0
 #define ASIZ_task_sigmask_lock	0x00000001
-#define AOFF_task_sig	0x000009e8
+#define AOFF_task_sig	0x000009f8
 #define ASIZ_task_sig	0x00000008
-#define AOFF_task_signal	0x000009f0
+#define AOFF_task_signal	0x00000a00
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x000009f8
+#define AOFF_task_blocked	0x00000a08
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000a00
+#define AOFF_task_sigqueue	0x00000a10
 #define ASIZ_task_sigqueue	0x00000008
-#define AOFF_task_sigqueue_tail	0x00000a08
+#define AOFF_task_sigqueue_tail	0x00000a18
 #define ASIZ_task_sigqueue_tail	0x00000008
-#define AOFF_task_sas_ss_sp	0x00000a10
+#define AOFF_task_sas_ss_sp	0x00000a20
 #define ASIZ_task_sas_ss_sp	0x00000008
-#define AOFF_task_sas_ss_size	0x00000a18
+#define AOFF_task_sas_ss_size	0x00000a28
 #define ASIZ_task_sas_ss_size	0x00000008
-#define AOFF_task_parent_exec_id	0x00000a20
+#define AOFF_task_parent_exec_id	0x00000a30
 #define ASIZ_task_parent_exec_id	0x00000004
-#define AOFF_task_self_exec_id	0x00000a24
+#define AOFF_task_self_exec_id	0x00000a34
 #define ASIZ_task_self_exec_id	0x00000004
-#define AOFF_task_exit_sem	0x00000a28
+#define AOFF_task_exit_sem	0x00000a38
 #define ASIZ_task_exit_sem	0x00000038
-#define ASIZ_task	0x00000a60
+#define ASIZ_task	0x00000a70
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
@@ -610,152 +610,152 @@
 #define ASIZ_task_exec_domain	0x00000008
 #define AOFF_task_need_resched	0x00000020
 #define ASIZ_task_need_resched	0x00000008
-#define AOFF_task_counter	0x00000028
+#define AOFF_task_avg_slice	0x00000028
+#define ASIZ_task_avg_slice	0x00000008
+#define AOFF_task_lock_depth	0x00000030
+#define ASIZ_task_lock_depth	0x00000004
+#define AOFF_task_counter	0x00000038
 #define ASIZ_task_counter	0x00000008
-#define AOFF_task_priority	0x00000030
+#define AOFF_task_priority	0x00000040
 #define ASIZ_task_priority	0x00000008
-#define AOFF_task_avg_slice	0x00000038
-#define ASIZ_task_avg_slice	0x00000008
-#define AOFF_task_has_cpu	0x00000040
+#define AOFF_task_policy	0x00000048
+#define ASIZ_task_policy	0x00000008
+#define AOFF_task_mm	0x00000050
+#define ASIZ_task_mm	0x00000008
+#define AOFF_task_active_mm	0x00000058
+#define ASIZ_task_active_mm	0x00000008
+#define AOFF_task_has_cpu	0x00000060
 #define ASIZ_task_has_cpu	0x00000004
-#define AOFF_task_processor	0x00000044
+#define AOFF_task_processor	0x00000064
 #define ASIZ_task_processor	0x00000004
-#define AOFF_task_last_processor	0x00000048
-#define ASIZ_task_last_processor	0x00000004
-#define AOFF_task_lock_depth	0x0000004c
-#define ASIZ_task_lock_depth	0x00000004
-#define AOFF_task_next_task	0x00000050
+#define AOFF_task_run_list	0x00000068
+#define ASIZ_task_run_list	0x00000010
+#define AOFF_task_next_task	0x00000078
 #define ASIZ_task_next_task	0x00000008
-#define AOFF_task_prev_task	0x00000058
+#define AOFF_task_prev_task	0x00000080
 #define ASIZ_task_prev_task	0x00000008
-#define AOFF_task_run_list	0x00000060
-#define ASIZ_task_run_list	0x00000010
-#define AOFF_task_binfmt	0x00000070
+#define AOFF_task_last_processor	0x00000088
+#define ASIZ_task_last_processor	0x00000004
+#define AOFF_task_binfmt	0x00000090
 #define ASIZ_task_binfmt	0x00000008
-#define AOFF_task_exit_code	0x00000078
+#define AOFF_task_exit_code	0x00000098
 #define ASIZ_task_exit_code	0x00000004
-#define AOFF_task_exit_signal	0x0000007c
+#define AOFF_task_exit_signal	0x0000009c
 #define ASIZ_task_exit_signal	0x00000004
-#define AOFF_task_pdeath_signal	0x00000080
+#define AOFF_task_pdeath_signal	0x000000a0
 #define ASIZ_task_pdeath_signal	0x00000004
-#define AOFF_task_personality	0x00000088
+#define AOFF_task_personality	0x000000a8
 #define ASIZ_task_personality	0x00000008
-#define AOFF_task_pid	0x00000094
+#define AOFF_task_pid	0x000000b4
 #define ASIZ_task_pid	0x00000004
-#define AOFF_task_pgrp	0x00000098
+#define AOFF_task_pgrp	0x000000b8
 #define ASIZ_task_pgrp	0x00000004
-#define AOFF_task_tty_old_pgrp	0x0000009c
+#define AOFF_task_tty_old_pgrp	0x000000bc
 #define ASIZ_task_tty_old_pgrp	0x00000004
-#define AOFF_task_session	0x000000a0
+#define AOFF_task_session	0x000000c0
 #define ASIZ_task_session	0x00000004
-#define AOFF_task_leader	0x000000a4
+#define AOFF_task_leader	0x000000c4
 #define ASIZ_task_leader	0x00000004
-#define AOFF_task_p_opptr	0x000000a8
+#define AOFF_task_p_opptr	0x000000c8
 #define ASIZ_task_p_opptr	0x00000008
-#define AOFF_task_p_pptr	0x000000b0
+#define AOFF_task_p_pptr	0x000000d0
 #define ASIZ_task_p_pptr	0x00000008
-#define AOFF_task_p_cptr	0x000000b8
+#define AOFF_task_p_cptr	0x000000d8
 #define ASIZ_task_p_cptr	0x00000008
-#define AOFF_task_p_ysptr	0x000000c0
+#define AOFF_task_p_ysptr	0x000000e0
 #define ASIZ_task_p_ysptr	0x00000008
-#define AOFF_task_p_osptr	0x000000c8
+#define AOFF_task_p_osptr	0x000000e8
 #define ASIZ_task_p_osptr	0x00000008
-#define AOFF_task_pidhash_next	0x000000d0
+#define AOFF_task_pidhash_next	0x000000f0
 #define ASIZ_task_pidhash_next	0x00000008
-#define AOFF_task_pidhash_pprev	0x000000d8
+#define AOFF_task_pidhash_pprev	0x000000f8
 #define ASIZ_task_pidhash_pprev	0x00000008
-#define AOFF_task_wait_chldexit	0x000000e0
+#define AOFF_task_wait_chldexit	0x00000100
 #define ASIZ_task_wait_chldexit	0x00000030
-#define AOFF_task_vfork_sem	0x00000110
+#define AOFF_task_vfork_sem	0x00000130
 #define ASIZ_task_vfork_sem	0x00000008
-#define AOFF_task_policy	0x00000118
-#define ASIZ_task_policy	0x00000008
-#define AOFF_task_rt_priority	0x00000120
+#define AOFF_task_rt_priority	0x00000138
 #define ASIZ_task_rt_priority	0x00000008
-#define AOFF_task_it_real_value	0x00000128
+#define AOFF_task_it_real_value	0x00000140
 #define ASIZ_task_it_real_value	0x00000008
-#define AOFF_task_it_prof_value	0x00000130
+#define AOFF_task_it_prof_value	0x00000148
 #define ASIZ_task_it_prof_value	0x00000008
-#define AOFF_task_it_virt_value	0x00000138
+#define AOFF_task_it_virt_value	0x00000150
 #define ASIZ_task_it_virt_value	0x00000008
-#define AOFF_task_it_real_incr	0x00000140
+#define AOFF_task_it_real_incr	0x00000158
 #define ASIZ_task_it_real_incr	0x00000008
-#define AOFF_task_it_prof_incr	0x00000148
+#define AOFF_task_it_prof_incr	0x00000160
 #define ASIZ_task_it_prof_incr	0x00000008
-#define AOFF_task_it_virt_incr	0x00000150
+#define AOFF_task_it_virt_incr	0x00000168
 #define ASIZ_task_it_virt_incr	0x00000008
-#define AOFF_task_real_timer	0x00000158
+#define AOFF_task_real_timer	0x00000170
 #define ASIZ_task_real_timer	0x00000028
-#define AOFF_task_times	0x00000180
+#define AOFF_task_times	0x00000198
 #define ASIZ_task_times	0x00000020
-#define AOFF_task_start_time	0x000001a0
+#define AOFF_task_start_time	0x000001b8
 #define ASIZ_task_start_time	0x00000008
-#define AOFF_task_per_cpu_utime	0x000001a8
+#define AOFF_task_per_cpu_utime	0x000001c0
 #define ASIZ_task_per_cpu_utime	0x00000100
-#define AOFF_task_min_flt	0x000003a8
+#define AOFF_task_min_flt	0x000003c0
 #define ASIZ_task_min_flt	0x00000008
-#define AOFF_task_maj_flt	0x000003b0
+#define AOFF_task_maj_flt	0x000003c8
 #define ASIZ_task_maj_flt	0x00000008
-#define AOFF_task_nswap	0x000003b8
+#define AOFF_task_nswap	0x000003d0
 #define ASIZ_task_nswap	0x00000008
-#define AOFF_task_cmin_flt	0x000003c0
+#define AOFF_task_cmin_flt	0x000003d8
 #define ASIZ_task_cmin_flt	0x00000008
-#define AOFF_task_cmaj_flt	0x000003c8
+#define AOFF_task_cmaj_flt	0x000003e0
 #define ASIZ_task_cmaj_flt	0x00000008
-#define AOFF_task_cnswap	0x000003d0
+#define AOFF_task_cnswap	0x000003e8
 #define ASIZ_task_cnswap	0x00000008
-#define AOFF_task_uid	0x000003dc
+#define AOFF_task_uid	0x000003f4
 #define ASIZ_task_uid	0x00000004
-#define AOFF_task_euid	0x000003e0
+#define AOFF_task_euid	0x000003f8
 #define ASIZ_task_euid	0x00000004
-#define AOFF_task_suid	0x000003e4
+#define AOFF_task_suid	0x000003fc
 #define ASIZ_task_suid	0x00000004
-#define AOFF_task_fsuid	0x000003e8
+#define AOFF_task_fsuid	0x00000400
 #define ASIZ_task_fsuid	0x00000004
-#define AOFF_task_gid	0x000003ec
+#define AOFF_task_gid	0x00000404
 #define ASIZ_task_gid	0x00000004
-#define AOFF_task_egid	0x000003f0
+#define AOFF_task_egid	0x00000408
 #define ASIZ_task_egid	0x00000004
-#define AOFF_task_sgid	0x000003f4
+#define AOFF_task_sgid	0x0000040c
 #define ASIZ_task_sgid	0x00000004
-#define AOFF_task_fsgid	0x000003f8
+#define AOFF_task_fsgid	0x00000410
 #define ASIZ_task_fsgid	0x00000004
-#define AOFF_task_ngroups	0x000003fc
+#define AOFF_task_ngroups	0x00000414
 #define ASIZ_task_ngroups	0x00000004
-#define AOFF_task_groups	0x00000400
+#define AOFF_task_groups	0x00000418
 #define ASIZ_task_groups	0x00000080
-#define AOFF_task_cap_effective	0x00000480
+#define AOFF_task_cap_effective	0x00000498
 #define ASIZ_task_cap_effective	0x00000004
-#define AOFF_task_cap_inheritable	0x00000484
+#define AOFF_task_cap_inheritable	0x0000049c
 #define ASIZ_task_cap_inheritable	0x00000004
-#define AOFF_task_cap_permitted	0x00000488
+#define AOFF_task_cap_permitted	0x000004a0
 #define ASIZ_task_cap_permitted	0x00000004
-#define AOFF_task_user	0x00000490
+#define AOFF_task_user	0x000004a8
 #define ASIZ_task_user	0x00000008
-#define AOFF_task_rlim	0x00000498
+#define AOFF_task_rlim	0x000004b0
 #define ASIZ_task_rlim	0x000000a0
-#define AOFF_task_used_math	0x00000538
+#define AOFF_task_used_math	0x00000550
 #define ASIZ_task_used_math	0x00000002
-#define AOFF_task_comm	0x0000053a
+#define AOFF_task_comm	0x00000552
 #define ASIZ_task_comm	0x00000010
-#define AOFF_task_link_count	0x0000054c
+#define AOFF_task_link_count	0x00000564
 #define ASIZ_task_link_count	0x00000004
-#define AOFF_task_tty	0x00000550
+#define AOFF_task_tty	0x00000568
 #define ASIZ_task_tty	0x00000008
-#define AOFF_task_semundo	0x00000558
+#define AOFF_task_semundo	0x00000570
 #define ASIZ_task_semundo	0x00000008
-#define AOFF_task_semsleeping	0x00000560
+#define AOFF_task_semsleeping	0x00000578
 #define ASIZ_task_semsleeping	0x00000008
-#define AOFF_task_thread	0x00000570
+#define AOFF_task_thread	0x00000580
 #define ASIZ_task_thread	0x00000460
-#define AOFF_task_fs	0x000009d0
+#define AOFF_task_fs	0x000009e0
 #define ASIZ_task_fs	0x00000008
-#define AOFF_task_files	0x000009d8
+#define AOFF_task_files	0x000009e8
 #define ASIZ_task_files	0x00000008
-#define AOFF_task_mm	0x000009e0
-#define ASIZ_task_mm	0x00000008
-#define AOFF_task_active_mm	0x000009e8
-#define ASIZ_task_active_mm	0x00000008
 #define AOFF_task_sigmask_lock	0x000009f0
 #define ASIZ_task_sigmask_lock	0x0000000c
 #define AOFF_task_sig	0x00000a00
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- v2.3.39/linux/include/asm-sparc64/floppy.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc64/floppy.h	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.23 1999/09/21 14:39:34 davem Exp $
+/* $Id: floppy.h,v 1.24 2000/01/09 15:16:34 ecd Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -574,7 +574,6 @@
 		struct linux_ebus_device *edev = 0;
 		unsigned long config = 0;
 		unsigned long auxio_reg;
-		unsigned char cfg;
 
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
@@ -669,9 +668,7 @@
 			return sun_floppy_types[0];
 
 		/* Enable PC-AT mode. */
-		cfg = ns87303_readb(config, ASC);
-		cfg |= 0xc0;
-		ns87303_writeb(config, ASC, cfg);
+		ns87303_modify(config, ASC, 0, 0xc0);
 
 #ifdef PCI_FDC_SWAP_DRIVES
 		/*
@@ -682,15 +679,9 @@
 			 * Set the drive exchange bit in FCR on NS87303,
 			 * make shure other bits are sane before doing so.
 			 */
-			cfg = ns87303_readb(config, FER);
-			cfg &= ~(FER_EDM);
-			ns87303_writeb(config, FER, cfg);
-			cfg = ns87303_readb(config, ASC);
-			cfg &= ~(ASC_DRV2_SEL);
-			ns87303_writeb(config, ASC, cfg);
-			cfg = ns87303_readb(config, FCR);
-			cfg |= FCR_LDE;
-			ns87303_writeb(config, FCR, cfg);
+			ns87303_modify(config, FER, FER_EDM, 0);
+			ns87303_modify(config, ASC, ASC_DRV2_SEL, 0);
+			ns87303_modify(config, FCR, 0, FCR_LDE);
 
 			cfg = sun_floppy_types[0];
 			sun_floppy_types[0] = sun_floppy_types[1];
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/ipcbuf.h linux/include/asm-sparc64/ipcbuf.h
--- v2.3.39/linux/include/asm-sparc64/ipcbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/ipcbuf.h	Thu Jan 13 12:03:00 2000
@@ -0,0 +1,28 @@
+#ifndef _SPARC64_IPCBUF_H
+#define _SPARC64_IPCBUF_H
+
+/* 
+ * The ipc64_perm structure for sparc64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit seq
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t	key;
+	__kernel_uid_t	uid;
+	__kernel_gid_t	gid;
+	__kernel_uid_t	cuid;
+	__kernel_gid_t	cgid;
+	__kernel_mode_t	mode; 
+	unsigned short	__pad1;
+	unsigned short	seq;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
+#endif /* _SPARC64_IPCBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/msgbuf.h linux/include/asm-sparc64/msgbuf.h
--- v2.3.39/linux/include/asm-sparc64/msgbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/msgbuf.h	Thu Jan 13 12:03:00 2000
@@ -0,0 +1,27 @@
+#ifndef _SPARC64_MSGBUF_H
+#define _SPARC64_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for sparc64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm msg_perm;
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	__kernel_time_t msg_ctime;	/* last change time */
+	unsigned long  msg_cbytes;	/* current number of bytes on queue */
+	unsigned long  msg_qnum;	/* number of messages in queue */
+	unsigned long  msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	unsigned long  __unused1;
+	unsigned long  __unused2;
+};
+
+#endif /* _SPARC64_MSGBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/ns87303.h linux/include/asm-sparc64/ns87303.h
--- v2.3.39/linux/include/asm-sparc64/ns87303.h	Sun Oct  4 10:22:44 1998
+++ linux/include/asm-sparc64/ns87303.h	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: ns87303.h,v 1.2 1998/09/13 15:38:50 ecd Exp $
+/* $Id: ns87303.h,v 1.3 2000/01/09 15:16:34 ecd Exp $
  * ns87303.h: Configuration Register Description for the
  *            National Semiconductor PC87303 (SuperIO).
  *
@@ -45,7 +45,7 @@
 #define FCR_LDE		0x10	/* Logical Drive Exchange                    */
 #define FCR_ZWS_ENA	0x20	/* Enable short host read/write in ECP/EPP   */
 
-/* Printer Controll Register (PCR) bits */
+/* Printer Control Register (PCR) bits */
 #define PCR_EPP_ENABLE	0x01
 #define PCR_EPP_IEEE	0x02	/* Enable EPP Version 1.9 (IEEE 1284)        */
 #define PCR_ECP_ENABLE	0x04
@@ -61,27 +61,51 @@
 #define ASC_LPT_IRQ7	0x01	/* Allways use IRQ7 for LPT                  */
 #define ASC_DRV2_SEL	0x02	/* Logical Drive Exchange controlled by TDR  */
 
+#define FER_RESERVED	0x00
+#define FAR_RESERVED	0x00
+#define PTR_RESERVED	0x73
+#define FCR_RESERVED	0xc4
+#define PCR_RESERVED	0x10
+#define KRR_RESERVED	0x00
+#define PMC_RESERVED	0x98
+#define TUP_RESERVED	0xfb
+#define SIP_RESERVED	0x00
+#define ASC_RESERVED	0x18
+#define CS0CF0_RESERVED	0x00
+#define CS0CF1_RESERVED	0x08
+#define CS1CF0_RESERVED	0x00
+#define CS1CF1_RESERVED	0x08
+
 #ifdef __KERNEL__
 
 #include <asm/system.h>
 #include <asm/io.h>
 
-static __inline__ void ns87303_writeb(unsigned long port, int index,
-				     unsigned char value)
+static __inline__ int ns87303_modify(unsigned long port, unsigned int index,
+				     unsigned char clr, unsigned char set)
 {
+	static unsigned char reserved[] = {
+		FER_RESERVED, FAR_RESERVED, PTR_RESERVED, FCR_RESERVED,
+		PCR_RESERVED, KRR_RESERVED, PMC_RESERVED, TUP_RESERVED,
+		SIP_RESERVED, ASC_RESERVED, CS0CF0_RESERVED, CS0CF1_RESERVED,
+		CS1CF0_RESERVED, CS1CF1_RESERVED
+	};
 	unsigned long flags;
+	unsigned char value;
+
+	if (index > 0x0d)
+		return -EINVAL;
 
 	save_flags(flags); cli();
 	outb(index, port);
+	value = inb(port + 1);
+	value &= ~(reserved[index] | clr);
+	value |= set;
 	outb(value, port + 1);
 	outb(value, port + 1);
 	restore_flags(flags);
-}
 
-static __inline__ unsigned char ns87303_readb(unsigned long port, int index)
-{
-	outb(index, port);
-	return inb(port + 1);
+	return 0;
 }
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/parport.h linux/include/asm-sparc64/parport.h
--- v2.3.39/linux/include/asm-sparc64/parport.h	Tue Aug 31 17:29:14 1999
+++ linux/include/asm-sparc64/parport.h	Thu Jan 13 12:03:00 2000
@@ -1,4 +1,4 @@
-/* $Id: parport.h,v 1.5 1999/08/30 10:14:52 davem Exp $
+/* $Id: parport.h,v 1.6 2000/01/09 15:16:34 ecd Exp $
  * parport.h: sparc64 specific parport initialization and dma.
  *
  * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
@@ -19,8 +19,6 @@
 #define __maybe_initdata __initdata
 #endif
 
-#undef HAVE_SLOW_DEVICES
-
 #define PARPORT_PC_MAX_PORTS	PARPORT_MAX
 
 static struct linux_ebus_dma *sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
@@ -33,7 +31,7 @@
 	writel(EBUS_DCSR_RESET, &sparc_ebus_dmas[dmanr]->dcsr);
 	udelay(1);
 	dcsr = EBUS_DCSR_BURST_SZ_16 | EBUS_DCSR_TCI_DIS |
-	       EBUS_DCSR_EN_CNT;
+	       EBUS_DCSR_EN_CNT | EBUS_DCSR_INT_EN;
 	writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
 }
 
@@ -62,11 +60,8 @@
 		writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
 
 		dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
-		if (dcsr & EBUS_DCSR_ERR_PEND) {
+		if (dcsr & EBUS_DCSR_ERR_PEND)
 			reset_dma(dmanr);
-			dcsr &= ~(EBUS_DCSR_ERR_PEND);
-		}
-		writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
 	}
 }
 
@@ -105,15 +100,11 @@
 static __inline__ int
 get_dma_residue(unsigned int dmanr)
 {
-	unsigned int dcsr;
 	int res;
 
 	res = readl(&sparc_ebus_dmas[dmanr]->dbcr);
-	if (res != 0) {
-		dcsr = readl(&sparc_ebus_dmas[dmanr]->dcsr);
+	if (res != 0)
 		reset_dma(dmanr);
-		writel(dcsr, &sparc_ebus_dmas[dmanr]->dcsr);
-	}
 	return res;
 }
 
@@ -136,36 +127,25 @@
 			if (!strcmp(edev->prom_name, "ecpp")) {
 				unsigned long base = edev->resource[0].start;
 				unsigned long config = edev->resource[1].start;
-				unsigned char cfg;
 
 				sparc_ebus_dmas[count] =
 						(struct linux_ebus_dma *)
 							edev->resource[2].start;
 				reset_dma(count);
 
+				/* Configure IRQ to Push Pull, Level Low */
 				/* Enable ECP, set bit 2 of the CTR first */
 				outb(0x04, base + 0x02);
-				cfg = ns87303_readb(config, PCR);
-				cfg |= (PCR_ECP_ENABLE | PCR_ECP_CLK_ENA);
-				ns87303_writeb(config, PCR, cfg);
+				ns87303_modify(config, PCR,
+					       PCR_EPP_ENABLE |
+					       PCR_IRQ_ODRAIN,
+					       PCR_ECP_ENABLE |
+					       PCR_ECP_CLK_ENA |
+					       PCR_IRQ_POLAR);
 
 				/* CTR bit 5 controls direction of port */
-				cfg = ns87303_readb(config, PTR);
-				cfg |= PTR_LPT_REG_DIR;
-				ns87303_writeb(config, PTR, cfg);
-
-				/* Configure IRQ to Push Pull, Level Low */
-				cfg = ns87303_readb(config, PCR);
-				cfg &= ~(PCR_IRQ_ODRAIN);
-				cfg |= PCR_IRQ_POLAR;
-				ns87303_writeb(config, PCR, cfg);
-
-#ifndef HAVE_SLOW_DEVICES
-				/* Enable Zero Wait State for ECP */
-				cfg = ns87303_readb(config, FCR);
-				cfg |= FCR_ZWS_ENA;
-				ns87303_writeb(config, FCR, cfg);
-#endif
+				ns87303_modify(config, PTR,
+					       0, PTR_LPT_REG_DIR);
 
 				if (parport_pc_probe_port(base, base + 0x400,
 							  edev->irqs[0],
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/pci.h linux/include/asm-sparc64/pci.h
--- v2.3.39/linux/include/asm-sparc64/pci.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc64/pci.h	Thu Jan 13 12:03:00 2000
@@ -9,6 +9,9 @@
  */
 #define pcibios_assign_all_busses()	0
 
+#define PCIBIOS_MIN_IO		0UL
+#define PCIBIOS_MIN_MEM		0UL
+
 struct pci_dev;
 
 /* Allocate and map kernel buffer using consistant mode DMA for PCI device.
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/posix_types.h linux/include/asm-sparc64/posix_types.h
--- v2.3.39/linux/include/asm-sparc64/posix_types.h	Wed Mar 10 16:53:38 1999
+++ linux/include/asm-sparc64/posix_types.h	Sat Jan 15 22:08:29 2000
@@ -29,6 +29,13 @@
 typedef int                    __kernel_daddr_t;
 typedef long                   __kernel_off_t;
 typedef char *                 __kernel_caddr_t;
+typedef unsigned short	       __kernel_uid16_t;
+typedef unsigned short	       __kernel_gid16_t;
+
+typedef __kernel_uid_t 	       __kernel_old_uid_t;
+typedef __kernel_gid_t         __kernel_old_gid_t;
+typedef __kernel_uid_t	       __kernel_uid32_t;
+typedef __kernel_gid_t	       __kernel_gid32_t;
 
 /* Note this piece of asymmetry from the v9 ABI.  */
 typedef int		       __kernel_suseconds_t;
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/sembuf.h linux/include/asm-sparc64/sembuf.h
--- v2.3.39/linux/include/asm-sparc64/sembuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/sembuf.h	Thu Jan 13 12:03:00 2000
@@ -0,0 +1,22 @@
+#ifndef _SPARC64_SEMBUF_H
+#define _SPARC64_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for sparc64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+	__kernel_time_t	sem_otime;		/* last semop time */
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
+#endif /* _SPARC64_SEMBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/shmbuf.h linux/include/asm-sparc64/shmbuf.h
--- v2.3.39/linux/include/asm-sparc64/shmbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/shmbuf.h	Thu Jan 13 12:03:00 2000
@@ -0,0 +1,38 @@
+#ifndef _SPARC64_SHMBUF_H
+#define _SPARC64_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for sparc64 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	__kernel_time_t		shm_ctime;	/* last change time */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _SPARC64_SHMBUF_H */
diff -u --recursive --new-file v2.3.39/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- v2.3.39/linux/include/asm-sparc64/unistd.h	Fri Jan  7 19:13:22 2000
+++ linux/include/asm-sparc64/unistd.h	Fri Jan 14 14:52:08 2000
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.37 2000/01/05 07:37:55 jj Exp $ */
+/* $Id: unistd.h,v 1.39 2000/01/11 17:34:05 jj Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -46,11 +46,11 @@
 #define __NR_sigaltstack	 28 /* Common					   */
 #define __NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */
 #define __NR_utime               30 /* Implemented via utimes() under SunOS        */
-/* #define __NR_stty             31    Implemented via ioctl() under SunOS         */
-/* #define __NR_gtty             32    Implemented via ioctl() under SunOS         */
+/* #define __NR_lchown32         31    Linux sparc32 specific                      */
+/* #define __NR_fchown32         32    Linux sparc32 specific                      */
 #define __NR_access              33 /* Common                                      */
 #define __NR_nice                34 /* Implemented via get/setpriority() in SunOS  */
-/* #define __NR_ftime            35    Implemented via gettimeofday() in SunOS     */
+/* #define __NR_chown32          35    Linux sparc32 specific                      */
 #define __NR_sync                36 /* Common                                      */
 #define __NR_kill                37 /* Common                                      */
 #define __NR_stat                38 /* Common                                      */
@@ -59,7 +59,7 @@
 #define __NR_dup                 41 /* Common                                      */
 #define __NR_pipe                42 /* Common                                      */
 #define __NR_times               43 /* Implemented via getrusage() in SunOS        */
-/* #define __NR_profil           44    Common                                      */
+/* #define __NR_getuid32         44    Linux sparc32 specific                      */
 #define __NR_umount2             45 /* Linux Specific                              */
 #define __NR_setgid              46 /* Implemented via setregid() in SunOS         */
 #define __NR_getgid              47 /* Common                                      */
@@ -68,7 +68,7 @@
 #define __NR_getegid             50 /* SunOS calls getgid()                        */
 #define __NR_acct                51 /* Common                                      */
 #define __NR_memory_ordering	 52 /* Linux Specific				   */
-/* #define __NR_mctl             53    SunOS specific                              */
+/* #define __NR_getgid32         53    Linux sparc32 specific                      */
 #define __NR_ioctl               54 /* Common                                      */
 #define __NR_reboot              55 /* Common                                      */
 /* #define __NR_mmap2		 56    Linux sparc32 Specific                      */
@@ -84,32 +84,32 @@
 #define __NR_vfork               66 /* Common                                      */
 #define __NR_pread               67 /* Linux Specific                              */
 #define __NR_pwrite              68 /* Linux Specific                              */
-/* #define __NR_sbrk             69    SunOS Specific                              */
-/* #define __NR_sstk             70    SunOS Specific                              */
+/* #define __NR_geteuid32        69    Linux sparc32, sbrk under SunOS             */
+/* #define __NR_getegid32        70    Linux sparc32, sstk under SunOS             */
 #define __NR_mmap                71 /* Common                                      */
-/* #define __NR_vadvise          72    SunOS Specific                              */
+/* #define __NR_setreuid32       72    Linux sparc32, vadvise under SunOS          */
 #define __NR_munmap              73 /* Common                                      */
 #define __NR_mprotect            74 /* Common                                      */
-/* #define __NR_madvise          75    SunOS Specific                              */
+#define __NR_madvise             75 /* Common                                      */
 #define __NR_vhangup             76 /* Common                                      */
 /* #define __NR_truncate64       77    Linux sparc32 Specific			   */
-/* #define __NR_mincore          78    SunOS Specific                              */
+#define __NR_mincore             78 /* Common                                      */
 #define __NR_getgroups           79 /* Common                                      */
 #define __NR_setgroups           80 /* Common                                      */
 #define __NR_getpgrp             81 /* Common                                      */
-/* #define __NR_setpgrp          82    setpgid, same difference...                 */
+/* #define __NR_setgroups32      82    Linux sparc32, setpgrp under SunOS          */
 #define __NR_setitimer           83 /* Common                                      */
 /* #define __NR_ftruncate64      84    Linux sparc32 Specific			   */
 #define __NR_swapon              85 /* Common                                      */
 #define __NR_getitimer           86 /* Common                                      */
-/* #define __NR_gethostname      87    SunOS Specific                              */
+/* #define __NR_setuid32         87    Linux sparc32, gethostname under SunOS      */
 #define __NR_sethostname         88 /* Common                                      */
-/* #define __NR_getdtablesize    89    SunOS Specific                              */
+/* #define __NR_setgid32         89    Linux sparc32, getdtablesize under SunOS    */
 #define __NR_dup2                90 /* Common                                      */
-/* #define __NR_getdopt          91    SunOS Specific                              */
+/* #define __NR_setfsuid32       91    Linux sparc32, getdopt under SunOS          */
 #define __NR_fcntl               92 /* Common                                      */
 #define __NR_select              93 /* Common                                      */
-/* #define __NR_setdopt          94    SunOS Specific                              */
+/* #define __NR_setfsgid32       94    Linux sparc32, setdopt under SunOS          */
 #define __NR_fsync               95 /* Common                                      */
 #define __NR_setpriority         96 /* Common                                      */
 #define __NR_socket              97 /* Common                                      */
@@ -123,14 +123,14 @@
 #define __NR_rt_sigtimedwait    105 /* Linux Specific                              */
 #define __NR_rt_sigqueueinfo    106 /* Linux Specific                              */
 #define __NR_rt_sigsuspend      107 /* Linux Specific                              */
-/* #define __NR_sigvec          108    SunOS Specific                              */
-/* #define __NR_sigblock        109    SunOS Specific                              */
-/* #define __NR_sigsetmask      110    SunOS Specific                              */
-/* #define __NR_sigpause        111    SunOS Specific                              */
-/* #define __NR_sigstack        112    SunOS Specific                              */
+#define __NR_setresuid          108 /* Linux Specific, sigvec under SunOS	   */
+#define __NR_getresuid          109 /* Linux Specific, sigblock under SunOS	   */
+#define __NR_setresgid          110 /* Linux Specific, sigsetmask under SunOS	   */
+#define __NR_getresgid          111 /* Linux Specific, sigpause under SunOS	   */
+/* #define __NR_setregid32       75    Linux sparc32, sigstack under SunOS         */
 #define __NR_recvmsg            113 /* Common                                      */
 #define __NR_sendmsg            114 /* Common                                      */
-/* #define __NR_vtrace          115    SunOS Specific                              */
+/* #define __NR_getgroups32     115    Linux sparc32, vtrace under SunOS           */
 #define __NR_gettimeofday       116 /* Common                                      */
 #define __NR_getrusage          117 /* Common                                      */
 #define __NR_getsockopt         118 /* Common                                      */
diff -u --recursive --new-file v2.3.39/linux/include/linux/acpi.h linux/include/linux/acpi.h
--- v2.3.39/linux/include/linux/acpi.h	Thu Jan  6 12:57:48 2000
+++ linux/include/linux/acpi.h	Thu Jan 20 16:06:39 2000
@@ -356,6 +356,8 @@
 	ACPI_GPE_LEVEL,
 	ACPI_EVENT,
 	ACPI_P_BLK,
+	ACPI_ENTER_LVL2_LAT,
+	ACPI_ENTER_LVL3_LAT,
 	ACPI_P_LVL2_LAT,
 	ACPI_P_LVL3_LAT,
 	ACPI_S0_SLP_TYP,
@@ -400,5 +402,33 @@
 
 #define ACPI_PIIX4_PMREGMISC	0x80
 #define	  ACPI_PIIX4_PMIOSE	0x01
+
+/*
+ * VIA-specific ACPI info (for systems with VT82C586B but no ACPI tables)
+ */
+
+#define ACPI_VIA_INT_MODEL     0x00
+
+#define ACPI_VIA_SMI_CMD       0x002f
+#define ACPI_VIA_ACPI_ENABLE   0xa1
+#define ACPI_VIA_ACPI_DISABLE  0xa0
+
+#define ACPI_VIA_PM1_EVT       0x0000
+#define ACPI_VIA_PM1_CNT       0x0004
+#define ACPI_VIA_PM_TMR	       0x0008
+#define ACPI_VIA_GPE0	       0x0020
+#define ACPI_VIA_P_BLK	       0x0010
+
+#define ACPI_VIA_PM1_EVT_LEN   0x04
+#define ACPI_VIA_PM1_CNT_LEN   0x02
+#define ACPI_VIA_PM_TM_LEN     0x04
+#define ACPI_VIA_GPE0_LEN      0x04
+
+#define ACPI_VIA_DUTY_OFFSET   1
+#define ACPI_VIA_DUTY_WIDTH    3
+
+#define ACPI_VIA_DAY_ALARM     0x7d
+#define ACPI_VIA_MON_ALARM     0x7e
+#define ACPI_VIA_CENTURY       0x7f
 
 #endif /* _LINUX_ACPI_H */
diff -u --recursive --new-file v2.3.39/linux/include/linux/blkdev.h linux/include/linux/blkdev.h
--- v2.3.39/linux/include/linux/blkdev.h	Tue Dec 14 01:27:24 1999
+++ linux/include/linux/blkdev.h	Thu Jan 20 16:05:41 2000
@@ -104,7 +104,8 @@
 extern struct sec_size * blk_sec[MAX_BLKDEV];
 extern struct blk_dev_struct blk_dev[MAX_BLKDEV];
 extern wait_queue_head_t wait_for_request;
-extern void resetup_one_dev(struct gendisk *dev, int drive);
+extern void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size);
+extern void register_disk(struct gendisk *dev, kdev_t first, unsigned minors, struct block_device_operations *ops, long size);
 extern void unplug_device(void * data);
 extern void make_request(int major,int rw, struct buffer_head * bh);
 
diff -u --recursive --new-file v2.3.39/linux/include/linux/byteorder/generic.h linux/include/linux/byteorder/generic.h
--- v2.3.39/linux/include/linux/byteorder/generic.h	Tue Sep  1 10:50:11 1998
+++ linux/include/linux/byteorder/generic.h	Thu Jan 20 10:48:36 2000
@@ -129,7 +129,7 @@
  * also have a macro for them in case some strange program
  * wants to take the address of the thing or something..
  *
- * Note that these traditionally return a "long", even though
+ * Note that these used to return a "long" in libc5, even though
  * long is often 64-bit these days.. Thus the casts.
  *
  * They have to be macros in order to do the constant folding
@@ -146,9 +146,14 @@
  * Do the prototypes. Somebody might want to take the
  * address or some such sick thing..
  */
+#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
+extern __u32			ntohl(__u32);
+extern __u32			htonl(__u32);
+#else
 extern unsigned long int	ntohl(unsigned long int);
-extern unsigned short int	ntohs(unsigned short int);
 extern unsigned long int	htonl(unsigned long int);
+#endif
+extern unsigned short int	ntohs(unsigned short int);
 extern unsigned short int	htons(unsigned short int);
 
 
@@ -159,9 +164,14 @@
 #define ___ntohl(x) __be32_to_cpu(x)
 #define ___ntohs(x) __be16_to_cpu(x)
 
+#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2)
+#define htonl(x) ___htonl(x)
+#define ntohl(x) ___ntohl(x)
+#else
 #define htonl(x) ((unsigned long)___htonl(x))
-#define htons(x) ___htons(x)
 #define ntohl(x) ((unsigned long)___ntohl(x))
+#endif
+#define htons(x) ___htons(x)
 #define ntohs(x) ___ntohs(x)
 
 #endif /* OPTIMIZE */
diff -u --recursive --new-file v2.3.39/linux/include/linux/capability.h linux/include/linux/capability.h
--- v2.3.39/linux/include/linux/capability.h	Fri Oct 15 15:25:14 1999
+++ linux/include/linux/capability.h	Thu Jan 20 16:05:32 2000
@@ -89,9 +89,9 @@
 /* Overrides the following restrictions that the effective user ID
    shall match the file owner ID when setting the S_ISUID and S_ISGID
    bits on that file; that the effective group ID (or one of the
-   supplementary group IDs shall match the file owner ID when setting
+   supplementary group IDs) shall match the file owner ID when setting
    the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are
-   cleared on successful return from chown(2). */
+   cleared on successful return from chown(2) (not implemented). */
 
 #define CAP_FSETID           4
 
diff -u --recursive --new-file v2.3.39/linux/include/linux/cyclades.h linux/include/linux/cyclades.h
--- v2.3.39/linux/include/linux/cyclades.h	Mon Oct  4 15:49:30 1999
+++ linux/include/linux/cyclades.h	Mon Jan 17 22:19:08 2000
@@ -1,4 +1,4 @@
-/* $Revision: 2.6 $$Date: 1998/08/10 16:57:01 $
+/* $Revision: 3.0 $$Date: 1998/11/02 14:20:59 $
  * linux/include/linux/cyclades.h
  *
  * This file was initially written by
@@ -7,6 +7,9 @@
  *
  * This file contains the general definitions for the cyclades.c driver
  *$Log: cyclades.h,v $
+ *Revision 3.0  1998/11/02 14:20:59  ivan
+ *added nports field on cyclades_card structure;
+ *
  *Revision 2.5  1998/08/03 16:57:01  ivan
  *added cyclades_idle_stats structure;
  * 
@@ -502,6 +505,7 @@
     int irq;
     int num_chips;	/* 0 if card absent, -1 if Z/PCI, else Y */
     int first_line;	/* minor number of first channel on card */
+    int nports;		/* Number of ports in the card */
     int bus_index;	/* address shift - 0 for ISA, 1 for PCI */
     int	intr_enabled;	/* FW Interrupt flag - 0 disabled, 1 enabled */
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.3.39/linux/include/linux/elf.h linux/include/linux/elf.h
--- v2.3.39/linux/include/linux/elf.h	Fri Oct 15 15:25:14 1999
+++ linux/include/linux/elf.h	Thu Jan 20 16:05:55 2000
@@ -78,6 +78,10 @@
  */
 #define EM_ALPHA	0x9026
 
+/*
+ * This is an interim value for S390 architecture
+ */
+#define EM_S390         0xA390
 
 /* This is the info that is needed to parse the dynamic section of the file */
 #define DT_NULL		0
diff -u --recursive --new-file v2.3.39/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.3.39/linux/include/linux/fb.h	Fri Jan  7 19:13:23 2000
+++ linux/include/linux/fb.h	Sun Jan 16 10:54:22 2000
@@ -197,6 +197,12 @@
 	__u32 framebuffer;
 };
 
+/* VESA Blanking Levels */
+#define VESA_NO_BLANKING        0
+#define VESA_VSYNC_SUSPEND      1
+#define VESA_HSYNC_SUSPEND      2
+#define VESA_POWERDOWN          3
+
 struct fb_monspecs {
 	__u32 hfmin;			/* hfreq lower limit (Hz) */
 	__u32 hfmax; 			/* hfreq upper limit (Hz) */
@@ -261,9 +267,13 @@
    char modename[40];			/* default video mode */
    kdev_t node;
    int flags;
+   int open;                            /* Has this been open already ? */
 #define FBINFO_FLAG_MODULE	1	/* Low-level driver is a module */
+   struct fb_var_screeninfo var;        /* Current var */
+   struct fb_fix_screeninfo fix;        /* Current fix */
+   struct fb_monspecs monspecs;         /* Current Monitor specs */
    struct fb_ops *fbops;
-   struct fb_monspecs monspecs;
+   char *screen_base;                   /* Virtual address */
    struct display *disp;		/* initial display variable */
    struct vc_data *display_fg;		/* Console visible on this display */
    char fontname[40];			/* default font name */
@@ -275,8 +285,11 @@
    void (*blank)(int, struct fb_info*);	/* tell fb to (un)blank the screen */
 					/* arg = 0: unblank */
 					/* arg > 0: VESA level (arg-1) */
-
+   void *pseudo_palette;                /* Fake palette of 16 colors and 
+					   the cursor's color for non
+                                           palette mode */
    /* From here on everything is device dependent */
+   void *par;	
 };
 
 #ifdef MODULE
@@ -382,13 +395,6 @@
 		       struct fb_info *fb_info);
 extern struct fb_cmap *fb_default_cmap(int len);
 extern void fb_invert_cmaps(void);
-
-/* VESA Blanking Levels */
-#define VESA_NO_BLANKING	0
-#define VESA_VSYNC_SUSPEND	1
-#define VESA_HSYNC_SUSPEND	2
-#define VESA_POWERDOWN		3
-
 
 struct fb_videomode {
     const char *name;	/* optional */
diff -u --recursive --new-file v2.3.39/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.39/linux/include/linux/fs.h	Tue Jan 11 22:31:44 2000
+++ linux/include/linux/fs.h	Thu Jan 20 16:05:31 2000
@@ -773,7 +773,6 @@
 extern struct block_device *bdget(dev_t);
 extern void bdput(struct block_device *);
 extern int blkdev_open(struct inode *, struct file *);
-extern int blkdev_close(struct inode *, struct file *);
 extern struct file_operations def_blk_fops;
 extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
 extern int blkdev_get(struct block_device *, mode_t, unsigned, int);
@@ -1025,7 +1024,6 @@
 
 extern ssize_t char_read(struct file *, char *, size_t, loff_t *);
 extern ssize_t block_read(struct file *, char *, size_t, loff_t *);
-extern int block_fsync(struct file *, struct dentry *);
 extern int read_ahead[];
 
 extern ssize_t char_write(struct file *, const char *, size_t, loff_t *);
diff -u --recursive --new-file v2.3.39/linux/include/linux/genhd.h linux/include/linux/genhd.h
--- v2.3.39/linux/include/linux/genhd.h	Thu Aug 12 12:26:06 1999
+++ linux/include/linux/genhd.h	Thu Jan 20 16:05:26 2000
@@ -53,9 +53,7 @@
 	int minor_shift;		/* number of times minor is shifted to
 					   get real minor */
 	int max_p;			/* maximum partitions per device */
-	int max_nr;			/* maximum number of real devices */
 
-	void (*init)(struct gendisk *);	/* Initialization called before we do our thing */
 	struct hd_struct *part;		/* [indexed by minor] */
 	int *sizes;			/* [idem], device size in blocks */
 	int nr_real;			/* number of real devices */
diff -u --recursive --new-file v2.3.39/linux/include/linux/hdreg.h linux/include/linux/hdreg.h
--- v2.3.39/linux/include/linux/hdreg.h	Mon Dec 20 18:48:22 1999
+++ linux/include/linux/hdreg.h	Thu Jan 20 16:05:29 2000
@@ -59,8 +59,8 @@
 #define WIN_CHECKPOWERMODE1	0xE5
 #define WIN_CHECKPOWERMODE2	0x98
 
-#define WIN_DOORLOCK		0xde	/* lock door on removable drives */
-#define WIN_DOORUNLOCK		0xdf	/* unlock door on removable drives */
+#define WIN_DOORLOCK		0xDE	/* lock door on removable drives */
+#define WIN_DOORUNLOCK		0xDF	/* unlock door on removable drives */
 
 #define WIN_MULTREAD		0xC4	/* read sectors using multiple mode */
 #define WIN_MULTWRITE		0xC5	/* write sectors using multiple mode */
@@ -68,20 +68,24 @@
 #define WIN_IDENTIFY		0xEC	/* ask drive to identify itself	*/
 #define WIN_IDENTIFY_DMA	0xEE	/* same as WIN_IDENTIFY, but DMA */
 #define WIN_SETFEATURES		0xEF	/* set special drive features */
-#define WIN_READDMA		0xc8	/* read sectors using DMA transfers */
-#define WIN_WRITEDMA		0xca	/* write sectors using DMA transfers */
+#define WIN_READDMA		0xC8	/* read sectors using DMA transfers */
+#define WIN_WRITEDMA		0xCA	/* write sectors using DMA transfers */
+
+#define WIN_QUEUED_SERVICE	0xA2	/* */
+#define WIN_READDMA_QUEUED	0xC7	/* read sectors using Queued DMA transfers */
+#define WIN_WRITEDMA_QUEUED	0xCC	/* write sectors using Queued DMA transfers */
 
 #define WIN_READ_BUFFER		0xE4	/* force read only 1 sector */
 #define WIN_WRITE_BUFFER	0xE8	/* force write only 1 sector */
 
-#define WIN_SMART		0xb0	/* self-monitoring and reporting */
+#define WIN_SMART		0xB0	/* self-monitoring and reporting */
 
 /* Additional drive command codes used by ATAPI devices. */
 #define WIN_PIDENTIFY		0xA1	/* identify ATAPI device	*/
 #define WIN_SRST		0x08	/* ATAPI soft reset command */
-#define WIN_PACKETCMD		0xa0	/* Send a packet command. */
+#define WIN_PACKETCMD		0xA0	/* Send a packet command. */
 
-#define EXABYTE_ENABLE_NEST	0xf0
+#define EXABYTE_ENABLE_NEST	0xF0
 
 /* WIN_SMART sub-commands */
 
@@ -227,32 +231,43 @@
 	unsigned short  eide_dma_time;	/* recommended mword dma cycle time (ns) */
 	unsigned short  eide_pio;       /* min cycle time (ns), no IORDY  */
 	unsigned short  eide_pio_iordy; /* min cycle time (ns), with IORDY */
-	unsigned short  word69;
-	unsigned short  word70;
+#if 0
+	unsigned short  words69_74[6];	/* reserved words 69-74 */
+#else
+	unsigned short  word69;		/* reserved (word 69) */
+	unsigned short  word70;		/* reserved (word 70) */
 	/* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
-	unsigned short  word71;
-	unsigned short  word72;
-	unsigned short  word73;
-	unsigned short  word74;
-	unsigned short  word75;
-	unsigned short  word76;
-	unsigned short  word77;
-	unsigned short  word78;
-	unsigned short  word79;
-	unsigned short  word80;
-	unsigned short  word81;
-	unsigned short  command_sets;	/* bits 0:Smart 1:Security 2:Removable 3:PM */
-	unsigned short  word83;		/* bits 14:Smart Enabled 13:0 zero */
-	unsigned short  word84;
-	unsigned short  word85;
-	unsigned short  word86;
-	unsigned short  word87;
-	unsigned short  dma_ultra;
+	unsigned short  word71;		/* reserved (word 71) */
+	unsigned short  word72;		/* reserved (word 72) */
+	unsigned short  word73;		/* reserved (word 73) */
+	unsigned short  word74;		/* reserved (word 74) */
+#endif
+	unsigned short  queue_depth;	/*  */
+#if 0
+	unsigned short  words76_79[4];	/* reserved words 76-79 */
+#else
+	unsigned short  word76;		/* reserved (word 76) */
+	unsigned short  word77;		/* reserved (word 77) */
+	unsigned short  word78;		/* reserved (word 78) */
+	unsigned short  word79;		/* reserved (word 79) */
+#endif
+	unsigned short  major_rev_num;	/*  */
+	unsigned short  minor_rev_num;	/*  */
+	unsigned short  command_set_1;	/* bits 0:Smart 1:Security 2:Removable 3:PM */
+	unsigned short  command_set_2;	/* bits 14:Smart Enabled 13:0 zero */
+	unsigned short  cfsse;		/* command set-feature supported extensions */
+	unsigned short  cfs_enable_1;	/* command set-feature enabled */
+	unsigned short  cfs_enable_2;	/* command set-feature enabled */
+	unsigned short  csf_default;	/* command set-feature default */
+	unsigned short  dma_ultra;	/*  */
 	unsigned short	word89;		/* reserved (word 89) */
 	unsigned short	word90;		/* reserved (word 90) */
-	unsigned short	word91;		/* reserved (word 91) */
+	unsigned short	CurAPMvalues;	/* current APM values */
 	unsigned short	word92;		/* reserved (word 92) */
-	unsigned short	word93;		/* reserved (word 93) */
+	unsigned short	hw_config;	/* hardware config */
+#if 0
+	unsigned short  words94_126[34];/* reserved words 94-126 */
+#else
 	unsigned short	word94;		/* reserved (word 94) */
 	unsigned short	word95;		/* reserved (word 95) */
 	unsigned short	word96;		/* reserved (word 96) */
@@ -286,9 +301,27 @@
 	unsigned short	word124;	/* reserved (word 124) */
 	unsigned short	word125;	/* reserved (word 125) */
 	unsigned short	word126;	/* reserved (word 126) */
+#endif
 	unsigned short	word127;	/* reserved (word 127) */
-	unsigned short	security;	/* bits 0:support 1:enabled 2:locked 3:frozen */
-	unsigned short	reserved[127];
+	unsigned short	dlf;		/* device lock function
+					 * 15:9	reserved
+					 * 8	security level 1:max 0:high
+					 * 7:6	reserved
+					 * 5	enhanced erase
+					 * 4	expire
+					 * 3	frozen
+					 * 2	locked
+					 * 1	en/disabled
+					 * 0	capability
+					 */
+	unsigned short  csfo;		/* current set features options
+					 * 15:4	reserved
+					 * 3	auto reassign
+					 * 2	reverting
+					 * 1	read-look-ahead
+					 * 0	write cache
+					 */
+	unsigned short	reserved[126];
 };
 
 /*
diff -u --recursive --new-file v2.3.39/linux/include/linux/hfs_fs.h linux/include/linux/hfs_fs.h
--- v2.3.39/linux/include/linux/hfs_fs.h	Wed Aug 18 16:45:40 1999
+++ linux/include/linux/hfs_fs.h	Thu Jan 20 16:08:20 2000
@@ -140,6 +140,19 @@
 			*order[HFS_HDR_MAX];	/* 'descr' ordered by offset */
 };
 
+/* header layout for netatalk's v1 appledouble file format */
+struct hfs_nat_hdr {
+	hfs_lword_t	magic;
+	hfs_lword_t	version;
+	hfs_byte_t	homefs[16];
+	hfs_word_t	entries;
+	hfs_byte_t	descrs[12*5];
+	hfs_byte_t	real_name[255];	/* id=3 */
+	hfs_byte_t	comment[200];	/* id=4 XXX: not yet implemented */
+	hfs_byte_t	old_info[16];	/* id=7 */
+	hfs_u8		finderinfo[32]; /* id=9 */
+};
+
 /* 
  * Default header layout for Netatalk and AppleDouble
  */
diff -u --recursive --new-file v2.3.39/linux/include/linux/highuid.h linux/include/linux/highuid.h
--- v2.3.39/linux/include/linux/highuid.h	Tue Jan 11 22:31:44 2000
+++ linux/include/linux/highuid.h	Thu Jan 20 16:05:29 2000
@@ -1,25 +1,27 @@
 #ifndef _LINUX_HIGHUID_H
 #define _LINUX_HIGHUID_H
 
+#include <linux/config.h>
 #include <linux/types.h>
 
 /*
  * general notes:
  *
- * UID16_COMPAT_NEEDED is defined in include/asm-{arch}/posix_types.h
- * if the given architecture needs to support backwards compatibility
- * for old system calls.
+ * CONFIG_UID16 is defined if the given architecture needs to
+ * support backwards compatibility for old system calls.
  *
- * old_uid_t and old_gid_t are only used if UID16_COMPAT_NEEDED
- * is defined.
+ * kernel code should use uid_t and gid_t at all times when dealing with
+ * kernel-private data.
+ *
+ * old_uid_t and old_gid_t should only be different if CONFIG_UID16 is
+ * defined, else the platform should provide dummy typedefs for them
+ * such that they are equivalent to __kernel_{u,g}id_t.
  *
  * uid16_t and gid16_t are used on all architectures. (when dealing
  * with structures hard coded to 16 bits, such as in filesystems)
  */
 
 
-#ifdef UID16_COMPAT_NEEDED
-
 /*
  * This is the "overflow" UID and GID. They are used to signify uid/gid
  * overflow to old programs when they request uid/gid information but are
@@ -36,6 +38,7 @@
 #define DEFAULT_OVERFLOWUID	65534
 #define DEFAULT_OVERFLOWGID	65534
 
+#ifdef CONFIG_UID16
 
 /* prevent uid mod 65536 effect by returning a default value for high UIDs */
 #define high2lowuid(uid) ((uid) > 65535) ? (old_uid_t)overflowuid : (old_uid_t)(uid)
@@ -54,11 +57,19 @@
 #define NEW_TO_OLD_UID(uid)	high2lowuid(uid)
 #define NEW_TO_OLD_GID(gid)	high2lowgid(gid)
 
+/* specific to fs/stat.c */
 #define SET_OLDSTAT_UID(stat, uid)	(stat).st_uid = high2lowuid(uid)
 #define SET_OLDSTAT_GID(stat, gid)	(stat).st_gid = high2lowgid(gid)
 #define SET_STAT_UID(stat, uid)		(stat).st_uid = high2lowuid(uid)
 #define SET_STAT_GID(stat, gid)		(stat).st_gid = high2lowgid(gid)
 
+/* specific to kernel/signal.c */
+#ifdef UID16_SIGINFO_COMPAT_NEEDED
+#define SET_SIGINFO_UID16(var, uid)	var = high2lowuid(uid)
+#else
+#define SET_SIGINFO_UID16(var, uid)	do { ; } while (0)
+#endif
+
 #else
 
 #define SET_UID16(var, uid)	do { ; } while (0)
@@ -71,9 +82,9 @@
 #define SET_STAT_UID(stat, uid)		(stat).st_uid = uid
 #define SET_STAT_GID(stat, gid)		(stat).st_gid = gid
 
-#define high2lowuid(x)		(x)
+#define SET_SIGINFO_UID16(var, uid)	do { ; } while (0)
 
-#endif /* UID16_COMPAT_NEEDED */
+#endif /* CONFIG_UID16 */
 
 
 /*
diff -u --recursive --new-file v2.3.39/linux/include/linux/ide.h linux/include/linux/ide.h
--- v2.3.39/linux/include/linux/ide.h	Fri Jan  7 19:13:23 2000
+++ linux/include/linux/ide.h	Thu Jan 20 16:05:38 2000
@@ -513,17 +513,17 @@
  */
 #define IDE_SUBDRIVER_VERSION	1
 
-typedef int	(ide_cleanup_proc)(ide_drive_t *);
-typedef ide_startstop_t (ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long);
-typedef void	(ide_end_request_proc)(byte, ide_hwgroup_t *);
-typedef int 	(ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
-typedef int	(ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
-typedef void 	(ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
-typedef int	(ide_check_media_change_proc)(ide_drive_t *);
-typedef void	(ide_pre_reset_proc)(ide_drive_t *);
-typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
-typedef ide_startstop_t (ide_special_proc)(ide_drive_t *);
-typedef void	(ide_setting_proc)(ide_drive_t *);
+typedef int		(ide_cleanup_proc)(ide_drive_t *);
+typedef ide_startstop_t	(ide_do_request_proc)(ide_drive_t *, struct request *, unsigned long);
+typedef void		(ide_end_request_proc)(byte, ide_hwgroup_t *);
+typedef int		(ide_ioctl_proc)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
+typedef int		(ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
+typedef void		(ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
+typedef int		(ide_check_media_change_proc)(ide_drive_t *);
+typedef void		(ide_pre_reset_proc)(ide_drive_t *);
+typedef unsigned long	(ide_capacity_proc)(ide_drive_t *);
+typedef ide_startstop_t	(ide_special_proc)(ide_drive_t *);
+typedef void		(ide_setting_proc)(ide_drive_t *);
 
 typedef struct ide_driver_s {
 	const char			*name;
@@ -757,7 +757,6 @@
 int  ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
 void ide_timer_expiry (unsigned long data);
 void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
-void ide_geninit (struct gendisk *gd);
 void do_ide0_request (request_queue_t * q);
 #if MAX_HWIFS > 1
 void do_ide1_request (request_queue_t * q);
@@ -831,7 +830,7 @@
 #endif /* CONFIG_BLK_DEV_OFFBOARD */
 
 unsigned long ide_find_free_region (unsigned short size) __init;
-void ide_scan_pcibus (void) __init;
+void ide_scan_pcibus (int scan_direction) __init;
 #endif
 #ifdef CONFIG_BLK_DEV_IDEDMA
 #define BAD_DMA_DRIVE		0
diff -u --recursive --new-file v2.3.39/linux/include/linux/init.h linux/include/linux/init.h
--- v2.3.39/linux/include/linux/init.h	Tue Jan  4 13:57:21 2000
+++ linux/include/linux/init.h	Thu Jan 20 16:05:29 2000
@@ -1,6 +1,8 @@
 #ifndef _LINUX_INIT_H
 #define _LINUX_INIT_H
 
+#include <linux/config.h>
+
 /* These macros are used to mark some functions or 
  * initialized data (doesn't apply to uninitialized data)
  * as `initialization' functions. The kernel can take this
@@ -68,9 +70,9 @@
  * or exit time.
  */
 #define __init		__attribute__ ((__section__ (".text.init")))
-#define __exit		__attribute__ ((unused, __section__(".text.init")))
+#define __exit		__attribute__ ((unused, __section__(".text.exit")))
 #define __initdata	__attribute__ ((__section__ (".data.init")))
-#define __exitdata	__attribute__ ((unused, __section__ (".data.init")))
+#define __exitdata	__attribute__ ((unused, __section__ (".data.exit")))
 #define __initsetup	__attribute__ ((unused,__section__ (".setup.init")))
 #define __init_call	__attribute__ ((unused,__section__ (".initcall.init")))
 
@@ -111,6 +113,18 @@
 #define __initlocaldata  __initdata
 #else
 #define __initlocaldata
+#endif
+
+#ifdef CONFIG_HOTPLUG
+#define __devinit
+#define __devinitdata
+#define __devexit
+#define __devexitdata
+#else
+#define __devinit __init
+#define __devinitdata __initdata
+#define __devexit __exit
+#define __devexitdata __exitdata
 #endif
 
 #endif /* _LINUX_INIT_H */
diff -u --recursive --new-file v2.3.39/linux/include/linux/input.h linux/include/linux/input.h
--- v2.3.39/linux/include/linux/input.h	Fri Jan  7 19:13:23 2000
+++ linux/include/linux/input.h	Thu Jan 20 09:48:48 2000
@@ -284,6 +284,13 @@
 #define BTN_START		0x13b
 #define BTN_MODE		0x13c
 
+#define BTN_DIGI		0x140
+#define BTN_PEN			0x140
+#define BTN_RUBBER		0x141
+#define BTN_PEN_SIDE		0x142
+#define BTN_PEN_SIDE2		0x143
+#define BTN_NEAR		0x144
+
 #define KEY_MAX			0x1ff
 
 /*
@@ -319,16 +326,18 @@
 #define ABS_HAT2Y		0x15
 #define ABS_HAT3X		0x16
 #define ABS_HAT3Y		0x17
-#define ABS_MISC		0x18
+#define ABS_PRESSURE		0x18
+#define ABS_DISTANCE		0x19
+#define ABS_MISC		0x1a
 #define ABS_MAX			0x1f
 
 /*
  * LEDs
  */
 
-#define LED_SCROLLL		0x00
-#define LED_NUML		0x01
-#define LED_CAPSL		0x02
+#define LED_NUML		0x00
+#define LED_CAPSL		0x01
+#define LED_SCROLLL		0x02
 #define LED_COMPOSE		0x03
 #define LED_KANA		0x04
 #define LED_MAX			0x0f
diff -u --recursive --new-file v2.3.39/linux/include/linux/isapnp.h linux/include/linux/isapnp.h
--- v2.3.39/linux/include/linux/isapnp.h	Tue Jan 11 22:31:44 2000
+++ linux/include/linux/isapnp.h	Thu Jan 20 16:05:26 2000
@@ -128,7 +128,9 @@
 	struct isapnp_resources *next;	/* next resource */
 };
 
-#if defined(CONFIG_ISAPNP) || (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
+#if defined(CONFIG_ISAPNP) || defined(CONFIG_ISAPNP_MODULE)
+
+#define __ISAPNP__
 
 /* lowlevel configuration */
 int isapnp_present(void);
diff -u --recursive --new-file v2.3.39/linux/include/linux/kbd_kern.h linux/include/linux/kbd_kern.h
--- v2.3.39/linux/include/linux/kbd_kern.h	Wed Aug 18 16:43:33 1999
+++ linux/include/linux/kbd_kern.h	Thu Jan 20 16:06:43 2000
@@ -69,6 +69,8 @@
 
 extern int do_poke_blanked_console;
 
+extern void (*kbd_ledfunc)(unsigned int led);
+
 extern inline void show_console(void)
 {
 	do_poke_blanked_console = 1;
diff -u --recursive --new-file v2.3.39/linux/include/linux/major.h linux/include/linux/major.h
--- v2.3.39/linux/include/linux/major.h	Fri Jan  7 19:13:23 2000
+++ linux/include/linux/major.h	Thu Jan 20 10:48:35 2000
@@ -108,7 +108,11 @@
 #define SPECIALIX_NORMAL_MAJOR 75
 #define SPECIALIX_CALLOUT_MAJOR 76
 
+#define DASD_MAJOR      94	/* Official assignations from Peter */
+
 #define LVM_CHAR_MAJOR	109	/* Logical Volume Manager */
+
+#define MDISK_MAJOR     95	/* Official assignations from Peter */
 
 #define I2O_MAJOR		80	/* 80->87 */
 
diff -u --recursive --new-file v2.3.39/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.3.39/linux/include/linux/mm.h	Fri Jan  7 19:13:23 2000
+++ linux/include/linux/mm.h	Thu Jan 20 16:05:41 2000
@@ -44,7 +44,7 @@
 	struct vm_area_struct *vm_next;
 
 	pgprot_t vm_page_prot;
-	unsigned short vm_flags;
+	unsigned long vm_flags;
 
 	/* AVL tree of VM areas per task, sorted by address */
 	short vm_avl_height;
@@ -66,26 +66,26 @@
 /*
  * vm_flags..
  */
-#define VM_READ		0x0001	/* currently active flags */
-#define VM_WRITE	0x0002
-#define VM_EXEC		0x0004
-#define VM_SHARED	0x0008
-
-#define VM_MAYREAD	0x0010	/* limits for mprotect() etc */
-#define VM_MAYWRITE	0x0020
-#define VM_MAYEXEC	0x0040
-#define VM_MAYSHARE	0x0080
-
-#define VM_GROWSDOWN	0x0100	/* general info on the segment */
-#define VM_GROWSUP	0x0200
-#define VM_SHM		0x0400	/* shared memory area, don't swap out */
-#define VM_DENYWRITE	0x0800	/* ETXTBSY on write attempts.. */
-
-#define VM_EXECUTABLE	0x1000
-#define VM_LOCKED	0x2000
-#define VM_IO           0x4000  /* Memory mapped I/O or similar */
+#define VM_READ		0x00000001	/* currently active flags */
+#define VM_WRITE	0x00000002
+#define VM_EXEC		0x00000004
+#define VM_SHARED	0x00000008
+
+#define VM_MAYREAD	0x00000010	/* limits for mprotect() etc */
+#define VM_MAYWRITE	0x00000020
+#define VM_MAYEXEC	0x00000040
+#define VM_MAYSHARE	0x00000080
+
+#define VM_GROWSDOWN	0x00000100	/* general info on the segment */
+#define VM_GROWSUP	0x00000200
+#define VM_SHM		0x00000400	/* shared memory area, don't swap out */
+#define VM_DENYWRITE	0x00000800	/* ETXTBSY on write attempts.. */
+
+#define VM_EXECUTABLE	0x00001000
+#define VM_LOCKED	0x00002000
+#define VM_IO           0x00004000  /* Memory mapped I/O or similar */
 
-#define VM_STACK_FLAGS	0x0177
+#define VM_STACK_FLAGS	0x00000177
 
 /*
  * mapping from the currently active vm_flags protection bits (the
diff -u --recursive --new-file v2.3.39/linux/include/linux/module.h linux/include/linux/module.h
--- v2.3.39/linux/include/linux/module.h	Tue Dec 14 01:27:24 1999
+++ linux/include/linux/module.h	Thu Jan 20 16:05:29 2000
@@ -188,6 +188,10 @@
 __attribute__((section(".modinfo"))) =		\
 "parm_desc_" __MODULE_STRING(var) "=" desc
 
+#define MODULE_DEVICE_TABLE(type,name)	\
+const struct type##_device_id * __module_##type##_device_table = name
+/* not put to .modinfo section to avoid section type conflicts */
+
 /* The attributes of a section are set the first time the section is
    seen; we want .modinfo to not be allocated.  */
 
@@ -218,6 +222,7 @@
 #define MODULE_SUPPORTED_DEVICE(name)
 #define MODULE_PARM(var,type)
 #define MODULE_PARM_DESC(var,desc)
+#define MODULE_DEVICE_TABLE(type,name)
 
 #ifndef __GENKSYMS__
 
diff -u --recursive --new-file v2.3.39/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h
--- v2.3.39/linux/include/linux/ncp_fs.h	Tue Jan 11 22:31:44 2000
+++ linux/include/linux/ncp_fs.h	Thu Jan 20 16:07:58 2000
@@ -37,6 +37,20 @@
 	__u32 directory_id;
 };
 
+struct ncp_fs_info_v2 {
+	int version;
+	unsigned long mounted_uid;
+	unsigned int connection;
+	unsigned int buffer_size;
+
+	unsigned int volume_number;
+	__u32 directory_id;
+
+	__u32 dummy1;
+	__u32 dummy2;
+	__u32 dummy3;
+};
+
 struct ncp_sign_init
 {
 	char sign_root[8];
@@ -90,19 +104,15 @@
 };
 
 #define	NCP_IOC_NCPREQUEST		_IOR('n', 1, struct ncp_ioctl_request)
-#define	NCP_IOC_GETMOUNTUID		_IOW('n', 2, __kernel_uid_t)
-
-#if 1
-#ifdef __KERNEL__
-/* remove after ncpfs-2.0.13 gets released or at the beginning of kernel-2.1. codefreeze */
-#define	NCP_IOC_GETMOUNTUID_INT		_IOW('n', 2, unsigned int)
-#endif
-#endif
+#define	NCP_IOC_GETMOUNTUID		_IOW('n', 2, __kernel_old_uid_t)
+#define NCP_IOC_GETMOUNTUID2		_IOW('n', 2, unsigned long)
 
 #define NCP_IOC_CONN_LOGGED_IN          _IO('n', 3)
 
-#define NCP_GET_FS_INFO_VERSION (1)
+#define NCP_GET_FS_INFO_VERSION    (1)
 #define NCP_IOC_GET_FS_INFO             _IOWR('n', 4, struct ncp_fs_info)
+#define NCP_GET_FS_INFO_VERSION_V2 (2)
+#define NCP_IOC_GET_FS_INFO_V2		_IOWR('n', 4, struct ncp_fs_info_v2)
 
 #define NCP_IOC_SIGN_INIT		_IOR('n', 5, struct ncp_sign_init)
 #define NCP_IOC_SIGN_WANTED		_IOR('n', 6, int)
@@ -123,8 +133,6 @@
 
 #define NCP_IOC_GETDENTRYTTL		_IOW('n', 12, __u32)
 #define NCP_IOC_SETDENTRYTTL		_IOR('n', 12, __u32)
-
-#define	NCP_IOC_GETMOUNTUID32		_IOW('n', 13, __kernel_uid32_t)
 
 /*
  * The packet size to allocate. One page should be enough.
diff -u --recursive --new-file v2.3.39/linux/include/linux/ncp_fs_sb.h linux/include/linux/ncp_fs_sb.h
--- v2.3.39/linux/include/linux/ncp_fs_sb.h	Wed Dec  8 14:11:28 1999
+++ linux/include/linux/ncp_fs_sb.h	Thu Jan 20 16:05:26 2000
@@ -18,7 +18,7 @@
 
 struct ncp_server {
 
-	struct ncp_mount_data m;	/* Nearly all of the mount data is of
+	struct ncp_mount_data_kernel m;	/* Nearly all of the mount data is of
 					   interest for us later, so we store
 					   it completely. */
 
diff -u --recursive --new-file v2.3.39/linux/include/linux/ncp_mount.h linux/include/linux/ncp_mount.h
--- v2.3.39/linux/include/linux/ncp_mount.h	Sat Oct  9 11:47:50 1999
+++ linux/include/linux/ncp_mount.h	Thu Jan 20 16:05:26 2000
@@ -40,4 +40,50 @@
 	__kernel_mode_t dir_mode;
 };
 
+#define NCP_MOUNT_VERSION_V4	(4)
+
+struct ncp_mount_data_v4 {
+	int version;
+	unsigned long flags;	/* NCP_MOUNT_* flags */
+	/* MIPS uses long __kernel_uid_t, but... */
+	/* we neever pass -1, so it is safe */
+	unsigned long mounted_uid;	/* Who may umount() this filesystem? */
+	/* MIPS uses long __kernel_pid_t */
+	long wdog_pid;		/* Who cares for our watchdog packets? */
+
+	unsigned int ncp_fd;	/* The socket to the ncp port */
+	unsigned int time_out;	/* How long should I wait after
+				   sending a NCP request? */
+	unsigned int retry_count;	/* And how often should I retry? */
+
+	/* MIPS uses long __kernel_uid_t... */
+	/* we never pass -1, so it is safe */
+	unsigned long uid;
+	unsigned long gid;
+	/* MIPS uses unsigned long __kernel_mode_t */
+	unsigned long file_mode;
+	unsigned long dir_mode;
+};
+
+#ifdef __KERNEL__
+
+struct ncp_mount_data_kernel {
+	unsigned long    flags;		/* NCP_MOUNT_* flags */
+	unsigned int	 int_flags;	/* internal flags */
+#define NCP_IMOUNT_LOGGEDIN_POSSIBLE	0x0001
+	__kernel_uid32_t mounted_uid;	/* Who may umount() this filesystem? */
+	__kernel_pid_t   wdog_pid;		/* Who cares for our watchdog packets? */
+	unsigned int     ncp_fd;	/* The socket to the ncp port */
+	unsigned int     time_out;	/* How long should I wait after
+					   sending a NCP request? */
+	unsigned int     retry_count;	/* And how often should I retry? */
+	unsigned char	 mounted_vol[NCP_VOLNAME_LEN + 1];
+	__kernel_uid32_t uid;
+	__kernel_gid32_t gid;
+	__kernel_mode_t  file_mode;
+	__kernel_mode_t  dir_mode;
+};
+
+#endif /* __KERNEL__ */
+
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.3.39/linux/include/linux/pci.h	Tue Jan 11 22:31:44 2000
+++ linux/include/linux/pci.h	Thu Jan 20 16:05:26 2000
@@ -492,53 +492,42 @@
 #define pci_for_each_dev(dev) \
 	for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next))
 
+#define pci_for_each_dev_reverse(dev) \
+	for(dev = pci_dev_g(pci_devices.prev); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.prev))
+
 /* Helper functions for low-level code (drivers/pci/setup.c) */
 
 int pci_claim_resource(struct pci_dev *, int);
-void pci_assign_unassigned_resources(u32 min_io, u32 min_mem);
+void pci_assign_unassigned_resources(void);
 void pci_set_bus_ranges(void);
 void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
 		    int (*)(struct pci_dev *, u8, u8));
 
 /* New-style probing supporting hot-pluggable devices */
 
+struct pci_device_id {
+	unsigned int vendor, device;		/* Vendor and device ID or PCI_ANY_ID */
+	unsigned int subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
+	unsigned int class, class_mask;		/* (class,subclass,prog-if) triplet */
+	unsigned long driver_data;		/* Data private to the driver */
+};
+
 struct pci_driver {
 	struct list_head node;
 	char *name;
-	int (*probe)(struct pci_dev *dev);	/* New device inserted, check if known */
-	void (*remove)(struct pci_dev *dev);	/* Device removed */
+	const struct pci_device_id *id_table;	/* NULL if wants all devices */
+	int (*probe)(struct pci_dev *dev, const struct pci_device_id *id);	/* New device inserted */
+	void (*remove)(struct pci_dev *dev);	/* Device removed (NULL if not a hot-plug capable driver) */
 	void (*suspend)(struct pci_dev *dev);	/* Device suspended */
 	void (*resume)(struct pci_dev *dev);	/* Device woken up */
 };
 
-void pci_register_driver(struct pci_driver *);
+int pci_register_driver(struct pci_driver *);
 void pci_unregister_driver(struct pci_driver *);
 void pci_insert_device(struct pci_dev *, struct pci_bus *);
 void pci_remove_device(struct pci_dev *);
 struct pci_driver *pci_dev_driver(struct pci_dev *);
-
-/*
- * simple PCI probing for drivers (drivers/pci/helper.c)
- */
- 
-struct pci_simple_probe_entry;
-typedef int (*pci_simple_probe_callback) (struct pci_dev *dev, int match_num,
-				   	  const struct pci_simple_probe_entry *ent,
-					  void *drvr_data);
-
-struct pci_simple_probe_entry {
-	unsigned short vendor;	/* vendor id, PCI_ANY_ID, or 0 for last entry */
-	unsigned short device;	/* device id, PCI_ANY_ID, or 0 for last entry */
-	unsigned short subsys_vendor; /* subsystem vendor id, 0 for don't care */
-	unsigned short subsys_device; /* subsystem device id, 0 for don't care */
-	void *dev_data;		/* driver-private, entry-specific data */
-};
-
-int pci_simple_probe (const struct pci_simple_probe_entry *list,
-		      size_t match_limit, pci_simple_probe_callback cb,
-		      void *drvr_data);
-
-
+const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, struct pci_dev *dev);
 
 /*
  *  If the system does not have PCI, clearly these return errors.  Define
@@ -574,10 +563,6 @@
 
 extern inline void pci_set_master(struct pci_dev *dev) { }
 extern inline int pci_enable_device(struct pci_dev *dev) { return 0; }
-
-extern inline int pci_simple_probe (const struct pci_simple_probe_entry *list,
-	size_t match_limit, pci_simple_probe_callback cb, void *drvr_data)
-{ return 0; }
 
 #endif /* !CONFIG_PCI */
 
diff -u --recursive --new-file v2.3.39/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.3.39/linux/include/linux/pci_ids.h	Tue Jan 11 22:31:45 2000
+++ linux/include/linux/pci_ids.h	Fri Jan 14 00:50:53 2000
@@ -253,6 +253,12 @@
 #define PCI_DEVICE_ID_AMD_LANCE		0x2000
 #define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
 #define PCI_DEVICE_ID_AMD_SCSI		0x2020
+#define PCI_DEVICE_ID_AMD_FE_GATE_7006	0x7006
+#define PCI_DEVICE_ID_AMD_VIPER_7403	0x7403
+#define PCI_DEVICE_ID_AMD_VIPER_7408	0x7408
+#define PCI_DEVICE_ID_AMD_VIPER_7409	0x7409
+#define PCI_DEVICE_ID_AMD_VIPER_740B	0x740B
+#define PCI_DEVICE_ID_AMD_VIPER_740C	0x740C
 
 #define PCI_VENDOR_ID_TRIDENT		0x1023
 #define PCI_DEVICE_ID_TRIDENT_9320	0x9320
@@ -501,6 +507,7 @@
 #define PCI_DEVICE_ID_CMD_643		0x0643
 #define PCI_DEVICE_ID_CMD_646		0x0646
 #define PCI_DEVICE_ID_CMD_647		0x0647
+#define PCI_DEVICE_ID_CMD_648		0x0648
 #define PCI_DEVICE_ID_CMD_670		0x0670
 
 #define PCI_VENDOR_ID_VISION		0x1098
@@ -787,6 +794,7 @@
 #define PCI_DEVICE_ID_RICOH_RL5C465	0x0465
 #define PCI_DEVICE_ID_RICOH_RL5C466	0x0466
 #define PCI_DEVICE_ID_RICOH_RL5C475	0x0475
+#define PCI_DEVICE_ID_RICOH_RL5C476	0x0476
 #define PCI_DEVICE_ID_RICOH_RL5C478	0x0478
 
 #define PCI_VENDOR_ID_ARTOP		0x1191
diff -u --recursive --new-file v2.3.39/linux/include/linux/posix_types.h linux/include/linux/posix_types.h
--- v2.3.39/linux/include/linux/posix_types.h	Sun Dec 27 22:18:28 1998
+++ linux/include/linux/posix_types.h	Thu Jan 20 10:48:35 2000
@@ -1,15 +1,7 @@
 #ifndef _LINUX_POSIX_TYPES_H
 #define _LINUX_POSIX_TYPES_H
 
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-#ifndef NULL
-# define NULL		((void *) 0)
-#endif
+#include <linux/stddef.h>
 
 /*
  * This allows for 1024 file descriptors: if NR_OPEN is ever grown
diff -u --recursive --new-file v2.3.39/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.3.39/linux/include/linux/sched.h	Tue Jan 11 22:31:45 2000
+++ linux/include/linux/sched.h	Thu Jan 20 16:05:41 2000
@@ -120,10 +120,6 @@
 	int sched_priority;
 };
 
-#ifndef NULL
-#define NULL ((void *) 0)
-#endif
-
 #ifdef __KERNEL__
 
 #include <linux/spinlock.h>
diff -u --recursive --new-file v2.3.39/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- v2.3.39/linux/include/linux/smb_fs.h	Tue Jan 11 22:31:45 2000
+++ linux/include/linux/smb_fs.h	Thu Jan 20 16:07:57 2000
@@ -14,7 +14,7 @@
 /*
  * ioctl commands
  */
-#define	SMB_IOC_GETMOUNTUID		_IOR('u', 1, __kernel_uid_t)
+#define	SMB_IOC_GETMOUNTUID		_IOR('u', 1, __kernel_old_uid_t)
 #define SMB_IOC_NEWCONN                 _IOW('u', 2, struct smb_conn_opt)
 
 /* __kernel_uid_t can never change, so we have to use __kernel_uid32_t */
diff -u --recursive --new-file v2.3.39/linux/include/linux/smp.h linux/include/linux/smp.h
--- v2.3.39/linux/include/linux/smp.h	Sat Oct  9 11:47:50 1999
+++ linux/include/linux/smp.h	Thu Jan 20 16:05:30 2000
@@ -80,7 +80,7 @@
 #define smp_threads_ready			1
 #define kernel_lock()
 #define cpu_logical_map(cpu)			0
-#define smp_call_function(func,info,retry,wait)	0
+#define smp_call_function(func,info,retry,wait)	({ 0; })
 
 #endif
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/linux/spinlock.h linux/include/linux/spinlock.h
--- v2.3.39/linux/include/linux/spinlock.h	Fri Sep 10 23:57:37 1999
+++ linux/include/linux/spinlock.h	Thu Jan 20 16:05:28 2000
@@ -53,7 +53,7 @@
 
 #define spin_lock_init(lock)	do { } while(0)
 #define spin_lock(lock)		(void)(lock) /* Not "unused variable". */
-#define spin_trylock(lock)	(1)
+#define spin_trylock(lock)	({1; })
 #define spin_unlock_wait(lock)	do { } while(0)
 #define spin_unlock(lock)	do { } while(0)
 
diff -u --recursive --new-file v2.3.39/linux/include/linux/stddef.h linux/include/linux/stddef.h
--- v2.3.39/linux/include/linux/stddef.h	Sat Nov 23 02:29:04 1996
+++ linux/include/linux/stddef.h	Thu Jan 20 10:48:35 2000
@@ -2,7 +2,11 @@
 #define _LINUX_STDDEF_H
 
 #undef NULL
+#if defined(__cplusplus)
+#define NULL 0
+#else
 #define NULL ((void *)0)
+#endif
 
 #undef offsetof
 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
diff -u --recursive --new-file v2.3.39/linux/include/linux/string.h linux/include/linux/string.h
--- v2.3.39/linux/include/linux/string.h	Fri Jun 25 14:35:42 1999
+++ linux/include/linux/string.h	Thu Jan 20 16:05:36 2000
@@ -2,10 +2,7 @@
 #define _LINUX_STRING_H_
 
 #include <linux/types.h>	/* for size_t */
-
-#ifndef NULL
-#define NULL ((void *) 0)
-#endif
+#include <linux/stddef.h>	/* for NULL */
 
 #ifdef __cplusplus
 extern "C" {
diff -u --recursive --new-file v2.3.39/linux/include/linux/tty.h linux/include/linux/tty.h
--- v2.3.39/linux/include/linux/tty.h	Tue Jan  4 13:57:21 2000
+++ linux/include/linux/tty.h	Thu Jan 20 16:05:34 2000
@@ -348,6 +348,8 @@
 extern int lp_init(void);
 extern int pty_init(void);
 extern void tty_init(void);
+extern int mxser_init(void);
+extern int moxa_init(void);
 extern int ip2_init(void);
 extern int pcxe_init(void);
 extern int pc_init(void);
diff -u --recursive --new-file v2.3.39/linux/include/linux/types.h linux/include/linux/types.h
--- v2.3.39/linux/include/linux/types.h	Tue Jan 11 22:31:45 2000
+++ linux/include/linux/types.h	Thu Jan 20 16:05:26 2000
@@ -1,6 +1,7 @@
 #ifndef _LINUX_TYPES_H
 #define _LINUX_TYPES_H
 
+#include <linux/config.h>
 #include <linux/posix_types.h>
 #include <asm/types.h>
 
@@ -23,6 +24,12 @@
 typedef __kernel_uid16_t        uid16_t;
 typedef __kernel_gid16_t        gid16_t;
 
+#ifdef CONFIG_UID16
+/* This is defined by include/asm-{arch}/posix_types.h */
+typedef __kernel_old_uid_t	old_uid_t;
+typedef __kernel_old_gid_t	old_gid_t;
+#endif /* CONFIG_UID16 */
+
 /* libc5 includes this file to define uid_t, thus uid_t can never change
  * when it is included by non-kernel code
  */
@@ -30,10 +37,6 @@
 typedef __kernel_uid_t		uid_t;
 typedef __kernel_gid_t		gid_t;
 #endif /* __KERNEL__ */
-
-/* This is defined by include/asm-{arch}/posix_types.h */
-typedef __kernel_old_uid_t	old_uid_t;
-typedef __kernel_old_gid_t	old_gid_t;
 
 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
 typedef __kernel_loff_t		loff_t;
diff -u --recursive --new-file v2.3.39/linux/include/net/if_inet6.h linux/include/net/if_inet6.h
--- v2.3.39/linux/include/net/if_inet6.h	Thu Aug 26 13:05:41 1999
+++ linux/include/net/if_inet6.h	Fri Jan 14 11:25:21 2000
@@ -119,5 +119,59 @@
 
 	memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32));
 }
+
+extern __inline__ void ipv6_tr_mc_map(struct in6_addr *addr, char *buf)
+{
+	/* All nodes FF01::1, FF02::1, FF02::1:FFxx:xxxx */
+
+	if (((addr->s6_addr[0] == 0xFF) &&
+	    ((addr->s6_addr[1] == 0x01) || (addr->s6_addr[1] == 0x02)) &&
+	     (addr->s6_addr16[1] == 0) &&
+	     (addr->s6_addr32[1] == 0) &&
+	     (addr->s6_addr32[2] == 0) &&
+	     (addr->s6_addr16[6] == 0) &&
+	     (addr->s6_addr[15] == 1)) ||
+	    ((addr->s6_addr[0] == 0xFF) &&
+	     (addr->s6_addr[1] == 0x02) &&
+	     (addr->s6_addr16[1] == 0) &&
+	     (addr->s6_addr32[1] == 0) &&
+	     (addr->s6_addr16[4] == 0) &&
+	     (addr->s6_addr[10] == 0) &&
+	     (addr->s6_addr[11] == 1) &&
+	     (addr->s6_addr[12] == 0xff)))
+	{
+		buf[0]=0xC0;
+		buf[1]=0x00;
+		buf[2]=0x01;
+		buf[3]=0x00;
+		buf[4]=0x00;
+		buf[5]=0x00;
+	/* All routers FF0x::2 */
+	} else if ((addr->s6_addr[0] ==0xff) &&
+		((addr->s6_addr[1] & 0xF0) == 0) &&
+		(addr->s6_addr16[1] == 0) &&
+		(addr->s6_addr32[1] == 0) &&
+		(addr->s6_addr32[2] == 0) &&
+		(addr->s6_addr16[6] == 0) &&
+		(addr->s6_addr[15] == 2))
+	{
+		buf[0]=0xC0;
+		buf[1]=0x00;
+		buf[2]=0x02;
+		buf[3]=0x00;
+		buf[4]=0x00;
+		buf[5]=0x00;
+	} else {
+		unsigned char i ; 
+		
+		i = addr->s6_addr[15] & 7 ; 
+		buf[0]=0xC0;
+		buf[1]=0x00;
+		buf[2]=0x00;
+		buf[3]=0x01 << i ; 
+		buf[4]=0x00;
+		buf[5]=0x00;
+	}
+}
 #endif
 #endif
diff -u --recursive --new-file v2.3.39/linux/include/pcmcia/cisreg.h linux/include/pcmcia/cisreg.h
--- v2.3.39/linux/include/pcmcia/cisreg.h	Thu Nov 11 20:11:54 1999
+++ linux/include/pcmcia/cisreg.h	Tue Jan 18 22:29:17 2000
@@ -1,5 +1,5 @@
 /*
- * cisreg.h 1.14 1999/10/25 20:23:17
+ * cisreg.h 1.16 2000/01/16 19:19:14
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -30,7 +30,9 @@
 #ifndef _LINUX_CISREG_H
 #define _LINUX_CISREG_H
 
-/* Offsets from ConfigBase for CIS registers */
+/*
+ * Offsets from ConfigBase for CIS registers
+ */
 #define CISREG_COR		0x00
 #define CISREG_CCSR		0x02
 #define CISREG_PRR		0x04
@@ -112,5 +114,22 @@
 #define FEMR_BAM_ENA		0x0020
 #define FEMR_PWM_ENA		0x0040
 #define FEMR_WKUP_MASK		0x4000
+
+/*
+ * Indirect Addressing Registers for Zoomed Video: these are addresses
+ * in common memory space
+ */
+#define CISREG_ICTRL0		0x02	/* control registers */
+#define CISREG_ICTRL1		0x03
+#define CISREG_IADDR0		0x04	/* address registers */
+#define CISREG_IADDR1		0x05
+#define CISREG_IADDR2		0x06
+#define CISREG_IADDR3		0x07
+#define CISREG_IDATA0		0x08	/* data registers */
+#define CISREG_IDATA1		0x09
+
+#define ICTRL0_COMMON		0x01
+#define ICTRL0_AUTOINC		0x02
+#define ICTRL0_BYTEGRAN		0x04
 
 #endif /* _LINUX_CISREG_H */
diff -u --recursive --new-file v2.3.39/linux/include/pcmcia/cistpl.h linux/include/pcmcia/cistpl.h
--- v2.3.39/linux/include/pcmcia/cistpl.h	Tue Dec 14 01:27:24 1999
+++ linux/include/pcmcia/cistpl.h	Tue Jan 18 22:29:17 2000
@@ -1,5 +1,5 @@
 /*
- * cistpl.h 1.31 1999/10/25 20:23:17
+ * cistpl.h 1.32 2000/01/11 19:06:50
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -33,10 +33,13 @@
 #define CISTPL_NULL		0x00
 #define CISTPL_DEVICE		0x01
 #define CISTPL_LONGLINK_CB	0x02
+#define CISTPL_INDIRECT		0x03
 #define CISTPL_CONFIG_CB	0x04
 #define CISTPL_CFTABLE_ENTRY_CB	0x05
 #define CISTPL_LONGLINK_MFC	0x06
 #define CISTPL_BAR		0x07
+#define CISTPL_PWR_MGMNT	0x08
+#define CISTPL_EXTDEVICE	0x09
 #define CISTPL_CHECKSUM		0x10
 #define CISTPL_LONGLINK_A	0x11
 #define CISTPL_LONGLINK_C	0x12
@@ -67,6 +70,7 @@
 #define CISTPL_BATTERY		0x45
 /* Layer 3 tuples */
 #define CISTPL_ORG		0x46
+#define CISTPL_SPCL		0x90
 
 typedef struct cistpl_longlink_t {
     u_int	addr;
diff -u --recursive --new-file v2.3.39/linux/include/pcmcia/cs.h linux/include/pcmcia/cs.h
--- v2.3.39/linux/include/pcmcia/cs.h	Wed Dec 29 13:13:21 1999
+++ linux/include/pcmcia/cs.h	Tue Jan 11 21:49:26 2000
@@ -441,7 +441,7 @@
 int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req);
 int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req);
 int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req);
-int pcmcia_get_first_window(client_handle_t *handle, win_req_t *req);
+int pcmcia_get_first_window(window_handle_t *win, win_req_t *req);
 int pcmcia_get_next_window(window_handle_t *win, win_req_t *req);
 int pcmcia_get_status(client_handle_t handle, cs_status_t *status);
 int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
@@ -464,6 +464,7 @@
 int pcmcia_insert_card(client_handle_t handle, client_req_t *req);
 int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask);
 int pcmcia_report_error(client_handle_t handle, error_info_t *err);
+struct pci_bus *pcmcia_lookup_bus(client_handle_t handle);
 
 /* rsrc_mgr.c */
 int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj);
diff -u --recursive --new-file v2.3.39/linux/include/pcmcia/cs_types.h linux/include/pcmcia/cs_types.h
--- v2.3.39/linux/include/pcmcia/cs_types.h	Thu Nov 11 20:11:54 1999
+++ linux/include/pcmcia/cs_types.h	Tue Jan 18 22:29:17 2000
@@ -1,5 +1,5 @@
 /*
- * cs_types.h 1.16 1999/10/25 20:23:17
+ * cs_types.h 1.17 2000/01/18 01:14:36
  *
  * The contents of this file are subject to the Mozilla Public License
  * Version 1.1 (the "License"); you may not use this file except in
@@ -30,7 +30,11 @@
 #ifndef _LINUX_CS_TYPES_H
 #define _LINUX_CS_TYPES_H
 
+#ifdef __KERNEL__
 #include <linux/types.h>
+#else
+#include <sys/types.h>
+#endif
 
 typedef u_short	socket_t;
 typedef u_short	ioaddr_t;
diff -u --recursive --new-file v2.3.39/linux/include/pcmcia/version.h linux/include/pcmcia/version.h
--- v2.3.39/linux/include/pcmcia/version.h	Thu Nov 11 20:11:54 1999
+++ linux/include/pcmcia/version.h	Tue Jan 18 22:29:17 2000
@@ -1,4 +1,4 @@
-/* version.h 1.76 1999/10/26 18:55:56 (David Hinds) */
+/* version.h 1.81 1999/12/23 21:37:32 (David Hinds) */
 
-#define CS_RELEASE "3.1.4"
-#define CS_RELEASE_CODE 0x3104
+#define CS_RELEASE "3.1.9"
+#define CS_RELEASE_CODE 0x3109
diff -u --recursive --new-file v2.3.39/linux/init/main.c linux/init/main.c
--- v2.3.39/linux/init/main.c	Fri Jan  7 19:13:23 2000
+++ linux/init/main.c	Thu Jan 20 09:51:42 2000
@@ -61,6 +61,10 @@
 #include <net/irda/irda_device.h>
 #endif
 
+#ifdef CONFIG_X86_IO_APIC
+#include <asm/smp.h>
+#endif
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -426,7 +430,14 @@
 
 #ifndef __SMP__
 
+#ifdef CONFIG_X86_IO_APIC
+static void __init smp_init(void)
+{
+	IO_APIC_init_uniprocessor();
+}
+#else
 #define smp_init()	do { } while (0)
+#endif
 
 #else
 
diff -u --recursive --new-file v2.3.39/linux/ipc/msg.c linux/ipc/msg.c
--- v2.3.39/linux/ipc/msg.c	Tue Jan 11 22:31:45 2000
+++ linux/ipc/msg.c	Tue Jan 11 21:49:26 2000
@@ -851,13 +851,13 @@
 	int i, len = 0;
 
 	down(&msg_ids.sem);
-	len += sprintf(buffer, "       key      msqid perms cbytes  qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n");
+	len += sprintf(buffer, "       key      msqid perms      cbytes       qnum lspid lrpid   uid   gid  cuid  cgid      stime      rtime      ctime\n");
 
 	for(i = 0; i <= msg_ids.max_id; i++) {
 		struct msg_queue * msq;
 		msq = msg_lock(i);
 		if(msq != NULL) {
-			len += sprintf(buffer + len, "%10d %10d  %4o  %5u %5u %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
+			len += sprintf(buffer + len, "%10d %10d  %4o  %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
 				msq->q_perm.key,
 				msg_buildid(i,msq->q_perm.seq),
 				msq->q_perm.mode,
diff -u --recursive --new-file v2.3.39/linux/ipc/sem.c linux/ipc/sem.c
--- v2.3.39/linux/ipc/sem.c	Tue Jan 11 22:31:45 2000
+++ linux/ipc/sem.c	Tue Jan 11 21:49:26 2000
@@ -1047,14 +1047,14 @@
 	off_t begin = 0;
 	int i, len = 0;
 
-	len += sprintf(buffer, "       key      semid perms nsems   uid   gid  cuid  cgid      otime      ctime\n");
+	len += sprintf(buffer, "       key      semid perms      nsems   uid   gid  cuid  cgid      otime      ctime\n");
 	down(&sem_ids.sem);
 
 	for(i = 0; i <= sem_ids.max_id; i++) {
 		struct sem_array *sma;
 		sma = sem_lock(i);
 		if(sma) {
-			len += sprintf(buffer + len, "%10d %10d  %4o %5u %5u %5u %5u %5u %10lu %10lu\n",
+			len += sprintf(buffer + len, "%10d %10d  %4o %10lu %5u %5u %5u %5u %10lu %10lu\n",
 				sma->sem_perm.key,
 				sem_buildid(i,sma->sem_perm.seq),
 				sma->sem_perm.mode,
diff -u --recursive --new-file v2.3.39/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.39/linux/ipc/shm.c	Tue Jan 11 22:31:45 2000
+++ linux/ipc/shm.c	Tue Jan 11 19:18:38 2000
@@ -31,16 +31,14 @@
 
 struct shmid_kernel /* private to the kernel */
 {	
-	struct {
-		struct kern_ipc_perm	shm_perm;
-		size_t			shm_segsz;
-		time_t			shm_atime;
-		time_t			shm_dtime;
-		time_t			shm_ctime;
-		pid_t			shm_cpid;
-		pid_t			shm_lpid;
-		unsigned long		shm_nattch;
-	} u;
+	struct kern_ipc_perm	shm_perm;
+	size_t			shm_segsz;
+	time_t			shm_atime;
+	time_t			shm_dtime;
+	time_t			shm_ctime;
+	pid_t			shm_cpid;
+	pid_t			shm_lpid;
+	unsigned long		shm_nattch;
 	unsigned long		shm_npages; /* size of segment (pages) */
 	pte_t			**shm_dir;  /* ptr to array of ptrs to frames -> SHMMAX */ 
 	struct vm_area_struct	*attaches;  /* descriptors for attaches */
@@ -57,7 +55,7 @@
 #define shm_get(id)	((struct shmid_kernel*)ipc_get(&shm_ids,id))
 #define shm_rmid(id)	((struct shmid_kernel*)ipc_rmid(&shm_ids,id))
 #define shm_checkid(s, id)	\
-	ipc_checkid(&shm_ids,&s->u.shm_perm,id)
+	ipc_checkid(&shm_ids,&s->shm_perm,id)
 #define shm_buildid(id, seq) \
 	ipc_buildid(&shm_ids, id, seq)
 
@@ -174,7 +172,7 @@
 		shm_unlock(shmid);
 		return -EIDRM;
 	}
-	if (ipcperms(&shp->u.shm_perm, flg)) {
+	if (ipcperms(&shp->shm_perm, flg)) {
 		shm_unlock(shmid);
 		return -EACCES;
 	}
@@ -204,28 +202,28 @@
 		kfree(shp);
 		return -ENOMEM;
 	}
-	id = ipc_addid(&shm_ids, &shp->u.shm_perm, shm_ctlmni);
+	id = ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni);
 	if(id == -1) {
 		shm_free(shp->shm_dir,numpages);
 		kfree(shp);
 		return -ENOSPC;
 	}
-	shp->u.shm_perm.key = key;
-	shp->u.shm_perm.mode = (shmflg & S_IRWXUGO);
-	shp->u.shm_segsz = size;
-	shp->u.shm_cpid = current->pid;
+	shp->shm_perm.key = key;
+	shp->shm_perm.mode = (shmflg & S_IRWXUGO);
+	shp->shm_segsz = size;
+	shp->shm_cpid = current->pid;
 	shp->attaches = NULL;
-	shp->u.shm_lpid = shp->u.shm_nattch = 0;
-	shp->u.shm_atime = shp->u.shm_dtime = 0;
-	shp->u.shm_ctime = CURRENT_TIME;
+	shp->shm_lpid = shp->shm_nattch = 0;
+	shp->shm_atime = shp->shm_dtime = 0;
+	shp->shm_ctime = CURRENT_TIME;
 	shp->shm_npages = numpages;
-	shp->id = shm_buildid(id,shp->u.shm_perm.seq);
+	shp->id = shm_buildid(id,shp->shm_perm.seq);
 	init_MUTEX(&shp->sem);
 
 	shm_tot += numpages;
 	shm_unlock(id);
 
-	return shm_buildid(id,shp->u.shm_perm.seq);
+	return shm_buildid(id,shp->shm_perm.seq);
 }
 
 asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
@@ -247,10 +245,10 @@
 		shp = shm_lock(id);
 		if(shp==NULL)
 			BUG();
-		if (ipcperms(&shp->u.shm_perm, shmflg))
+		if (ipcperms(&shp->shm_perm, shmflg))
 			err = -EACCES;
 		else
-			err = shm_buildid(id, shp->u.shm_perm.seq);
+			err = shm_buildid(id, shp->shm_perm.seq);
 		shm_unlock(id);
 	}
 	up(&shm_ids.sem);
@@ -274,8 +272,8 @@
 		up(&shm_ids.sem);
 		return;
 	}
-	if(shm_checkid(shp,shmid) || shp->u.shm_nattch > 0 ||
-	    !(shp->u.shm_perm.mode & SHM_DEST)) {
+	if(shm_checkid(shp,shmid) || shp->shm_nattch > 0 ||
+	    !(shp->shm_perm.mode & SHM_DEST)) {
 		shm_unlock(shmid);
 		goto out_up;
 	}
@@ -464,7 +462,7 @@
 			err = -EINVAL;
 			if (shmid > shm_ids.max_id)
 				goto out_unlock;
-			result = shm_buildid(shmid, shp->u.shm_perm.seq);
+			result = shm_buildid(shmid, shp->shm_perm.seq);
 		} else {
 			err = -EIDRM;
 			if(shm_checkid(shp,shmid))
@@ -472,16 +470,16 @@
 			result = 0;
 		}
 		err=-EACCES;
-		if (ipcperms (&shp->u.shm_perm, S_IRUGO))
+		if (ipcperms (&shp->shm_perm, S_IRUGO))
 			goto out_unlock;
-		kernel_to_ipc64_perm(&shp->u.shm_perm, &tbuf.shm_perm);
-		tbuf.shm_segsz	= shp->u.shm_segsz;
-		tbuf.shm_atime	= shp->u.shm_atime;
-		tbuf.shm_dtime	= shp->u.shm_dtime;
-		tbuf.shm_ctime	= shp->u.shm_ctime;
-		tbuf.shm_cpid	= shp->u.shm_cpid;
-		tbuf.shm_lpid	= shp->u.shm_lpid;
-		tbuf.shm_nattch	= shp->u.shm_nattch;
+		kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm);
+		tbuf.shm_segsz	= shp->shm_segsz;
+		tbuf.shm_atime	= shp->shm_atime;
+		tbuf.shm_dtime	= shp->shm_dtime;
+		tbuf.shm_ctime	= shp->shm_ctime;
+		tbuf.shm_cpid	= shp->shm_cpid;
+		tbuf.shm_lpid	= shp->shm_lpid;
+		tbuf.shm_nattch	= shp->shm_nattch;
 		shm_unlock(shmid);
 		if(copy_shmid_to_user (buf, &tbuf, version))
 			return -EFAULT;
@@ -503,7 +501,7 @@
 		err=-EIDRM;
 		if(shm_checkid(shp,shmid))
 			goto out_unlock;
-		ipcp = &shp->u.shm_perm;
+		ipcp = &shp->shm_perm;
 		if(cmd==SHM_LOCK) {
 			if (!(ipcp->mode & SHM_LOCKED)) {
 				ipcp->mode |= SHM_LOCKED;
@@ -538,23 +536,23 @@
 	if(shm_checkid(shp,shmid))
 		goto out_unlock_up;
 	err=-EPERM;
-	if (current->euid != shp->u.shm_perm.uid &&
-	    current->euid != shp->u.shm_perm.cuid && 
+	if (current->euid != shp->shm_perm.uid &&
+	    current->euid != shp->shm_perm.cuid && 
 	    !capable(CAP_SYS_ADMIN)) {
 		goto out_unlock_up;
 	}
 
 	switch (cmd) {
 	case IPC_SET:
-		shp->u.shm_perm.uid = setbuf.uid;
-		shp->u.shm_perm.gid = setbuf.gid;
-		shp->u.shm_perm.mode = (shp->u.shm_perm.mode & ~S_IRWXUGO)
+		shp->shm_perm.uid = setbuf.uid;
+		shp->shm_perm.gid = setbuf.gid;
+		shp->shm_perm.mode = (shp->shm_perm.mode & ~S_IRWXUGO)
 			| (setbuf.mode & S_IRWXUGO);
-		shp->u.shm_ctime = CURRENT_TIME;
+		shp->shm_ctime = CURRENT_TIME;
 		break;
 	case IPC_RMID:
-		shp->u.shm_perm.mode |= SHM_DEST;
-		if (shp->u.shm_nattch <= 0) {
+		shp->shm_perm.mode |= SHM_DEST;
+		if (shp->shm_nattch <= 0) {
 			shm_unlock(shmid);
 			up(&shm_ids.sem);
 			killseg (shmid);
@@ -662,7 +660,7 @@
 		goto out_up;
 
 	err = -EACCES;
-	if (ipcperms(&shp->u.shm_perm, flg))
+	if (ipcperms(&shp->shm_perm, flg))
 		goto out_unlock_up;
 
 	err = -EIDRM;
@@ -675,7 +673,7 @@
 		err = -ENOMEM;
 		addr = 0;
 	again:
-		if (!(addr = get_unmapped_area(addr, (unsigned long)shp->u.shm_segsz)))
+		if (!(addr = get_unmapped_area(addr, (unsigned long)shp->shm_segsz)))
 			goto out_unlock_up;
 		if(addr & (SHMLBA - 1)) {
 			addr = (addr + (SHMLBA - 1)) & ~(SHMLBA - 1);
@@ -702,7 +700,7 @@
 	if (addr < current->mm->start_stack &&
 	    addr > current->mm->start_stack - PAGE_SIZE*(shp->shm_npages + 4))
 		goto out_unlock_up;
-	if (!(shmflg & SHM_REMAP) && find_vma_intersection(current->mm, addr, addr + (unsigned long)shp->u.shm_segsz))
+	if (!(shmflg & SHM_REMAP) && find_vma_intersection(current->mm, addr, addr + (unsigned long)shp->shm_segsz))
 		goto out_unlock_up;
 
 	shm_unlock(shmid);
@@ -726,7 +724,7 @@
 	shmd->vm_pgoff = 0;
 	shmd->vm_ops = &shm_vm_ops;
 
-	shp->u.shm_nattch++;	    /* prevent destruction */
+	shp->shm_nattch++;	    /* prevent destruction */
 	shm_unlock(shp->id);
 	err = shm_map (shmd);
 	shm_lock(shmid); /* cannot fail */
@@ -735,8 +733,8 @@
 
 	insert_attach(shp,shmd);  /* insert shmd into shp->attaches */
 
-	shp->u.shm_lpid = current->pid;
-	shp->u.shm_atime = CURRENT_TIME;
+	shp->shm_lpid = current->pid;
+	shp->shm_atime = CURRENT_TIME;
 
 	*raddr = addr;
 	err = 0;
@@ -749,7 +747,7 @@
 failed_shm_map:
 	{
 		int delete = 0;
-		if (--shp->u.shm_nattch <= 0 && shp->u.shm_perm.mode & SHM_DEST)
+		if (--shp->shm_nattch <= 0 && shp->shm_perm.mode & SHM_DEST)
 			delete = 1;
 		shm_unlock(shmid);
 		up(&current->mm->mmap_sem);
@@ -769,9 +767,9 @@
 	if(shp != shm_lock(shp->id))
 		BUG();
 	insert_attach(shp,shmd);  /* insert shmd into shp->attaches */
-	shp->u.shm_nattch++;
-	shp->u.shm_atime = CURRENT_TIME;
-	shp->u.shm_lpid = current->pid;
+	shp->shm_nattch++;
+	shp->shm_atime = CURRENT_TIME;
+	shp->shm_lpid = current->pid;
 	shm_unlock(shp->id);
 }
 
@@ -791,10 +789,10 @@
 	if(shp != shm_lock(shp->id))
 		BUG();
 	remove_attach(shp,shmd);  /* remove from shp->attaches */
-  	shp->u.shm_lpid = current->pid;
-	shp->u.shm_dtime = CURRENT_TIME;
+  	shp->shm_lpid = current->pid;
+	shp->shm_dtime = CURRENT_TIME;
 	id=-1;
-	if (--shp->u.shm_nattch <= 0 && shp->u.shm_perm.mode & SHM_DEST)
+	if (--shp->shm_nattch <= 0 && shp->shm_perm.mode & SHM_DEST)
 		id=shp->id;
 	shm_unlock(shp->id);
 	if(id!=-1)
@@ -936,7 +934,7 @@
 	shm_lockall();
 check_id:
 	shp = shm_get(swap_id);
-	if(shp==NULL || shp->u.shm_perm.mode & SHM_LOCKED) {
+	if(shp==NULL || shp->shm_perm.mode & SHM_LOCKED) {
 next_id:
 		swap_idx = 0;
 		if (++swap_id > shm_ids.max_id) {
@@ -1061,20 +1059,20 @@
 			else
 				format = BIG_STRING;
 	    		len += sprintf(buffer + len, format,
-				shp->u.shm_perm.key,
-				shm_buildid(i, shp->u.shm_perm.seq),
-				shp->u.shm_perm.mode,
-				shp->u.shm_segsz,
-				shp->u.shm_cpid,
-				shp->u.shm_lpid,
-				shp->u.shm_nattch,
-				shp->u.shm_perm.uid,
-				shp->u.shm_perm.gid,
-				shp->u.shm_perm.cuid,
-				shp->u.shm_perm.cgid,
-				shp->u.shm_atime,
-				shp->u.shm_dtime,
-				shp->u.shm_ctime);
+				shp->shm_perm.key,
+				shm_buildid(i, shp->shm_perm.seq),
+				shp->shm_perm.mode,
+				shp->shm_segsz,
+				shp->shm_cpid,
+				shp->shm_lpid,
+				shp->shm_nattch,
+				shp->shm_perm.uid,
+				shp->shm_perm.gid,
+				shp->shm_perm.cuid,
+				shp->shm_perm.cgid,
+				shp->shm_atime,
+				shp->shm_dtime,
+				shp->shm_ctime);
 			shm_unlock(i);
 
 			pos += len;
diff -u --recursive --new-file v2.3.39/linux/kernel/Makefile linux/kernel/Makefile
--- v2.3.39/linux/kernel/Makefile	Tue Jan 11 22:31:45 2000
+++ linux/kernel/Makefile	Wed Jan 12 09:20:56 2000
@@ -13,9 +13,13 @@
 O_TARGET := kernel.o
 O_OBJS    = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.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 uid16.o
+	    sysctl.o acct.o capability.o ptrace.o timer.o
 
 OX_OBJS  += signal.o
+
+ifeq ($(CONFIG_UID16),y)
+O_OBJS += uid16.o
+endif
 
 ifeq ($(CONFIG_KMOD),y)
 O_OBJS += kmod.o
diff -u --recursive --new-file v2.3.39/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.39/linux/kernel/ksyms.c	Tue Jan 11 22:31:45 2000
+++ linux/kernel/ksyms.c	Tue Jan 18 18:54:21 2000
@@ -42,6 +42,7 @@
 #include <linux/mmzone.h>
 #include <linux/mm.h>
 #include <linux/capability.h>
+#include <linux/highuid.h>
 
 #if defined(CONFIG_PROC_FS)
 #include <linux/proc_fs.h>
@@ -261,7 +262,8 @@
 EXPORT_SYMBOL(blkdev_put);
 EXPORT_SYMBOL(ioctl_by_bdev);
 EXPORT_SYMBOL(gendisk_head);
-EXPORT_SYMBOL(resetup_one_dev);
+EXPORT_SYMBOL(grok_partitions);
+EXPORT_SYMBOL(register_disk);
 EXPORT_SYMBOL(unplug_device);
 EXPORT_SYMBOL(make_request);
 EXPORT_SYMBOL(tq_disk);
@@ -429,6 +431,9 @@
 EXPORT_SYMBOL(__down_trylock);
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(brw_page);
+
+EXPORT_SYMBOL(fs_overflowuid);
+EXPORT_SYMBOL(fs_overflowgid);
 
 /* all busmice */
 EXPORT_SYMBOL(add_mouse_randomness);
diff -u --recursive --new-file v2.3.39/linux/kernel/sched.c linux/kernel/sched.c
--- v2.3.39/linux/kernel/sched.c	Fri Jan  7 19:13:23 2000
+++ linux/kernel/sched.c	Thu Jan 20 09:51:42 2000
@@ -82,7 +82,7 @@
 
 #ifdef __SMP__
 
-#define idle_task(cpu) (init_tasks[cpu_number_map[(cpu)]])
+#define idle_task(cpu) (init_tasks[cpu_number_map(cpu)])
 #define can_schedule(p)	(!(p)->has_cpu)
 
 #else
@@ -1168,10 +1168,10 @@
 	 * We have to do a little magic to get the first
 	 * process right in SMP mode.
 	 */
-	int cpu=hard_smp_processor_id();
+	int cpu = smp_processor_id();
 	int nr;
 
-	init_task.processor=cpu;
+	init_task.processor = cpu;
 
 	for(nr = 0; nr < PIDHASH_SZ; nr++)
 		pidhash[nr] = NULL;
diff -u --recursive --new-file v2.3.39/linux/kernel/signal.c linux/kernel/signal.c
--- v2.3.39/linux/kernel/signal.c	Tue Jan 11 22:31:45 2000
+++ linux/kernel/signal.c	Thu Jan 20 10:48:35 2000
@@ -132,56 +132,41 @@
 		int reset = 1;
 
 		/* Collect the siginfo appropriate to this signal.  */
-		if (sig < SIGRTMIN) {
-			/* XXX: As an extension, support queueing exactly
-			   one non-rt signal if SA_SIGINFO is set, so that
-			   we can get more detailed information about the
-			   cause of the signal.  */
-			/* Deciding not to init these couple of fields is
-			   more expensive that just initializing them.  */
+		struct signal_queue *q, **pp;
+		pp = &current->sigqueue;
+		q = current->sigqueue;
+
+		/* Find the one we're interested in ... */
+		for ( ; q ; pp = &q->next, q = q->next)
+			if (q->info.si_signo == sig)
+				break;
+		if (q) {
+			if ((*pp = q->next) == NULL)
+				current->sigqueue_tail = pp;
+			*info = q->info;
+			kmem_cache_free(signal_queue_cachep,q);
+			atomic_dec(&nr_queued_signals);
+
+			/* then see if this signal is still pending. */
+			q = *pp;
+			while (q) {
+				if (q->info.si_signo == sig) {
+					reset = 0;
+					break;
+				}
+				q = q->next;
+			}
+		} else {
+			/* Ok, it wasn't in the queue.  It must have
+			   been sent either by a non-rt mechanism and
+			   we ran out of queue space.  So zero out the
+			   info.  */
 			info->si_signo = sig;
 			info->si_errno = 0;
 			info->si_code = 0;
 			info->si_pid = 0;
 			info->si_uid = 0;
-			SET_UID16(info->si_uid16, 0);
-		} else {
-			struct signal_queue *q, **pp;
-			pp = &current->sigqueue;
-			q = current->sigqueue;
-
-			/* Find the one we're interested in ... */
-			for ( ; q ; pp = &q->next, q = q->next)
-				if (q->info.si_signo == sig)
-					break;
-			if (q) {
-				if ((*pp = q->next) == NULL)
-					current->sigqueue_tail = pp;
-				*info = q->info;
-				kmem_cache_free(signal_queue_cachep,q);
-				atomic_dec(&nr_queued_signals);
-				
-				/* then see if this signal is still pending. */
-				q = *pp;
-				while (q) {
-					if (q->info.si_signo == sig) {
-						reset = 0;
-						break;
-					}
-					q = q->next;
-				}
-			} else {
-				/* Ok, it wasn't in the queue.  It must have
-				   been sent either by a non-rt mechanism and
-				   we ran out of queue space.  So zero out the
-				   info.  */
-				info->si_signo = sig;
-				info->si_errno = 0;
-				info->si_code = 0;
-				info->si_pid = 0;
-				info->si_uid = 0;
-				SET_UID16(info->si_uid16, 0);
-			}
+			SET_SIGINFO_UID16(info->si_uid16, 0);
 		}
 
 		if (reset)
@@ -255,6 +240,8 @@
 {
 	unsigned long flags;
 	int ret;
+	struct signal_queue *q = 0;
+
 
 #if DEBUG_SIG
 printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
@@ -307,43 +294,38 @@
 	if (ignored_signal(sig, t))
 		goto out;
 
-	if (sig < SIGRTMIN) {
-		/* Non-real-time signals are not queued.  */
-		/* XXX: As an extension, support queueing exactly one
-		   non-rt signal if SA_SIGINFO is set, so that we can
-		   get more detailed information about the cause of
-		   the signal.  */
-		if (sigismember(&t->signal, sig))
-			goto out;
-	} else {
-		/* Real-time signals must be queued if sent by sigqueue, or
-		   some other real-time mechanism.  It is implementation
-		   defined whether kill() does so.  We attempt to do so, on
-		   the principle of least surprise, but since kill is not
-		   allowed to fail with EAGAIN when low on memory we just
-		   make sure at least one signal gets delivered and don't
-		   pass on the info struct.  */
-
-		struct signal_queue *q = 0;
-
-		if (atomic_read(&nr_queued_signals) < max_queued_signals) {
-			q = (struct signal_queue *)
-			    kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
-		}
-		
-		if (q) {
-			atomic_inc(&nr_queued_signals);
-			q->next = NULL;
-			*t->sigqueue_tail = q;
-			t->sigqueue_tail = &q->next;
-			switch ((unsigned long) info) {
+	/* Support queueing exactly one non-rt signal, so that we
+	   can get more detailed information about the cause of
+	   the signal. */
+	if (sig < SIGRTMIN && sigismember(&t->signal, sig))
+		goto out;
+
+	/* Real-time signals must be queued if sent by sigqueue, or
+	   some other real-time mechanism.  It is implementation
+	   defined whether kill() does so.  We attempt to do so, on
+	   the principle of least surprise, but since kill is not
+	   allowed to fail with EAGAIN when low on memory we just
+	   make sure at least one signal gets delivered and don't
+	   pass on the info struct.  */
+
+	if (atomic_read(&nr_queued_signals) < max_queued_signals) {
+		q = (struct signal_queue *)
+			kmem_cache_alloc(signal_queue_cachep, GFP_ATOMIC);
+	}
+
+	if (q) {
+		atomic_inc(&nr_queued_signals);
+		q->next = NULL;
+		*t->sigqueue_tail = q;
+		t->sigqueue_tail = &q->next;
+		switch ((unsigned long) info) {
 			case 0:
 				q->info.si_signo = sig;
 				q->info.si_errno = 0;
 				q->info.si_code = SI_USER;
 				q->info.si_pid = current->pid;
 				q->info.si_uid = current->uid;
-				SET_UID16(q->info.si_uid16, current->uid);
+				SET_SIGINFO_UID16(q->info.si_uid16, current->uid);
 				break;
 			case 1:
 				q->info.si_signo = sig;
@@ -351,17 +333,16 @@
 				q->info.si_code = SI_KERNEL;
 				q->info.si_pid = 0;
 				q->info.si_uid = 0;
-				SET_UID16(q->info.si_uid16, 0);
+				SET_SIGINFO_UID16(q->info.si_uid16, 0);
 				break;
 			default:
 				q->info = *info;
 				break;
-			}
-		} else {
-			/* Queue overflow, we have to abort. */
-			ret = -EAGAIN;
-			goto out;
 		}
+	} else {
+		/* Queue overflow, we have to abort. */
+		ret = -EAGAIN;
+		goto out;
 	}
 
 	sigaddset(&t->signal, sig);
@@ -739,6 +720,7 @@
 	 * Invert the set of allowed signals to get those we
 	 * want to block.
 	 */
+	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
 	signotset(&these);
 
 	if (uts) {
@@ -801,7 +783,7 @@
 	info.si_code = SI_USER;
 	info.si_pid = current->pid;
 	info.si_uid = current->uid;
-	SET_UID16(info.si_uid16, current->uid);
+	SET_SIGINFO_UID16(info.si_uid16, current->uid);
 
 	return kill_something_info(sig, &info, pid);
 }
@@ -875,7 +857,8 @@
 					if (q->info.si_signo != sig)
 						pp = &q->next;
 					else {
-						*pp = q->next;
+						if ((*pp = q->next) == NULL)
+							current->sigqueue_tail = pp;
 						kmem_cache_free(signal_queue_cachep, q);
 						atomic_dec(&nr_queued_signals);
 					}
@@ -922,10 +905,18 @@
 			goto out;
 
 		error = -EINVAL;
-		if (ss_flags & ~SS_DISABLE)
+		/*
+		 *
+		 * Note - this code used to test ss_flags incorrectly
+		 *  	  old code may have been written using ss_flags==0
+		 *	  to mean ss_flags==SS_ONSTACK (as this was the only
+		 *	  way that worked) - this fix preserves that older
+		 *	  mechanism
+		 */
+		if (ss_flags != SS_DISABLE && ss_flags != SS_ONSTACK && ss_flags != 0)
 			goto out;
 
-		if (ss_flags & SS_DISABLE) {
+		if (ss_flags == SS_DISABLE) {
 			ss_size = 0;
 			ss_sp = NULL;
 		} else {
diff -u --recursive --new-file v2.3.39/linux/lib/inflate.c linux/lib/inflate.c
--- v2.3.39/linux/lib/inflate.c	Tue Aug 31 17:29:15 1999
+++ linux/lib/inflate.c	Fri Jan 14 17:56:38 2000
@@ -7,7 +7,7 @@
  * Adapted for booting Linux by Hannu Savolainen 1993
  * based on gzip-1.0.3 
  *
- * Nicolas Pitre <nico@visuaide.com>, 1999/04/14 :
+ * Nicolas Pitre <nico@cam.org>, 1999/04/14 :
  *   Little mods for all variable to reside either into rodata or bss segments
  *   by marking constant variables with 'const' and initializing all the others
  *   at run-time only.  This allows for the kernel uncompressor to run
diff -u --recursive --new-file v2.3.39/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.39/linux/mm/filemap.c	Fri Jan  7 19:13:23 2000
+++ linux/mm/filemap.c	Tue Jan 11 11:38:55 2000
@@ -547,24 +547,22 @@
 
 /*
  * Read in an entire cluster at once.  A cluster is usually a 64k-
- * aligned block that includes the address requested in "offset."
+ * aligned block that includes the page requested in "offset."
  */
-static int read_cluster_nonblocking(struct file * file, unsigned long offset)
+static int read_cluster_nonblocking(struct file * file, unsigned long offset,
+	unsigned long filesize)
 {
-	int error = 0;
-	unsigned long filesize = (file->f_dentry->d_inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	unsigned long pages = CLUSTER_PAGES;
 
 	offset = CLUSTER_OFFSET(offset);
 	while ((pages-- > 0) && (offset < filesize)) {
-		error = page_cache_read(file, offset);
-		if (error >= 0)
-			offset ++;
-		else
-			break;
+		int error = page_cache_read(file, offset);
+		if (error < 0)
+			return error;
+		offset ++;
 	}
 
-	return error;
+	return 0;
 }
 
 /* 
@@ -1364,7 +1362,7 @@
 	 * so we need to map a zero page.
 	 */
 	if (pgoff < size)
-		error = read_cluster_nonblocking(file, pgoff);
+		error = read_cluster_nonblocking(file, pgoff, size);
 	else
 		error = page_cache_read(file, pgoff);
 
diff -u --recursive --new-file v2.3.39/linux/mm/highmem.c linux/mm/highmem.c
--- v2.3.39/linux/mm/highmem.c	Fri Jan  7 19:13:23 2000
+++ linux/mm/highmem.c	Thu Jan 20 09:51:42 2000
@@ -128,7 +128,7 @@
 	flush_tlb_all();
 }
 
-static unsigned long map_new_virtual(struct page *page)
+static inline unsigned long map_new_virtual(struct page *page)
 {
 	unsigned long vaddr;
 	int count;
@@ -170,12 +170,6 @@
 	}
 	vaddr = PKMAP_ADDR(last_pkmap_nr);
 	pkmap_page_table[last_pkmap_nr] = mk_pte(page, kmap_prot);
-	/*
-	 * Subtle! For some reason if we dont do this TLB flush then
-	 * we get data corruption and weird behavior in dbench runs.
-	 * But invlpg this should not be necessery ... Any ideas?
-	 */
-	__flush_tlb_one(vaddr);
 
 	pkmap_count[last_pkmap_nr] = 1;
 	page->virtual = vaddr;
diff -u --recursive --new-file v2.3.39/linux/mm/slab.c linux/mm/slab.c
--- v2.3.39/linux/mm/slab.c	Fri Jan  7 19:13:23 2000
+++ linux/mm/slab.c	Thu Jan 13 11:54:37 2000
@@ -216,6 +216,8 @@
 
 #endif	/* SLAB_DEBUG_SUPPORT */
 
+#define SLAB_CACHE_NAME_LEN	20	/* max name length for a slab cache */
+
 /* Cache struct - manages a cache.
  * First four members are commonly referenced during an alloc/free operation.
  */
@@ -241,7 +243,7 @@
 	size_t			  c_colour;	/* cache colouring range */
 	size_t			  c_colour_next;/* cache colouring */
 	unsigned long		  c_failures;
-	const char		 *c_name;
+	char			  c_name[SLAB_CACHE_NAME_LEN];
 	struct kmem_cache_s	 *c_nextp;
 	kmem_cache_t		 *c_index_cachep;
 #if	SLAB_STATS
@@ -667,7 +669,6 @@
 /* Create a cache:
  * Returns a ptr to the cache on success, NULL on failure.
  * Cannot be called within a int, but can be interrupted.
- * NOTE: The 'name' is assumed to be memory that is _not_  going to disappear.
  */
 kmem_cache_t *
 kmem_cache_create(const char *name, size_t size, size_t offset,
@@ -687,6 +688,10 @@
 		printk("%sNULL ptr\n", func_nm);
 		goto opps;
 	}
+	if (strlen(name) >= SLAB_CACHE_NAME_LEN) {
+		printk("%sname too long\n", func_nm);
+		goto opps;
+	}
 	if (in_interrupt()) {
 		printk("%sCalled during int - %s\n", func_nm, name);
 		goto opps;
@@ -948,7 +953,8 @@
 	cachep->c_ctor = ctor;
 	cachep->c_dtor = dtor;
 	cachep->c_magic = SLAB_C_MAGIC;
-	cachep->c_name = name;		/* Simply point to the name. */
+	/* Copy name over so we don't have problems with unloaded modules */
+	strcpy(cachep->c_name, name);
 	spin_lock_init(&cachep->c_spinlock);
 
 	/* Need the semaphore to access the chain. */
@@ -1026,12 +1032,7 @@
 }
 
 /* Shrink a cache.  Releases as many slabs as possible for a cache.
- * It is expected this function will be called by a module when it is
- * unloaded.  The cache is _not_ removed, this creates too many problems and
- * the cache-structure does not take up much room.  A module should keep its
- * cache pointer(s) in unloaded memory, so when reloaded it knows the cache
- * is available.  To help debugging, a zero exit status indicates all slabs
- * were released.
+ * To help debugging, a zero exit status indicates all slabs were released.
  */
 int
 kmem_cache_shrink(kmem_cache_t *cachep)
@@ -1049,6 +1050,12 @@
 /*
  * Remove a kmem_cache_t object from the slab cache. When returns 0 it
  * completed succesfully. -arca
+ *
+ * It is expected this function will be called by a module when it is
+ * unloaded.  This will remove the cache completely, and avoid a duplicate
+ * cache being allocated each time a module is loaded and unloaded, if the
+ * module doesn't have persistent in-kernel storage across loads and unloads.
+ *
  */
 int kmem_cache_destroy(kmem_cache_t * cachep)
 {
diff -u --recursive --new-file v2.3.39/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.39/linux/mm/vmscan.c	Fri Jan  7 19:13:23 2000
+++ linux/mm/vmscan.c	Thu Jan 13 13:31:30 2000
@@ -503,7 +503,7 @@
 		do {
 			/* kswapd is critical to provide GFP_ATOMIC
 			   allocations (not GFP_HIGHMEM ones). */
-			if (nr_free_buffer_pages() >= freepages.high)
+			if (nr_free_pages() - nr_free_highpages() >= freepages.high)
 				break;
 			if (!do_try_to_free_pages(GFP_KSWAPD, 0))
 				break;
diff -u --recursive --new-file v2.3.39/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.3.39/linux/net/ax25/af_ax25.c	Tue Nov 23 22:42:21 1999
+++ linux/net/ax25/af_ax25.c	Thu Jan 20 10:48:35 2000
@@ -95,6 +95,7 @@
  *	AX.25 037	Jonathan(G4KLX)		New timer architecture.
  *      AX.25 038       Matthias(DG2FEF)        Small fixes to the syscall interface to make kernel
  *                                              independent of AX25_MAX_DIGIS used by applications.
+ *                      Tomi(OH2BNS)            Fixed ax25_getname().
  */
 
 #include <linux/config.h>
@@ -1256,8 +1257,6 @@
 	newsk->sleep = &newsock->wait;
 
 	/* Now attach up the new socket */
-	skb->sk = NULL;
-	skb->destructor = NULL;
 	kfree_skb(skb);
 	sk->ack_backlog--;
 	newsock->sk    = newsk;
@@ -1269,37 +1268,34 @@
 static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
 {
 	struct sock *sk = sock->sk;
+	struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)uaddr;
 	unsigned char ndigi, i;
-	struct full_sockaddr_ax25 fsa;
 
 	if (peer != 0) {
 		if (sk->state != TCP_ESTABLISHED)
 			return -ENOTCONN;
 
-		fsa.fsa_ax25.sax25_family = AF_AX25;
-		fsa.fsa_ax25.sax25_call   = sk->protinfo.ax25->dest_addr;
-		fsa.fsa_ax25.sax25_ndigis = 0;
+		fsa->fsa_ax25.sax25_family = AF_AX25;
+		fsa->fsa_ax25.sax25_call   = sk->protinfo.ax25->dest_addr;
+		fsa->fsa_ax25.sax25_ndigis = 0;
 
 		if (sk->protinfo.ax25->digipeat != NULL) {
 			ndigi = sk->protinfo.ax25->digipeat->ndigi;
-			fsa.fsa_ax25.sax25_ndigis = ndigi;
+			fsa->fsa_ax25.sax25_ndigis = ndigi;
 			for (i = 0; i < ndigi; i++)
-				fsa.fsa_digipeater[i] = sk->protinfo.ax25->digipeat->calls[i];
+				fsa->fsa_digipeater[i] = sk->protinfo.ax25->digipeat->calls[i];
 		}
 	} else {
-		fsa.fsa_ax25.sax25_family = AF_AX25;
-		fsa.fsa_ax25.sax25_call   = sk->protinfo.ax25->source_addr;
-		fsa.fsa_ax25.sax25_ndigis = 1;
+		fsa->fsa_ax25.sax25_family = AF_AX25;
+		fsa->fsa_ax25.sax25_call   = sk->protinfo.ax25->source_addr;
+		fsa->fsa_ax25.sax25_ndigis = 1;
 		if (sk->protinfo.ax25->ax25_dev != NULL) {
-			memcpy(&fsa.fsa_digipeater[0], sk->protinfo.ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN);
+			memcpy(&fsa->fsa_digipeater[0], sk->protinfo.ax25->ax25_dev->dev->dev_addr, AX25_ADDR_LEN);
 		} else {
-			fsa.fsa_digipeater[0] = null_ax25_address;
+			fsa->fsa_digipeater[0] = null_ax25_address;
 		}
 	}
-	if (*uaddr_len > sizeof (struct full_sockaddr_ax25))
-		*uaddr_len = sizeof (struct full_sockaddr_ax25);
-	memcpy(uaddr, &fsa, *uaddr_len);
-
+	*uaddr_len = sizeof (struct full_sockaddr_ax25);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.39/linux/net/ax25/ax25_ds_subr.c linux/net/ax25/ax25_ds_subr.c
--- v2.3.39/linux/net/ax25/ax25_ds_subr.c	Mon Jan 12 15:28:19 1998
+++ linux/net/ax25/ax25_ds_subr.c	Thu Jan 20 10:48:35 2000
@@ -150,6 +150,7 @@
 	if ((skb = alloc_skb(2, GFP_ATOMIC)) == NULL)
 		return;
 
+	skb->nh.raw = skb->data;
 	p = skb_put(skb, 2);
 
 	*p++ = cmd;
diff -u --recursive --new-file v2.3.39/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v2.3.39/linux/net/ax25/ax25_in.c	Thu Aug 26 13:05:44 1999
+++ linux/net/ax25/ax25_in.c	Thu Jan 20 10:48:35 2000
@@ -93,6 +93,7 @@
 
 					skbn->dev   = ax25->ax25_dev->dev;
 					skbn->h.raw = skbn->data;
+					skbn->nh.raw = skbn->data;
 
 					/* Copy data from the fragments */
 					while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
diff -u --recursive --new-file v2.3.39/linux/net/ax25/ax25_ip.c linux/net/ax25/ax25_ip.c
--- v2.3.39/linux/net/ax25/ax25_ip.c	Thu Aug 26 13:05:44 1999
+++ linux/net/ax25/ax25_ip.c	Thu Jan 20 10:48:35 2000
@@ -161,6 +161,7 @@
 			dst_c = *dst;
 
 			skb_pull(ourskb, AX25_HEADER_LEN - 1);	/* Keep PID */
+			skb->nh.raw = skb->data;
 
 			ax25_send_frame(ourskb, ax25_dev->values[AX25_VALUES_PACLEN], &src_c, 
 &dst_c, route->digipeat, dev);
diff -u --recursive --new-file v2.3.39/linux/net/ax25/ax25_out.c linux/net/ax25/ax25_out.c
--- v2.3.39/linux/net/ax25/ax25_out.c	Thu Aug 26 13:05:45 1999
+++ linux/net/ax25/ax25_out.c	Thu Jan 20 10:48:35 2000
@@ -174,7 +174,7 @@
 
 			if (ka9qfrag == 1) {
 				skb_reserve(skbn, frontlen + 2);
-
+				skbn->nh.raw = skbn->data + (skb->nh.raw - skb->data);
 				memcpy(skb_put(skbn, len), skb->data, len);
 				p = skb_push(skbn, 2);
 
@@ -187,6 +187,7 @@
 				}
 			} else {
 				skb_reserve(skbn, frontlen + 1);
+				skbn->nh.raw = skbn->data + (skb->nh.raw - skb->data);
 				memcpy(skb_put(skbn, len), skb->data, len);
 				p = skb_push(skbn, 1);
 				*p = AX25_P_TEXT;
diff -u --recursive --new-file v2.3.39/linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c
--- v2.3.39/linux/net/ax25/ax25_subr.c	Wed Aug 18 11:38:48 1999
+++ linux/net/ax25/ax25_subr.c	Thu Jan 20 10:48:35 2000
@@ -240,7 +240,8 @@
 		return;	/* Next SABM will get DM'd */
 
 	skb_reserve(skb, AX25_BPQ_HEADER_LEN + ax25_addr_size(digi));
-
+	skb->nh.raw = skb->data;
+	
 	ax25_digi_invert(digi, &retdigi);
 
 	dptr = skb_put(skb, 1);
diff -u --recursive --new-file v2.3.39/linux/net/ax25/ax25_timer.c linux/net/ax25/ax25_timer.c
--- v2.3.39/linux/net/ax25/ax25_timer.c	Wed May 20 18:55:17 1998
+++ linux/net/ax25/ax25_timer.c	Thu Jan 20 10:48:35 2000
@@ -22,6 +22,7 @@
  *			Joerg(DL1BKE)	Fixed DAMA Slave. We are *required* to start with
  *					standard AX.25 mode.
  *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
+ *                      Tomi(OH2BNS)    Fixed heartbeat expiry (check ax25_dev).
  */
 
 #include <linux/config.h>
@@ -153,8 +154,12 @@
 static void ax25_heartbeat_expiry(unsigned long param)
 {
 	ax25_cb *ax25 = (ax25_cb *)param;
+	int proto = AX25_PROTO_STD_SIMPLEX;
 
-	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
+	if (ax25->ax25_dev)
+		proto = ax25->ax25_dev->values[AX25_VALUES_PROTOCOL];
+
+	switch (proto) {
 		case AX25_PROTO_STD_SIMPLEX:
 		case AX25_PROTO_STD_DUPLEX:
 			ax25_std_heartbeat_expiry(ax25);
diff -u --recursive --new-file v2.3.39/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v2.3.39/linux/net/ipv4/route.c	Fri Jan  7 19:13:23 2000
+++ linux/net/ipv4/route.c	Thu Jan 20 10:48:35 2000
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.77 2000/01/06 00:41:59 davem Exp $
+ * Version:	$Id: route.c,v 1.78 2000/01/13 00:06:58 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -816,8 +816,8 @@
 reject_redirect:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-		printk(KERN_INFO "Redirect from %lX/%s to %lX ignored."
-		       "Path = %lX -> %lX, tos %02x\n",
+		printk(KERN_INFO "Redirect from %X/%s to %X ignored."
+		       "Path = %X -> %X, tos %02x\n",
 		       ntohl(old_gw), dev->name, ntohl(new_gw),
 		       ntohl(saddr), ntohl(daddr), tos);
 #endif
@@ -2261,8 +2261,9 @@
 	if (!rt_hash_table)
 		panic("Failed to allocate IP route cache hash table\n");
 
-	printk("IP: routing cache hash table of %u buckets, %dKbytes\n",
-	       rt_hash_mask, (rt_hash_mask*sizeof(struct rt_hash_bucket))/1024);
+	printk("IP: routing cache hash table of %u buckets, %ldKbytes\n",
+	       rt_hash_mask,
+	       (long) (rt_hash_mask*sizeof(struct rt_hash_bucket))/1024);
 
 	for (rt_hash_log=0; (1<<rt_hash_log) != rt_hash_mask; rt_hash_log++)
 		/* NOTHING */;
diff -u --recursive --new-file v2.3.39/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.39/linux/net/ipv4/tcp_ipv4.c	Tue Jan 11 22:31:46 2000
+++ linux/net/ipv4/tcp_ipv4.c	Thu Jan 20 10:48:35 2000
@@ -1874,7 +1874,7 @@
 	/* Ouch!, this should not happen. */
 	if (!sk->saddr || !sk->rcv_saddr) {
 		printk(KERN_WARNING "tcp_v4_rebuild_header(): not valid sock addrs: "
-		       "saddr=%08lX rcv_saddr=%08lX\n",
+		       "saddr=%08X rcv_saddr=%08X\n",
 		       ntohl(sk->saddr), 
 		       ntohl(sk->rcv_saddr));
 		return 0;
diff -u --recursive --new-file v2.3.39/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.3.39/linux/net/ipv4/tcp_output.c	Tue Jan 11 22:31:46 2000
+++ linux/net/ipv4/tcp_output.c	Thu Jan 13 12:03:00 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_output.c,v 1.114 2000/01/09 02:19:43 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.116 2000/01/13 00:19:49 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1031,7 +1031,7 @@
 	unsigned long timeout;
 
 	/* Stay within the limit we were given */
-	timeout = tp->ato;
+	timeout = (tp->ato << 1) >> 1;
 	if (timeout > max_timeout)
 		timeout = max_timeout;
 	timeout += jiffies;
@@ -1070,10 +1070,14 @@
 			 *
 			 * This is the one possible way that we can delay an
 			 * ACK and have tp->ato indicate that we are in
-			 * quick ack mode, so clear it.
+			 * quick ack mode, so clear it.  It is also the only
+			 * possible way for ato to be zero, when ACK'ing a
+			 * SYNACK because we've taken no ATO measurement yet.
 			 */
-			if(tcp_in_quickack_mode(tp))
+			if (tcp_in_quickack_mode(tp))
 				tcp_exit_quickack_mode(tp);
+			if (!tp->ato)
+				tp->ato = tp->rto;
 			tcp_send_delayed_ack(sk, HZ/2);
 			return;
 		}
diff -u --recursive --new-file v2.3.39/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.3.39/linux/net/ipv6/addrconf.c	Wed Dec 29 13:13:21 1999
+++ linux/net/ipv6/addrconf.c	Fri Jan 14 11:25:21 2000
@@ -670,6 +670,7 @@
 {
 	switch (dev->type) {
 	case ARPHRD_ETHER:
+	case ARPHRD_IEEE802_TR:
 		if (dev->addr_len != ETH_ALEN)
 			return -1;
 		memcpy(eui, dev->dev_addr, 3);
@@ -1191,7 +1192,8 @@
 
 	ASSERT_RTNL();
 
-	if (dev->type != ARPHRD_ETHER) {
+	if ((dev->type != ARPHRD_ETHER)  && 
+	    (dev->type != ARPHRD_IEEE802_TR)) {
 		/* Alas, we support only Ethernet autoconfiguration. */
 		return;
 	}
@@ -1990,7 +1992,8 @@
 		case ARPHRD_LOOPBACK:	
 			init_loopback(dev);
 			break;
-		case ARPHRD_ETHER:	
+		case ARPHRD_ETHER:
+		case ARPHRD_IEEE802_TR:	
 			addrconf_dev_config(dev);
 			break;
 		default:
diff -u --recursive --new-file v2.3.39/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
--- v2.3.39/linux/net/ipv6/ndisc.c	Tue Jan 11 22:31:46 2000
+++ linux/net/ipv6/ndisc.c	Fri Jan 14 11:25:21 2000
@@ -161,6 +161,9 @@
 	case ARPHRD_FDDI:
 		ipv6_eth_mc_map(addr, buf);
 		return 0;
+	case ARPHRD_IEEE802_TR:
+		ipv6_tr_mc_map(addr,buf);
+		return 0;
 	default:
 		if (dir) {
 			memcpy(buf, dev->broadcast, dev->addr_len);
@@ -968,9 +971,22 @@
 				   does DAD, otherwise we ignore solicitations
 				   until DAD timer expires.
 				 */
-				if (addr_type == IPV6_ADDR_ANY)
-					addrconf_dad_failure(ifp);
-				else
+				if (addr_type == IPV6_ADDR_ANY) {
+					if (dev->type == ARPHRD_IEEE802_TR) { 
+						unsigned char *sadr = skb->mac.raw ;
+						if (((sadr[8] &0x7f) != (dev->dev_addr[0] & 0x7f)) ||
+						(sadr[9] != dev->dev_addr[1]) ||
+						(sadr[10] != dev->dev_addr[2]) ||
+						(sadr[11] != dev->dev_addr[3]) ||
+						(sadr[12] != dev->dev_addr[4]) ||
+						(sadr[13] != dev->dev_addr[5])) 
+						{
+							addrconf_dad_failure(ifp) ; 
+						}
+					} else {
+						addrconf_dad_failure(ifp);
+					}
+				} else
 					in6_ifa_put(ifp);
 				return 0;
 			}
diff -u --recursive --new-file v2.3.39/linux/net/netrom/nr_loopback.c linux/net/netrom/nr_loopback.c
--- v2.3.39/linux/net/netrom/nr_loopback.c	Wed Aug 18 11:38:49 1999
+++ linux/net/netrom/nr_loopback.c	Thu Jan 20 10:48:35 2000
@@ -11,6 +11,7 @@
  *
  *	History
  *	NET/ROM 007	Tomi(OH2BNS)	Created this file.
+ *                                      Small change in nr_loopback_queue().
  *
  */
 
@@ -44,17 +45,17 @@
 {
 	struct sk_buff *skbn;
 
-	skbn = skb_clone(skb, GFP_ATOMIC);
+	if ((skbn = alloc_skb(skb->len, GFP_ATOMIC)) != NULL) {
+		memcpy(skb_put(skbn, skb->len), skb->data, skb->len);
+		skbn->h.raw = skbn->data;
 
-	kfree_skb(skb);
-
-	if (skbn != NULL) {
 		skb_queue_tail(&loopback_queue, skbn);
 
 		if (!nr_loopback_running())
 			nr_set_loopback_timer();
 	}
 
+	kfree_skb(skb);
 	return 1;
 }
 
diff -u --recursive --new-file v2.3.39/linux/net/rose/af_rose.c linux/net/rose/af_rose.c
--- v2.3.39/linux/net/rose/af_rose.c	Tue Nov 23 22:42:21 1999
+++ linux/net/rose/af_rose.c	Thu Jan 20 10:48:35 2000
@@ -20,6 +20,7 @@
  *	ROSE 003	Jonathan(G4KLX)	New timer architecture.
  *					Implemented idle timer.
  *					Added use count to neighbour.
+ *                      Tomi(OH2BNS)    Fixed rose_getname().
  */
 
 #include <linux/config.h>
@@ -893,7 +894,7 @@
 static int rose_getname(struct socket *sock, struct sockaddr *uaddr,
 	int *uaddr_len, int peer)
 {
-	struct sockaddr_rose *srose = (struct sockaddr_rose *)uaddr;
+	struct full_sockaddr_rose *srose = (struct full_sockaddr_rose *)uaddr;
 	struct sock *sk = sock->sk;
 	int n;
 
@@ -901,42 +902,21 @@
 		if (sk->state != TCP_ESTABLISHED)
 			return -ENOTCONN;
 		srose->srose_family = AF_ROSE;
-		srose->srose_ndigis = 0;
 		srose->srose_addr   = sk->protinfo.rose->dest_addr;
 		srose->srose_call   = sk->protinfo.rose->dest_call;
 		srose->srose_ndigis = sk->protinfo.rose->dest_ndigis;
-		if (*uaddr_len >= sizeof(struct full_sockaddr_rose)) {
-			struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)uaddr;
-			for (n = 0 ; n < sk->protinfo.rose->dest_ndigis ; n++)
-				full_srose->srose_digis[n] = sk->protinfo.rose->dest_digis[n];
-			*uaddr_len = sizeof(struct full_sockaddr_rose);
-		} else {
-			if (sk->protinfo.rose->dest_ndigis >= 1) {
-				srose->srose_ndigis = 1;
-				srose->srose_digi = sk->protinfo.rose->dest_digis[0];
-			}
-			*uaddr_len = sizeof(struct sockaddr_rose);
-		}
+		for (n = 0 ; n < sk->protinfo.rose->dest_ndigis ; n++)
+			srose->srose_digis[n] = sk->protinfo.rose->dest_digis[n];
 	} else {
 		srose->srose_family = AF_ROSE;
-		srose->srose_ndigis = 0;
 		srose->srose_addr   = sk->protinfo.rose->source_addr;
 		srose->srose_call   = sk->protinfo.rose->source_call;
 		srose->srose_ndigis = sk->protinfo.rose->source_ndigis;
-		if (*uaddr_len >= sizeof(struct full_sockaddr_rose)) {
-			struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)uaddr;
-			for (n = 0 ; n < sk->protinfo.rose->source_ndigis ; n++)
-				full_srose->srose_digis[n] = sk->protinfo.rose->source_digis[n];
-			*uaddr_len = sizeof(struct full_sockaddr_rose);
-		} else {
-			if (sk->protinfo.rose->source_ndigis >= 1) {
-				srose->srose_ndigis = 1;
-				srose->srose_digi = sk->protinfo.rose->source_digis[sk->protinfo.rose->source_ndigis-1];
-			}
-			*uaddr_len = sizeof(struct sockaddr_rose);
-		}
+		for (n = 0 ; n < sk->protinfo.rose->source_ndigis ; n++)
+			srose->srose_digis[n] = sk->protinfo.rose->source_digis[n];
 	}
 
+	*uaddr_len = sizeof(struct full_sockaddr_rose);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.39/linux/net/sched/Config.in linux/net/sched/Config.in
--- v2.3.39/linux/net/sched/Config.in	Fri Jan  7 19:13:23 2000
+++ linux/net/sched/Config.in	Fri Jan 14 19:18:53 2000
@@ -17,7 +17,9 @@
 tristate '  TBF queue' CONFIG_NET_SCH_TBF
 tristate '  GRED queue' CONFIG_NET_SCH_GRED
 tristate '  Diffserv field marker' CONFIG_NET_SCH_DSMARK
-tristate '  Ingress Qdisc' CONFIG_NET_SCH_INGRESS
+if [ "$CONFIG_NETFILTER" = "y" ]; then
+   tristate '  Ingress Qdisc' CONFIG_NET_SCH_INGRESS
+fi
 bool '  QoS support' CONFIG_NET_QOS
 if [ "$CONFIG_NET_QOS" = "y" ]; then
    bool '    Rate estimator' CONFIG_NET_ESTIMATOR
diff -u --recursive --new-file v2.3.39/linux/net/sched/sch_ingress.c linux/net/sched/sch_ingress.c
--- v2.3.39/linux/net/sched/sch_ingress.c	Fri Jan  7 19:13:23 2000
+++ linux/net/sched/sch_ingress.c	Fri Jan 14 19:18:53 2000
@@ -25,9 +25,9 @@
 #include <linux/list.h>
 
 
+#undef DEBUG_INGRESS
 
-
-#if 0  /* control */
+#ifdef DEBUG_INGRESS  /* control */
 #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
 #else
 #define DPRINTK(format,args...)
@@ -56,7 +56,9 @@
 static int ingress_graft(struct Qdisc *sch,unsigned long arg,
     struct Qdisc *new,struct Qdisc **old)
 {
+#ifdef DEBUG_INGRESS
 	struct ingress_qdisc_data *p = PRIV(sch);
+#endif
 
 	DPRINTK("ingress_graft(sch %p,[qdisc %p],new %p,old %p)\n",
 		sch, p, new, old);
@@ -73,8 +75,9 @@
 
 static unsigned long ingress_get(struct Qdisc *sch,u32 classid)
 {
+#ifdef DEBUG_INGRESS
 	struct ingress_qdisc_data *p = PRIV(sch);
-
+#endif
 	DPRINTK("ingress_get(sch %p,[qdisc %p],classid %x)\n", sch, p, classid);
 	return TC_H_MIN(classid) + 1;
 }
@@ -95,8 +98,9 @@
 static int ingress_change(struct Qdisc *sch, u32 classid, u32 parent,
     struct rtattr **tca, unsigned long *arg)
 {
+#ifdef DEBUG_INGRESS
 	struct ingress_qdisc_data *p = PRIV(sch);
-
+#endif
 	DPRINTK("ingress_change(sch %p,[qdisc %p],classid %x,parent %x),"
 		"arg 0x%lx\n", sch, p, classid, parent, *arg);
 	DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
@@ -107,8 +111,9 @@
 
 static void ingress_walk(struct Qdisc *sch,struct qdisc_walker *walker)
 {
+#ifdef DEBUG_INGRESS
 	struct ingress_qdisc_data *p = PRIV(sch);
-
+#endif
 	DPRINTK("ingress_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
 	DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
 }
@@ -180,8 +185,9 @@
 
 static int ingress_drop(struct Qdisc *sch)
 {
+#ifdef DEBUG_INGRESS
 	struct ingress_qdisc_data *p = PRIV(sch);
-
+#endif
 	DPRINTK("ingress_drop(sch %p,[qdisc %p])\n", sch, p);
 	return 0;
 }
@@ -217,7 +223,6 @@
 			
 	return fwres;
 }
-
 
 /* after iptables */
 static struct nf_hook_ops ing_ops =
diff -u --recursive --new-file v2.3.39/linux/net/socket.c linux/net/socket.c
--- v2.3.39/linux/net/socket.c	Tue Dec  7 09:32:52 1999
+++ linux/net/socket.c	Tue Jan 11 14:19:17 2000
@@ -85,7 +85,7 @@
 #include <linux/netfilter.h>
 
 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
-static long long sock_lseek(struct file *file, long long offset, int whence);
+static loff_t sock_lseek(struct file *file, loff_t offset, int whence);
 static ssize_t sock_read(struct file *file, char *buf,
 			 size_t size, loff_t *ppos);
 static ssize_t sock_write(struct file *file, const char *buf,
@@ -419,7 +419,7 @@
  *	Sockets are not seekable.
  */
 
-static long long sock_lseek(struct file *file,long long offset, int whence)
+static loff_t sock_lseek(struct file *file, loff_t offset, int whence)
 {
 	return -ESPIPE;
 }
diff -u --recursive --new-file v2.3.39/linux/net/sunrpc/svc.c linux/net/sunrpc/svc.c
--- v2.3.39/linux/net/sunrpc/svc.c	Wed Dec  8 14:11:28 1999
+++ linux/net/sunrpc/svc.c	Thu Jan 20 10:48:35 2000
@@ -358,7 +358,7 @@
 	goto sendit;
 
 err_bad_auth:
-	dprintk("svc: authentication failed (%ld)\n", ntohl(auth_stat));
+	dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
 	serv->sv_stats->rpcbadauth++;
 	resp->buf[-1] = xdr_one;	/* REJECT */
 	svc_putlong(resp, xdr_one);	/* AUTH_ERROR */
diff -u --recursive --new-file v2.3.39/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c
--- v2.3.39/linux/net/sunrpc/svcsock.c	Thu Aug 26 13:05:46 1999
+++ linux/net/sunrpc/svcsock.c	Thu Jan 20 10:48:35 2000
@@ -266,10 +266,10 @@
 	set_fs(oldfs);
 #endif
 
-	dprintk("svc: socket %p sendto([%p %d... ], %d, %d) = %d\n",
-			rqstp->rq_sock,
-			iov[0].iov_base, iov[0].iov_len, nr,
-			buflen, len);
+	dprintk("svc: socket %p sendto([%p %lu... ], %d, %d) = %d\n",
+		rqstp->rq_sock, iov[0].iov_base,
+		(unsigned long) iov[0].iov_len, nr,
+		buflen, len);
 
 	return len;
 }
@@ -326,8 +326,8 @@
 	set_fs(oldfs);
 #endif
 
-	dprintk("svc: socket %p recvfrom(%p, %d) = %d\n", rqstp->rq_sock,
-				iov[0].iov_base, iov[0].iov_len, len);
+	dprintk("svc: socket %p recvfrom(%p, %lu) = %d\n", rqstp->rq_sock,
+		iov[0].iov_base, (unsigned long) iov[0].iov_len, len);
 
 	return len;
 }
@@ -526,16 +526,18 @@
 	newsock->ops = ops = sock->ops;
 
 	if ((err = ops->accept(sock, newsock, O_NONBLOCK)) < 0) {
-		printk(KERN_WARNING "%s: accept failed (err %d)!\n",
-					serv->sv_name, -err);
+		if (net_ratelimit())
+			printk(KERN_WARNING "%s: accept failed (err %d)!\n",
+				   serv->sv_name, -err);
 		goto failed;		/* aborted connection or whatever */
 	}
 
 	slen = sizeof(sin);
 	err = ops->getname(newsock, (struct sockaddr *) &sin, &slen, 1);
 	if (err < 0) {
-		printk(KERN_WARNING "%s: peername failed (err %d)!\n",
-					serv->sv_name, -err);
+		if (net_ratelimit())
+			printk(KERN_WARNING "%s: peername failed (err %d)!\n",
+				   serv->sv_name, -err);
 		goto failed;		/* aborted connection or whatever */
 	}
 
@@ -543,10 +545,11 @@
 	 * hosts here, but we have no generic client tables. For now,
 	 * we just punt connects from unprivileged ports. */
 	if (ntohs(sin.sin_port) >= 1024) {
-		printk(KERN_WARNING
-			"%s: connect from unprivileged port: %s:%d",
-			serv->sv_name, 
-			in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+		if (net_ratelimit())
+			printk(KERN_WARNING
+				   "%s: connect from unprivileged port: %s:%d",
+				   serv->sv_name, 
+				   in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
 		goto failed;
 	}
 
@@ -913,7 +916,7 @@
 	int		error;
 	int		type;
 
-	dprintk("svc: svc_create_socket(%s, %d, %08lx:%d)\n",
+	dprintk("svc: svc_create_socket(%s, %d, %08x:%d)\n",
 				serv->sv_program->pg_name, protocol,
 				ntohl(sin->sin_addr.s_addr),
 				ntohs(sin->sin_port));
diff -u --recursive --new-file v2.3.39/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.3.39/linux/net/sunrpc/xprt.c	Fri Oct 15 15:25:14 1999
+++ linux/net/sunrpc/xprt.c	Thu Jan 20 10:48:35 2000
@@ -1541,7 +1541,7 @@
 	struct socket	*sock;
 	int		type, err;
 
-	dprintk("RPC:      xprt_create_socket(%08lx, %s %d)\n",
+	dprintk("RPC:      xprt_create_socket(%08x, %s %d)\n",
 			   sap? ntohl(sap->sin_addr.s_addr) : 0,
 			   (proto == IPPROTO_UDP)? "udp" : "tcp", proto);
 
diff -u --recursive --new-file v2.3.39/linux/scripts/cramfs/GNUmakefile linux/scripts/cramfs/GNUmakefile
--- v2.3.39/linux/scripts/cramfs/GNUmakefile	Wed Dec 31 16:00:00 1969
+++ linux/scripts/cramfs/GNUmakefile	Tue Jan 11 10:24:58 2000
@@ -0,0 +1,11 @@
+CFLAGS = -Wall -O2
+CPPFLAGS = -I../../fs/cramfs
+LDLIBS = -lz
+PROGS = mkcramfs
+
+all: $(PROGS)
+
+distclean clean:
+	rm -f $(PROGS)
+
+.PHONY: all clean
diff -u --recursive --new-file v2.3.39/linux/scripts/cramfs/mkcramfs.c linux/scripts/cramfs/mkcramfs.c
--- v2.3.39/linux/scripts/cramfs/mkcramfs.c	Wed Dec 29 13:13:22 1999
+++ linux/scripts/cramfs/mkcramfs.c	Tue Jan 11 10:24:58 2000
@@ -6,7 +6,9 @@
 #include <sys/fcntl.h>
 #include <dirent.h>
 #include <stdlib.h>
+#include <errno.h>
 #include <string.h>
+#include <assert.h>
 
 /* zlib required.. */
 #include <zlib.h>
@@ -17,11 +19,11 @@
 
 #include "cramfs.h"
 
-#define PAGE_CACHE_SIZE (4096)
-
 static const char *progname = "mkcramfs";
 
-void usage(void)
+/* N.B. If you change the disk format of cramfs, please update fs/cramfs/README. */
+
+static void usage(void)
 {
 	fprintf(stderr, "Usage: '%s dirname outfile'\n"
 		" where <dirname> is the root of the\n"
@@ -29,6 +31,27 @@
 	exit(1);
 }
 
+/*
+ * If DO_HOLES is defined, then mkcramfs can create explicit holes in the
+ * data, which saves 26 bytes per hole (which is a lot smaller a saving than
+ * most filesystems).
+ *
+ * Note that kernels up to at least 2.3.39 don't support cramfs holes, which
+ * is why this defaults to undefined at the moment.
+ */
+/* #define DO_HOLES 1 */
+
+#define PAGE_CACHE_SIZE (4096)
+/* The kernel assumes PAGE_CACHE_SIZE as block size. */
+static unsigned int blksize = PAGE_CACHE_SIZE;
+
+static int warn_dev, warn_gid, warn_link, warn_namelen, warn_size, warn_uid;
+
+#ifndef MIN
+# define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+/* In-core version of inode / directory entry. */
 struct entry {
 	/* stats */
 	char *name;
@@ -37,34 +60,51 @@
 	/* FS data */
 	void *uncompressed;
 	unsigned int dir_offset;	/* Where in the archive is the directory entry? */
-	unsigned int data_offset;	/* Where in the archive is the start of the data? */
 
 	/* organization */
-	struct entry *child;
+	struct entry *child; /* null for non-directories and empty directories */
 	struct entry *next;
 };
 
 /*
- * We should mind about memory leaks and
- * checking for out-of-memory.
- *
- * We don't.
+ * Width of various bitfields in struct cramfs_inode.
+ * Used only to generate warnings.
  */
-static unsigned int parse_directory(const char *name, struct entry **prev)
+#define SIZE_WIDTH 24
+#define UID_WIDTH 16
+#define GID_WIDTH 8
+#define OFFSET_WIDTH 26
+
+/*
+ * The longest file name component to allow for in the input directory tree.
+ * Ext2fs (and many others) allow up to 255 bytes.  A couple of filesystems
+ * allow longer (e.g. smbfs 1024), but there isn't much use in supporting
+ * >255-byte names in the input directory tree given that such names get
+ * truncated to 255 bytes when written to cramfs.
+ */
+#define MAX_INPUT_NAMELEN 255
+
+static unsigned int parse_directory(const char *name, struct entry **prev, loff_t *fslen_ub)
 {
 	DIR *dir;
 	int count = 0, totalsize = 0;
 	struct dirent *dirent;
 	char *path, *endpath;
-	int len = strlen(name);
+	size_t len = strlen(name);
 
 	dir = opendir(name);
 	if (!dir) {
 		perror(name);
 		exit(2);
 	}
-	/* Set up the path.. */
-	path = malloc(4096);
+
+	/* Set up the path. */
+	/* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */
+	path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1);
+	if (!path) {
+		perror(NULL);
+		exit(1);
+	}
 	memcpy(path, name, len);
 	endpath = path + len;
 	*endpath = '/';
@@ -73,7 +113,8 @@
 	while ((dirent = readdir(dir)) != NULL) {
 		struct entry *entry;
 		struct stat st;
-		int fd, size;
+		int size;
+		size_t namelen;
 
 		/* Ignore "." and ".." - we won't be adding them to the archive */
 		if (dirent->d_name[0] == '.') {
@@ -84,44 +125,119 @@
 					continue;
 			}
 		}
-		strcpy(endpath, dirent->d_name);
+		namelen = strlen(dirent->d_name);
+		if (namelen > MAX_INPUT_NAMELEN) {
+			fprintf(stderr,
+				"Very long (%u bytes) filename `%s' found.\n"
+				" Please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile.  Exiting.\n",
+				namelen, dirent->d_name);
+			exit(1);
+		}
+		memcpy(endpath, dirent->d_name, namelen + 1);
 
 		if (lstat(path, &st) < 0) {
 			perror(endpath);
 			continue;
 		}
 		entry = calloc(1, sizeof(struct entry));
+		if (!entry) {
+			perror(NULL);
+			exit(5);
+		}
 		entry->name = strdup(dirent->d_name);
+		if (!entry->name) {
+			perror(NULL);
+			exit(1);
+		}
+		if (namelen > 255) {
+			/* Can't happen when reading from ext2fs. */
+
+			/* TODO: we ought to avoid chopping in half
+			   multi-byte UTF8 characters. */
+			entry->name[namelen = 255] = '\0';
+			warn_namelen = 1;
+		}
 		entry->mode = st.st_mode;
 		entry->size = st.st_size;
 		entry->uid = st.st_uid;
+		if (entry->uid >= 1 << UID_WIDTH)
+			warn_uid = 1;
 		entry->gid = st.st_gid;
-		size = sizeof(struct cramfs_inode) + (~3 & (strlen(entry->name) + 3));
+		if (entry->gid >= 1 << GID_WIDTH)
+			/* TODO: We ought to replace with a default
+                           gid instead of truncating; otherwise there
+                           are security problems.  Maybe mode should
+                           be &= ~070.  Same goes for uid once Linux
+                           supports >16-bit uids. */
+			warn_gid = 1;
+		size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3);
+		*fslen_ub += size;
 		if (S_ISDIR(st.st_mode)) {
-			entry->size = parse_directory(path, &entry->child);
+			entry->size = parse_directory(path, &entry->child, fslen_ub);
 		} else if (S_ISREG(st.st_mode)) {
+			/* TODO: We ought to open files in do_compress, one
+			   at a time, instead of amassing all these memory
+			   maps during parse_directory (which don't get used
+			   until do_compress anyway).  As it is, we tend to
+			   get EMFILE errors (especially if mkcramfs is run
+			   by non-root).
+
+			   While we're at it, do analagously for symlinks
+			   (which would just save a little memory). */
 			int fd = open(path, O_RDONLY);
 			if (fd < 0) {
 				perror(path);
 				continue;
 			}
-			if (entry->size)
-				entry->uncompressed = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
-			if (-1 == (int) (long) entry->uncompressed) {
-				perror("mmap");
-				exit(5);
+			if (entry->size) {
+				if ((entry->size >= 1 << SIZE_WIDTH)) {
+					warn_size = 1;
+					entry->size = (1 << SIZE_WIDTH) - 1;
+				}
+
+				entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, fd, 0);
+				if (-1 == (int) (long) entry->uncompressed) {
+					perror("mmap");
+					exit(5);
+				}
+				if (st.st_nlink > 1) {
+					/* TODO: Although cramfs doesn't
+					   support hard links, we could still
+					   share data offset values between
+					   different inodes (safe because
+					   read-only).  This would give at
+					   least the space saving of hard
+					   links.  Just keep a hash mapping
+					   <st_ino, st_dev> onto struct
+					   entry*.  Alternatively, steal some
+					   code from Roger Wolff's `same'
+					   program, which creates a hash of
+					   file data contents. */
+					warn_link = 1;
+				}
 			}
 			close(fd);
 		} else if (S_ISLNK(st.st_mode)) {
-			entry->uncompressed = malloc(st.st_size);
-			if (readlink(path, entry->uncompressed, st.st_size) < 0) {
+			entry->uncompressed = malloc(entry->size);
+			if (!entry->uncompressed) {
+				perror(NULL);
+				exit(5);
+			}
+			if (readlink(path, entry->uncompressed, entry->size) < 0) {
 				perror(path);
 				continue;
 			}
 		} else {
 			entry->size = st.st_rdev;
+			if (entry->size & -(1<<SIZE_WIDTH))
+				warn_dev = 1;
 		}
 
+		if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))
+			/* block pointers & data expansion allowance + data */
+			*fslen_ub += ((4+26)*((entry->size - 1) / blksize + 1)
+				      + MIN(entry->size + 3, st.st_blocks << 9));
+
 		/* Link it into the list */
 		*prev = entry;
 		prev = &entry->next;
@@ -133,7 +249,7 @@
 	return totalsize;
 }
 
-static void set_random(void *area, int size)
+static void set_random(void *area, size_t size)
 {
 	int fd = open("/dev/random", O_RDONLY);
 
@@ -144,6 +260,7 @@
 	memset(area, 0x00, size);
 }
 
+/* Returns sizeof(struct cramfs_super), which includes the root inode. */
 static unsigned int write_superblock(struct entry *root, char *base)
 {
 	struct cramfs_super *super = (struct cramfs_super *) base;
@@ -151,6 +268,8 @@
 
 	super->magic = CRAMFS_MAGIC;
 	super->flags = 0;
+	/* Note: 0x10000 is meaningless, which is a bug; but
+	   super->size is never used anyway. */
 	super->size = 0x10000;
 	memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature));
 	set_random(super->fsid, sizeof(super->fsid));
@@ -168,6 +287,11 @@
 static void set_data_offset(struct entry *entry, char *base, unsigned long offset)
 {
 	struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset);
+	assert ((offset & 3) == 0);
+	if (offset >= (1 << (2 + OFFSET_WIDTH))) {
+		fprintf(stderr, "filesystem too big.  Exiting.\n");
+		exit(1);
+	}
 	inode->offset = (offset >> 2);
 }
 
@@ -178,25 +302,28 @@
  * we've seen.
  */
 #define MAXENTRIES (100)
-static int stack_entries = 0;
-static struct entry *entry_stack[MAXENTRIES];
-
 static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset)
 {
+	int stack_entries = 0;
+	struct entry *entry_stack[MAXENTRIES];
+
 	for (;;) {
+		int dir_start = stack_entries;
 		while (entry) {
 			struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset);
-			int len = strlen(entry->name);
+			size_t len = strlen(entry->name);
 
 			entry->dir_offset = offset;
-			offset += sizeof(struct cramfs_inode);
 
 			inode->mode = entry->mode;
 			inode->uid = entry->uid;
 			inode->gid = entry->gid;
 			inode->size = entry->size;
-			inode->offset = 0;	/* Fill in later */
+			inode->offset = 0;
+			/* Non-empty directories, regfiles and symlinks will
+			   write over inode->offset later. */
 
+			offset += sizeof(struct cramfs_inode);
 			memcpy(base + offset, entry->name, len);
 			/* Pad up the name to a 4-byte boundary */
 			while (len & 3) {
@@ -206,14 +333,41 @@
 			inode->namelen = len >> 2;
 			offset += len;
 
+			/* TODO: this may get it wrong for chars >= 0x80.
+			   Most filesystems use UTF8 encoding for filenames,
+			   whereas the console is a single-byte character
+			   set like iso-latin-1. */
 			printf("  %s\n", entry->name);
-
 			if (entry->child) {
+				if (stack_entries >= MAXENTRIES) {
+					fprintf(stderr, "Exceeded MAXENTRIES.  Raise this value in mkcramfs.c and recompile.  Exiting.\n");
+					exit(1);
+				}
 				entry_stack[stack_entries] = entry;
 				stack_entries++;
 			}
 			entry = entry->next;
 		}
+
+		/*
+		 * Reverse the order the stack entries pushed during
+                 * this directory, for a small optimization of disk
+                 * access in the created fs.  This change makes things
+                 * `ls -UR' order.
+		 */
+		{
+			struct entry **lo = entry_stack + dir_start;
+			struct entry **hi = entry_stack + stack_entries;
+			struct entry *tmp;
+
+			while (lo < --hi) {
+				tmp = *lo;
+				*lo++ = *hi;
+				*hi = tmp;
+			}
+		}
+
+		/* Pop a subdirectory entry from the stack, and recurse. */
 		if (!stack_entries)
 			break;
 		stack_entries--;
@@ -226,35 +380,61 @@
 	return offset;
 }
 
+#ifdef DO_HOLES
+/*
+ * Returns non-zero iff the first LEN bytes from BEGIN are all NULs.
+ */
+static int
+is_zero(char const *begin, unsigned len)
+{
+	return (len-- == 0 ||
+		(begin[0] == '\0' &&
+		 (len-- == 0 ||
+		  (begin[1] == '\0' &&
+		   (len-- == 0 ||
+		    (begin[2] == '\0' &&
+		     (len-- == 0 ||
+		      (begin[3] == '\0' &&
+		       memcmp(begin, begin + 4, len) == 0))))))));
+}
+#else /* !DO_HOLES */
+# define is_zero(_begin,_len) (0)  /* Never create holes. */
+#endif /* !DO_HOLES */
+
 /*
  * One 4-byte pointer per block and then the actual blocked
  * output. The first block does not need an offset pointer,
- * as it will start immediately after the pointer block.
+ * as it will start immediately after the pointer block;
+ * so the i'th pointer points to the end of the i'th block
+ * (i.e. the start of the (i+1)'th block or past EOF).
  *
  * Note that size > 0, as a zero-sized file wouldn't ever
  * have gotten here in the first place.
  */
-static unsigned int do_compress(char *base, unsigned int offset, char *uncompressed, unsigned int size)
+static unsigned int do_compress(char *base, unsigned int offset, char const *name, char *uncompressed, unsigned int size)
 {
 	unsigned long original_size = size;
 	unsigned long original_offset = offset;
 	unsigned long new_size;
-	unsigned long blocks = (size - 1) / PAGE_CACHE_SIZE + 1;
+	unsigned long blocks = (size - 1) / blksize + 1;
 	unsigned long curr = offset + 4 * blocks;
 	int change;
 
 	do {
+		unsigned long len = 2 * blksize;
 		unsigned int input = size;
-		unsigned long len = 8192;
-		if (input > PAGE_CACHE_SIZE)
-			input = PAGE_CACHE_SIZE;
-		compress(base + curr, &len, uncompressed, input);
-		uncompressed += input;
+		if (input > blksize)
+			input = blksize;
 		size -= input;
-		curr += len;
+		if (!is_zero (uncompressed, input)) {
+			compress(base + curr, &len, uncompressed, input);
+			uncompressed += input;
+			curr += len;
+		}
 
-		if (len > PAGE_CACHE_SIZE*2) {
-			printf("AIEEE: block expanded to > 2*blocklength (%d)\n", len);
+		if (len > blksize*2) {
+			/* (I don't think this can happen with zlib.) */
+			printf("AIEEE: block \"compressed\" to > 2*blocklength (%ld)\n", len);
 			exit(1);
 		}
 
@@ -262,67 +442,120 @@
 		offset += 4;
 	} while (size);
 
+	curr = (curr + 3) & ~3;
 	new_size = curr - original_offset;
+	/* TODO: Arguably, original_size in these 2 lines should be
+	   st_blocks * 512.  But if you say that then perhaps
+	   administrative data should also be included in both. */
 	change = new_size - original_size;
-	printf("%4.2f %% (%d bytes)\n", (change * 100) / (double) original_size, change);
+	printf("%5.2f%% (%d bytes)\t%s\n",
+	       (change * 100) / (double) original_size, change, name);
 
-	return (curr + 3) & ~3;
+	return curr;
 }
 
+
+/*
+ * Traverse the entry tree, writing data for every item that has
+ * non-null entry->compressed (i.e. every symlink and non-empty
+ * regfile).
+ *
+ * Frees the entry pointers as it goes.
+ */
 static unsigned int write_data(struct entry *entry, char *base, unsigned int offset)
 {
 	do {
 		if (entry->uncompressed) {
 			set_data_offset(entry, base, offset);
-			offset = do_compress(base, offset, entry->uncompressed, entry->size);
+			offset = do_compress(base, offset, entry->name, entry->uncompressed, entry->size);
 		}
-		if (entry->child)
+		else if (entry->child)
 			offset = write_data(entry->child, base, offset);
-		entry = entry->next;
+
+		/* Free the old before processing the next. */
+		{
+			struct entry *tmp = entry;
+			entry = entry->next;
+			free(tmp->name);
+			free(tmp);
+		}
 	} while (entry);
 	return offset;
 }
 
-/* This is the maximum rom-image you can create */
-#define MAXROM (64*1024*1024)
+
+/*
+ * Maximum size fs you can create is roughly 256MB.  (The last file's
+ * data must begin within 256MB boundary but can extend beyond that.)
+ *
+ * Note that if you want it to fit in a ROM then you're limited to what the
+ * hardware and kernel can support (64MB?).
+ */
+#define MAXFSLEN ((((1 << OFFSET_WIDTH) - 1) << 2) /* offset */ \
+		  + (1 << SIZE_WIDTH) - 1 /* filesize */ \
+		  + (1 << SIZE_WIDTH) * 4 / PAGE_CACHE_SIZE /* block pointers */ )
+
 
 /*
  * Usage:
  *
- *      mkcramfs directory-name
+ *      mkcramfs directory-name outfile
  *
  * where "directory-name" is simply the root of the directory
  * tree that we want to generate a compressed filesystem out
- * of..
+ * of.
  */
 int main(int argc, char **argv)
 {
 	struct stat st;
 	struct entry *root_entry;
 	char *rom_image;
-	unsigned int offset, written;
+	unsigned int offset;
+	ssize_t written;
 	int fd;
+	loff_t fslen_ub = 0; /* initial guess (upper-bound) of
+				required filesystem size */
+	char const *dirname;
 
 	if (argc)
 		progname = argv[0];
 	if (argc != 3)
 		usage();
 
-	if (stat(argv[1], &st) < 0) {
+	if (stat(dirname = argv[1], &st) < 0) {
 		perror(argv[1]);
 		exit(1);
 	}
 	fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666);
 
 	root_entry = calloc(1, sizeof(struct entry));
+	if (!root_entry) {
+		perror(NULL);
+		exit(5);
+	}
 	root_entry->mode = st.st_mode;
 	root_entry->uid = st.st_uid;
 	root_entry->gid = st.st_gid;
-	root_entry->name = "";
 
-	root_entry->size = parse_directory(argv[1], &root_entry->child);
+	root_entry->size = parse_directory(argv[1], &root_entry->child, &fslen_ub);
+	if (fslen_ub > MAXFSLEN) {
+		fprintf(stderr,
+			"warning: guestimate of required size (upper bound) is %luMB, but maximum image size is %uMB.  We might die prematurely.\n",
+			(unsigned long) (fslen_ub >> 20),
+			MAXFSLEN >> 20);
+		fslen_ub = MAXFSLEN;
+	}
 
-	rom_image = mmap(NULL, MAXROM, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	/* TODO: Why do we use a private/anonymous mapping here
+           followed by a write below, instead of just a shared mapping
+           and a couple of ftruncate calls?  Is it just to save us
+           having to deal with removing the file afterwards?  If we
+           really need this huge anonymous mapping, we ought to mmap
+           in smaller chunks, so that the user doesn't need nn MB of
+           RAM free.  If the reason is to be able to write to
+           un-mmappable block devices, then we could try shared mmap
+           and revert to anonymous mmap if the shared mmap fails. */
+	rom_image = mmap(NULL, fslen_ub, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	if (-1 == (int) (long) rom_image) {
 		perror("ROM image map");
 		exit(1);
@@ -334,7 +567,11 @@
 	printf("Directory data: %d bytes\n", offset);
 
 	offset = write_data(root_entry, rom_image, offset);
-	printf("Everything: %d bytes\n", offset);
+
+	/* We always write a multiple of blksize bytes, so that
+           losetup works. */
+	offset = ((offset - 1) | (blksize - 1)) + 1;
+	printf("Everything: %d kilobytes\n", offset >> 10);
 
 	written = write(fd, rom_image, offset);
 	if (written < 0) {
@@ -345,5 +582,33 @@
 		fprintf(stderr, "ROM image write failed (%d %d)\n", written, offset);
 		exit(1);
 	}
+
+	/* (These warnings used to come at the start, but they scroll off the
+           screen too quickly.) */
+	if (warn_namelen) /* (can't happen when reading from ext2fs) */
+		fprintf(stderr, /* bytes, not chars: think UTF8. */
+			"warning: filenames truncated to 255 bytes.\n");
+	if (warn_link)
+		fprintf(stderr,
+			"warning: cramfs cannot represent hard links.  You may want to change hard links in\n"
+			" %s with symlinks to other files in %s.\n",
+			dirname, dirname);
+	if (warn_size)
+		fprintf(stderr,
+			"warning: file sizes truncated to %luMB (minus 1 byte).\n",
+			1L << (SIZE_WIDTH - 20));
+	if (warn_uid) /* (not possible with current Linux versions) */
+		fprintf(stderr,
+			"warning: uids truncated to %u bits.  (This may be a security concern.)\n",
+			UID_WIDTH);
+	if (warn_gid)
+		fprintf(stderr,
+			"warning: gids truncated to %u bits.  (This may be a security concern.)\n",
+			GID_WIDTH);
+	if (warn_dev)
+		fprintf(stderr,
+			"WARNING: device numbers truncated to %u bits.  This almost certainly means\n"
+			"that some device files will be wrong.\n",
+			OFFSET_WIDTH);
 	return 0;
 }
diff -u --recursive --new-file v2.3.39/linux/scripts/mkdep.c linux/scripts/mkdep.c
--- v2.3.39/linux/scripts/mkdep.c	Thu Aug 26 13:05:47 1999
+++ linux/scripts/mkdep.c	Thu Jan 13 18:03:58 2000
@@ -21,6 +21,7 @@
  */
 
 #include <ctype.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
