diff -u --recursive --new-file v2.3.50/linux/CREDITS linux/CREDITS
--- v2.3.50/linux/CREDITS	Thu Mar  2 14:36:22 2000
+++ linux/CREDITS	Fri Mar 10 13:18:42 2000
@@ -258,6 +258,11 @@
 D: Author and maintainer of the QIC-02 tape driver
 S: The Netherlands
 
+N: Tomas Berndtsson
+E: tomas@nocrew.org
+W: http://tomas.nocrew.org/
+D: dsp56k device driver
+
 N: Ross Biro
 E: bir7@leland.Stanford.Edu
 D: Original author of the Linux networking code
@@ -350,6 +355,14 @@
 S: Lancaster, LA1 4DN
 S: UK, England
 
+N: Lars Brinkhoff
+E: lars@nocrew.org
+W: http://lars.nocrew.org/
+D: dsp56k device driver
+S: Kopmansg 2
+S: 411 13  Goteborg
+S: Sweden
+
 N: Andries Brouwer
 E: aeb@cwi.nl
 D: random Linux hacker
@@ -940,6 +953,13 @@
 S: 34131 Kassel
 S: Germany
 
+N: Christoph Hellwig
+E: chhellwig@gmx.net
+D: Sound/OSS hacking
+S: Triftstraße 26
+S: 38644 Goslar
+S: Germany
+
 N: Richard Henderson
 E: rth@twiddle.net
 E: rth@cygnus.com
@@ -1683,6 +1703,13 @@
 S: Fremont, California 94536
 S: USA
 
+N: Sam Mosel
+E: sam.mosel@computer.org
+D: Wacom Intuos USB Support
+S: 22 Seaview St
+S: Fullarton 5063
+S: South Australia
+
 N: Ian A. Murdock
 E: imurdock@gnu.ai.mit.edu
 D: Creator of Debian distribution
@@ -1753,6 +1780,11 @@
 S: 2364 Old Trail Drive
 S: Reston, Virginia 20191
 S: USA
+
+N: Fredrik Noring
+E: noring@nocrew.org
+W: http://www.lysator.liu.se/~noring/
+D: dsp56k device driver
 
 N: Michael O'Reilly
 E: michael@iinet.com.au
diff -u --recursive --new-file v2.3.50/linux/Documentation/Changes linux/Documentation/Changes
--- v2.3.50/linux/Documentation/Changes	Sat Feb 26 22:31:37 2000
+++ linux/Documentation/Changes	Wed Mar  8 09:16:24 2000
@@ -72,6 +72,10 @@
 General Information
 ===================
 
+   To use System V shared memory, you have to mount the shm filesystem
+somewhere and put the mountpoint into /proc/sys/kernel/shmpath.
+Default is /var/shm.
+
    <CTRL><ALT><DEL> now performs a cold reboot instead of a warm reboot
 for increased hardware compatibility.  If you want a warm reboot and
 know it works on your hardware, add a "reboot=warm" command line option
diff -u --recursive --new-file v2.3.50/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.50/linux/Documentation/Configure.help	Tue Mar  7 14:32:25 2000
+++ linux/Documentation/Configure.help	Fri Mar 10 10:55:44 2000
@@ -648,7 +648,7 @@
 
   It is SAFEST to say N to this question.
 
-3ware Hardware ATA-RAID support (EXPERIMENTAL)
+3ware Hardware ATA-RAID support
 CONFIG_BLK_DEV_3W_XXXX_RAID
   3ware is the only hardware ATA-Raid product in Linux to date.
   This card is 2,4, or 8 channel master mode support only.
@@ -745,9 +745,13 @@
   This is an Ultra DMA chipset for ATA-66.
   
   This driver adds up to 4 more EIDE devices sharing a single
-  interrupt. The HPT366 chipset in its current form is a non-bootable.
-  This driver requires dynamic tuning of the chipset during the
-  ide-probe at boot. It is reported to support DVD II drives, by the
+  interrupt. The HPT366 chipset in its current form is a non-bootable,
+  without special LILO commands for redirecting the reference to device 0x80.
+  The other solution is to include "CONFIG_BLK_DEV_OFFBOARD" unless your
+  mainboard has the chipset native mounted.  Regardless one should use the
+  fore mentioned option and call at LILO or include in your append-line:
+  "ide=reverse".  This driver requires dynamic tuning of the chipset during
+  the ide-probe at boot. It is reported to support DVD II drives, by the
   manufacturer.
 
   Please read the comments at the top of drivers/block/hpt366.c
@@ -2353,6 +2357,11 @@
   This is the frame buffer device driver for the builtin graphics
   chipset found in Amigas.
 
+  The driver is also available as a module ( = code which can be
+  inserted and removed from the running kernel whenever you want). The
+  module will be called amifb.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
 Amiga OCS chipset support
 CONFIG_FB_AMIGA_OCS
   This enables support for the original Agnus and Denise video chips,
@@ -3480,15 +3489,13 @@
    Add support for turning your DECnet Endnode into a level 1 or 2
    router. This is an unfinished option for developers only. If you do
    turn it on, then make sure that you also say Y to "Kernel/User
-   network link driver" and "Routing messages", since rtnetlink is the
-   only current method of configuration.
+   network link driver", "Routing messages" and "Network packet 
+   filtering". The first two are required to allow configuration via
+   rtnetlink (currently you need Alexey Kuznetsov's iproute2 package
+   from ftp.inr.ac.ru). The "Network packet filtering" option will
+   be required for the forthcoming routing daemon to work.
 
-DECnet Raw Socket Support
-CONFIG_DECNET_RAW
-   Add support for the SOCK_RAW type under DECnet. Used by userland
-   routing programs to receive routing messages from the kernel and
-   also as a general debugging aid to see what's going on "under the
-   hood".
+   See Documentation/networking/decnet.txt for more information.
 
 AppleTalk DDP
 CONFIG_ATALK
@@ -11144,10 +11151,8 @@
   Intel processors in P6 family, e.g.  Pentium Pro, Pentium II, 
   Pentium III, Xeon etc. You will obviously need the actual microcode
   binary data itself which is not shipped with the Linux kernel. 
-  With this support compiled you can use dd(1) to write microcode,
-  for example:
-
-     # dd if=/etc/microcode of=/dev/cpu/microcode bs=98304 count=1
+  You also need to say Y to "/dev file system support" in 'File systems'
+  section of the kernel configuration menu.
 
   You need to be superuser to do that. For latest news and information
   on obtaining all the required ingredients for this driver, check:
@@ -11439,11 +11444,15 @@
   This module initializes the older non Plug and Play sound galaxy
   cards from Aztech. It supports the Waverider Pro 32 - 3D and the
   Galaxy Washington 16.
+  If you compile the driver into the kernel, you have to add
+  "sgalaxy=<io>,<irq>,<dma>,<dma2>,<sgbase>" to the kernel command line.
 
 Support for AD1816(A) based cards (EXPERIMENTAL)
 CONFIG_SOUND_AD1816
   Say M here if you have a sound card based on the Analog Devices 
   AD1816(A) chip.
+  If you compile the driver into the kernel, you have to add
+  "ad1816=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
 
   NOTE: This driver is still EXPERIMENTAL. 
         See Documentation/sound/AD1816 for further information.
@@ -11453,6 +11462,9 @@
   Say Y or M if you have a Yamaha OPL3-SA1 sound chip, which is
   usually built into motherboards. Read Documentation/sound/OPL3-SA
   for details.
+  If you compile the driver into the kernel, you have to add
+  "opl3sa=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
+  command line.
 
 ProAudioSpectrum 16 support
 CONFIG_SOUND_PAS
@@ -11460,6 +11472,9 @@
   16 or Logitech SoundMan 16 sound card. Don't answer Y if you have
   some other card made by Media Vision or Logitech since they are not
   PAS16 compatible.
+  If you compile the driver into the kernel, you have to add
+  "pas2=<io>,<irq>,<dma>,<dma2>,<sbio>,<sbirq>,<sbdma>,<sbdma2>
+  to the kernel command line.
 
 100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support
 CONFIG_SOUND_SB
@@ -11477,6 +11492,8 @@
   Y here and also to "Additional lowlevel drivers" and to "SB32/AWE
   support" below and read Documentation/sound/INSTALL.awe. If you have
   an IBM Mwave card, say Y here and read Documentation/sound/mwave.
+  If you compile the driver into the kernel and don't want to use isapnp,
+  you have to add "sb=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
   
   You can say M here to compile this driver as a module; the module is
   called sb.o.
@@ -11492,6 +11509,8 @@
   Say Y here for any type of Gravis Ultrasound card, including
   the GUS or GUS MAX. See also Documentation/sound/ultrasound for
   more information on configuring this card with modules.
+  If you compile the driver into the kernel, you have to add
+  "gus=<io>,<irq>,<dma>,<dma2>" to the kernel command line.
 
 MPU-401 support (NOT for SB16)
 CONFIG_SOUND_MPU401
@@ -11503,12 +11522,16 @@
   was in the list of supported cards, look at the card specific
   instructions in the drivers/sound/Readme.cards file. It's safe to
   answer Y if you have a true MPU401 MIDI interface card.
+  If you compile the driver into the kernel, you have to add
+  "mpu401=<io>,<irq>" to the kernel command line.
 
 6850 UART support
 CONFIG_SOUND_UART6850
   This option enables support for MIDI interfaces based on the 6850
   UART chip. This interface is rarely found on sound cards. It's safe
   to answer N to this question.
+  If you compile the driver into the kernel, you have to add
+  "uart6850=<io>,<irq>" to the kernel command line.
 
 VIDC Sound
 CONFIG_VIDC_SOUND
@@ -11522,6 +11545,9 @@
   ADSP-2115 DSP chip + Echo ESC614 ASIC CHIP). For more information on
   how to compile it into the kernel or as a module see the file
   Documentation/sound/PSS.
+  If you compile the driver into the kernel, you have to add
+  "pss=<io>,<mssio>,<mssirq>,<mssdma>,<mpuio>,<mpuirq>" to the kernel
+  command line.
 
 Enable PSS mixer (Beethoven ADSP-16 and other compatible)
 CONFIG_PSS_MIXER
@@ -11580,6 +11606,8 @@
   specific instructions in drivers/sound/Readme.cards. Some drivers
   have their own MSS support and saying Y to this option will cause a
   conflict.
+  If you compile the driver into the kernel, you have to add
+  "ad1848=<io>,<irq>,<dma>,<dma2>[,<type>]" to the kernel command line.
 
 SGI Visual Workstation on-board audio
 CONFIG_SOUND_VWSND
@@ -11592,11 +11620,16 @@
   Answer Y if you have a sound card based on the Ensoniq SoundScape
   chipset. Such cards are being manufactured at least by Ensoniq, Spea
   and Reveal (Reveal makes also other cards).
+  If you compile the driver into the kernel, you have to add
+  "sscape=<io>,<irq>,<dma>,<mpuio>,<mpuirq>" to the kernel command line.
 
 MediaTriX AudioTriX Pro support
 CONFIG_SOUND_TRIX
   Answer Y if you have the AudioTriX Pro sound card manufactured
   by MediaTrix.
+  If you compile the driver into the kernel, you have to add
+  "trix=<io>,<irq>,<dma>,<dma2>,<sbio>,<sbirq>,<sbdma>,<mpuio>,<mpuirq>"
+  to the kernel command line.
 
 Have TRXPRO.HEX firmware file
 CONFIG_TRIX_HAVE_BOOT
@@ -11621,6 +11654,9 @@
   and Diamond (latest ones). Note however that the Tropez sound cards
   have their own driver; if you have one of those, say N here and Y or
   M to "Full support for Turtle Beach WaveFront", below. 
+  If you compile the driver into the kernel, you have to add
+  "mad16=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the
+  kernel command line.
 
   See also Documentation/sound/Opti and Documentation/sound/MAD16 for
   more information on setting these cards up as modules.
@@ -11640,7 +11676,10 @@
 Support for Crystal CS4232 based (PnP) cards
 CONFIG_SOUND_CS4232
   Say Y here if you have a card based on the Crystal CS4232 chip set,
-  which uses its own Plug and Play protocol. 
+  which uses its own Plug and Play protocol.
+  If you compile the driver into the kernel, you have to add
+  "cs4232=<io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>" to the kernel
+  command line.
 
   See Documentation/sound/CS4232 for more information on configuring
   this card.
@@ -11650,11 +11689,16 @@
   Say Y or M if you have a card based on one of these Yamaha
   sound chipsets. Read Documentation/sound/OPL3-SA2 for more
   information on configuring these cards.
+  If you compile the driver into the kernel, you have to add
+  "opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>" to the kernel
+  command line.
 
 Support for Turtle Beach Wave Front (Maui, Tropez) synthesizers
 CONFIG_SOUND_MAUI
   Say Y here if you have a Turtle Beach Wave Front, Maui, or Tropez
   sound card.
+  If you compile the driver into the kernel, you have to add
+  "maui=<io>,<irq>" to the kernel command line.
 
 Have OSWF.MOT firmware file
 CONFIG_MAUI_HAVE_BOOT
@@ -11742,18 +11786,6 @@
   and Pinnacle). Larger values reduce the chance of data overruns at
   the expense of overall latency. If unsure, use the default.
 
-/dev/dsp and /dev/audio support
-CONFIG_SOUND_AUDIO
-  If you say Y here, you will get the /dev/dsp and /dev/audio devices;
-  these are the analog-digital and digital-analog converter devices
-  and are very useful, so say Y.
-
-MIDI interface support
-CONFIG_SOUND_MIDI
-  Answering N disables /dev/midixx devices and access to any MIDI
-  ports using /dev/sequencer and /dev/music. This option also affects
-  any MPU401 and/or General MIDI compatible devices. Answer Y.
-
 FM synthesizer (YM3812/OPL-3) support
 CONFIG_SOUND_YM3812
   Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
@@ -11763,6 +11795,8 @@
   cards, however).
   Please read the file Documentation/sound/OPL3 if your card has an
   OPL3 chip.
+  If you compile the driver into the kernel, you have to add
+  "opl3=<io>" to the kernel command line.
 
   If unsure, say Y.
  
@@ -11771,15 +11805,8 @@
   This is support for the sound cards on Sun workstations. The code
   does not exist yet, so you might as well say N here.
 
-Additional low level drivers
-CONFIG_LOWLEVEL_SOUND
-  If you need additional low level sound drivers which have not yet
-  appeared, say Y. The answer to this question does not directly
-  affect the kernel; saying Y will simply cause this configure script
-  to present you with more options. If unsure, say Y.
-
 ACI mixer (miroPCM12/PCM20)
-CONFIG_ACI_MIXER
+CONFIG_SOUND_ACI_MIXER
   ACI (Audio Command Interface) is a protocol used to communicate with
   the microcontroller on some sound cards produced by miro, e.g. the
   miroSOUND PCM12 and PCM20. The main function of the ACI is to
@@ -11791,7 +11818,7 @@
   radio-miropcm20 driver.
 
 SB32/AWE support
-CONFIG_AWE32_SYNTH
+CONFIG_SOUND_AWE32_SYNTH
   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,
@@ -11799,7 +11826,7 @@
   info.
 
 Gallant's Audio Excel DSP 16 support (SC-6000 and SC-6600)
-CONFIG_AEDSP16
+CONFIG_SOUND_AEDSP16
   Answer Y if you have a Gallant's Audio Excel DSP 16 card. This
   driver supports Audio Excel DSP 16 but not the III nor PnP versions
   of this card.
@@ -11817,30 +11844,15 @@
   Documentation/sound/AudioExcelDSP16 to get more information about
   this driver and its configuration.
 
-I/O base for Audio Excel DSP 16
-CONFIG_AEDSP16_BASE
-  This is the base I/O address of the Audio Excel DSP 16 card. It must
-  be 220 or 240. If you compiled aedsp16.o as a module you can specify
-  this parameter as 'io=0xNNN'.
-
 Audio Excel DSP 16 (SBPro emulation)
 CONFIG_AEDSP16_SBPRO
   Answer Y if you want your audio card to emulate Sound Blaster Pro.
   You should then say Y to "100% Sound Blaster compatibles
   (SB16/32/64, ESS, Jazz16) support" and N to "Audio Excel DSP 16 (MSS
   emulation)".
-
-Audio Excel DSP 16 IRQ
-CONFIG_AEDSP16_SB_IRQ
-  This is the IRQ of the Audio Excel DSP 16 card. It must be 5, 7, 9,
-  10 or 11. If you compiled aedsp16.o as a module you can specify
-  this parameter as 'irq=NN'.
-
-Audio Excel DSP 16 DMA
-CONFIG_AEDSP16_SB_DMA
-  This is the IRQ of the Audio Excel DSP 16 card. It must be 0, 1 or
-  3. If you compiled aedsp16.o as a module you can specify this
-  parameter as 'dma=NN'.
+  If you compile the driver into the kernel, you have to add
+  "aedsp16=<io>,<irq>,<dma>,<mssio>,<mpuio>,<mouirq>" to the kernel
+  command line.
 
 Audio Excel DSP 16 (MSS emulation)
 CONFIG_AEDSP16_MSS
@@ -11848,18 +11860,6 @@
   System. You should then say Y to "Microsoft Sound System support"
   and say N to "Audio Excel DSP 16 (SBPro emulation)".
 
-Audio Excel DSP 16 IRQ
-CONFIG_AEDSP16_MSS_IRQ
-  This is the IRQ of the Audio Excel DSP 16 card. It must be 5, 7, 9,
-  10 or 11. If you compiled aedsp16.o as a module you can specify
-  this parameter as 'irq=NN'.
-
-Audio Excel DSP 16 DMA
-CONFIG_AEDSP16_MSS_DMA
-  This is the IRQ of the Audio Excel DSP 16 card. It must be 0, 1 
-  or 3. If you compiled aedsp16.o as a module you can specify this
-  parameter as 'dma=NN'.
-
 SC-6600 based audio cards (new Audio Excel DSP 16)
 CONFIG_SC6600
   The SC6600 is the new version of DSP mounted on the Audio Excel DSP
@@ -11886,13 +11886,6 @@
   you have selected for "MPU-401 support". If you are using this
   driver as a module you have to specify the MPU I/O base address with
   the parameter 'mpu_base=0xNNN'.
-
-MPU401 IRQ for Audio Excel DSP 16
-CONFIG_AEDSP16_MPU_IRQ
-  This is the IRQ of the MPU-401 emulation of your Audio Excel DSP 16
-  card. It must be 5, 7, 9, 10 or 0 (to disable MPU-401 interface). If
-  you compiled aedsp16.o as a module you can specify this parameter as
-  'mpu_irq=NN'.
 
 Ensoniq ES1370 based PCI sound cards
 CONFIG_SOUND_ES1370
diff -u --recursive --new-file v2.3.50/linux/Documentation/networking/decnet.txt linux/Documentation/networking/decnet.txt
--- v2.3.50/linux/Documentation/networking/decnet.txt	Sun Feb 20 21:12:38 2000
+++ linux/Documentation/networking/decnet.txt	Thu Mar  9 06:57:17 2000
@@ -30,10 +30,10 @@
 if you want to try out router support (not properly debugged yet)
 you'll need the following options as well...
 
-    CONFIG_DECNET_RAW (to receive routing packets)
     CONFIG_DECNET_ROUTER (to be able to add/delete routes)
     CONFIG_NETLINK (to allow rtnetlink)
     CONFIG_RTNETLINK (for communication with the kernel routing layer)
+    CONFIG_NETFILTER (will be required for the DECnet routing daemon)
 
 3) Command line options
 
@@ -93,7 +93,13 @@
 If you want to configure a DECnet router you'll need the iproute2 package
 since its the _only_ way to add and delete routes currently. Eventually
 there will be a routing daemon to send and receive routing messages for
-each interface and update the kernel routing tables accordingly.
+each interface and update the kernel routing tables accordingly. The
+routing daemon will use netfilter to listen to routing packets, and
+rtnetlink to update the kernels routing tables. 
+
+The DECnet raw socket layer has been removed since it was there purely
+for use by the routing daemon which will now use netfilter (a much cleaner
+and more generic solution) instead.
 
 5) How can I tell if its working ?
 
diff -u --recursive --new-file v2.3.50/linux/Documentation/sound/Introduction linux/Documentation/sound/Introduction
--- v2.3.50/linux/Documentation/sound/Introduction	Fri Jan 21 18:19:15 2000
+++ linux/Documentation/sound/Introduction	Wed Mar  8 11:37:03 2000
@@ -160,8 +160,6 @@
 =============
 
 The status of sound may be read/checked by:
-	cat /proc/sound
-	cat /dev/sndstat
         cat (anyfile).au >/dev/audio
 
 The status of the modules and which modules depend on 
diff -u --recursive --new-file v2.3.50/linux/Documentation/sound/Maestro linux/Documentation/sound/Maestro
--- v2.3.50/linux/Documentation/sound/Maestro	Wed Dec 29 13:13:12 1999
+++ linux/Documentation/sound/Maestro	Wed Mar  8 11:37:03 2000
@@ -30,8 +30,7 @@
 --------------------
 
 This OSS driver exports /dev/mixer and /dev/dsp to applications, which
-mostly adhere to the OSS spec.   This driver doesn't register itself
-with /dev/sndstat, so don't expect information to appear there.
+mostly adhere to the OSS spec.
 
 The /dev/dsp device exported behaves almost as expected.  Playback is
 supported in all the various lovely formats.  8/16bit stereo/mono from
diff -u --recursive --new-file v2.3.50/linux/Documentation/sound/OPL3-SA linux/Documentation/sound/OPL3-SA
--- v2.3.50/linux/Documentation/sound/OPL3-SA	Thu Apr 29 11:53:41 1999
+++ linux/Documentation/sound/OPL3-SA	Wed Mar  8 11:37:03 2000
@@ -48,33 +48,5 @@
 
 If you chose to build it as a module, just insmod the resulting softoss2.o
 
-A 'cat /dev/sndstat' with all the above options should look similar to this:
-
-  OSS/Free:3.8s2++-971130
-  Load type: Driver loaded as a module
-  Kernel: Linux iniquity 2.1.105 #145 Mon Jun 8 11:40:47 MST 1998 i586
-  Config options: 0
-
-  Installed drivers: 
-
-  Card config: 
-
-  Audio devices:
-  0: MSS audio codec (CS4231) (DUPLEX)
-
-  Synth devices:
-  0: Yamaha OPL-3
-  1: SoftOSS
-
-  Midi devices:
-  0: OPL3-SA (MPU401)
-
-  Timers:
-  0: System clock
-  1: MSS audio codec (CS4231)
-
-  Mixers:
-  0: MSS audio codec (CS4231)
-
 Questions? Comments?
 <stiker@northlink.com>
diff -u --recursive --new-file v2.3.50/linux/Documentation/sound/Opti linux/Documentation/sound/Opti
--- v2.3.50/linux/Documentation/sound/Opti	Sun Nov  7 16:37:33 1999
+++ linux/Documentation/sound/Opti	Wed Mar  8 11:37:03 2000
@@ -99,9 +99,7 @@
 
 When any sound device is opened the kernel requests auto-loading
 of char-major-14. There is a built-in alias that translates this
-request to loading the main sound module. The main sound module
-contains only common code which is needed by all the sound drivers,
-and the driver for /dev/sndstat.
+request to loading the main sound module.
 
 The sound module in its turn will request loading of a sub-driver
 for mixer, audio, midi or synthesizer device. The first 3 are
diff -u --recursive --new-file v2.3.50/linux/Documentation/sound/README.OSS linux/Documentation/sound/README.OSS
--- v2.3.50/linux/Documentation/sound/README.OSS	Thu Apr 29 11:53:41 1999
+++ linux/Documentation/sound/README.OSS	Wed Mar  8 11:37:03 2000
@@ -147,24 +147,9 @@
 at /var/adm/messages for more verbose error message.
 
 
-In general the easiest way to diagnose problems is to do "cat /dev/sndstat".
-
-If you get an error message, there are some problems with the driver setup:
-
-	- "No such file or directory" tells that the device files for
-	the sound driver are missing. Use the script at the end of
-	linux/drivers/sound/Readme.linux to create them.
-
-	- "No such device" tells that the sound driver is not in the kernel.
-	You have to reconfigure and recompile the kernel to have the sound
-	driver. Compiling the driver doesn't help alone. You have to boot
-	with the newly compiled one before the driver becomes active.
-	The Linux-HOWTO should help in this step.
-
 The following errors are likely with /dev/dsp and /dev/audio.
 
-	- "No such device or address". This error message should not happen
-	with /dev/sndstat but it's possible with the other sound devices.
+	- "No such device or address".
 	This error indicates that there are no suitable hardware for the
 	device file or the sound driver has been compiled without support for
 	this particular device. For example /dev/audio and /dev/dsp will not
@@ -180,10 +165,6 @@
 	with impossible parameters. Check that the application is
 	for sound driver version 2.X or later.
 
-In general the printout of /dev/sndstat should tell what is the problem.
-It's possible that there are bugs in the sound driver but 99% of the problems
-reported to me are caused by somehow incorrect setup during "make config".
-
 Linux installation
 ==================
 
@@ -226,17 +207,6 @@
 Problems
 --------
 
-If you have any kind of problems, there is a debugging feature which
-could help you to solve the problem. To use it, just execute the
-command:
-
-	cat /dev/sndstat 
-
-and look at the output. It should display some useful info about the
-driver configuration. If there is no /dev/sndstat 
-(/dev/sndstat: No such file or directory), ensure that you have executed the
-soundinstall script (at the end of this file).
-
 Common error messages:
 
 - /dev/???????: No such file or directory.
@@ -757,10 +727,6 @@
 The sound driver configuration dialog
 -------------------------------------
 
-If you already have the sound driver installed, consult a printout of
-"cat /dev/sndstat" when configuring the driver again. It gives the I/O,
-IRQ and DMA settings you used earlier.
-
 Sound configuration starts by making some yes/no questions. Be careful
 when answering to these questions since answering y to a question may
 prevent some later ones from being asked. For example don't answer y to
@@ -1417,8 +1383,7 @@
 Please check the version of sound driver you are using before 
 complaining that your card is not supported. It's possible you are 
 using a driver version which was released months before your card was
-introduced.  The driver's release date is listed after its version number in a
-"cat /dev/sndstat" printout and in the file linux/drivers/sound/soundvers.h.
+introduced.
 
 First of all, there is an easy way to make most sound cards work with Linux.
 Just use the DOS based driver to initialize the card to a known state, then use
diff -u --recursive --new-file v2.3.50/linux/Documentation/sound/Wavefront linux/Documentation/sound/Wavefront
--- v2.3.50/linux/Documentation/sound/Wavefront	Sun Nov  7 16:37:33 1999
+++ linux/Documentation/sound/Wavefront	Wed Mar  8 11:37:03 2000
@@ -293,36 +293,6 @@
 The "available DRAM" line will vary depending on how much added RAM
 your card has. Mine has 8MB.
 
-Next, check /dev/sndstat, which on my machine says:
----------------------------------------------------------------------
-OSS/Free:3.8s2++-971130
-Load type: Driver loaded as a module
-Kernel: Linux bd 2.1.106 #12 SMP Fri Jul 3 00:37:34 EDT 1998 i486
-Config options: 0
-
-Installed drivers: 
-
-Card config: 
-
-Audio devices:
-0: Crystal audio controller (CS4232) (DUPLEX)
-
-Synth devices:
-0: Turtle Beach WaveFront
-1: Yamaha OPL-3
-
-Midi devices:
-0: WaveFront Internal MIDI
-1: WaveFront External MIDI
-
-Timers:
-0: System clock
-1: Crystal audio controller (CS4232)
-
-Mixers:
-0: Crystal audio controller (CS4232)
------------------------------------------------------------
-
 To check basically functionality, use play(1) or splay(1) to send a
 .WAV or other audio file through the audio portion. Then use playmidi
 to play a General MIDI file. Try the "-D 0" to hear the
diff -u --recursive --new-file v2.3.50/linux/Documentation/sound/via82cxxx.txt linux/Documentation/sound/via82cxxx.txt
--- v2.3.50/linux/Documentation/sound/via82cxxx.txt	Fri Jan  7 19:13:21 2000
+++ linux/Documentation/sound/via82cxxx.txt	Wed Mar  8 11:37:03 2000
@@ -122,25 +122,7 @@
 Known bugs (patches/suggestions welcome)
 ------------------------------------------------------------------------
 1) Two MIDI devices are loaded by the sound driver.  Eliminate one of them. 
-Sample /proc/sound output:
-
-	Midi devices:
-	0: Sound Blaster
-	1: VIA 82Cxxx Audio driver 1.1.2
 
 2) Two mixer devices are loaded by the sound driver.  Eliminate one of
 them.  At least one bug report says that SB mixer does not work at all,
-only AC97 mixer.  Sample /proc/sound output:
-
-	Mixers:
-	0: via82cxxxAC97Mixer
-	1: Sound Blaster
-
-3) After unloading the driver, a SoundBlaster MIDI device is still 
-listed in /proc/sound.  Investigate what is not being unloaded,
-and fix it.  Sample /proc/sound output, after 'rmmod via82cxxx':
-
-	Midi devices:
-	0: Sound Blaster
-
-
+only AC97 mixer.
diff -u --recursive --new-file v2.3.50/linux/Makefile linux/Makefile
--- v2.3.50/linux/Makefile	Tue Mar  7 14:32:25 2000
+++ linux/Makefile	Fri Mar 10 15:36:47 2000
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 3
-SUBLEVEL = 50
+SUBLEVEL = 51
 EXTRAVERSION =
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
@@ -134,6 +134,10 @@
 
 ifdef CONFIG_NET_FC
 DRIVERS := $(DRIVERS) drivers/net/fc/fc.a
+endif
+
+ifdef CONFIG_ATALK
+DRIVERS := $(DRIVERS) drivers/net/appletalk/appletalk.a
 endif
 
 ifdef CONFIG_TR
diff -u --recursive --new-file v2.3.50/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.3.50/linux/arch/alpha/config.in	Sat Feb 26 22:31:38 2000
+++ linux/arch/alpha/config.in	Thu Mar  9 07:04:55 2000
@@ -270,7 +270,7 @@
 
 source drivers/usb/Config.in
 
-source drivers/misc/Config.in
+#source drivers/misc/Config.in
 
 source fs/Config.in
 
diff -u --recursive --new-file v2.3.50/linux/arch/alpha/defconfig linux/arch/alpha/defconfig
--- v2.3.50/linux/arch/alpha/defconfig	Fri Jan 21 18:19:15 2000
+++ linux/arch/alpha/defconfig	Thu Mar  9 07:04:55 2000
@@ -324,10 +324,6 @@
 # CONFIG_USB is not set
 
 #
-# Misc devices
-#
-
-#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
diff -u --recursive --new-file v2.3.50/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.3.50/linux/arch/alpha/kernel/osf_sys.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/alpha/kernel/osf_sys.c	Wed Mar  8 13:55:08 2000
@@ -303,18 +303,9 @@
 static int do_osf_statfs(struct dentry * dentry, struct osf_statfs *buffer, unsigned long bufsiz)
 {
 	struct statfs linux_stat;
-	struct inode * inode = dentry->d_inode;
-	struct super_block * sb = inode->i_sb;
-	int error;
-
-	error = -ENODEV;
-	if (sb && sb->s_op && sb->s_op->statfs) {
-		set_fs(KERNEL_DS);
-		error = sb->s_op->statfs(sb, &linux_stat, sizeof(linux_stat));
-		set_fs(USER_DS);
-		if (!error)
-			error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
-	}
+	int error = vfs_statfs(dentry->d_inode->i_sb, &linux_stat);
+	if (!error)
+		error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
 	return error;	
 }
 
diff -u --recursive --new-file v2.3.50/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.3.50/linux/arch/arm/Makefile	Tue Mar  7 14:32:25 2000
+++ linux/arch/arm/Makefile	Wed Mar  8 09:18:02 2000
@@ -12,7 +12,6 @@
 #
 # Copyright (C) 1995-1999 by Russell King
 
-LD		:= $(CROSS_COMPILE)ld
 OBJCOPY		:= $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
 CPP		:= $(CC) -E
 PERL		:= perl
diff -u --recursive --new-file v2.3.50/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.3.50/linux/arch/arm/config.in	Thu Mar  2 14:36:22 2000
+++ linux/arch/arm/config.in	Thu Mar  9 07:04:55 2000
@@ -214,7 +214,7 @@
 
 source drivers/usb/Config.in
 
-source drivers/misc/Config.in
+#source drivers/misc/Config.in
 
 if [ "$CONFIG_VT" = "y" ]; then
    mainmenu_option next_comment
diff -u --recursive --new-file v2.3.50/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.50/linux/arch/i386/config.in	Tue Mar  7 14:32:25 2000
+++ linux/arch/i386/config.in	Fri Mar 10 10:48:53 2000
@@ -50,9 +50,7 @@
    define_bool CONFIG_X86_PGE y
 fi
 
-if [ "$CONFIG_DEVFS_FS" = "y" ]; then
-   tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
-fi
+tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
 
 choice 'High Memory Support' \
 	"off    CONFIG_NOHIGHMEM \
@@ -142,7 +140,7 @@
 
 bool 'Power Management support' CONFIG_PM
 
-dep_bool '  ACPI support' CONFIG_ACPI $CONFIG_PM
+dep_tristate '  ACPI support' CONFIG_ACPI $CONFIG_PM
 if [ "$CONFIG_ACPI" != "n" ]; then
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       bool '    Enter S1 for sleep (EXPERIMENTAL)' CONFIG_ACPI_S1_SLEEP
@@ -231,7 +229,7 @@
 
 source drivers/usb/Config.in
 
-source drivers/misc/Config.in
+#source drivers/misc/Config.in
 
 source fs/Config.in
 
diff -u --recursive --new-file v2.3.50/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.50/linux/arch/i386/defconfig	Tue Mar  7 14:32:25 2000
+++ linux/arch/i386/defconfig	Fri Mar 10 12:55:40 2000
@@ -27,6 +27,7 @@
 CONFIG_X86_TSC=y
 CONFIG_X86_GOOD_APIC=y
 CONFIG_X86_PGE=y
+# CONFIG_MICROCODE is not set
 CONFIG_NOHIGHMEM=y
 # CONFIG_HIGHMEM4G is not set
 # CONFIG_HIGHMEM64G is not set
@@ -165,6 +166,7 @@
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
 
 #
 # Telephony Support
@@ -197,6 +199,7 @@
 #
 # SCSI low-level drivers
 #
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
@@ -334,7 +337,6 @@
 # CONFIG_PCMCIA_NMCLAN is not set
 # CONFIG_PCMCIA_SMC91C92 is not set
 # CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_AIRONET4500_CS is not set
 # CONFIG_ARCNET_COM20020_CS is not set
 # CONFIG_PCMCIA_3C575 is not set
 # CONFIG_PCMCIA_TULIP is not set
@@ -342,6 +344,7 @@
 CONFIG_PCMCIA_RAYCS=y
 # CONFIG_PCMCIA_NETWAVE is not set
 # CONFIG_PCMCIA_WAVELAN is not set
+# CONFIG_AIRONET4500_CS is not set
 CONFIG_PCMCIA_NETCARD=y
 
 #
@@ -402,7 +405,6 @@
 # CONFIG_WATCHDOG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-# CONFIG_EFI_RTC is not set
 
 #
 # Video For Linux
@@ -431,10 +433,6 @@
 # USB support
 #
 # CONFIG_USB is not set
-
-#
-# Misc devices
-#
 
 #
 # File systems
diff -u --recursive --new-file v2.3.50/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c
--- v2.3.50/linux/arch/i386/kernel/acpi.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/i386/kernel/acpi.c	Thu Mar  9 15:56:51 2000
@@ -50,7 +50,6 @@
  */
 extern unsigned long get_cmos_time(void);
 
-static int acpi_control_thread(void *context);
 static int acpi_do_ulong(ctl_table *ctl,
 			 int write,
 			 struct file *file,
@@ -72,8 +71,6 @@
 			 void *buffer,
 			 size_t *len);
 
-DECLARE_WAIT_QUEUE_HEAD(acpi_control_wait);
-
 static struct ctl_table_header *acpi_sysctl = NULL;
 
 static struct acpi_facp *acpi_facp = NULL;
@@ -105,7 +102,15 @@
 static int acpi_p_lvl2_tested = 0;
 static int acpi_p_lvl3_tested = 0;
 
-static int acpi_disabled = 0;
+enum
+{
+	ACPI_ENABLED,
+	ACPI_TABLES_ONLY,
+	ACPI_CHIPSET_ONLY,
+	ACPI_DISABLED,
+};
+
+static int acpi_enabled = ACPI_ENABLED;
 
 // bits 8-15 are SLP_TYPa, bits 0-7 are SLP_TYPb
 static unsigned long acpi_slp_typ[] = 
@@ -1296,13 +1301,21 @@
  */
 static int __init acpi_init(void)
 {
-	int pid;
-
-	if (acpi_disabled)
-		return -ENODEV;
-
-	if (acpi_find_tables() && acpi_find_chipset()) {
-		// no ACPI tables and not recognized chipset
+	switch(acpi_enabled)
+	{
+	case ACPI_ENABLED:
+		if (acpi_find_tables() && acpi_find_chipset())
+			return -ENODEV;
+		break;
+	case ACPI_TABLES_ONLY:
+		if (acpi_find_tables())
+			return -ENODEV;
+		break;
+	case ACPI_CHIPSET_ONLY:
+		if (acpi_find_chipset())
+			return -ENODEV;
+		break;
+	case ACPI_DISABLED:
 		return -ENODEV;
 	}
 
@@ -1342,10 +1355,6 @@
 
 	acpi_sysctl = register_sysctl_table(acpi_dir_table, 1);
 
-	pid = kernel_thread(acpi_control_thread,
-			    NULL,
-			    CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-
 	pm_power_off = acpi_power_off;
 
 	pm_active = 1;
@@ -1379,6 +1388,7 @@
 static void __exit acpi_exit(void)
 {
 	pm_idle = NULL;
+	pm_active = 0;
 	pm_power_off = NULL;
 
 	unregister_sysctl_table(acpi_sysctl);
@@ -1400,10 +1410,14 @@
 static int __init acpi_setup(char *str)
 {
 	while (str && *str) {
-		if (strncmp(str, "off", 3) == 0)
-			acpi_disabled = 1;
-		else if (strncmp(str, "on", 2) == 0)
-			acpi_disabled = 0;
+		if (strncmp(str, "on", 2) == 0)
+			acpi_enabled = ACPI_ENABLED;
+		else if (strncmp(str, "tables", 6) == 0)
+			acpi_enabled = ACPI_TABLES_ONLY;
+		else if (strncmp(str, "chipset", 7) == 0)
+			acpi_enabled = ACPI_CHIPSET_ONLY;
+		else if (strncmp(str, "off", 3) == 0)
+			acpi_enabled = ACPI_DISABLED;
 		str = strpbrk(str, ",");
 		if (str)
 			str += strspn(str, ",");
@@ -1413,24 +1427,5 @@
 
 __setup("acpi=", acpi_setup);
 
-/*
- * Manage idle devices
- */
-static int acpi_control_thread(void *context)
-{
-	exit_mm(current);
-	exit_files(current);
-	strcpy(current->comm, "acpi");
-	
-	for(;;) {
-		interruptible_sleep_on(&acpi_control_wait);
-		if (signal_pending(current))
-			break;
-
-		// find all idle devices and set idle timer
-	}
-
-	return 0;
-}
-
-__initcall(acpi_init);
+module_init(acpi_init);
+module_exit(acpi_exit);
diff -u --recursive --new-file v2.3.50/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.3.50/linux/arch/i386/kernel/apm.c	Sat Feb 26 22:31:38 2000
+++ linux/arch/i386/kernel/apm.c	Thu Mar  9 17:15:02 2000
@@ -590,11 +590,11 @@
 					continue;
 				if (hlt_counter)
 					continue;
-				asm volatile("cli" : : : "memory");
+				__cli();
 				if (!current->need_resched)
-					asm volatile("sti ; hlt" : : : "memory");
+					safe_halt();
 				else
-					asm volatile("sti" : : : "memory");
+					__sti();
 				continue;
 			}
 
diff -u --recursive --new-file v2.3.50/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.3.50/linux/arch/i386/kernel/pci-pc.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/i386/kernel/pci-pc.c	Thu Mar  9 07:08:04 2000
@@ -1044,17 +1044,17 @@
 			printk("PCI: Discovered primary peer bus %02x [IRQ]\n", i);
 }
 
-static void set_level_irq(unsigned irq)
+static void ali_set_level_irq(unsigned irq)
 {
 	unsigned char mask = 1 << (irq & 7);
 	unsigned int port = 0x4d0 + (irq >> 3);
 	unsigned char val = inb(port);
 
 	if (val & mask) {
-		printk("PCI irq %d was level\n", irq);
+		DBG("PCI irq %d was level\n", irq);
 		return;
 	}
-	printk("PCI irq %d was edge, turning into level-triggered\n", irq);
+	DBG("PCI irq %d was edge, turning into level-triggered\n", irq);
 	outb(val | mask, port);
 }
 
@@ -1070,18 +1070,17 @@
 			unsigned offset = 0x48 + (pirq >> 1);
 			unsigned shift = (pirq & 1) << 2;
 			pci_read_config_byte(router, offset, &byte);
-			printk("ALI: old %04x=%02x\n", offset, byte);
+			DBG("ALI: old %04x=%02x\n", offset, byte);
 			byte &= ~(0xf << shift);
 			byte |= val << shift;
-			printk("ALI: new %04x=%02x\n", offset, byte);
+			DBG("ALI: new %04x=%02x\n", offset, byte);
 			pci_write_config_byte(router, offset, byte);
-			set_level_irq(irq);
+			ali_set_level_irq(irq);
 			return irq;
 		}
 	}
 	return 0;
 }
-		
 
 /*
  *  In case BIOS forgets to tell us about IRQ, we try to look it up in the routing
@@ -1380,13 +1379,17 @@
 
 	if ((err = pcibios_enable_resources(dev)) < 0)
 		return err;
-	if (!dev->irq && pirq_table) {
+	if (!dev->irq) {
 		u8 pin;
 		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 		if (pin) {
-			char *msg = pcibios_lookup_irq(dev, pirq_table, pin, 1);
-			if (msg)
+			char *msg;
+			if (pirq_table && ((msg = pcibios_lookup_irq(dev, pirq_table, pin, 1))))
 				printk("PCI: Assigned IRQ %d to device %s [%s]\n", dev->irq, dev->slot_name, msg);
+			else
+				printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
+				       'A' + pin - 1, dev->slot_name,
+				       (pci_probe & PCI_BIOS_IRQ_SCAN) ? "" : " Please try using pci=biosirq.");
 		}
 	}
 	return 0;
diff -u --recursive --new-file v2.3.50/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.3.50/linux/arch/i386/kernel/process.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/i386/kernel/process.c	Thu Mar  9 17:15:02 2000
@@ -75,11 +75,11 @@
 static void default_idle(void)
 {
 	if (current_cpu_data.hlt_works_ok && !hlt_counter) {
-		asm volatile("cli" : : : "memory");
+		__cli();
 		if (!current->need_resched)
-			asm volatile("sti ; hlt" : : : "memory");
+			safe_halt();
 		else
-			asm volatile("sti" : : : "memory");
+			__sti();
 	}
 }
 
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/Makefile linux/arch/ia64/Makefile
--- v2.3.50/linux/arch/ia64/Makefile	Tue Mar  7 14:32:25 2000
+++ linux/arch/ia64/Makefile	Fri Mar 10 15:24:02 2000
@@ -5,7 +5,7 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1998, 1999 by David Mosberger-Tang <davidm@hpl.hp.com>
+# Copyright (C) 1998-2000 by David Mosberger-Tang <davidm@hpl.hp.com>
 #
 
 NM := $(CROSS_COMPILE)nm -B
@@ -14,12 +14,12 @@
 # next line is for HP compiler backend:
 #AFLAGS += -DGCC_RETVAL_POINTER_IN_R8
 # The next line is needed when compiling with the July snapshot of the Cygnus compiler:
-#EXTRA	= -ma0-bugs -D__GCC_DOESNT_KNOW_IN_REGS__
+#EXTRA	= -D__GCC_DOESNT_KNOW_IN_REGS__
 # next two lines are for the September snapshot of the Cygnus compiler:
 AFLAGS += -D__GCC_MULTIREG_RETVALS__
-EXTRA	= -ma0-bugs -D__GCC_MULTIREG_RETVALS__
+EXTRA	= -D__GCC_MULTIREG_RETVALS__
 
-CFLAGS := -g $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127
+CFLAGS := $(CFLAGS) -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f10-f15,f32-f127
 
 ifdef CONFIG_IA64_GENERIC
 	CORE_FILES      :=      arch/$(ARCH)/hp/hp.a	\
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/config.in linux/arch/ia64/config.in
--- v2.3.50/linux/arch/ia64/config.in	Sun Feb 13 19:29:03 2000
+++ linux/arch/ia64/config.in	Fri Mar 10 10:48:53 2000
@@ -35,7 +35,7 @@
 	define_bool CONFIG_IA64_SOFTSDV_HACKS y
 fi
 
-define_bool CONFIG_KCORE_ELF y	# On IA-64, we always want an ELF /dev/kcore.
+define_bool CONFIG_KCORE_ELF y	# On IA-64, we always want an ELF /proc/kcore.
 
 bool 'SMP support' CONFIG_SMP n
 bool 'Performance monitor support' CONFIG_PERFMON n
@@ -123,7 +123,7 @@
 
 source drivers/char/Config.in
 source drivers/usb/Config.in
-source drivers/misc/Config.in
+#source drivers/misc/Config.in
 
 source fs/Config.in
 
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/dig/iosapic.c linux/arch/ia64/dig/iosapic.c
--- v2.3.50/linux/arch/ia64/dig/iosapic.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/dig/iosapic.c	Fri Mar 10 15:24:02 2000
@@ -12,6 +12,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/pci.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -19,7 +20,6 @@
 
 #include <asm/io.h>
 #include <asm/iosapic.h>
-#include <asm/irq.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/delay.h>
@@ -258,6 +258,21 @@
 
 #define iosapic_shutdown_irq	iosapic_disable_irq
 
+static unsigned int
+iosapic_startup_irq (unsigned int irq)
+{
+	int pin;
+
+	pin = iosapic_pin(irq);
+	if (pin < 0)
+		/* happens during irq auto probing... */
+		return 0;
+	set_rte(iosapic_addr(irq), pin, iosapic_polarity(irq), iosapic_trigger(irq), 
+		iosapic_dmode(irq), (ia64_get_lid() >> 16) & 0xffff, irq);
+	enable_pin(pin, iosapic_addr(irq));
+	return 0;
+}
+
 static void
 iosapic_enable_irq (unsigned int irq)
 {
@@ -295,58 +310,26 @@
 	return readl(IO_SAPIC_WINDOW + base_addr);
 }
 
-static int
-iosapic_handle_irq (unsigned int irq, struct pt_regs *regs)
+static void
+iosapic_ack_irq (unsigned int irq)
 {
-	struct irqaction *action = 0;
-	struct irq_desc *id = irq_desc + irq;
-	unsigned int status;
-	int retval;
-
-	spin_lock(&irq_controller_lock);
-	{
-		status = id->status;
-
-		/* do we need to do something IOSAPIC-specific to ACK the irq here??? */
-		/* Yes, but only level-triggered interrupts. We'll do that later */
-		if ((status & IRQ_INPROGRESS) == 0 && (status & IRQ_ENABLED) != 0) {
-			action = id->action;
-			status |= IRQ_INPROGRESS;
-		}
-		id->status = status & ~(IRQ_REPLAY | IRQ_WAITING);
-	}
-	spin_unlock(&irq_controller_lock);
-
-	if (!action) {
-		if (!(id->status & IRQ_AUTODETECT))
-			printk("iosapic_handle_irq: unexpected interrupt %u;"
-			       "disabling it (status=%x)\n", irq, id->status);
-		/*
-		 * If we don't have a handler, disable the pin so we
-		 * won't get any further interrupts (until
-		 * re-enabled).  --davidm 99/12/17
-		 */
-		iosapic_disable_irq(irq);
-		return 0;
-	}
-
-	retval = invoke_irq_handlers (irq, regs, action);
+}
 
+static void
+iosapic_end_irq (unsigned int irq)
+{
 	if (iosapic_trigger(irq) == IO_SAPIC_LEVEL)	/* ACK Level trigger interrupts */
 		writel(irq, iosapic_addr(irq) + IO_SAPIC_EOI);
+}
 
-	spin_lock(&irq_controller_lock);
-	{
-		status = (id->status & ~IRQ_INPROGRESS);
-		id->status = status;
-	}
-	spin_unlock(&irq_controller_lock);
-
-	return retval;
+static void
+iosapic_set_affinity (unsigned int irq, unsigned long mask)
+{
+	printk("iosapic_set_affinity: not implemented yet\n");
 }
 
-void __init
-iosapic_init (unsigned long addr)
+void
+iosapic_init (unsigned long address)
 {
 	int	i;
 #ifdef CONFIG_IA64_IRQ_ACPI
@@ -357,18 +340,9 @@
 #endif
 
 	/*
-	 * Disable all local interrupts
-	 */
-
-	ia64_set_itv(0, 1);
-	ia64_set_lrr0(0, 1);	
-	ia64_set_lrr1(0, 1);	
-
-	/*
 	 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support
 	 * enabled.
 	 */
-
 	outb(0xff, 0xA1);
 	outb(0xff, 0x21);
 
@@ -376,10 +350,13 @@
 	memset(iosapic_vector, 0x0, sizeof(iosapic_vector));
 	for (i = 0; i < NR_IRQS; i++) {
 		iosapic_pin(i) = 0xff;
-		iosapic_addr(i) = (unsigned long) ioremap(IO_SAPIC_DEFAULT_ADDR, 0);
+		iosapic_addr(i) = (unsigned long) ioremap(address, 0);
 	}
 	/* XXX this should come from systab or some such: */
+# if 0
+	/* this doesn't look right --davidm 00/03/07 */
 	iosapic_pin(TIMER_IRQ) = 5;	/* System Clock Interrupt */
+# endif
 	iosapic_pin(0x40) = 3;	/* Keyboard */
 	iosapic_pin(0x92) = 9;	/* COM1 Serial Port */
 	iosapic_pin(0x80) = 4;	/* Periodic Interrupt */
@@ -396,7 +373,7 @@
 	i = -1;
 	while (intr_routing[++i].srcbus != 0xff) {
 		if (intr_routing[i].srcbus == BUS_ISA) {
-			vector = map_legacy_irq(intr_routing[i].srcbusirq);
+			vector = isa_irq_to_vector(intr_routing[i].srcbusirq);
 		} else if (intr_routing[i].srcbus == BUS_PCI) {
 			vector = intr_routing[i].iosapic_pin;
 		} else {
@@ -414,7 +391,7 @@
 		       iosapic_trigger(vector));
 # endif
 	}
-#else /* !defined(CONFIG_IA64_SOFTSDV_HACKS) && !defined(CONFIG_IA64_IRQ_ACPI) */
+#else /* !defined(CONFIG_IA64_SOFTSDV_HACKS) && defined(CONFIG_IA64_IRQ_ACPI) */
 	/* 
 	 * Map the legacy ISA devices into the IOAPIC data; We'll override these
 	 * later with data from the ACPI Interrupt Source Override table.
@@ -425,8 +402,8 @@
 	 * here, so that this works on BigSur but will go ask Intel. --wfd 2000-Jan-19
 	 *
 	 */
-	for (i =0 ; i < IA64_MIN_VECTORED_IRQ; i++) {
-		irq = map_legacy_irq(i);
+	for (i =0 ; i < 16; i++) {
+		irq = isa_irq_to_vector(i);
 		iosapic_pin(irq) = i; 
 		iosapic_bus(irq) = BUS_ISA;
 		iosapic_busdata(irq) = 0;
@@ -445,7 +422,9 @@
 	ia64_boot_param.pci_vectors = (__u64) __va(ia64_boot_param.pci_vectors);
 	vectors = (struct pci_vector_struct *) ia64_boot_param.pci_vectors;
 	for (i = 0; i < ia64_boot_param.num_pci_vectors; i++) {
-		irq = map_legacy_irq(vectors[i].irq);
+		irq = vectors[i].irq;
+		if (irq < 16)
+			irq = isa_irq_to_vector(irq);
 
 		iosapic_bustype(irq) = BUS_PCI;
 		iosapic_pin(irq) = irq - iosapic_baseirq(irq);
@@ -469,34 +448,19 @@
 #endif /* !CONFIG_IA64_IRQ_ACPI */
 }
 
-static void
-iosapic_startup_irq (unsigned int irq)
-{
-	int pin;
-
-	if (irq == TIMER_IRQ)
-		return;
-	pin = iosapic_pin(irq);
-	if (pin < 0)
-		/* happens during irq auto probing... */
-		return;
-	set_rte(iosapic_addr(irq), pin, iosapic_polarity(irq), iosapic_trigger(irq), 
-		iosapic_dmode(irq), (ia64_get_lid() >> 16) & 0xffff, irq);
-	enable_pin(pin, iosapic_addr(irq));
-}
-
 struct hw_interrupt_type irq_type_iosapic = {
-	"IOSAPIC",
-	iosapic_init,
-	iosapic_startup_irq,
-	iosapic_shutdown_irq,
-	iosapic_handle_irq,
-	iosapic_enable_irq,
-	iosapic_disable_irq
+	typename:	"IOSAPIC",
+	startup:	iosapic_startup_irq,
+	shutdown:	iosapic_shutdown_irq,
+	enable:		iosapic_enable_irq,
+	disable:	iosapic_disable_irq,
+	ack:		iosapic_ack_irq,
+	end:		iosapic_end_irq,
+	set_affinity:	iosapic_set_affinity
 };
 
 void
-dig_irq_init (struct irq_desc desc[NR_IRQS])
+dig_irq_init (void)
 {
 	int i;
 
@@ -505,10 +469,20 @@
 	 * claimed by someone else already (e.g., timer or IPI are
 	 * handled internally).
 	 */
+#if 0
 	for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) {
-		if (irq_desc[i].handler == &irq_type_default)
+		if (irq_desc[i].handler == &no_irq_type)
 			irq_desc[i].handler = &irq_type_iosapic;
 	}
+#else
+	for (i = 0; i <= IA64_MAX_VECTORED_IRQ; ++i) {
+		if (irq_desc[i].handler == &no_irq_type)
+			irq_desc[i].handler = &irq_type_iosapic;
+	}
+#endif
+#ifndef CONFIG_IA64_DIG
+	iosapic_init(IO_SAPIC_DEFAULT_ADDR);
+#endif
 }
 
 void
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/hp/hpsim_irq.c linux/arch/ia64/hp/hpsim_irq.c
--- v2.3.50/linux/arch/ia64/hp/hpsim_irq.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/hp/hpsim_irq.c	Fri Mar 10 15:24:02 2000
@@ -1,83 +1,42 @@
 /*
  * Platform dependent support for HP simulator.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/kdev_t.h>
-#include <linux/console.h>
-
-#include <asm/delay.h>
-#include <asm/irq.h>
-#include <asm/pal.h>
-#include <asm/machvec.h>
-#include <asm/pgtable.h>
-#include <asm/sal.h>
 
+#include <linux/init.h>
+#include <linux/irq.h>
 
-static int
-irq_hp_sim_handle_irq (unsigned int irq, struct pt_regs *regs)
+static unsigned int
+hpsim_irq_startup (unsigned int irq)
 {
-	struct irqaction *action = 0;
-	struct irq_desc *id = irq_desc + irq;
-	unsigned int status;
-	int retval;
-
-	spin_lock(&irq_controller_lock);
-	{
-		status = id->status;
-		if ((status & IRQ_INPROGRESS) == 0 && (status & IRQ_ENABLED) != 0) {
-			action = id->action;
-			status |= IRQ_INPROGRESS;
-		}
-		id->status = status & ~(IRQ_REPLAY | IRQ_WAITING);
-	}
-	spin_unlock(&irq_controller_lock);
-
-	if (!action) {
-		if (!(id->status & IRQ_AUTODETECT))
-			printk("irq_hpsim_handle_irq: unexpected interrupt %u\n", irq);
-		return 0;
-	}
-
-	retval = invoke_irq_handlers(irq, regs, action);
-
-	spin_lock(&irq_controller_lock);
-	{
-		id->status &= ~IRQ_INPROGRESS;
-	}
-	spin_unlock(&irq_controller_lock);
-
-	return retval;
+	return 0;
 }
 
 static void
-irq_hp_sim_noop (unsigned int irq)
+hpsim_irq_noop (unsigned int irq)
 {
 }
 
 static struct hw_interrupt_type irq_type_hp_sim = {
-	"hp_sim",
-	(void (*)(unsigned long)) irq_hp_sim_noop,	/* init */
-	irq_hp_sim_noop,				/* startup */
-	irq_hp_sim_noop,				/* shutdown */
-	irq_hp_sim_handle_irq,				/* handle */
-	irq_hp_sim_noop,				/* enable */
-	irq_hp_sim_noop,				/* disable */
+	typename:	"hpsim",
+	startup:	hpsim_irq_startup,
+	shutdown:	hpsim_irq_noop,
+	enable:		hpsim_irq_noop,
+	disable:	hpsim_irq_noop,
+	ack:		hpsim_irq_noop,
+	end:		hpsim_irq_noop,
+	set_affinity:	(void (*)(unsigned int, unsigned long)) hpsim_irq_noop,
 };
 
-void
-hpsim_irq_init (struct irq_desc desc[NR_IRQS])
+void __init
+hpsim_irq_init (void)
 {
 	int i;
 
 	for (i = IA64_MIN_VECTORED_IRQ; i <= IA64_MAX_VECTORED_IRQ; ++i) {
-		irq_desc[i].handler = &irq_type_hp_sim;
+		if (irq_desc[i].handler == &no_irq_type)
+			irq_desc[i].handler = &irq_type_hp_sim;
 	}
 }
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/ia32/binfmt_elf32.c linux/arch/ia64/ia32/binfmt_elf32.c
--- v2.3.50/linux/arch/ia64/ia32/binfmt_elf32.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/ia64/ia32/binfmt_elf32.c	Fri Mar 10 15:24:02 2000
@@ -50,13 +50,13 @@
 	pmd = pmd_alloc(pgd, address);
 	if (!pmd) {
 		__free_page(page);
-		oom(tsk);
+		force_sig(SIGKILL, tsk);
 		return 0;
 	}
 	pte = pte_alloc(pmd, address);
 	if (!pte) {
 		__free_page(page);
-		oom(tsk);
+		force_sig(SIGKILL, tsk);
 		return 0;
 	}
 	if (!pte_none(*pte)) {
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/Makefile linux/arch/ia64/kernel/Makefile
--- v2.3.50/linux/arch/ia64/kernel/Makefile	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/kernel/Makefile	Fri Mar 10 15:24:02 2000
@@ -15,7 +15,7 @@
 all: kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
-O_OBJS	 := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_default.o irq_internal.o ivt.o \
+O_OBJS	 := acpi.o entry.o gate.o efi.o efi_stub.o irq.o irq_ia64.o irq_internal.o ivt.o \
 	    pal.o pci-dma.o process.o perfmon.o ptrace.o sal.o sal_stub.o semaphore.o setup.o signal.o \
 	    sys_ia64.o traps.o time.o unaligned.o unwind.o
 #O_OBJS   := fpreg.o
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/acpi.c linux/arch/ia64/kernel/acpi.c
--- v2.3.50/linux/arch/ia64/kernel/acpi.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/kernel/acpi.c	Fri Mar 10 15:24:02 2000
@@ -11,6 +11,7 @@
 #include <linux/config.h>
 
 #include <linux/init.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/smp.h>
@@ -22,7 +23,6 @@
 #include <asm/efi.h>
 #include <asm/io.h>
 #include <asm/iosapic.h>
-#include <asm/irq.h>
 
 #undef ACPI_DEBUG		/* Guess what this does? */
 
@@ -83,8 +83,8 @@
 	 */
 #ifdef CONFIG_IA64_DIG
 	acpi_entry_iosapic_t *iosapic = (acpi_entry_iosapic_t *) p;
-	unsigned int ver;
-	int l, v, pins;
+	unsigned int ver, v;
+	int l, pins;
 
 	ver = iosapic_version(iosapic->address);
 	pins = (ver >> 16) & 0xff;
@@ -94,9 +94,11 @@
 	       iosapic->irq_base, iosapic->irq_base + pins);
 	
 	for (l = 0; l < pins; l++) {
-		v = map_legacy_irq(iosapic->irq_base + l);
+		v = iosapic->irq_base + l;
+		if (v < 16)
+			v = isa_irq_to_vector(v);
 		if (v > IA64_MAX_VECTORED_IRQ) {
-			printk("    !!! IRQ %d > 255\n", v);
+			printk("    !!! bad IOSAPIC interrupt vector: %u\n", v);
 			continue;
 		}
 		/* XXX Check for IOSAPIC collisions */
@@ -115,7 +117,7 @@
 acpi_legacy_irq(char *p)
 {
 	/*
-	 * This is not good.  ACPI is not necessarily limited to CONFIG_IA64_SV, yet
+	 * This is not good.  ACPI is not necessarily limited to CONFIG_IA64_DIG, yet
 	 * ACPI does not necessarily imply IOSAPIC either.  Perhaps there should be
 	 * a means for platform_setup() to register ACPI handlers?
 	 */
@@ -124,7 +126,7 @@
 	unsigned char vector; 
 	int i;
 
-	vector = map_legacy_irq(legacy->isa_irq);
+	vector = isa_irq_to_vector(legacy->isa_irq);
 
 	/*
 	 * Clobber any old pin mapping.  It may be that it gets replaced later on
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/efi.c linux/arch/ia64/kernel/efi.c
--- v2.3.50/linux/arch/ia64/kernel/efi.c	Sun Feb 13 19:29:03 2000
+++ linux/arch/ia64/kernel/efi.c	Fri Mar 10 15:24:02 2000
@@ -227,8 +227,8 @@
 		panic("Woah! Can't find EFI system table.\n");
 	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) 
 		panic("Woah! EFI system table signature incorrect\n");
-	if (efi.systab->hdr.revision != EFI_SYSTEM_TABLE_REVISION)
-		printk("Warning: EFI system table version mismatch: "
+	if ((efi.systab->hdr.revision ^ EFI_SYSTEM_TABLE_REVISION) >> 16 != 0)
+		printk("Warning: EFI system table major version mismatch: "
 		       "got %d.%02d, expected %d.%02d\n",
 		       efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff,
 		       EFI_SYSTEM_TABLE_REVISION >> 16, EFI_SYSTEM_TABLE_REVISION & 0xffff);
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/entry.S linux/arch/ia64/kernel/entry.S
--- v2.3.50/linux/arch/ia64/kernel/entry.S	Sun Feb 13 19:29:03 2000
+++ linux/arch/ia64/kernel/entry.S	Fri Mar 10 15:24:02 2000
@@ -738,7 +738,7 @@
 	st8.spill [r2]=r9	// store errno in pt_regs.r8 and set unat bit
 	st8.spill [r3]=r10	// store error indication in pt_regs.r10 and set unat bit
 	br.cond.sptk.many ia64_leave_kernel
-	.endp __ret_from_syscall
+	.endp handle_syscall_error
 
 #ifdef CONFIG_SMP
 	/*
@@ -767,7 +767,9 @@
 invoke_do_softirq:
 	alloc loc0=ar.pfs,8,2,0,0
 	mov loc1=rp
+(pEOI)	mov cr.eoi=r0
 	;;
+(pEOI)	cmp.ne pEOI,p0=r0,r0
 	br.call.sptk.few rp=do_softirq
 .ret9:
 	mov ar.pfs=loc0
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/fw-emu.c linux/arch/ia64/kernel/fw-emu.c
--- v2.3.50/linux/arch/ia64/kernel/fw-emu.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/kernel/fw-emu.c	Fri Mar 10 15:24:02 2000
@@ -139,6 +139,24 @@
 	movl r9 =0x100000064		/* proc_ratio (1/100) */
 	movl r10=0x100000100		/* bus_ratio<<32 (1/256) */
 	movl r11=0x100000064		/* itc_ratio<<32 (1/100) */
+	;;
+1:	cmp.eq p6,p7=1,r28		/* PAL_CACHE_FLUSH */
+(p7)	br.cond.sptk.few 1f
+	mov r9=ar.lc
+	movl r8=524288			/* flush 512k million cache lines (16MB) */
+	;;
+	mov ar.lc=r8
+	movl r8=0xe000000000000000
+	;;
+.loop:	fc r8
+	add r8=32,r8
+	br.cloop.sptk.few .loop
+	sync.i
+	;;
+	srlz.i
+	;;
+	mov ar.lc=r9
+	mov r8=r0
 1:	br.cond.sptk.few rp
 	.endp pal_emulator_static\n");
 
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/gate.S linux/arch/ia64/kernel/gate.S
--- v2.3.50/linux/arch/ia64/kernel/gate.S	Sun Feb 13 19:29:03 2000
+++ linux/arch/ia64/kernel/gate.S	Fri Mar 10 15:24:02 2000
@@ -82,7 +82,7 @@
 	br.call.sptk.many rp=invoke_sighandler
 .ret0:	mov r15=__NR_rt_sigreturn
 	break __BREAK_SYSCALL
-	.endp ia64_sigramp
+	.endp ia64_sigtramp
 
 	.proc invoke_sighandler
 invoke_sighandler:
@@ -167,7 +167,7 @@
 	br.ret.sptk.few b6
 cont:	mov ar.pfs=r8				// ar.pfs = CFM0
 	br.ret.sptk.few rp			// re-establish CFM0
-	.endp invoke_signal_handler
+	.endp invoke_sighandler
 
 	.proc setup_rbs
 setup_rbs:
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/irq.c linux/arch/ia64/kernel/irq.c
--- v2.3.50/linux/arch/ia64/kernel/irq.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/ia64/kernel/irq.c	Fri Mar 10 15:24:02 2000
@@ -1,105 +1,146 @@
 /*
- * linux/arch/ia64/kernel/irq.c
+ *	linux/arch/ia64/kernel/irq.c
  *
- * Copyright (C) 1998-2000 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
- * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
  *
- *  6/10/99: Updated to bring in sync with x86 version to facilitate
- *	     support for SMP and different interrupt controllers.
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
  */
 
-#include <linux/config.h>
+/*
+ * (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.
+ */
 
-#include <linux/sched.h>
+#include <linux/config.h>
+#include <linux/ptrace.h>
 #include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
 #include <linux/ioport.h>
-#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
 #include <linux/malloc.h>
-#include <linux/ptrace.h>
-#include <linux/random.h>	/* for rand_initialize_irq() */
-#include <linux/signal.h>
-#include <linux/smp.h>
+#include <linux/random.h>
 #include <linux/smp_lock.h>
-#include <linux/threads.h>
-
-#ifdef CONFIG_KDB
-# include <linux/kdb.h>
-#endif
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/irq.h>
+#include <linux/proc_fs.h>
 
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/system.h>
 #include <asm/bitops.h>
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
 #include <asm/delay.h>
-#include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/machvec.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
 
-/* This is used to detect bad usage of probe_irq_on()/probe_irq_off().  */
-#define PROBE_IRQ_COOKIE	0xfeedC0FFEE
 
-struct irq_desc irq_desc[NR_IRQS];
 
 /*
- * Micro-access to controllers is serialized over the whole
- * system. We never hold this lock when we call the actual
- * IRQ handler.
+ * Linux has a controller-independent x86 interrupt architecture.
+ * every controller has a 'controller-template', that is used
+ * by the main code to do the right thing. Each driver-visible
+ * interrupt source is transparently wired to the apropriate
+ * controller. Thus drivers need not be aware of the
+ * interrupt-controller.
+ *
+ * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
+ * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
+ * (IO-APICs assumed to be messaging to Pentium local-APICs)
+ *
+ * the code is designed to be easily extended with new/different
+ * interrupt controllers, without having to do assembly magic.
  */
-spinlock_t irq_controller_lock;
 
-#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
-spinlock_t ivr_read_lock;
-#endif
+irq_cpustat_t irq_stat [NR_CPUS];
 
-unsigned int local_bh_count[NR_CPUS];
 /*
- * used in irq_enter()/irq_exit()
+ * Controller mappings for all interrupt sources:
  */
-unsigned int local_irq_count[NR_CPUS];
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
+	{ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
 
-static struct irqaction timer_action = { NULL, 0, 0, NULL, NULL, NULL};
+static void register_irq_proc (unsigned int irq);
 
-#ifdef CONFIG_SMP
-static struct irqaction ipi_action = { NULL, 0, 0, NULL, NULL, NULL};
-#endif
+/*
+ * Special irq handlers.
+ */
+
+void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
 
 /*
- * Legacy IRQ to IA-64 vector translation table.  Any vector not in
- * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30)
+ * Generic no controller code
  */
-__u8 irq_to_vector_map[IA64_MIN_VECTORED_IRQ] = {
-	/* 8259 IRQ translation, first 16 entries */
-	TIMER_IRQ, 0x50, 0x0f, 0x51, 0x52, 0x53, 0x43, 0x54,
-	0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41,
-};
 
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq)
+{
 /*
- * Reverse of the above table.
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves, it doesnt deserve
+ * a generic callback i think.
  */
-static __u8 vector_to_legacy_map[256];
+#if CONFIG_X86
+	printk("unexpected IRQ trap at vector %02x\n", irq);
+#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
+	 * irq slots per priority level, and a 'hanging, unacked' IRQ
+	 * holds up an irq slot - in excessive cases (when multiple
+	 * unexpected vectors occur) that might lock up the APIC
+	 * completely.
+	 */
+	ack_APIC_irq();
+#endif
+#endif
+#if CONFIG_IA64
+	printk("Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id());
+#endif
+}
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none	disable_none
+#define end_none	enable_none
+
+struct hw_interrupt_type no_irq_type = {
+	"none",
+	startup_none,
+	shutdown_none,
+	enable_none,
+	disable_none,
+	ack_none,
+	end_none
+};
+
+volatile unsigned long irq_err_count;
 
 /*
- * used by proc fs (/proc/interrupts)
+ * Generic, controller-independent functions:
  */
-int
-get_irq_list (char *buf)
+
+int get_irq_list(char *buf)
 {
-	int i;
+	int i, j;
 	struct irqaction * action;
 	char *p = buf;
 
-#ifdef CONFIG_SMP
 	p += sprintf(p, "           ");
-	for (i = 0; i < smp_num_cpus; i++)
-		p += sprintf(p, "CPU%d       ", i);
+	for (j=0; j<smp_num_cpus; j++)
+		p += sprintf(p, "CPU%d       ",j);
 	*p++ = '\n';
-#endif
-	/*
-	 * Simply scans the external vectored interrupts
-	 */
-	for (i = 0; i < NR_IRQS; i++) {
+
+	for (i = 0 ; i < NR_IRQS ; i++) {
 		action = irq_desc[i].action;
 		if (!action) 
 			continue;
@@ -107,356 +148,496 @@
 #ifndef CONFIG_SMP
 		p += sprintf(p, "%10u ", kstat_irqs(i));
 #else
-		{
-			int j;
-			for (j = 0; j < smp_num_cpus; j++)
-				p += sprintf(p, "%10u ",
-					     kstat.irqs[cpu_logical_map(j)][i]);
-		}
+		for (j = 0; j < smp_num_cpus; j++)
+			p += sprintf(p, "%10u ",
+				kstat.irqs[cpu_logical_map(j)][i]);
 #endif
 		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
-		p += sprintf(p, "  %c%s", (action->flags & SA_INTERRUPT) ? '+' : ' ',
-			     action->name);
+		p += sprintf(p, "  %s", action->name);
 
-		for (action = action->next; action; action = action->next) {
-			p += sprintf(p, ", %c%s",
-				     (action->flags & SA_INTERRUPT)?'+':' ',
-				     action->name);
-		}
+		for (action=action->next; action; action = action->next)
+			p += sprintf(p, ", %s", action->name);
 		*p++ = '\n';
 	}
+	p += sprintf(p, "NMI: ");
+	for (j = 0; j < smp_num_cpus; j++)
+		p += sprintf(p, "%10u ",
+			atomic_read(&nmi_counter(cpu_logical_map(j))));
+	p += sprintf(p, "\n");
+#if CONFIG_SMP
+	p += sprintf(p, "LOC: ");
+	for (j = 0; j < smp_num_cpus; j++)
+		p += sprintf(p, "%10u ",
+			apic_timer_irqs[cpu_logical_map(j)]);
+	p += sprintf(p, "\n");
+#endif
+	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
 	return p - buf;
 }
 
-int usbfix;
 
-static int __init
-usbfix_option (char *str)
+/*
+ * Global interrupt locks for SMP. Allow interrupts to come in on any
+ * CPU, yet make cli/sti act globally to protect critical regions..
+ */
+
+#ifdef CONFIG_SMP
+unsigned char global_irq_holder = NO_PROC_ID;
+unsigned volatile int global_irq_lock;
+
+extern void show_stack(unsigned long* esp);
+
+static void show(char * str)
 {
-	printk("irq: enabling USB workaround\n");
-	usbfix = 1;
-	return 1;
+	int i;
+	int cpu = smp_processor_id();
+
+	printk("\n%s, CPU %d:\n", str, cpu);
+	printk("irq:  %d [",irqs_running());
+	for(i=0;i < smp_num_cpus;i++)
+		printk(" %d",local_irq_count(i));
+	printk(" ]\nbh:   %d [",spin_is_locked(&global_bh_lock) ? 1 : 0);
+	for(i=0;i < smp_num_cpus;i++)
+		printk(" %d",local_bh_count(i));
+
+	printk(" ]\nStack dumps:");
+	for(i=0;i< smp_num_cpus;i++) {
+		unsigned long esp;
+		if(i==cpu)
+			continue;
+		printk("\nCPU %d:",i);
+		esp = init_tss[i].esp0;
+		if(esp==NULL) {
+			/* tss->esp0 is set to NULL in cpu_init(),
+			 * it's initialized when the cpu returns to user
+			 * space. -- manfreds
+			 */
+			printk(" <unknown> ");
+			continue;
+		}
+		esp &= ~(THREAD_SIZE-1);
+		esp += sizeof(struct task_struct);
+		show_stack((void*)esp);
+ 	}
+	printk("\nCPU %d:",cpu);
+	show_stack(NULL);
+	printk("\n");
 }
+	
+#define MAXCOUNT 100000000
 
-__setup("usbfix", usbfix_option);
+/*
+ * I had a lockup scenario where a tight loop doing
+ * spin_unlock()/spin_lock() on CPU#1 was racing with
+ * spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but
+ * apparently the spin_unlock() information did not make it
+ * through to CPU#0 ... nasty, is this by design, do we have to limit
+ * 'memory update oscillation frequency' artificially like here?
+ *
+ * Such 'high frequency update' races can be avoided by careful design, but
+ * some of our major constructs like spinlocks use similar techniques,
+ * it would be nice to clarify this issue. Set this define to 0 if you
+ * want to check whether your system freezes.  I suspect the delay done
+ * by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but
+ * i thought that such things are guaranteed by design, since we use
+ * the 'LOCK' prefix.
+ */
+#define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 0
 
+#if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND
+# define SYNC_OTHER_CORES(x) udelay(x+1)
+#else
 /*
- * That's where the IVT branches when we get an external
- * interrupt. This branches to the correct hardware IRQ handler via
- * function ptr.
+ * We have to allow irqs to arrive between __sti and __cli
  */
-void
-ia64_handle_irq (unsigned long irq, struct pt_regs *regs)
+# define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
+#endif
+
+static inline void wait_on_irq(int cpu)
 {
-	unsigned long bsp, sp, saved_tpr;
+	int count = MAXCOUNT;
 
-#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
-# ifndef CONFIG_SMP
-	static unsigned int max_prio = 0;
-# endif
-	unsigned int prev_prio;
-	unsigned long eoi_ptr;
- 
-# ifdef CONFIG_USB
-	extern void reenable_usb (void);
-	extern void disable_usb (void);
+	for (;;) {
 
-	if (usbfix)
-		disable_usb();
-# endif
-	/*
-	 * Stop IPIs by getting the ivr_read_lock
-	 */
-	spin_lock(&ivr_read_lock);
+		/*
+		 * Wait until all interrupts are gone. Wait
+		 * for bottom half handlers unless we're
+		 * already executing in one..
+		 */
+		if (!irqs_running())
+			if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
+				break;
+
+		/* Duh, we have to loop. Release the lock to avoid deadlocks */
+		clear_bit(0,&global_irq_lock);
+
+		for (;;) {
+			if (!--count) {
+				show("wait_on_irq");
+				count = ~0;
+			}
+			__sti();
+			SYNC_OTHER_CORES(cpu);
+			__cli();
+			if (irqs_running())
+				continue;
+			if (global_irq_lock)
+				continue;
+			if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock))
+				continue;
+			if (!test_and_set_bit(0,&global_irq_lock))
+				break;
+		}
+	}
+}
 
-	/*
-	 * Disable PCI writes
-	 */
-	outl(0x80ff81c0, 0xcf8);
-	outl(0x73002188, 0xcfc);
-	eoi_ptr = inl(0xcfc);
+/*
+ * This is called when we want to synchronize with
+ * interrupts. We may for example tell a device to
+ * stop sending interrupts: but to make sure there
+ * are no interrupts that are executing on another
+ * CPU we need to call this function.
+ */
+void synchronize_irq(void)
+{
+	if (irqs_running()) {
+		/* Stupid approach */
+		cli();
+		sti();
+	}
+}
 
-	irq = ia64_get_ivr();
+static inline void get_irqlock(int cpu)
+{
+	if (test_and_set_bit(0,&global_irq_lock)) {
+		/* do we already hold the lock? */
+		if ((unsigned char) cpu == global_irq_holder)
+			return;
+		/* Uhhuh.. Somebody else got it. Wait.. */
+		do {
+			do {
+			} while (test_bit(0,&global_irq_lock));
+		} while (test_and_set_bit(0,&global_irq_lock));		
+	}
+	/* 
+	 * We also to make sure that nobody else is running
+	 * in an interrupt context. 
+	 */
+	wait_on_irq(cpu);
 
 	/*
-	 * Enable PCI writes
+	 * Ok, finally..
 	 */
-	outl(0x73182188, 0xcfc);
+	global_irq_holder = cpu;
+}
 
-	spin_unlock(&ivr_read_lock);
+#define EFLAGS_IF_SHIFT 9
 
-# ifdef CONFIG_USB
-	if (usbfix)
-		reenable_usb();
-# endif
+/*
+ * A global "cli()" while in an interrupt context
+ * turns into just a local cli(). Interrupts
+ * should use spinlocks for the (very unlikely)
+ * case that they ever want to protect against
+ * each other.
+ *
+ * If we already have local interrupts disabled,
+ * this will not turn a local disable into a
+ * global one (problems with spinlocks: this makes
+ * save_flags+cli+sti usable inside a spinlock).
+ */
+void __global_cli(void)
+{
+	unsigned int flags;
 
-# ifndef CONFIG_SMP
-	prev_prio = max_prio;
-	if (irq < max_prio) {
-		printk ("ia64_handle_irq: got irq %lu while %u was in progress!\n",
-			irq, max_prio);
-		
-	} else
-		max_prio = irq;
-# endif /* !CONFIG_SMP */
-#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
-
-	/* Always set TPR to limit maximum interrupt nesting depth to
-	 * 16 (without this, it would be ~240, which could easily lead
-	 * to kernel stack overflows.
-	 */
-	saved_tpr = ia64_get_tpr();
-	ia64_srlz_d();
-	ia64_set_tpr(irq);
-	ia64_srlz_d();
-
-	asm ("mov %0=ar.bsp" : "=r"(bsp));
-	asm ("mov %0=sp" : "=r"(sp));
-
-	if ((sp - bsp) < 1024) {
-		static long last_time;
-		static unsigned char count;
-
-		if (count > 5 && jiffies - last_time > 5*HZ)
-			count = 0;
-		if (++count < 5) {
-			last_time = jiffies;
-			printk("ia64_handle_irq: DANGER: less than 1KB of free stack space!!\n"
-			       "(bsp=0x%lx, sp=%lx)\n", bsp, sp);
-		}
-#ifdef CONFIG_KDB
-		kdb(KDB_REASON_PANIC, 0, regs);
-#endif		
+	__save_flags(flags);
+	if (flags & (1 << EFLAGS_IF_SHIFT)) {
+		int cpu = smp_processor_id();
+		__cli();
+		if (!local_irq_count(cpu))
+			get_irqlock(cpu);
 	}
+}
 
-	/*
-	 * The interrupt is now said to be in service
-	 */
-	if (irq >= NR_IRQS) {
-		printk("handle_irq: invalid irq=%lu\n", irq);
-		goto out;
-	}
+void __global_sti(void)
+{
+	int cpu = smp_processor_id();
 
-	++kstat.irqs[smp_processor_id()][irq];
+	if (!local_irq_count(cpu))
+		release_irqlock(cpu);
+	__sti();
+}
 
-	if (irq == IA64_SPURIOUS_INT) {
-		printk("handle_irq: spurious interrupt\n");
-		goto out;
-	}
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
+unsigned long __global_save_flags(void)
+{
+	int retval;
+	int local_enabled;
+	unsigned long flags;
+	int cpu = smp_processor_id();
 
-	/* 
-	 * Handle the interrupt by calling the hardware specific handler (IOSAPIC, Internal, etc).
-	 */
-	(*irq_desc[irq].handler->handle)(irq, regs);
-  out:
-#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
-	{
-		long pEOI;
-
-		asm ("mov %0=0;; (p1) mov %0=1" : "=r"(pEOI));
-		if (!pEOI) {
-			printk("Yikes: ia64_handle_irq() without pEOI!!\n");
-			asm volatile ("cmp.eq p1,p0=r0,r0" : "=r"(pEOI));
-# ifdef CONFIG_KDB
-			kdb(KDB_REASON_PANIC, 0, regs);
-# endif
-		}
+	__save_flags(flags);
+	local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
+	/* default to local */
+	retval = 2 + local_enabled;
+
+	/* check for global flags if we're not in an interrupt */
+	if (!local_irq_count(cpu)) {
+		if (local_enabled)
+			retval = 1;
+		if (global_irq_holder == cpu)
+			retval = 0;
 	}
+	return retval;
+}
 
-	local_irq_disable();
-# ifndef CONFIG_SMP
-	if (max_prio == irq)
-		max_prio = prev_prio;
-# endif /* !CONFIG_SMP */
-#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
-
-	ia64_srlz_d();
-	ia64_set_tpr(saved_tpr);
-	ia64_srlz_d();
+void __global_restore_flags(unsigned long flags)
+{
+	switch (flags) {
+	case 0:
+		__global_cli();
+		break;
+	case 1:
+		__global_sti();
+		break;
+	case 2:
+		__cli();
+		break;
+	case 3:
+		__sti();
+		break;
+	default:
+		printk("global_restore_flags: %08lx (%08lx)\n",
+			flags, (&flags)[-1]);
+	}
 }
 
+#endif
 
 /*
- * This should really return information about whether we should do
- * bottom half handling etc. Right now we end up _always_ checking the
- * bottom half, which is a waste of time and is not what some drivers
- * would prefer.
+ * This should really return information about whether
+ * we should do bottom half handling etc. Right now we
+ * end up _always_ checking the bottom half, which is a
+ * waste of time and is not what some drivers would
+ * prefer.
  */
-int
-invoke_irq_handlers (unsigned int irq, struct pt_regs *regs, struct irqaction *action)
+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
-	void (*handler)(int, void *, struct pt_regs *);
-	unsigned long flags, flags_union = 0;
+	int status;
 	int cpu = smp_processor_id();
-	unsigned int requested_irq;
-	void *dev_id;
 
 	irq_enter(cpu, irq);
 
-	if ((action->flags & SA_INTERRUPT) == 0)
+	status = 1;	/* Force the "do bottom halves" bit */
+
+	if (!(action->flags & SA_INTERRUPT))
 		__sti();
 
 	do {
-		flags = action->flags;
-		requested_irq = irq;
-		if ((flags & SA_LEGACY) != 0)
-			requested_irq = vector_to_legacy_map[irq];
-		flags_union |= flags;
-		handler = action->handler;
-		dev_id = action->dev_id;
+		status |= action->flags;
+		action->handler(irq, action->dev_id, regs);
 		action = action->next;
-		(*handler)(requested_irq, dev_id, regs);
 	} while (action);
-	if ((flags_union & SA_SAMPLE_RANDOM) != 0)
+	if (status & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
 	__cli();
 
 	irq_exit(cpu, irq);
-	return flags_union | 1;	/* force the "do bottom halves" bit */
+
+	return status;
 }
 
-void
-disable_irq_nosync (unsigned int irq)
+/*
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock. 
+ */
+void inline disable_irq_nosync(unsigned int irq)
 {
+	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
 
-	irq = map_legacy_irq(irq);
-
-	spin_lock_irqsave(&irq_controller_lock, flags);
-	if (irq_desc[irq].depth++ > 0) {
-		irq_desc[irq].status &= ~IRQ_ENABLED;
-		irq_desc[irq].handler->disable(irq);
+	spin_lock_irqsave(&desc->lock, flags);
+	if (!desc->depth++) {
+		desc->status |= IRQ_DISABLED;
+		desc->handler->disable(irq);
 	}
-	spin_unlock_irqrestore(&irq_controller_lock, flags);
+	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
 /*
  * Synchronous version of the above, making sure the IRQ is
  * no longer running on any other IRQ..
  */
-void
-disable_irq (unsigned int irq)
+void disable_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
 
-	irq = map_legacy_irq(irq);
-
-	if (!local_irq_count[smp_processor_id()]) {
+	if (!local_irq_count(smp_processor_id())) {
 		do {
 			barrier();
-		} while ((irq_desc[irq].status & IRQ_INPROGRESS) != 0);
+		} while (irq_desc[irq].status & IRQ_INPROGRESS);
 	}
 }
 
-void
-enable_irq (unsigned int irq)
+void enable_irq(unsigned int irq)
 {
+	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
 
-	irq = map_legacy_irq(irq);
-
-	spin_lock_irqsave(&irq_controller_lock, flags);
-	switch (irq_desc[irq].depth) {
-	      case 1:
-		irq_desc[irq].status |= IRQ_ENABLED;
-		(*irq_desc[irq].handler->enable)(irq);
-		/* fall through */
-	      default:
-		--irq_desc[irq].depth;
+	spin_lock_irqsave(&desc->lock, flags);
+	switch (desc->depth) {
+	case 1: {
+		unsigned int status = desc->status & ~IRQ_DISABLED;
+		desc->status = status;
+		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+			desc->status = status | IRQ_REPLAY;
+			hw_resend_irq(desc->handler,irq);
+		}
+		desc->handler->enable(irq);
+		/* fall-through */
+	}
+	default:
+		desc->depth--;
 		break;
-
-	      case 0:
-		printk("enable_irq: unbalanced from %p\n", __builtin_return_address(0));
+	case 0:
+		printk("enable_irq() unbalanced from %p\n",
+		       __builtin_return_address(0));
 	}
-	spin_unlock_irqrestore(&irq_controller_lock, flags);
+	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
 /*
- * This function encapsulates the initialization that needs to be
- * performed under the protection of lock irq_controller_lock.  The
- * lock must have been acquired by the time this is called.
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
  */
-static inline int
-setup_irq (unsigned int irq, struct irqaction *new)
-{
-	int shared = 0;
-	struct irqaction *old, **p;
+unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs)
+{	
+	/* 
+	 * We ack quickly, we don't want the irq controller
+	 * thinking we're snobs just because some other CPU has
+	 * disabled global interrupts (we have already done the
+	 * INT_ACK cycles, it's too late to try to pretend to the
+	 * controller that we aren't taking the interrupt).
+	 *
+	 * 0 return value means that this irq is already being
+	 * handled by some other CPU. (or is disabled)
+	 */
+	int cpu = smp_processor_id();
+	irq_desc_t *desc = irq_desc + irq;
+	struct irqaction * action;
+	unsigned int status;
 
-	p = &irq_desc[irq].action;
-	old = *p;
-	if (old) {
-		if (!(old->flags & new->flags & SA_SHIRQ)) {
-			return -EBUSY;
-		}
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-		shared = 1;
+	kstat.irqs[cpu][irq]++;
+	spin_lock(&desc->lock);
+	desc->handler->ack(irq);
+	/*
+	   REPLAY is when Linux resends an IRQ that was dropped earlier
+	   WAITING is used by probe to mark irqs that are being tested
+	   */
+	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+	status |= IRQ_PENDING; /* we _want_ to handle it */
+
+	/*
+	 * If the IRQ is disabled for whatever reason, we cannot
+	 * use the action we have.
+	 */
+	action = NULL;
+	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		action = desc->action;
+		status &= ~IRQ_PENDING; /* we commit to handling */
+		status |= IRQ_INPROGRESS; /* we are handling it */
 	}
-	*p = new;
+	desc->status = status;
 
-	/* when sharing do not unmask */
-	if (!shared) {
-		irq_desc[irq].depth = 0;
-		irq_desc[irq].status |= IRQ_ENABLED;
-		(*irq_desc[irq].handler->startup)(irq);
+	/*
+	 * If there is no IRQ handler or it was disabled, exit early.
+	   Since we set PENDING, if another processor is handling
+	   a different instance of this same irq, the other processor
+	   will take care of it.
+	 */
+	if (!action)
+{
+	desc->status = status & ~IRQ_INPROGRESS;
+		goto out;
+}
+
+	/*
+	 * Edge triggered interrupts need to remember
+	 * pending events.
+	 * This applies to any hw interrupts that allow a second
+	 * instance of the same irq to arrive while we are in do_IRQ
+	 * or in the handler. But the code here only handles the _second_
+	 * instance of the irq, not the third or fourth. So it is mostly
+	 * useful for irq hardware that does not mask cleanly in an
+	 * SMP environment.
+	 */
+	for (;;) {
+		spin_unlock(&desc->lock);
+		handle_IRQ_event(irq, regs, action);
+		spin_lock(&desc->lock);
+		
+		if (!(desc->status & IRQ_PENDING))
+			break;
+		desc->status &= ~IRQ_PENDING;
 	}
-	return 0;
+	desc->status &= ~IRQ_INPROGRESS;
+out:
+	/*
+	 * The ->end() handler has to deal with interrupts which got
+	 * disabled while the handler was running.
+	 */
+	desc->handler->end(irq);
+	spin_unlock(&desc->lock);
+
+#if 0
+	/*
+	 * let kernel exit path take care of this; we want to do the
+	 * CPU EOI before doing softirq() so a new interrupt can come
+	 * through
+	 */
+	if (softirq_state[cpu].active & softirq_state[cpu].mask)
+		do_softirq();
+#endif
+	return 1;
 }
 
-int
-request_irq (unsigned int requested_irq, void (*handler)(int, void *, struct pt_regs *),
-	     unsigned long irqflags, const char * devname, void *dev_id)
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
 {
-	int retval, need_kfree = 0;
-	struct irqaction *action;
-	unsigned long flags;
-	unsigned int irq;
+	int retval;
+	struct irqaction * action;
 
-#ifdef IA64_DEBUG
-	printk("request_irq(0x%x) called\n", requested_irq);
-#endif
+#if 1
 	/*
 	 * Sanity-check: shared interrupts should REALLY pass in
 	 * a real dev-ID, otherwise we'll have trouble later trying
 	 * to figure out which interrupt is which (messes up the
 	 * interrupt freeing logic etc).
 	 */
-	if ((irqflags & SA_SHIRQ) && !dev_id)
-		printk("Bad boy: %s (at %p) called us without a dev_id!\n",
-		       devname, current_text_addr());
-
-	irq = map_legacy_irq(requested_irq);
-	if (irq != requested_irq)
-		irqflags |= SA_LEGACY;
+	if (irqflags & SA_SHIRQ) {
+		if (!dev_id)
+			printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
+	}
+#endif
 
 	if (irq >= NR_IRQS)
 		return -EINVAL;
-
 	if (!handler)
 		return -EINVAL;
 
-	/*
-	 * The timer_action and ipi_action cannot be allocated
-	 * dynamically because its initialization happens really early
-	 * on in init/main.c at this point the memory allocator has
-	 * not yet been initialized.  So we use a statically reserved
-	 * buffer for it. In some sense that's no big deal because we
-	 * need one no matter what.
-	 */
-	if (irq == TIMER_IRQ)
-		action = &timer_action;
-#ifdef CONFIG_SMP
-	else if (irq == IPI_IRQ)
-		action = &ipi_action;
-#endif
-	else {
-		action = kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-		need_kfree = 1;
-	}
-
+	action = (struct irqaction *)
+			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
 	if (!action)
 		return -ENOMEM;
 
@@ -467,208 +648,412 @@
 	action->next = NULL;
 	action->dev_id = dev_id;
 
-	if ((irqflags & SA_SAMPLE_RANDOM) != 0)
-		rand_initialize_irq(irq);
-
-	spin_lock_irqsave(&irq_controller_lock, flags);
 	retval = setup_irq(irq, action);
-	spin_unlock_irqrestore(&irq_controller_lock, flags);
-
-	if (need_kfree && retval)
+	if (retval)
 		kfree(action);
-
 	return retval;
 }
 		
-void
-free_irq (unsigned int irq, void *dev_id)
+void free_irq(unsigned int irq, void *dev_id)
 {
-	struct irqaction *action, **p;
+	irq_desc_t *desc;
+	struct irqaction **p;
 	unsigned long flags;
 
-	/*
-	 * some sanity checks first
-	 */
-	if (irq >= NR_IRQS) {
-		printk("Trying to free IRQ%d\n",irq);
+	if (irq >= NR_IRQS)
 		return;
-	}
 
-	irq = map_legacy_irq(irq);
-
-	/*
-	 * Find the corresponding irqaction
-	 */
-	spin_lock_irqsave(&irq_controller_lock, flags);
-	for (p = &irq_desc[irq].action; (action = *p) != NULL; p = &action->next) {
-		if (action->dev_id != dev_id)
-			continue;
-
-		/* Found it - now remove it from the list of entries */
-		*p = action->next;
-		if (!irq_desc[irq].action) {
-			irq_desc[irq].status &= ~IRQ_ENABLED;
-			(*irq_desc[irq].handler->shutdown)(irq);
-		}
-
-		spin_unlock_irqrestore(&irq_controller_lock, flags);
-
-#ifdef CONFIG_SMP
-		/* Wait to make sure it's not being used on another CPU */
-		while (irq_desc[irq].status & IRQ_INPROGRESS)
-			barrier();
-#endif
+	desc = irq_desc + irq;
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	for (;;) {
+		struct irqaction * action = *p;
+		if (action) {
+			struct irqaction **pp = p;
+			p = &action->next;
+			if (action->dev_id != dev_id)
+				continue;
+
+			/* Found it - now remove it from the list of entries */
+			*pp = action->next;
+			if (!desc->action) {
+				desc->status |= IRQ_DISABLED;
+				desc->handler->shutdown(irq);
+			}
+			spin_unlock_irqrestore(&desc->lock,flags);
 
-		if (action != &timer_action
 #ifdef CONFIG_SMP
-		    && action != &ipi_action
+			/* Wait to make sure it's not being used on another CPU */
+			while (desc->status & IRQ_INPROGRESS)
+				barrier();
 #endif
-		   )
 			kfree(action);
+			return;
+		}
+		printk("Trying to free free IRQ%d\n",irq);
+		spin_unlock_irqrestore(&desc->lock,flags);
 		return;
 	}
-	printk("Trying to free free IRQ%d\n", irq);
 }
 
 /*
- * IRQ autodetection code.  Note that the return value of
- * probe_irq_on() is no longer being used (it's role has been replaced
- * by the IRQ_AUTODETECT flag).
+ * IRQ autodetection code..
+ *
+ * This depends on the fact that any interrupt that
+ * comes in on to an unassigned handler will get stuck
+ * with "IRQ_WAITING" cleared and the interrupt
+ * disabled.
  */
-unsigned long
-probe_irq_on (void)
+unsigned long probe_irq_on(void)
 {
-	struct irq_desc *id;
+	unsigned int i;
+	irq_desc_t *desc;
+	unsigned long val;
 	unsigned long delay;
 
-#ifdef IA64_DEBUG
-	printk("probe_irq_on() called\n");
-#endif
+	/* 
+	 * something may have generated an irq long ago and we want to
+	 * flush such a longstanding irq before considering it as spurious. 
+	 */
+	for (i = NR_IRQS-1; i > 0; i--)  {
+		desc = irq_desc + i;
 
-	spin_lock_irq(&irq_controller_lock);
-	for (id = irq_desc; id < irq_desc + NR_IRQS; ++id) {
-		if (!id->action) {
-			id->status |= IRQ_AUTODETECT | IRQ_WAITING;
-			(*id->handler->startup)(id - irq_desc);
-		}
+		spin_lock_irq(&desc->lock);
+		if (!irq_desc[i].action) 
+			irq_desc[i].handler->startup(i);
+		spin_unlock_irq(&desc->lock);
 	}
-	spin_unlock_irq(&irq_controller_lock);
 
-	/* wait for spurious interrupts to trigger: */
+	/* Wait for longstanding interrupts to trigger. */
+	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
+		/* about 20ms delay */ synchronize_irq();
 
+	/*
+	 * enable any unassigned irqs
+	 * (we must startup again here because if a longstanding irq
+	 * happened in the previous stage, it may have masked itself)
+	 */
+	for (i = NR_IRQS-1; i > 0; i--) {
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!desc->action) {
+			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
+			if (desc->handler->startup(i))
+				desc->status |= IRQ_PENDING;
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+
+	/*
+	 * Wait for spurious interrupts to trigger
+	 */
 	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
-		/* about 100ms delay */
-		synchronize_irq();
+		/* about 100ms delay */ synchronize_irq();
 
-	/* filter out obviously spurious interrupts: */
-	spin_lock_irq(&irq_controller_lock);
-	for (id = irq_desc; id < irq_desc + NR_IRQS; ++id) {
-		unsigned int status = id->status;
+	/*
+	 * Now filter out any obviously spurious interrupts
+	 */
+	val = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
 
-		if (!(status & IRQ_AUTODETECT))
-			continue;
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
 
-		if (!(status & IRQ_WAITING)) {
-			id->status = status & ~IRQ_AUTODETECT;
-			(*id->handler->shutdown)(id - irq_desc);
+		if (status & IRQ_AUTODETECT) {
+			/* It triggered already - consider it spurious. */
+			if (!(status & IRQ_WAITING)) {
+				desc->status = status & ~IRQ_AUTODETECT;
+				desc->handler->shutdown(i);
+			} else
+				if (i < 32)
+					val |= 1 << i;
 		}
+		spin_unlock_irq(&desc->lock);
 	}
-	spin_unlock_irq(&irq_controller_lock);
-	return PROBE_IRQ_COOKIE;		/* return meaningless return value  */
+
+	return val;
 }
 
-int
-probe_irq_off (unsigned long cookie)
+/*
+ * Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+unsigned int probe_irq_mask(unsigned long val)
 {
-	int irq_found, nr_irqs;
-	struct irq_desc *id;
+	int i;
+	unsigned int mask;
 
-#ifdef IA64_DEBUG
-	printk("probe_irq_off(cookie=0x%lx) -> ", cookie);
-#endif
+	mask = 0;
+	for (i = 0; i < 16; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			if (!(status & IRQ_WAITING))
+				mask |= 1 << i;
+
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+
+	return mask & val;
+}
 
-	if (cookie != PROBE_IRQ_COOKIE)
-		printk("bad irq probe from %p\n", __builtin_return_address(0));
+/*
+ * Return the one interrupt that triggered (this can
+ * handle any interrupt source)
+ */
+int probe_irq_off(unsigned long val)
+{
+	int i, irq_found, nr_irqs;
 
 	nr_irqs = 0;
 	irq_found = 0;
-	spin_lock_irq(&irq_controller_lock);
-	for (id = irq_desc + IA64_MIN_VECTORED_IRQ; id < irq_desc + NR_IRQS; ++id) {
-		unsigned int status = id->status;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
 
-		if (!(status & IRQ_AUTODETECT))
-			continue;
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
 
-		if (!(status & IRQ_WAITING)) {
-			if (!nr_irqs)
-				irq_found = (id - irq_desc);
-			++nr_irqs;
+		if (status & IRQ_AUTODETECT) {
+			if (!(status & IRQ_WAITING)) {
+				if (!nr_irqs)
+					irq_found = i;
+				nr_irqs++;
+			}
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
 		}
-		id->status = status & ~IRQ_AUTODETECT;
-		(*id->handler->shutdown)(id - irq_desc);
+		spin_unlock_irq(&desc->lock);
 	}
-	spin_unlock_irq(&irq_controller_lock);
 
 	if (nr_irqs > 1)
 		irq_found = -irq_found;
-
-#ifdef IA64_DEBUG
-	printk("%d\n", irq_found);
-#endif
 	return irq_found;
 }
 
-#ifdef CONFIG_SMP
-
-void __init
-init_IRQ_SMP (void)
+/* this was setup_x86_irq but it seems pretty generic */
+int setup_irq(unsigned int irq, struct irqaction * new)
 {
-	if (request_irq(IPI_IRQ, handle_IPI, 0, "IPI", NULL))
-		panic("Could not allocate IPI Interrupt Handler!");
+	int shared = 0;
+	unsigned long flags;
+	struct irqaction *old, **p;
+	irq_desc_t *desc = irq_desc + irq;
+
+	/*
+	 * Some drivers like serial.c use request_irq() heavily,
+	 * so we have to be careful not to interfere with a
+	 * running system.
+	 */
+	if (new->flags & SA_SAMPLE_RANDOM) {
+		/*
+		 * This function might sleep, we want to call it first,
+		 * outside of the atomic block.
+		 * Yes, this might clear the entropy pool if the wrong
+		 * driver is attempted to be loaded, without actually
+		 * installing a new handler, but is this really a problem,
+		 * only the sysadmin is able to do this.
+		 */
+		rand_initialize_irq(irq);
+	}
+
+	/*
+	 * The following block of code has to be executed atomically
+	 */
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ)) {
+			spin_unlock_irqrestore(&desc->lock,flags);
+			return -EBUSY;
+		}
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	*p = new;
+
+	if (!shared) {
+		desc->depth = 0;
+		desc->status &= ~IRQ_DISABLED;
+		desc->handler->startup(irq);
+	}
+	spin_unlock_irqrestore(&desc->lock,flags);
+
+	register_irq_proc(irq);
+	return 0;
 }
 
-#endif
+static struct proc_dir_entry * root_irq_dir;
+static struct proc_dir_entry * irq_dir [NR_IRQS];
+static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
+
+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+
+#define HEX_DIGITS 8
+
+static int irq_affinity_read_proc (char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	if (count < HEX_DIGITS+1)
+		return -EINVAL;
+	return sprintf (page, "%08lx\n", irq_affinity[(long)data]);
+}
 
-void __init
-init_IRQ (void)
+static unsigned int parse_hex_value (const char *buffer,
+		unsigned long count, unsigned long *ret)
 {
+	unsigned char hexnum [HEX_DIGITS];
+	unsigned long value;
 	int i;
 
-	for (i = 0; i < IA64_MIN_VECTORED_IRQ; ++i)
-		vector_to_legacy_map[irq_to_vector_map[i]] = i;
+	if (!count)
+		return -EINVAL;
+	if (count > HEX_DIGITS)
+		count = HEX_DIGITS;
+	if (copy_from_user(hexnum, buffer, count))
+		return -EFAULT;
+
+	/*
+	 * Parse the first 8 characters as a hex string, any non-hex char
+	 * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same.
+	 */
+	value = 0;
+
+	for (i = 0; i < count; i++) {
+		unsigned int c = hexnum[i];
 
-	for (i = 0; i < NR_IRQS; ++i) {
-		irq_desc[i].handler = &irq_type_default;
+		switch (c) {
+			case '0' ... '9': c -= '0'; break;
+			case 'a' ... 'f': c -= 'a'-10; break;
+			case 'A' ... 'F': c -= 'A'-10; break;
+		default:
+			goto out;
+		}
+		value = (value << 4) | c;
 	}
+out:
+	*ret = value;
+	return 0;
+}
 
-	irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal;
-#ifdef CONFIG_SMP
-	/* 
-	 * Configure the IPI vector and handler
+static int irq_affinity_write_proc (struct file *file, const char *buffer,
+					unsigned long count, void *data)
+{
+	int irq = (long) data, full_count = count, err;
+	unsigned long new_value;
+
+	if (!irq_desc[irq].handler->set_affinity)
+		return -EIO;
+
+	err = parse_hex_value(buffer, count, &new_value);
+
+#if CONFIG_SMP
+	/*
+	 * Do not allow disabling IRQs completely - it's a too easy
+	 * way to make the system unusable accidentally :-) At least
+	 * one online CPU still has to be targeted.
 	 */
-	irq_desc[IPI_IRQ].handler = &irq_type_ia64_internal;
-	init_IRQ_SMP();
+	if (!(new_value & cpu_online_map))
+		return -EINVAL;
 #endif
 
-	ia64_set_pmv(1 << 16);
-	ia64_set_cmcv(CMC_IRQ);			/* XXX fix me */
+	irq_affinity[irq] = new_value;
+	irq_desc[irq].handler->set_affinity(irq, new_value);
+
+	return full_count;
+}
+
+static int prof_cpu_mask_read_proc (char *page, char **start, off_t off,
+			int count, int *eof, void *data)
+{
+	unsigned long *mask = (unsigned long *) data;
+	if (count < HEX_DIGITS+1)
+		return -EINVAL;
+	return sprintf (page, "%08lx\n", *mask);
+}
+
+static int prof_cpu_mask_write_proc (struct file *file, const char *buffer,
+					unsigned long count, void *data)
+{
+	unsigned long *mask = (unsigned long *) data, full_count = count, err;
+	unsigned long new_value;
 
-	platform_irq_init(irq_desc);
+	err = parse_hex_value(buffer, count, &new_value);
+	if (err)
+		return err;
 
-	/* clear TPR to enable all interrupt classes: */
-	ia64_set_tpr(0);
+	*mask = new_value;
+	return full_count;
 }
 
-/* TBD:
- * 	Certain IA64 platforms can have inter-processor interrupt support.
- * 	This interface is supposed to default to the IA64 IPI block-based
- * 	mechanism if the platform doesn't provide a separate mechanism
- *	for IPIs.
- *	Choices : (1) Extend hw_interrupt_type interfaces 
- *		  (2) Use machine vector mechanism
- *	For now defining the following interface as a place holder.
- */
-void
-ipi_send (int cpu, int vector, int delivery_mode)
+#define MAX_NAMELEN 10
+
+static void register_irq_proc (unsigned int irq)
+{
+	struct proc_dir_entry *entry;
+	char name [MAX_NAMELEN];
+
+	if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type))
+		return;
+
+	memset(name, 0, MAX_NAMELEN);
+	sprintf(name, "%d", irq);
+
+	/* create /proc/irq/1234 */
+	irq_dir[irq] = proc_mkdir(name, root_irq_dir);
+
+	/* create /proc/irq/1234/smp_affinity */
+	entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]);
+
+	entry->nlink = 1;
+	entry->data = (void *)(long)irq;
+	entry->read_proc = irq_affinity_read_proc;
+	entry->write_proc = irq_affinity_write_proc;
+
+	smp_affinity_entry[irq] = entry;
+}
+
+unsigned long prof_cpu_mask = -1;
+
+void init_irq_proc (void)
 {
+	struct proc_dir_entry *entry;
+	int i;
+
+	/* create /proc/irq */
+	root_irq_dir = proc_mkdir("irq", 0);
+
+	/* create /proc/irq/prof_cpu_mask */
+	entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir);
+
+	entry->nlink = 1;
+	entry->data = (void *)&prof_cpu_mask;
+	entry->read_proc = prof_cpu_mask_read_proc;
+	entry->write_proc = prof_cpu_mask_write_proc;
+
+	/*
+	 * Create entries for all existing IRQs.
+	 */
+	for (i = 0; i < NR_IRQS; i++) {
+		if (irq_desc[i].handler == &no_irq_type)
+			continue;
+		register_irq_proc(i);
+	}
 }
+
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/irq_default.c linux/arch/ia64/kernel/irq_default.c
--- v2.3.50/linux/arch/ia64/kernel/irq_default.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/kernel/irq_default.c	Wed Dec 31 16:00:00 1969
@@ -1,30 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/sched.h>
-
-#include <asm/irq.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-
-
-static int
-irq_default_handle_irq (unsigned int irq, struct pt_regs *regs)
-{
-	printk("Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id());
-	return 0;		/* don't call do_bottom_half() for spurious interrupts */
-}
-
-static void
-irq_default_noop (unsigned int irq)
-{
-	/* nuthing to do... */
-}
-
-struct hw_interrupt_type irq_type_default = {
-	"default",
-	(void (*)(unsigned long)) irq_default_noop,	/* init */
-	irq_default_noop,				/* startup */
-	irq_default_noop,				/* shutdown */
-	irq_default_handle_irq,				/* handle */
-	irq_default_noop,				/* enable */
-	irq_default_noop				/* disable */
-};
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/irq_ia64.c linux/arch/ia64/kernel/irq_ia64.c
--- v2.3.50/linux/arch/ia64/kernel/irq_ia64.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ia64/kernel/irq_ia64.c	Fri Mar 10 15:24:02 2000
@@ -0,0 +1,247 @@
+/*
+ * linux/arch/ia64/kernel/irq.c
+ *
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998, 1999 Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 1999-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ *  6/10/99: Updated to bring in sync with x86 version to facilitate
+ *	     support for SMP and different interrupt controllers.
+ */
+
+#include <linux/config.h>
+
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel_stat.h>
+#include <linux/malloc.h>
+#include <linux/ptrace.h>
+#include <linux/random.h>	/* for rand_initialize_irq() */
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/threads.h>
+
+#ifdef CONFIG_KDB
+# include <linux/kdb.h>
+#endif
+
+#include <asm/bitops.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/hw_irq.h>
+#include <asm/machvec.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+spinlock_t ivr_read_lock;
+#endif
+
+/*
+ * Legacy IRQ to IA-64 vector translation table.  Any vector not in
+ * this table maps to itself (ie: irq 0x30 => IA64 vector 0x30)
+ */
+__u8 isa_irq_to_vector_map[IA64_MIN_VECTORED_IRQ] = {
+	/* 8259 IRQ translation, first 16 entries */
+	0x60, 0x50, 0x0f, 0x51, 0x52, 0x53, 0x43, 0x54,
+	0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x40, 0x41
+};
+
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+
+int usbfix;
+
+static int __init
+usbfix_option (char *str)
+{
+	printk("irq: enabling USB workaround\n");
+	usbfix = 1;
+	return 1;
+}
+
+__setup("usbfix", usbfix_option);
+
+#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+
+/*
+ * That's where the IVT branches when we get an external
+ * interrupt. This branches to the correct hardware IRQ handler via
+ * function ptr.
+ */
+void
+ia64_handle_irq (unsigned long vector, struct pt_regs *regs)
+{
+	unsigned long bsp, sp, saved_tpr;
+
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+# ifndef CONFIG_SMP
+	static unsigned int max_prio = 0;
+# endif
+	unsigned int prev_prio;
+	unsigned long eoi_ptr;
+ 
+# ifdef CONFIG_USB
+	extern void reenable_usb (void);
+	extern void disable_usb (void);
+
+	if (usbfix)
+		disable_usb();
+# endif
+	/*
+	 * Stop IPIs by getting the ivr_read_lock
+	 */
+	spin_lock(&ivr_read_lock);
+
+	/*
+	 * Disable PCI writes
+	 */
+	outl(0x80ff81c0, 0xcf8);
+	outl(0x73002188, 0xcfc);
+	eoi_ptr = inl(0xcfc);
+
+	vector = ia64_get_ivr();
+
+	/*
+	 * Enable PCI writes
+	 */
+	outl(0x73182188, 0xcfc);
+
+	spin_unlock(&ivr_read_lock);
+
+# ifdef CONFIG_USB
+	if (usbfix)
+		reenable_usb();
+# endif
+
+# ifndef CONFIG_SMP
+	prev_prio = max_prio;
+	if (vector < max_prio) {
+		printk ("ia64_handle_irq: got vector %lu while %u was in progress!\n",
+			vector, max_prio);
+		
+	} else
+		max_prio = vector;
+# endif /* !CONFIG_SMP */
+#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+
+	/*
+	 * Always set TPR to limit maximum interrupt nesting depth to
+	 * 16 (without this, it would be ~240, which could easily lead
+	 * to kernel stack overflows.
+	 */
+	saved_tpr = ia64_get_tpr();
+	ia64_srlz_d();
+	ia64_set_tpr(vector);
+	ia64_srlz_d();
+
+	asm ("mov %0=ar.bsp" : "=r"(bsp));
+	asm ("mov %0=sp" : "=r"(sp));
+
+	if ((sp - bsp) < 1024) {
+		static long last_time;
+		static unsigned char count;
+
+		if (count > 5 && jiffies - last_time > 5*HZ)
+			count = 0;
+		if (++count < 5) {
+			last_time = jiffies;
+			printk("ia64_handle_irq: DANGER: less than 1KB of free stack space!!\n"
+			       "(bsp=0x%lx, sp=%lx)\n", bsp, sp);
+		}
+#ifdef CONFIG_KDB
+		kdb(KDB_REASON_PANIC, 0, regs);
+#endif		
+	}
+
+	/*
+	 * The interrupt is now said to be in service
+	 */
+	if (vector >= NR_IRQS) {
+		printk("handle_irq: invalid vector %lu\n", vector);
+		goto out;
+	}
+
+	do_IRQ(vector, regs);
+  out:
+#ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
+	{
+		long pEOI;
+
+		asm ("mov %0=0;; (p1) mov %0=1" : "=r"(pEOI));
+		if (!pEOI) {
+			printk("Yikes: ia64_handle_irq() without pEOI!!\n");
+			asm volatile ("cmp.eq p1,p0=r0,r0" : "=r"(pEOI));
+# ifdef CONFIG_KDB
+			kdb(KDB_REASON_PANIC, 0, regs);
+# endif
+		}
+	}
+
+	local_irq_disable();
+# ifndef CONFIG_SMP
+	if (max_prio == vector)
+		max_prio = prev_prio;
+# endif /* !CONFIG_SMP */
+#endif /* CONFIG_ITANIUM_ASTEP_SPECIFIC */
+
+	ia64_srlz_d();
+	ia64_set_tpr(saved_tpr);
+	ia64_srlz_d();
+}
+
+#ifdef CONFIG_SMP
+
+void __init
+init_IRQ_SMP (void)
+{
+	if (request_irq(IPI_IRQ, handle_IPI, 0, "IPI", NULL))
+		panic("Could not allocate IPI Interrupt Handler!");
+}
+
+#endif
+
+void __init
+init_IRQ (void)
+{
+	/*
+	 * Disable all local interrupts
+	 */
+	ia64_set_itv(0, 1);
+	ia64_set_lrr0(0, 1);	
+	ia64_set_lrr1(0, 1);	
+
+	irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal;
+#ifdef CONFIG_SMP
+	/* 
+	 * Configure the IPI vector and handler
+	 */
+	irq_desc[IPI_IRQ].handler = &irq_type_ia64_internal;
+	init_IRQ_SMP();
+#endif
+
+	ia64_set_pmv(1 << 16);
+	ia64_set_cmcv(CMC_IRQ);			/* XXX fix me */
+
+	platform_irq_init();
+
+	/* clear TPR to enable all interrupt classes: */
+	ia64_set_tpr(0);
+}
+
+/* TBD:
+ * 	Certain IA64 platforms can have inter-processor interrupt support.
+ * 	This interface is supposed to default to the IA64 IPI block-based
+ * 	mechanism if the platform doesn't provide a separate mechanism
+ *	for IPIs.
+ *	Choices : (1) Extend hw_interrupt_type interfaces 
+ *		  (2) Use machine vector mechanism
+ *	For now defining the following interface as a place holder.
+ */
+void
+ipi_send (int cpu, int vector, int delivery_mode)
+{
+}
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/irq_internal.c linux/arch/ia64/kernel/irq_internal.c
--- v2.3.50/linux/arch/ia64/kernel/irq_internal.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/ia64/kernel/irq_internal.c	Fri Mar 10 15:24:02 2000
@@ -6,51 +6,16 @@
  *
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 2000 Hewlett-Packard Co
+ * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
-#include <linux/kernel.h>
-#include <linux/sched.h>
+#include <linux/irq.h>
 
-#include <asm/irq.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-
-/*
- * This is identical to IOSAPIC handle_irq.  It may go away . . .
- */
-static int
-internal_handle_irq (unsigned int irq, struct pt_regs *regs)
+static unsigned int
+internal_noop_startup (unsigned int irq)
 {
-	struct irqaction *action = 0;
-	struct irq_desc *id = irq_desc + irq;
-	unsigned int status;
-	int retval;
-
-	spin_lock(&irq_controller_lock);
-	{
-		status = id->status;
-		if ((status & IRQ_ENABLED) != 0)
-			action = id->action;
-		id->status = status & ~(IRQ_REPLAY | IRQ_WAITING);
-	}
-	spin_unlock(&irq_controller_lock);
-
-	if (!action) {
-		if (!(id->status & IRQ_AUTODETECT))
-			printk("irq_hpsim_handle_irq: unexpected interrupt %u\n", irq);
-		return 0;
-	}
-
-	retval = invoke_irq_handlers(irq, regs, action);
-
-	spin_lock(&irq_controller_lock);
-	{
-		status = (id->status & ~IRQ_INPROGRESS);
-		id->status = status;
-	}
-	spin_unlock(&irq_controller_lock);
-
-	return retval;
+	return 0;
 }
 
 static void
@@ -60,12 +25,12 @@
 }
 
 struct hw_interrupt_type irq_type_ia64_internal = {
-	"IA64-internal",
-	(void (*)(unsigned long)) internal_noop,	/* init */
-	internal_noop,					/* startup */
-	internal_noop,					/* shutdown */
-	internal_handle_irq,				/* handle */
-	internal_noop,					/* enable */
-	internal_noop					/* disable */
+	typename:	"IA64-internal",
+	startup:	internal_noop_startup,
+	shutdown:	internal_noop,
+	enable:		internal_noop,
+	disable:	internal_noop,
+	ack:		internal_noop,
+	end:		internal_noop,
+	set_affinity:	(void (*)(unsigned int, unsigned long)) internal_noop
 };
-
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/irq_lock.c linux/arch/ia64/kernel/irq_lock.c
--- v2.3.50/linux/arch/ia64/kernel/irq_lock.c	Sun Feb 13 19:29:03 2000
+++ linux/arch/ia64/kernel/irq_lock.c	Fri Mar 10 15:24:02 2000
@@ -281,7 +281,7 @@
                 __sti();
                 break;
         default:
-                printk("global_restore_flags: %08lx (%08lx)\n",
-                        flags, (&flags)[-1]);
+		printk("global_restore_flags: %08lx (%08lx) from %p\n",
+		       flags, (&flags)[-1], __builtin_return_address(0));
         }
 }
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/pci.c linux/arch/ia64/kernel/pci.c
--- v2.3.50/linux/arch/ia64/kernel/pci.c	Sun Feb 13 19:29:03 2000
+++ linux/arch/ia64/kernel/pci.c	Fri Mar 10 15:24:02 2000
@@ -164,13 +164,6 @@
 	return;
 }
 
-int
-pci_assign_resource (struct pci_dev *dev, int i)
-{
-	printk("pci_assign_resource: not implemented!\n");
-	return -ENODEV;
-}
-
 void __init
 pcibios_update_resource(struct pci_dev *dev, struct resource *root,
 			struct resource *res, int resource)
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/perfmon.c linux/arch/ia64/kernel/perfmon.c
--- v2.3.50/linux/arch/ia64/kernel/perfmon.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/kernel/perfmon.c	Fri Mar 10 15:24:02 2000
@@ -1,15 +1,53 @@
-#include <linux/config.h>
+/*
+ * This file contains the code to configure and read/write the ia64 performance
+ * monitoring stuff.
+ *
+ * Originaly Written by Ganesh Venkitachalam, IBM Corp.
+ * Modifications by David Mosberger-Tang, Hewlett-Packard Co.
+ * Copyright (C) 1999 Ganesh Venkitachalam <venkitac@us.ibm.com>
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 
 #include <asm/errno.h>
-#include <asm/irq.h>
+#include <asm/hw_irq.h>
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+/* Long blurb on how this works: 
+ * We set dcr.pp, psr.pp, and the appropriate pmc control values with
+ * this.  Notice that we go about modifying _each_ task's pt_regs to
+ * set cr_ipsr.pp.  This will start counting when "current" does an
+ * _rfi_. Also, since each task's cr_ipsr.pp, and cr_ipsr is inherited
+ * across forks, we do _not_ need additional code on context
+ * switches. On stopping of the counters we dont need to go about
+ * changing every task's cr_ipsr back to where it wuz, because we can
+ * just set pmc[0]=1. But we do it anyways becuase we will probably
+ * add thread specific accounting later.
+ *
+ * The obvious problem with this is that on SMP systems, it is a bit
+ * of work (when someone wants to do it:-)) - it would be easier if we
+ * just added code to the context-switch path, but if we wanted to support
+ * per-thread accounting, the context-switch path might be long unless 
+ * we introduce a flag in the task_struct. Right now, the following code 
+ * will NOT work correctly on MP (for more than one reason:-)).
+ *
+ * The short answer is that to make this work on SMP,  we would need 
+ * to lock the run queue to ensure no context switches, send 
+ * an IPI to each processor, and in that IPI handler, set processor regs,
+ * and just modify the psr bit of only the _current_ thread, since we have 
+ * modified the psr bit correctly in the kernel stack for every process 
+ * which is not running. Also, we need pmd arrays per-processor, and 
+ * the READ_PMD command will need to get values off of other processors. 
+ * IPIs are the answer, irrespective of what the question is. Might 
+ * crash on SMP systems without the lock_kernel().
+ */
+
 #ifdef CONFIG_PERFMON
 
 #define MAX_PERF_COUNTER	4	/* true for Itanium, at least */
@@ -22,33 +60,12 @@
 
 struct perfmon_counter {
         unsigned long data;
-        int counter_num;
+        unsigned long counter_num;
 };
 
 unsigned long pmds[MAX_PERF_COUNTER];
-struct task_struct *perf_owner;
+struct task_struct *perf_owner=NULL;
 
-/*
- * We set dcr.pp, psr.pp, and the appropriate pmc control values with
- * this.  Notice that we go about modifying _each_ task's pt_regs to
- * set cr_ipsr.pp.  This will start counting when "current" does an
- * _rfi_. Also, since each task's cr_ipsr.pp, and cr_ipsr is inherited
- * across forks, we do _not_ need additional code on context
- * switches. On stopping of the counters we dont _need_ to go about
- * changing every task's cr_ipsr back to where it wuz, because we can
- * just set pmc[0]=1. But we do it anyways becuase we will probably
- * add thread specific accounting later.
- *
- * The obvious problem with this is that on SMP systems, it is a bit
- * of work (when someone wants to do it) - it would be easier if we
- * just added code to the context-switch path.  I think we would need
- * to lock the run queue to ensure no context switches, send an IPI to
- * each processor, and in that IPI handler, just modify the psr bit of
- * only the _current_ thread, since we have modified the psr bit
- * correctly in the kernel stack for every process which is not
- * running.  Might crash on SMP systems without the
- * lock_kernel(). Hence the lock..
- */
 asmlinkage unsigned long
 sys_perfmonctl (int cmd1, int cmd2, void *ptr)
 {
@@ -66,7 +83,7 @@
 		if (!access_ok(VERIFY_READ, cptr, sizeof(struct perf_counter)*cmd2))
 			return -EFAULT;
 
-		if (cmd2 >= MAX_PERF_COUNTER)
+		if (cmd2 > MAX_PERF_COUNTER)
 			return -EFAULT;
 
 		if (perf_owner && perf_owner != current)
@@ -91,15 +108,12 @@
 			/*
 			 * This is a no can do.  It obviously wouldn't
 			 * work on SMP where another process may not
-			 * be blocked at all.
-			 *
-			 * Perhaps we need a global predicate in the
-			 * leave_kernel path to control if pp should
-			 * be on or off?
+			 * be blocked at all. We need to put in a  perfmon 
+			 * IPI to take care of MP systems. See blurb above.
 			 */
 			lock_kernel();
 			for_each_task(p) {
-				regs = (struct pt_regs *) (((char *)p) + IA64_STK_OFFSET) - 1;
+				regs = (struct pt_regs *) (((char *)p) + IA64_STK_OFFSET) -1 ;	
 				ia64_psr(regs)->pp = 1;
 			}
 			unlock_kernel();
@@ -108,12 +122,18 @@
                 break;
 
 	      case READ_PMDS:
-		if (cmd2 >= MAX_PERF_COUNTER)
+		if (cmd2 > MAX_PERF_COUNTER)
 			return -EFAULT;
 		if (!access_ok(VERIFY_WRITE, cptr, sizeof(struct perf_counter)*cmd2))
 			return -EFAULT;
+
+		/* This looks shady, but IMHO this will work fine. This is  
+		 * the sequence that I could come up with to avoid races
+		 * with the interrupt handler. See explanation in the 
+		 * following comment.
+		 */
+
 		local_irq_save(flags);
-		/* XXX this looks wrong */
 		__asm__ __volatile__("rsm psr.pp\n");
 		dcr = ia64_get_dcr();
 		dcr &= ~IA64_DCR_PP;
@@ -121,23 +141,23 @@
 		local_irq_restore(flags);
 
 		/*
-		 * We cannot touch pmc[0] to stop counting here, as
+		 * We cannot write to pmc[0] to stop counting here, as
 		 * that particular instruction might cause an overflow
-		 * and the mask in pmc[0] might get lost. I'm not very
+		 * and the mask in pmc[0] might get lost. I'm _not_ 
 		 * sure of the hardware behavior here. So we stop
 		 * counting by psr.pp = 0. And we reset dcr.pp to
 		 * prevent an interrupt from mucking up psr.pp in the
 		 * meanwhile. Perfmon interrupts are pended, hence the
-		 * above code should be ok if one of the above
-		 * instructions cause overflows. Is this ok?  When I
-		 * muck with dcr, is the cli/sti needed??
+		 * above code should be ok if one of the above instructions 
+		 * caused overflows, i.e the interrupt should get serviced
+		 * when we re-enabled interrupts. When I muck with dcr, 
+		 * is the irq_save/restore needed?
 		 */
-		for (i = 0, cnum = 4; i < MAX_PERF_COUNTER; i++, cnum++, cptr++) {
+		for (i = 0, cnum = 4;i < MAX_PERF_COUNTER; i++, cnum++, cptr++){
 			pmd = pmds[i] + (ia64_get_pmd(cnum) & PERF_OVFL_VAL);
 			put_user(pmd, &cptr->data);
 		}
 		local_irq_save(flags);
-		/* XXX this looks wrong */
 		__asm__ __volatile__("ssm psr.pp");
 		dcr = ia64_get_dcr();
 		dcr |= IA64_DCR_PP;
@@ -158,11 +178,8 @@
 		/*
 		 * This is a no can do.  It obviously wouldn't
 		 * work on SMP where another process may not
-		 * be blocked at all.
-		 *
-		 * Perhaps we need a global predicate in the
-		 * leave_kernel path to control if pp should
-		 * be on or off?
+		 * be blocked at all. We need to put in a  perfmon 
+		 * IPI to take care of MP systems. See blurb above.
 		 */
 		lock_kernel();
 		for_each_task(p) {
@@ -170,7 +187,7 @@
 			ia64_psr(regs)->pp = 0;
 		}
 		unlock_kernel();
-		perf_owner = 0;
+		perf_owner = NULL;
 		break;
 
 	      default:
@@ -184,12 +201,12 @@
 {
 	unsigned long mask, i, cnum, val;
 
-	mask = ia64_get_pmd(0) >> 4;
+	mask = ia64_get_pmc(0) >> 4;
 	for (i = 0, cnum = 4; i < MAX_PERF_COUNTER; cnum++, i++, mask >>= 1) {
 		if (mask & 0x1) 
 			val = PERF_OVFL_VAL;
 		else
-			/* since we got an interrupt, might as well clear every pmd. */
+		/* since we got an interrupt, might as well clear every pmd. */
 			val = ia64_get_pmd(cnum) & PERF_OVFL_VAL;
 		pmds[i] += val;
 		ia64_set_pmd(cnum, 0);
@@ -214,10 +231,10 @@
 	}
 	ia64_set_pmv(PERFMON_IRQ);
 	ia64_srlz_d();
+	printk("Initialized perfmon vector to %u\n",PERFMON_IRQ);
 }
 
 #else /* !CONFIG_PERFMON */
-
 asmlinkage unsigned long
 sys_perfmonctl (int cmd1, int cmd2, void *ptr)
 {
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/process.c linux/arch/ia64/kernel/process.c
--- v2.3.50/linux/arch/ia64/kernel/process.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/ia64/kernel/process.c	Fri Mar 10 15:24:02 2000
@@ -99,7 +99,7 @@
 			(*pm_idle)();
 #ifdef CONFIG_ITANIUM_ASTEP_SPECIFIC
 		if (ia64_get_itm() < ia64_get_itc()) {
-			extern void ia64_reset_itm();
+			extern void ia64_reset_itm (void);
 
 			printk("cpu_idle: ITM in past, resetting it...\n");
 			ia64_reset_itm();
@@ -238,7 +238,7 @@
 ia64_elf_core_copy_regs (struct pt_regs *pt, elf_gregset_t dst)
 {
 	struct switch_stack *sw = ((struct switch_stack *) pt) - 1;
-	unsigned long ar_ec, cfm, ar_bsp, ndirty, *krbs;
+	unsigned long ar_ec, cfm, ar_bsp, ndirty, *krbs, addr;
 
 	ar_ec = (sw->ar_pfs >> 52) & 0x3f;
 
@@ -249,8 +249,18 @@
 	}
 
 	krbs = (unsigned long *) current + IA64_RBS_OFFSET/8;
-	ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 16));
-	ar_bsp = (long) ia64_rse_skip_regs((long *) pt->ar_bspstore, ndirty);
+	ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19));
+	ar_bsp = (unsigned long) ia64_rse_skip_regs((long *) pt->ar_bspstore, ndirty);
+
+	/*
+	 * Write portion of RSE backing store living on the kernel
+	 * stack to the VM of the process.
+	 */
+	for (addr = pt->ar_bspstore; addr < ar_bsp; addr += 8) {
+		long val;
+		if (ia64_peek(pt, current, addr, &val) == 0)
+			access_process_vm(current, addr, &val, sizeof(val), 1);
+	}
 
 	/*	r0-r31
 	 *	NaT bits (for r0-r31; bit N == 1 iff rN is a NaT)
@@ -310,7 +320,6 @@
 {
 	int error;
 
-	lock_kernel();
 	filename = getname(filename);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
@@ -318,7 +327,6 @@
 	error = do_execve(filename, argv, envp, regs);
 	putname(filename);
 out:
-	unlock_kernel();
 	return error;
 }
 
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/semaphore.c linux/arch/ia64/kernel/semaphore.c
--- v2.3.50/linux/arch/ia64/kernel/semaphore.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/kernel/semaphore.c	Fri Mar 10 15:24:02 2000
@@ -138,9 +138,10 @@
 int
 __down_trylock (struct semaphore *sem)
 {
+	unsigned long flags;
 	int sleepers;
 
-	spin_lock_irq(&semaphore_lock);
+	spin_lock_irqsave(&semaphore_lock, flags);
 	sleepers = sem->sleepers + 1;
 	sem->sleepers = 0;
 
@@ -151,7 +152,7 @@
 	if (!atomic_add_negative(sleepers, &sem->count))
 		wake_up(&sem->wait);
 
-	spin_unlock_irq(&semaphore_lock);
+	spin_unlock_irqrestore(&semaphore_lock, flags);
 	return 1;
 }
 
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/setup.c linux/arch/ia64/kernel/setup.c
--- v2.3.50/linux/arch/ia64/kernel/setup.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/kernel/setup.c	Fri Mar 10 15:24:02 2000
@@ -101,6 +101,7 @@
 setup_arch (char **cmdline_p)
 {
 	unsigned long max_pfn, bootmap_start, bootmap_size;
+	u64 progress;
 
 	/*
 	 * The secondary bootstrap loader passes us the boot
@@ -167,6 +168,7 @@
 	conswitchp = &dummy_con;
 # endif
 #endif
+	paging_init();
 	platform_setup(cmdline_p);
 }
 
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/time.c linux/arch/ia64/kernel/time.c
--- v2.3.50/linux/arch/ia64/kernel/time.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/ia64/kernel/time.c	Fri Mar 10 15:24:02 2000
@@ -10,21 +10,17 @@
  */
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/time.h>
 
 #include <asm/delay.h>
 #include <asm/efi.h>
-#include <asm/irq.h>
-#include <asm/machvec.h>
+#include <asm/hw_irq.h>
 #include <asm/ptrace.h>
 #include <asm/sal.h>
 #include <asm/system.h>
-#ifdef CONFIG_KDB
-# include <linux/kdb.h>
-#endif
-
 
 extern rwlock_t xtime_lock;
 extern volatile unsigned long lost_ticks;
@@ -43,8 +39,12 @@
 static void
 do_profile (unsigned long ip)
 {
+	extern unsigned long prof_cpu_mask;
 	extern char _stext;
 
+	if (!((1UL << smp_processor_id()) & prof_cpu_mask))
+		return;
+
 	if (prof_buffer && current->pid) {
 		ip -= (unsigned long) &_stext;
 		ip >>= prof_shift;
@@ -65,7 +65,7 @@
  * update to jiffy.  The xtime_lock must be at least read-locked when
  * calling this routine.
  */
-static /*inline*/ unsigned long
+static inline unsigned long
 gettimeoffset (void)
 {
 	unsigned long now = ia64_get_itc();
@@ -198,7 +198,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	timer_interrupt(0, 0, current);
+	timer_interrupt(0, 0, ia64_task_regs(current));
 	local_irq_restore(flags);
 }
 
@@ -293,15 +293,19 @@
 	ia64_cpu_local_tick();
 }
 
+static struct irqaction timer_irqaction = {
+	handler:	timer_interrupt,
+	flags:		SA_INTERRUPT,
+	name:		"timer"
+};
+
 void __init
 time_init (void)
 {
-	/*
-	 * Request the IRQ _before_ doing anything to cause that
-	 * interrupt to be posted.
-	 */
-	if (request_irq(TIMER_IRQ, timer_interrupt, 0, "timer", NULL)) 
-		panic("Could not allocate timer IRQ!");
+	/* we can't do request_irq() here because the kmalloc() would fail... */
+	irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
+	irq_desc[TIMER_IRQ].handler = &irq_type_ia64_internal;
+	setup_irq(TIMER_IRQ, &timer_irqaction);
 
 	efi_gettimeofday(&xtime);
 	ia64_init_itm();
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/kernel/traps.c linux/arch/ia64/kernel/traps.c
--- v2.3.50/linux/arch/ia64/kernel/traps.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/ia64/kernel/traps.c	Fri Mar 10 15:24:02 2000
@@ -456,7 +456,7 @@
 
 	      case 32: /* fp fault */
 	      case 33: /* fp trap */
-		result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, &isr);
+		result = handle_fpu_swa((vector == 32) ? 1 : 0, regs, isr);
 		if (result < 0) {
 			siginfo.si_signo = SIGFPE;
 			siginfo.si_errno = 0;
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/lib/copy_page.S linux/arch/ia64/lib/copy_page.S
--- v2.3.50/linux/arch/ia64/lib/copy_page.S	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/lib/copy_page.S	Fri Mar 10 15:24:02 2000
@@ -15,6 +15,9 @@
  */
 #include <asm/page.h>
 
+#define PIPE_DEPTH	6
+#define EPI		p[PIPE_DEPTH-1]
+
 #define lcount		r16
 #define saved_pr	r17
 #define saved_lc	r18
@@ -34,10 +37,10 @@
 	.proc copy_page
 
 copy_page:
-	alloc saved_pfs=ar.pfs,10,0,0,8	// we need 6 roatating (8 minimum)
-					// + 2 input
+	alloc saved_pfs=ar.pfs,3,((2*PIPE_DEPTH+7)&~7),0,((2*PIPE_DEPTH+7)&~7)
 
-	.rotr t1[4], t2[4]	// our 2 pipelines with depth of 4 each
+	.rotr t1[PIPE_DEPTH], t2[PIPE_DEPTH]
+	.rotp p[PIPE_DEPTH]
 
 	mov saved_lc=ar.lc	// save ar.lc ahead of time
 	mov saved_pr=pr		// rotating predicates are preserved
@@ -53,29 +56,30 @@
 	mov pr.rot=1<<16	// pr16=1 & pr[17-63]=0 , 63 not modified
 
 	mov ar.lc=lcount	// set loop counter
-	mov ar.ec=4		// ar.ec must match pipeline depth
+	mov ar.ec=PIPE_DEPTH	// ar.ec must match pipeline depth
 	;;
 
 	// We need to preload the n-1 stages of the pipeline (n=depth).
 	// We do this during the "prolog" of the loop: we execute
 	// n-1 times the "load" bundle. Then both loads & stores are
 	// enabled until we reach the end of the last word of the page
-	// on the load side. Then, we enter the epilogue (controlled by ec)
-	// where we just do the stores and no loads n-1 times : drain the pipe.
+	// on the load side. Then, we enter the epilog (controlled by ec)
+	// where we just do the stores and no loads n times : drain the pipe
+	// (we exit the loop when ec=1).
 	//
 	// The initialization of the prolog is done via the predicate registers:
-	// the choice of pr19 DEPENDS on the depth of the pipeline (n).
+	// the choice of EPI DEPENDS on the depth of the pipeline (n).
 	// When lc > 0 pr63=1 and it is fed back into pr16 and pr16-pr62 
 	// are then shifted right at every iteration,
-	// Thus by initializing pr16=1 and pr17-19=0 (19=16+4-1) before the loop
-	// we get pr19=1 after 4 iterations (n in our case).
+	// Thus by initializing pr16=1 and the rest to 0 before the loop
+	// we get EPI=1 after n iterations.
 	//
 1:				// engage loop now, let the magic happen...
 (p16)	ld8 t1[0]=[src1],16	// new data on top of pipeline in 1st stream
 (p16)	ld8 t2[0]=[src2],16	// new data on top of pipeline in 2nd stream
 	nop.i 0x0
-(p19)	st8 [tgt1]=t1[3],16	// store top of  1st pipeline
-(p19)	st8 [tgt2]=t2[3],16	// store top of 2nd pipeline
+(EPI)	st8 [tgt1]=t1[PIPE_DEPTH-1],16	// store top of  1st pipeline
+(EPI)	st8 [tgt2]=t2[PIPE_DEPTH-1],16	// store top of 2nd pipeline
 	br.ctop.dptk.few 1b	// once lc==0, ec-- & p16=0
 				// stores but no loads anymore
 	;;
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/lib/copy_user.S linux/arch/ia64/lib/copy_user.S
--- v2.3.50/linux/arch/ia64/lib/copy_user.S	Sat Feb 26 22:31:39 2000
+++ linux/arch/ia64/lib/copy_user.S	Fri Mar 10 15:24:02 2000
@@ -1,3 +1,34 @@
+/*
+ *
+ * Optimized version of the copy_user() routine.
+ * It is used to copy date across the kernel/user boundary.
+ *
+ * The source and destination are always on opposite side of
+ * the boundary. When reading from user space we must catch
+ * faults on loads. When writing to user space we must catch
+ * errors on stores. Note that because of the nature of the copy
+ * we don't need to worry about overlapping regions.
+ *
+ *
+ * Inputs:
+ *	in0	address of source buffer
+ * 	in1	address of destination buffer
+ *	in2	number of bytes to copy
+ *
+ * Outputs: 
+ * 	ret0	0 in case of sucess. The number of bytes NOT copied in
+ * 		case of error.
+ *
+ * Copyright (C) 2000 Hewlett-Packard Co
+ * Copyright (C) 2000 Stephane Eranian <eranian@hpl.hp.com>
+ *
+ * Fixme:
+ *	- handle the case where we have more than 16 bytes and the alignment
+ * 	  are different.
+ *	- more benchmarking
+ * 	- fix extraneous stop bit introduced by the EX() macro.
+ */
+
 // The label comes first because our store instruction contains a comma
 // and confuse the preprocessor otherwise
 //
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/lib/strncpy_from_user.S linux/arch/ia64/lib/strncpy_from_user.S
--- v2.3.50/linux/arch/ia64/lib/strncpy_from_user.S	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/lib/strncpy_from_user.S	Fri Mar 10 15:24:02 2000
@@ -1,6 +1,5 @@
 /*
- * Just like strncpy() except for the return value.  If no fault occurs during
- * the copying, the number of bytes copied is returned.  If a fault occurs,
+ * Just like strncpy() except that if a fault occurs during copying,
  * -EFAULT is returned.
  *
  * Inputs:
@@ -10,8 +9,11 @@
  * Outputs:
  *	r8:	-EFAULT in case of fault or number of bytes copied if no fault
  * 
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * 00/03/06 D. Mosberger Fixed to return proper return value (bug found by
+ *			 by Andreas Schwab <schwab@suse.de>).
  */
 
 #define EX(x...)				\
@@ -30,24 +32,26 @@
 	.global __strncpy_from_user
 	.proc __strncpy_from_user
 __strncpy_from_user:
-	alloc r11=ar.pfs,3,0,0,0
+	alloc r2=ar.pfs,3,0,0,0
+	mov r8=0
 	mov r9=in1
+	;;
 	add r10=in1,in2
+	cmp.eq p6,p0=r0,in2
+(p6)	br.ret.spnt.many rp
 
 	// XXX braindead copy loop---this needs to be optimized
 .Loop1:
-	EX(ld1 r8=[in1],1)
-	;;
-	st1 [in0]=r8,1
-	cmp.ltu p6,p0=in1,r10
+	EX(ld1 r8=[in1],1;; st1 [in0]=r8,1; cmp.ne p6,p7=r8,r0)
 	;;
-(p6)	cmp.ne.and p6,p0=r8,r0
+(p6)	cmp.ne.unc p8,p0=in1,r10
+(p8)	br.cond.dpnt.few .Loop1
 	;;
-(p6)	br.cond.dpnt.few .Loop1
+(p6)	mov r8=in2		// buffer filled up---return buffer length
+(p7)	sub r8=in1,r9,1		// return string length (excluding NUL character)
+	br.ret.sptk.few rp
 
-1:	sub r8=in1,r9		// length of string (including NUL character)
 .Lexit:
-	mov ar.pfs=r11
 	br.ret.sptk.few rp
 
 	.endp __strncpy_from_user
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/mm/init.c linux/arch/ia64/mm/init.c
--- v2.3.50/linux/arch/ia64/mm/init.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/mm/init.c	Fri Mar 10 15:24:02 2000
@@ -241,13 +241,13 @@
 	pmd = pmd_alloc(pgd, address);
 	if (!pmd) {
 		__free_page(page);
-		oom(current);
+		panic("Out of memory.");
 		return 0;
 	}
 	pte = pte_alloc(pmd, address);
 	if (!pte) {
 		__free_page(page);
-		oom(current);
+		panic("Out of memory.");
 		return 0;
 	}
 	if (!pte_none(*pte)) {
diff -u --recursive --new-file v2.3.50/linux/arch/ia64/mm/tlb.c linux/arch/ia64/mm/tlb.c
--- v2.3.50/linux/arch/ia64/mm/tlb.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/ia64/mm/tlb.c	Fri Mar 10 15:24:02 2000
@@ -97,7 +97,7 @@
 	stride0 = ia64_ptce_info.stride[0];
 	stride1 = ia64_ptce_info.stride[1];
 
-	save_and_cli(flags);
+	__save_and_cli(flags);
 	for (i = 0; i < count0; ++i) {
 		for (j = 0; j < count1; ++j) {
 			asm volatile ("ptc.e %0" :: "r"(addr));
@@ -105,7 +105,7 @@
 		}
 		addr += stride0;
 	}
-	restore_flags(flags);
+	__restore_flags(flags);
 	ia64_insn_group_barrier();
 	ia64_srlz_i();			/* srlz.i implies srlz.d */
 	ia64_insn_group_barrier();
diff -u --recursive --new-file v2.3.50/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.3.50/linux/arch/mips/config.in	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/config.in	Thu Mar  9 07:04:56 2000
@@ -293,7 +293,7 @@
 
 source drivers/usb/Config.in
 
-source drivers/misc/Config.in
+#source drivers/misc/Config.in
 
 source fs/Config.in
 
diff -u --recursive --new-file v2.3.50/linux/arch/mips/defconfig linux/arch/mips/defconfig
--- v2.3.50/linux/arch/mips/defconfig	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/defconfig	Thu Mar  9 07:04:56 2000
@@ -292,10 +292,6 @@
 # CONFIG_USB is not set
 
 #
-# Misc devices
-#
-
-#
 # File systems
 #
 # CONFIG_QUOTA is not set
diff -u --recursive --new-file v2.3.50/linux/arch/mips/defconfig-decstation linux/arch/mips/defconfig-decstation
--- v2.3.50/linux/arch/mips/defconfig-decstation	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/defconfig-decstation	Thu Mar  9 07:04:56 2000
@@ -184,10 +184,6 @@
 # CONFIG_USB is not set
 
 #
-# Misc devices
-#
-
-#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
diff -u --recursive --new-file v2.3.50/linux/arch/mips/defconfig-ip22 linux/arch/mips/defconfig-ip22
--- v2.3.50/linux/arch/mips/defconfig-ip22	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/defconfig-ip22	Thu Mar  9 07:04:56 2000
@@ -292,10 +292,6 @@
 # CONFIG_USB is not set
 
 #
-# Misc devices
-#
-
-#
 # File systems
 #
 # CONFIG_QUOTA is not set
diff -u --recursive --new-file v2.3.50/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.3.50/linux/arch/mips/kernel/sysirix.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/mips/kernel/sysirix.c	Wed Mar  8 13:55:08 2000
@@ -725,8 +725,6 @@
 			   int len, int fs_type)
 {
 	struct dentry *dentry;
-	struct inode *inode;
-	mm_segment_t old_fs;
 	struct statfs kbuf;
 	int error, i;
 
@@ -745,11 +743,7 @@
 	if (IS_ERR(dentry))
 		goto out;
 
-	inode = dentry->d_inode;
-	old_fs = get_fs(); set_fs(get_ds());
-	error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf,
-	                                  sizeof(struct statfs));
-	set_fs(old_fs);
+	error = vfs_statfs(dentry->d_inode->i_sb, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -775,9 +769,7 @@
 
 asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
 {
-	struct inode *inode;
 	struct statfs kbuf;
-	mm_segment_t old_fs;
 	struct file *file;
 	int error, i;
 
@@ -790,23 +782,7 @@
 		goto out;
 	}
 
-	if (!(inode = file->f_dentry->d_inode)) {
-		error = -ENOENT;
-		goto out_f;
-	}
-	if (!inode->i_sb) {
-		error = -ENODEV;
-		goto out_f;
-	}
-	if (!inode->i_sb->s_op->statfs) {
-		error = -ENOSYS;
-		goto out_f;
-	}
-
-	old_fs = get_fs(); set_fs(get_ds());
-	error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf,
-	                                  sizeof(struct statfs));
-	set_fs(old_fs);
+	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
 	if (error)
 		goto out_f;
 
@@ -1509,8 +1485,6 @@
 asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
 {
 	struct dentry *dentry;
-	struct inode *inode;
-	mm_segment_t old_fs;
 	struct statfs kbuf;
 	int error, i;
 
@@ -1524,16 +1498,7 @@
 	error = PTR_ERR(dentry);
 	if(!IS_ERR(dentry))
 		goto out;
-	inode = dentry->d_inode;
-
-	error = -ENOSYS;
-	if(!inode->i_sb->s_op->statfs)
-		goto dput_and_out;
-
-	old_fs = get_fs(); set_fs(get_ds());
-	error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf,
-	                                  sizeof(struct statfs));
-	set_fs(old_fs);
+	error = vfs_statfs(dentry->d_inode->i_sb, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -1568,8 +1533,6 @@
 
 asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
 {
-	struct inode *inode;
-	mm_segment_t old_fs;
 	struct statfs kbuf;
 	struct file *file;
 	int error, i;
@@ -1585,23 +1548,7 @@
 		error = -EBADF;
 		goto out;
 	}
-	if (!(inode = file->f_dentry->d_inode)) {
-		error = -ENOENT;
-		goto out_f;
-	}
-	if (!inode->i_sb) {
-		error = -ENODEV;
-		goto out_f;
-	}
-	if (!inode->i_sb->s_op->statfs) {
-		error = -ENOSYS;
-		goto out_f;
-	}
-
-	old_fs = get_fs(); set_fs(get_ds());
-	error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf,
-	                                  sizeof(struct statfs));
-	set_fs(old_fs);
+	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
 	if (error)
 		goto out_f;
 
@@ -1813,8 +1760,6 @@
 asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf)
 {
 	struct dentry *dentry;
-	struct inode *inode;
-	mm_segment_t old_fs;
 	struct statfs kbuf;
 	int error, i;
 
@@ -1828,15 +1773,7 @@
 	error = PTR_ERR(dentry);
 	if(IS_ERR(dentry))
 		goto out;
-	error = -ENOSYS;
-	inode = dentry->d_inode;
-	if(!inode->i_sb->s_op->statfs)
-		goto dput_and_out;
-
-	old_fs = get_fs(); set_fs(get_ds());
-	error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf,
-	                                  sizeof(struct statfs));
-	set_fs(old_fs);
+	error = vfs_statfs(dentry->d_inode->i_sb, &kbuf);
 	if (error)
 		goto dput_and_out;
 
@@ -1871,8 +1808,6 @@
 
 asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
 {
-	struct inode *inode;
-	mm_segment_t old_fs;
 	struct statfs kbuf;
 	struct file *file;
 	int error, i;
@@ -1888,23 +1823,7 @@
 		error = -EBADF;
 		goto out;
 	}
-	if (!(inode = file->f_dentry->d_inode)) {
-		error = -ENOENT;
-		goto out_f;
-	}
-	if (!inode->i_sb) {
-		error = -ENODEV;
-		goto out_f;
-	}
-	if (!inode->i_sb->s_op->statfs) {
-		error = -ENOSYS;
-		goto out_f;
-	}
-
-	old_fs = get_fs(); set_fs(get_ds());
-	error = inode->i_sb->s_op->statfs(inode->i_sb, &kbuf,
-	                                  sizeof(struct statfs));
-	set_fs(old_fs);
+	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &kbuf);
 	if (error)
 		goto out_f;
 
diff -u --recursive --new-file v2.3.50/linux/arch/mips64/config.in linux/arch/mips64/config.in
--- v2.3.50/linux/arch/mips64/config.in	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/config.in	Thu Mar  9 07:04:56 2000
@@ -177,7 +177,6 @@
 
 source drivers/usb/Config.in
 
-# drivers/misc has currently only i386 specific devices.
 #source drivers/misc/Config.in
 
 source fs/Config.in
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.3.50/linux/arch/ppc/boot/Makefile	Thu Feb 10 17:11:04 2000
+++ linux/arch/ppc/boot/Makefile	Wed Mar  8 09:18:02 2000
@@ -53,7 +53,6 @@
 
 OBJECTS := head.o misc.o ../coffboot/zlib.o
 CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin
-OBJCOPY = $(CROSS_COMPILE)objcopy
 OBJCOPY_ARGS = -O elf32-powerpc
 
 OBJECTS += vreset.o kbd.o of1275.o
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/chrpboot/Makefile linux/arch/ppc/chrpboot/Makefile
--- v2.3.50/linux/arch/ppc/chrpboot/Makefile	Thu Feb 10 17:11:04 2000
+++ linux/arch/ppc/chrpboot/Makefile	Wed Mar  8 09:18:02 2000
@@ -18,7 +18,6 @@
 
 CFLAGS	= $(CPPFLAGS) -O -fno-builtin -DSTDC_HEADERS
 LD_ARGS = -Ttext 0x00400000
-OBJCOPY = $(CROSS_COMPILE)objcopy
 
 OBJS = crt0.o start.o main.o misc.o ../coffboot/string.o ../coffboot/zlib.o image.o sysmap.o
 LIBS = $(TOPDIR)/lib/lib.a
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- v2.3.50/linux/arch/ppc/coffboot/Makefile	Thu Feb 10 17:11:04 2000
+++ linux/arch/ppc/coffboot/Makefile	Wed Mar  8 09:18:02 2000
@@ -5,14 +5,10 @@
 
 HOSTCFLAGS = -O -I$(TOPDIR)/include
 
-CC	= $(CROSS_COMPILE)gcc
-LD	= $(CROSS_COMPILE)ld
 CFLAGS	= $(CPPFLAGS) -O -fno-builtin
-OBJCOPY = $(CROSS_COMPILE)objcopy
 OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
 COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic
 CHRP_LD_ARGS = -Ttext 0x00400000
-GZ = gzip -9
 
 COFFOBJS = coffcrt0.o start.o coffmain.o misc.o string.o zlib.o image.o
 CHRPOBJS = crt0.o start.o chrpmain.o misc.o string.o zlib.o image.o
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig
--- v2.3.50/linux/arch/ppc/configs/common_defconfig	Tue Mar  7 14:32:25 2000
+++ linux/arch/ppc/configs/common_defconfig	Thu Mar  9 07:04:49 2000
@@ -1,5 +1,5 @@
 #
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
 #
 # CONFIG_UID16 is not set
 
@@ -33,7 +33,6 @@
 #
 # General setup
 #
-# CONFIG_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI=y
 CONFIG_NET=y
@@ -46,6 +45,10 @@
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_PCI_NAMES is not set
 # CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
 # CONFIG_PARPORT is not set
 CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
@@ -53,6 +56,7 @@
 CONFIG_PMAC_PBOOK=y
 CONFIG_MAC_FLOPPY=y
 CONFIG_MAC_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
 CONFIG_ADB=y
 CONFIG_ADB_CUDA=y
 CONFIG_ADB_MACIO=y
@@ -69,27 +73,21 @@
 # Plug and Play configuration
 #
 # CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
 CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=y
-
-#
-# IDE chipset support/bugfixes
-#
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
@@ -108,10 +106,6 @@
 CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_CPQ_DA is not set
-
-#
-# Additional Block Devices
-#
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
@@ -144,18 +138,10 @@
 # CONFIG_IP_MROUTE is not set
 CONFIG_IP_ALIAS=y
 CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
 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=m
 # CONFIG_DECNET is not set
@@ -177,10 +163,6 @@
 # SCSI support
 #
 CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
@@ -189,10 +171,6 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
-
-#
-# 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
@@ -272,6 +250,13 @@
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPDDP is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -299,6 +284,7 @@
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
 CONFIG_DE4X5=y
 # CONFIG_TULIP is not set
 # CONFIG_DGRS is not set
@@ -324,13 +310,6 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_LTPC is not set
-# CONFIG_COPS is not set
-# CONFIG_IPDDP is not set
 CONFIG_PPP=y
 # CONFIG_PPP_ASYNC is not set
 # CONFIG_PPP_SYNC_TTY is not set
@@ -344,7 +323,7 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring driver support
+# Token Ring devices
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -397,7 +376,7 @@
 CONFIG_FB_MATROX_G100=y
 # CONFIG_FB_MATROX_MULTIHEAD is not set
 CONFIG_FB_ATY=y
-# CONFIG_FB_ATY128 is not set
+CONFIG_FB_ATY128=y
 CONFIG_FB_3DFX=y
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
@@ -456,7 +435,6 @@
 # CONFIG_WATCHDOG is not set
 CONFIG_NVRAM=y
 # CONFIG_RTC is not set
-# CONFIG_EFI_RTC is not set
 
 #
 # Video For Linux
@@ -471,28 +449,17 @@
 #
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
 # CONFIG_AGP is not set
 
 #
 # USB support
 #
 CONFIG_USB=y
-
-#
-# USB Controllers
-#
 # CONFIG_USB_UHCI is not set
 # CONFIG_USB_UHCI_ALT is not set
 CONFIG_USB_OHCI=y
-
-#
-# Miscellaneous USB options
-#
 # CONFIG_USB_DEVICEFS is not set
-
-#
-# USB Devices
-#
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_SCANNER is not set
 # CONFIG_USB_AUDIO is not set
@@ -503,14 +470,11 @@
 # CONFIG_USB_OV511 is not set
 # CONFIG_USB_DC2XX is not set
 # CONFIG_USB_STORAGE is not set
+# CONFIG_USB_USS720 is not set
 # CONFIG_USB_DABUSB is not set
 # CONFIG_USB_PLUSB is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RIO500 is not set
-
-#
-# USB HID
-#
 # CONFIG_USB_HID is not set
 CONFIG_USB_KBD=y
 CONFIG_USB_MOUSE=y
@@ -546,6 +510,7 @@
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -559,6 +524,7 @@
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
@@ -630,7 +596,6 @@
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 CONFIG_SOUND_OSS=y
-# CONFIG_SOUND_DMAP is not set
 # CONFIG_SOUND_AD1816 is not set
 # CONFIG_SOUND_SGALAXY is not set
 CONFIG_SOUND_CS4232=m
@@ -643,7 +608,9 @@
 # CONFIG_SOUND_NM256 is not set
 # CONFIG_SOUND_MAD16 is not set
 # CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
 # CONFIG_SOUND_PSS is not set
+# CONFIG_PSS_HAVE_BOOT is not set
 # CONFIG_SOUND_SOFTOSS is not set
 # CONFIG_SOUND_SB is not set
 # CONFIG_SOUND_WAVEFRONT is not set
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.50/linux/arch/ppc/defconfig	Tue Mar  7 14:32:25 2000
+++ linux/arch/ppc/defconfig	Thu Mar  9 07:04:49 2000
@@ -1,5 +1,5 @@
 #
-# Automatically generated make config: don't edit
+# Automatically generated by make menuconfig: don't edit
 #
 # CONFIG_UID16 is not set
 
@@ -33,7 +33,6 @@
 #
 # General setup
 #
-# CONFIG_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI=y
 CONFIG_NET=y
@@ -46,6 +45,10 @@
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_PCI_NAMES is not set
 # CONFIG_HOTPLUG is not set
+
+#
+# Parallel port support
+#
 # CONFIG_PARPORT is not set
 CONFIG_VGA_CONSOLE=y
 CONFIG_FB=y
@@ -53,6 +56,7 @@
 CONFIG_PMAC_PBOOK=y
 CONFIG_MAC_FLOPPY=y
 CONFIG_MAC_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
 CONFIG_ADB=y
 CONFIG_ADB_CUDA=y
 CONFIG_ADB_MACIO=y
@@ -69,27 +73,21 @@
 # Plug and Play configuration
 #
 # CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
 CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
 # CONFIG_BLK_DEV_HD_IDE is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=y
-
-#
-# IDE chipset support/bugfixes
-#
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
@@ -108,10 +106,6 @@
 CONFIG_IDEDMA_AUTO=y
 # CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_CPQ_DA is not set
-
-#
-# Additional Block Devices
-#
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_MD is not set
@@ -144,18 +138,10 @@
 # CONFIG_IP_MROUTE is not set
 CONFIG_IP_ALIAS=y
 CONFIG_SYN_COOKIES=y
-
-#
-# (it is safe to leave these untouched)
-#
 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=m
 # CONFIG_DECNET is not set
@@ -177,10 +163,6 @@
 # SCSI support
 #
 CONFIG_SCSI=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
@@ -189,10 +171,6 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
-
-#
-# 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
@@ -272,6 +250,13 @@
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_LTPC is not set
+# CONFIG_COPS is not set
+# CONFIG_IPDDP is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -299,6 +284,7 @@
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
 CONFIG_DE4X5=y
 # CONFIG_TULIP is not set
 # CONFIG_DGRS is not set
@@ -324,13 +310,6 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
-
-#
-# Appletalk devices
-#
-# CONFIG_LTPC is not set
-# CONFIG_COPS is not set
-# CONFIG_IPDDP is not set
 CONFIG_PPP=y
 # CONFIG_PPP_ASYNC is not set
 # CONFIG_PPP_SYNC_TTY is not set
@@ -344,7 +323,7 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring driver support
+# Token Ring devices
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -397,7 +376,7 @@
 CONFIG_FB_MATROX_G100=y
 # CONFIG_FB_MATROX_MULTIHEAD is not set
 CONFIG_FB_ATY=y
-# CONFIG_FB_ATY128 is not set
+CONFIG_FB_ATY128=y
 CONFIG_FB_3DFX=y
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
@@ -456,7 +435,6 @@
 # CONFIG_WATCHDOG is not set
 CONFIG_NVRAM=y
 # CONFIG_RTC is not set
-# CONFIG_EFI_RTC is not set
 
 #
 # Video For Linux
@@ -471,28 +449,17 @@
 #
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
+# CONFIG_DRM_TDFX is not set
 # CONFIG_AGP is not set
 
 #
 # USB support
 #
 CONFIG_USB=y
-
-#
-# USB Controllers
-#
 # CONFIG_USB_UHCI is not set
 # CONFIG_USB_UHCI_ALT is not set
 CONFIG_USB_OHCI=y
-
-#
-# Miscellaneous USB options
-#
 # CONFIG_USB_DEVICEFS is not set
-
-#
-# USB Devices
-#
 # CONFIG_USB_PRINTER is not set
 # CONFIG_USB_SCANNER is not set
 # CONFIG_USB_AUDIO is not set
@@ -503,14 +470,11 @@
 # CONFIG_USB_OV511 is not set
 # CONFIG_USB_DC2XX is not set
 # CONFIG_USB_STORAGE is not set
+# CONFIG_USB_USS720 is not set
 # CONFIG_USB_DABUSB is not set
 # CONFIG_USB_PLUSB is not set
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RIO500 is not set
-
-#
-# USB HID
-#
 # CONFIG_USB_HID is not set
 CONFIG_USB_KBD=y
 CONFIG_USB_MOUSE=y
@@ -546,6 +510,7 @@
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -559,6 +524,7 @@
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
@@ -630,7 +596,6 @@
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
 CONFIG_SOUND_OSS=y
-# CONFIG_SOUND_DMAP is not set
 # CONFIG_SOUND_AD1816 is not set
 # CONFIG_SOUND_SGALAXY is not set
 CONFIG_SOUND_CS4232=m
@@ -643,7 +608,9 @@
 # CONFIG_SOUND_NM256 is not set
 # CONFIG_SOUND_MAD16 is not set
 # CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
 # CONFIG_SOUND_PSS is not set
+# CONFIG_PSS_HAVE_BOOT is not set
 # CONFIG_SOUND_SOFTOSS is not set
 # CONFIG_SOUND_SB is not set
 # CONFIG_SOUND_WAVEFRONT is not set
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c
--- v2.3.50/linux/arch/ppc/kernel/chrp_time.c	Thu Feb 10 17:11:04 2000
+++ linux/arch/ppc/kernel/chrp_time.c	Wed Mar  8 09:18:23 2000
@@ -173,7 +173,7 @@
 	}
 	freq *= 30;
 	divisor = 30; 
-        printk("time_init: decrementer frequency = %lu/%d (%d MHz)\n", freq,
+        printk("time_init: decrementer frequency = %lu/%d (%ld MHz)\n", freq,
 	       divisor, (freq/divisor)>>20);
         decrementer_count = freq / HZ / divisor;
         count_period_num = divisor;
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.3.50/linux/arch/ppc/kernel/irq.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/ppc/kernel/irq.c	Wed Mar  8 09:18:23 2000
@@ -677,7 +677,7 @@
 
 	err = parse_hex_value(buffer, count, &new_value);
 
-#if CONFIG_SMP
+#if 0/*CONFIG_SMP*/
 	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
 	 * way to make the system unusable accidentally :-) At least
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- v2.3.50/linux/arch/ppc/kernel/open_pic.c	Sun Feb 13 19:29:03 2000
+++ linux/arch/ppc/kernel/open_pic.c	Wed Mar  8 09:18:23 2000
@@ -97,7 +97,7 @@
 #define check_arg_cpu(cpu)	do {} while (0)
 #endif
 
-static void no_action(int ir1, void *dev, struct pt_regs *regs)
+void no_action(int ir1, void *dev, struct pt_regs *regs)
 {
 }
 
@@ -301,7 +301,7 @@
 	NumSources = 0x10;
 #else
 	/* for non-distributed OpenPIC implementations it's in the IDU -- Cort */
-	ISU = OpenPIC->Source;
+	ISU = (OpenPIC_Source *)OpenPIC->Source;
 #endif
 }
 
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.3.50/linux/arch/ppc/kernel/prom.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/ppc/kernel/prom.c	Wed Mar  8 09:18:23 2000
@@ -114,9 +114,6 @@
 static void clearscreen(void);
 static void flushscreen(void);
 
-void prom_drawchar(char c);
-void prom_drawstring(const char *c);
-void prom_drawhex(unsigned long v);
 static void scrollscreen(void);
 
 static void draw_byte(unsigned char c, long locX, long locY);
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/mbxboot/Makefile linux/arch/ppc/mbxboot/Makefile
--- v2.3.50/linux/arch/ppc/mbxboot/Makefile	Mon Dec 20 18:48:21 1999
+++ linux/arch/ppc/mbxboot/Makefile	Wed Mar  8 09:18:02 2000
@@ -27,11 +27,9 @@
 
 TFTPIMAGE=/tftpboot/zImage.mbx
 ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00100000
-GZIP_FLAGS = -v9
 
 OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o
 CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx
-OBJCOPY = $(CROSS_COMPILE)objcopy
 OBJCOPY_ARGS = -O elf32-powerpc
 
 ifeq ($(CONFIG_MBX),y)
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/treeboot/Makefile linux/arch/ppc/treeboot/Makefile
--- v2.3.50/linux/arch/ppc/treeboot/Makefile	Tue Jan 11 22:31:38 2000
+++ linux/arch/ppc/treeboot/Makefile	Wed Mar  8 09:18:02 2000
@@ -10,11 +10,6 @@
 
 HOSTCFLAGS = -O -I$(TOPDIR)/include
 
-CC	= $(CROSS_COMPILE)gcc
-LD	= $(CROSS_COMPILE)ld
-OBJCOPY = $(CROSS_COMPILE)objcopy
-OBJDUMP	= $(CROSS_COMPILE)objdump
-
 GZIP	= gzip -vf9
 RM	= rm -f
 MKEVIMG	= mkevimg -l
diff -u --recursive --new-file v2.3.50/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.3.50/linux/arch/ppc/xmon/xmon.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/ppc/xmon/xmon.c	Wed Mar  8 09:18:23 2000
@@ -7,6 +7,7 @@
 #include <linux/sched.h>
 #include <asm/ptrace.h>
 #include <asm/string.h>
+#include <asm/prom.h>
 #include "nonstdio.h"
 #include "privinst.h"
 
@@ -81,7 +82,7 @@
 static struct bpt *at_breakpoint(unsigned pc);
 static void bpt_cmds(void);
 static void cacheflush(void);
-static char *pretty_lookup_name(unsigned long addr);
+static char *pretty_print_addr(unsigned long addr);
 static char *lookup_name(unsigned long addr);
 
 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
@@ -141,7 +142,7 @@
 	prom_drawstring(" msr="); prom_drawhex(excp->msr);
 	prom_drawstring(" trap="); prom_drawhex(excp->trap);
 	prom_drawstring(" sp="); prom_drawhex(excp->gpr[1]);
-	sp = &excp->gpr[0];
+	sp = (unsigned *)&excp->gpr[0];
 	for (i = 0; i < 32; ++i) {
 		if ((i & 7) == 0)
 			prom_drawstring("\n");
@@ -544,10 +545,10 @@
 void
 excprint(struct pt_regs *fp)
 {
-	printf("vector: %x at pc = %x %s",
-	       fp->trap, fp->nip, pretty_lookup_name(fp->nip));
-	printf(", msr = %x, sp = %x [%x]\n",
-	       fp->msr, fp->gpr[1], fp);
+	printf("vector: %x at pc = %x",
+	       fp->trap, fp->nip);
+	printf(", lr = %x, msr = %x, sp = %x [%x]\n",
+	       fp->link, fp->msr, fp->gpr[1], fp);
 	if (fp->trap == 0x300 || fp->trap == 0x600)
 		printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
 	if (current)
@@ -1385,25 +1386,14 @@
 	lineptr = str;
 }
 
-/*
- * We use this array a lot here.  We assume we don't have multiple
- * instances of xmon running and that we don't use the return value of
- * any functions other than printing them.
- *  -- Cort
- */
-char last[64];
-static char *pretty_lookup_name(unsigned long addr)
+static char *pretty_print_addr(unsigned long addr)
 {
+	printf("%08x", addr);
 	if ( lookup_name(addr) )
-	{
-		sprintf(last, " (%s)", lookup_name(addr));
-		return last;
-	}
-	else
-		return NULL;
+		printf(" %s", lookup_name(addr) );
+	return NULL;
 }
 
-
 static char *lookup_name(unsigned long addr)
 {
 	extern char *sysmap;
@@ -1413,11 +1403,8 @@
 
 	if ( !sysmap || !sysmap_size )
 		return NULL;
-	
-	/* adjust if addr is relative to kernelbase */
-	if ( addr < PAGE_OFFSET )
-		addr += PAGE_OFFSET;
-
+return NULL;	
+#if 0
 	cmp = simple_strtoul(c, &c, 8);
 	strcpy( last, strsep( &c, "\n"));
 	while ( c < (sysmap+sysmap_size) )
@@ -1427,6 +1414,7 @@
 			break;
 		strcpy( last, strsep( &c, "\n"));
 	}
-	return last;
+	return NULLlast;
+#endif	
 }
 
diff -u --recursive --new-file v2.3.50/linux/arch/sh/config.in linux/arch/sh/config.in
--- v2.3.50/linux/arch/sh/config.in	Tue Mar  7 14:32:25 2000
+++ linux/arch/sh/config.in	Thu Mar  9 07:04:56 2000
@@ -155,7 +155,7 @@
    source drivers/char/pcmcia/Config.in
 fi
 
-source drivers/misc/Config.in
+#source drivers/misc/Config.in
 
 source fs/Config.in
 
diff -u --recursive --new-file v2.3.50/linux/arch/sh/defconfig linux/arch/sh/defconfig
--- v2.3.50/linux/arch/sh/defconfig	Tue Mar  7 14:32:25 2000
+++ linux/arch/sh/defconfig	Thu Mar  9 07:04:56 2000
@@ -96,10 +96,6 @@
 # CONFIG_UNIX98_PTYS is not set
 
 #
-# Misc devices
-#
-
-#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
diff -u --recursive --new-file v2.3.50/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.3.50/linux/arch/sparc/defconfig	Thu Mar  2 14:36:22 2000
+++ linux/arch/sparc/defconfig	Thu Mar  9 06:57:17 2000
@@ -83,6 +83,10 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 CONFIG_SUNOS_EMUL=y
+
+#
+# Parallel port support
+#
 # CONFIG_PARPORT is not set
 # CONFIG_PRINTER is not set
 
@@ -146,7 +150,6 @@
 CONFIG_DECNET=m
 CONFIG_DECNET_SIOCGIFCONF=y
 # CONFIG_DECNET_ROUTER is not set
-CONFIG_DECNET_RAW=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
diff -u --recursive --new-file v2.3.50/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.3.50/linux/arch/sparc/kernel/sparc_ksyms.c	Sat Feb 26 22:31:42 2000
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Thu Mar  9 06:57:17 2000
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.93 2000/02/26 11:02:45 anton Exp $
+/* $Id: sparc_ksyms.c,v 1.94 2000/02/28 04:00:53 anton Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -107,16 +107,10 @@
 EXPORT_SYMBOL_PRIVATE(_rw_write_enter);
 #endif
 #ifdef __SMP__
-#ifdef DEBUG_IRQLOCK
 EXPORT_SYMBOL(__global_save_flags);
 EXPORT_SYMBOL(__global_restore_flags);
 EXPORT_SYMBOL(__global_sti);
 EXPORT_SYMBOL(__global_cli);
-#else
-EXPORT_SYMBOL_PRIVATE(_global_restore_flags);
-EXPORT_SYMBOL_PRIVATE(_global_sti);
-EXPORT_SYMBOL_PRIVATE(_global_cli);
-#endif
 #endif
 
 /* rw semaphores */
diff -u --recursive --new-file v2.3.50/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.3.50/linux/arch/sparc/kernel/sys_sunos.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/sparc/kernel/sys_sunos.c	Thu Mar  9 06:57:17 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.113 2000/02/16 07:31:29 davem Exp $
+/* $Id: sys_sunos.c,v 1.114 2000/03/07 22:27:27 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.50/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- v2.3.50/linux/arch/sparc/lib/Makefile	Tue Jan  4 13:57:16 2000
+++ linux/arch/sparc/lib/Makefile	Thu Mar  9 06:57:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.31 1999/12/28 11:50:39 jj Exp $
+# $Id: Makefile,v 1.32 2000/02/28 04:00:48 anton Exp $
 # Makefile for Sparc library files..
 #
 
@@ -7,10 +7,6 @@
 	strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
 	copy_user.o locks.o atomic.o bitops.o debuglocks.o lshrdi3.o \
 	ashldi3.o rwsem.o
-
-ifdef CONFIG_SMP
-OBJS += irqlock.o
-endif
 
 lib.a: $(OBJS)
 	$(AR) rcs lib.a $(OBJS)
diff -u --recursive --new-file v2.3.50/linux/arch/sparc/lib/irqlock.S linux/arch/sparc/lib/irqlock.S
--- v2.3.50/linux/arch/sparc/lib/irqlock.S	Thu Apr 22 19:24:51 1999
+++ linux/arch/sparc/lib/irqlock.S	Wed Dec 31 16:00:00 1969
@@ -1,122 +0,0 @@
-/* $Id: irqlock.S,v 1.5 1999/04/20 13:22:37 anton Exp $
- * irqlock.S: High performance IRQ global locking and interrupt entry.
- *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <asm/psr.h>
-#include <asm/smp.h>
-
-	.text
-	.align	4
-
-	/* Weird calling conventions... %g7=flags, %g4=%prev_o7
-	 * Very clever for the __global_sti case, the inline which
-	 * gets us here clears %g7 and it just works.
-	 */
-	.globl	___global_restore_flags, ___global_sti, ___global_cli
-___global_restore_flags:
-	bne,a	___global_cli
-	 rd	%tbr, %g7
-	rd	%tbr, %g2
-
-___global_sti:
-	sethi	%hi(global_irq_holder), %g1
-	sethi	%hi(global_irq_lock), %g3
-	srl	%g2, 12, %g2
-	ldub	[%g1 + %lo(global_irq_holder)], %g5
-	and	%g2, 3, %g2
-	cmp	%g5, %g2
-	bne	1f
-	 mov	NO_PROC_ID, %g5
-	stb	%g5, [%g1 + %lo(global_irq_holder)]
-	stb	%g0, [%g3 + %lo(global_irq_lock)]
-1:
-	rd	%psr, %g3
-	andcc	%g7, 2, %g0
-	bne,a	1f
-	 or	%g3, PSR_PIL, %g3
-	andn	%g3, PSR_PIL, %g3
-1:
-	wr	%g3, 0x0, %psr
-	nop
-__global_cli_out:			! All togther now... "fuuunnnnn"
-	retl
-	 mov	%g4, %o7
-
-__spin_on_global_irq_lock:
-	orcc	%g2, 0x0, %g0
-	bne,a	__spin_on_global_irq_lock
-	 ldub	[%g1], %g2
-	b,a	1f
-
-	/* This is a royal pain in the ass to make fast... 8-( */
-___global_cli:
-	sethi	%hi(global_irq_lock), %g5
-	srl	%g7, 12, %g7
-	sethi	%hi(global_irq_holder), %g3
-	and	%g7, 3, %g7
-	ldub	[%g3 + %lo(global_irq_holder)], %g1
-	rd	%psr, %g2
-	cmp	%g1, %g7
-	or	%g2, PSR_PIL, %g2
-	be	__global_cli_out
-	 wr	%g2, 0x0, %psr			! XXX some sparcs may choke on this...
-	sethi	%hi(local_irq_count), %g3
-	or	%g3, %lo(local_irq_count), %g3
-	or	%g5, %lo(global_irq_lock), %g1
-1:
-	ldstub	[%g1], %g2
-	orcc	%g2, 0x0, %g0
-	bne,a	__spin_on_global_irq_lock
-	 ldub	[%g1], %g2
-__wait_on_irq:
-	sll	%g7, 2, %g7
-	ld	[%g3 + %g7], %g2
-	sethi	%hi(global_irq_count), %g1
-	or	%g1, %lo(global_irq_count), %g1
-	srl	%g7, 2, %g7
-	ld	[%g1], %g5
-	sra	%g5, 8, %g5
-__wait_on_irq_loop:
-	cmp	%g5, %g2
-	sethi	%hi(global_irq_holder), %g3
-	be,a	__global_cli_out	! Mamamia, Mamamia, this is the fast path
-	 stb	%g7, [%g3 + %lo(global_irq_holder)]
-1:
-	ldstub	[%g1 + 3], %g3
-	orcc	%g3, 0x0, %g0
-	bne	1b
-	 ld	[%g1], %g3
-	sra	%g3, 8, %g3
-	sub	%g3, %g2, %g3
-	sll	%g3, 8, %g3
-	st	%g3, [%g1]
-	sethi	%hi(global_irq_lock), %g3
-	stb	%g0, [%g3 + %lo(global_irq_lock)]
-0:
-	ld	[%g1], %g5
-9:
-	ldub	[%g3 + %lo(global_irq_lock)], %g3
-	sra	%g5, 8, %g5
-	orcc	%g3, %g5, %g0
-	bne	0b
-	 sethi	%hi(global_irq_lock), %g3
-	ldstub	[%g3 + %lo(global_irq_lock)], %g5
-	orcc	%g5, 0x0, %g0
-	bne,a	9b
-	 ld	[%g1], %g5
-1:
-	ldstub	[%g1 + 3], %g3
-	orcc	%g3, 0x0, %g0
-	bne	1b
-	 ld	[%g1], %g3
-	sra	%g3, 8, %g3
-	add	%g3, %g2, %g5
-	sll	%g5, 8, %g3
-	b	__wait_on_irq_loop
-	 st	%g3, [%g1]
-
-#if 0 /* XXX I'm not delirious enough to debug this yet. */
-	 add	%o7, (8 + (__wait_on_irq_loop - . - 4)), %o7	! AIEEEEE
-#endif
diff -u --recursive --new-file v2.3.50/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.3.50/linux/arch/sparc/mm/init.c	Sat Feb 26 22:31:42 2000
+++ linux/arch/sparc/mm/init.c	Thu Mar  9 06:57:17 2000
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.81 2000/02/26 11:59:31 anton Exp $
+/*  $Id: init.c,v 1.83 2000/03/07 23:12:35 anton Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -121,8 +121,8 @@
 	int i;
 
 	/* Limit maximum memory until we implement highmem for sparc */
-	if (cmdline_memory_size > 0x9000000)
-		cmdline_memory_size = 0x9000000;
+	if (!cmdline_memory_size || cmdline_memory_size > 0x0d000000)
+		cmdline_memory_size = 0x0d000000;
 
 	/* XXX It is a bit ambiguous here, whether we should
 	 * XXX treat the user specified mem=xxx as total wanted
@@ -138,7 +138,7 @@
 			sp_banks[i].num_bytes;
 		if (cmdline_memory_size) {
 			if (end_of_phys_memory > cmdline_memory_size) {
-				if (cmdline_memory_size > sp_banks[i].base_addr) {
+				if (cmdline_memory_size < sp_banks[i].base_addr) {
 					end_of_phys_memory =
 						sp_banks[i-1].base_addr +
 						sp_banks[i-1].num_bytes;
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.3.50/linux/arch/sparc64/Makefile	Wed Dec 29 13:13:13 1999
+++ linux/arch/sparc64/Makefile	Fri Mar 10 09:43:04 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.41 1999/12/21 04:02:23 davem Exp $
+# $Id: Makefile,v 1.42 2000/03/09 05:56:43 jj Exp $
 # sparc64/Makefile
 #
 # Makefile for the architecture dependent flags and dependencies on the
@@ -14,8 +14,9 @@
 
 CC		:= sparc64-linux-gcc
 
-IS_EGCS := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
+NEW_GCC := $(shell if $(CC) -m64 -mcmodel=medlow -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo y; else echo n; fi; )
 NEW_GAS := $(shell if $(LD) --version 2>&1 | grep 'elf64_sparc' > /dev/null; then echo y; else echo n; fi)
+UNDECLARED_REGS := $(shell if $(CC) -c -x assembler /dev/null -Wa,--help | grep undeclared-regs > /dev/null; then echo y; else echo n; fi; )
 
 ifneq ($(NEW_GAS),y)
 AS		= sparc64-linux-as
@@ -28,19 +29,26 @@
 LD		:= $(LD) -m elf64_sparc
 endif
 ELFTOAOUT	= elftoaout
+ifneq ($(UNDECLARED_REGS),y)
+CC_UNDECL	=
+else
+CC_UNDECL	= -Wa,--undeclared-regs
+AS		:= $(AS) --undeclared-regs
+endif
 
 #
 # Uncomment the first CFLAGS if you are doing kgdb source level
 # debugging of the kernel to get the proper debugging information.
 
 #CFLAGS := $(CFLAGS) -g -pipe -fcall-used-g5 -fcall-used-g7 
-ifneq ($(IS_EGCS),y)
+ifneq ($(NEW_GCC),y)
   CFLAGS := $(CFLAGS) -pipe -mno-fpu -mtune=ultrasparc -mmedlow \
 	    -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
 else
   CFLAGS := $(CFLAGS) -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow \
-	    -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare
-  AFLAGS += -m64 -mcpu=ultrasparc
+	    -ffixed-g4 -fcall-used-g5 -fcall-used-g7 -Wno-sign-compare \
+	    $(CC_UNDECL)
+  AFLAGS += -m64 -mcpu=ultrasparc $(CC_UNDECL)
 endif
 
 # Uncomment this to get spinlock/rwlock debugging on SMP.
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.3.50/linux/arch/sparc64/defconfig	Thu Mar  2 14:36:22 2000
+++ linux/arch/sparc64/defconfig	Thu Mar  9 06:57:17 2000
@@ -97,6 +97,10 @@
 CONFIG_BINFMT_MISC=m
 # CONFIG_SUNOS_EMUL is not set
 CONFIG_SOLARIS_EMUL=m
+
+#
+# Parallel port support
+#
 CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
 CONFIG_PARPORT_PC_FIFO=y
@@ -176,7 +180,6 @@
 CONFIG_DECNET=m
 CONFIG_DECNET_SIOCGIFCONF=y
 # CONFIG_DECNET_ROUTER is not set
-CONFIG_DECNET_RAW=y
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_BRIDGE is not set
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/kernel/pci_iommu.c linux/arch/sparc64/kernel/pci_iommu.c
--- v2.3.50/linux/arch/sparc64/kernel/pci_iommu.c	Sun Feb 20 21:12:38 2000
+++ linux/arch/sparc64/kernel/pci_iommu.c	Fri Mar 10 09:43:04 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_iommu.c,v 1.10 2000/02/18 13:48:54 davem Exp $
+/* $Id: pci_iommu.c,v 1.11 2000/03/10 02:42:15 davem Exp $
  * pci_iommu.c: UltraSparc PCI controller IOM/STC support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -34,46 +34,96 @@
 			     : "r" (__val), "r" (__reg), \
 			       "i" (ASI_PHYS_BYPASS_EC_E))
 
+/* Must be invoked under the IOMMU lock. */
+static void __iommu_flushall(struct pci_iommu *iommu)
+{
+	unsigned long tag;
+	int entry;
+
+	tag = iommu->iommu_flush + (0xa580UL - 0x0210UL);
+	for (entry = 0; entry < 16; entry++) {
+		pci_iommu_write(tag, 0);
+		tag += 8;
+	}
+
+	/* Ensure completion of previous PIO writes. */
+	(void) pci_iommu_read(iommu->write_complete_reg);
+
+	/* Now update everyone's flush point. */
+	for (entry = 0; entry < PBM_NCLUSTERS; entry++) {
+		iommu->alloc_info[entry].flush =
+			iommu->alloc_info[entry].next;
+	}
+}
+
 static iopte_t *alloc_streaming_cluster(struct pci_iommu *iommu, unsigned long npages)
 {
-	iopte_t *iopte;
-	unsigned long cnum, ent;
+	iopte_t *iopte, *limit;
+	unsigned long cnum, ent, flush_point;
 
 	cnum = 0;
 	while ((1UL << cnum) < npages)
 		cnum++;
-	iopte  = iommu->page_table + (cnum << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS));
-	iopte += ((ent = iommu->lowest_free[cnum]) << cnum);
+	iopte  = (iommu->page_table +
+		  (cnum << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
 
-	if (iopte_val(iopte[(1UL << cnum)]) == 0UL) {
-		/* Fast path. */
-		iommu->lowest_free[cnum] = ent + 1;
-	} else {
-		unsigned long pte_off = 1;
+	if (cnum == 0)
+		limit = (iommu->page_table +
+			 iommu->lowest_consistent_map);
+	else
+		limit = (iopte +
+			 (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
 
-		ent += 1;
-		do {
-			pte_off++;
-			ent++;
-		} while (iopte_val(iopte[(pte_off << cnum)]) != 0UL);
-		iommu->lowest_free[cnum] = ent;
+	iopte += ((ent = iommu->alloc_info[cnum].next) << cnum);
+	flush_point = iommu->alloc_info[cnum].flush;
+	
+	for (;;) {
+		if (iopte_val(*iopte) == 0UL) {
+			if ((iopte + (1 << cnum)) >= limit)
+				ent = 0;
+			else
+				ent = ent + 1;
+			iommu->alloc_info[cnum].next = ent;
+			if (ent == flush_point)
+				__iommu_flushall(iommu);
+			break;
+		}
+		iopte += (1 << cnum);
+		ent++;
+		if (iopte >= limit) {
+			iopte = (iommu->page_table +
+				 (cnum <<
+				  (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
+			ent = 0;
+		}
+		if (ent == flush_point)
+			__iommu_flushall(iommu);
 	}
 
 	/* I've got your streaming cluster right here buddy boy... */
 	return iopte;
 }
 
-static inline void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base, unsigned long npages)
+static void free_streaming_cluster(struct pci_iommu *iommu, dma_addr_t base,
+				   unsigned long npages, unsigned long ctx)
 {
 	unsigned long cnum, ent;
 
 	cnum = 0;
 	while ((1UL << cnum) < npages)
 		cnum++;
+
 	ent = (base << (32 - PAGE_SHIFT + PBM_LOGCLUSTERS - iommu->page_table_sz_bits))
 		>> (32 + PBM_LOGCLUSTERS + cnum - iommu->page_table_sz_bits);
-	if (ent < iommu->lowest_free[cnum])
-		iommu->lowest_free[cnum] = ent;
+
+	/* If the global flush might not have caught this entry,
+	 * adjust the flush point such that we will flush before
+	 * ever trying to reuse it.
+	 */
+#define between(X,Y,Z)	(((Z) - (Y)) >= ((X) - (Y)))
+	if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush))
+		iommu->alloc_info[cnum].flush = ent;
+#undef between
 }
 
 /* We allocate consistent mappings from the end of cluster zero. */
@@ -92,8 +142,13 @@
 				if (iopte_val(*iopte) & IOPTE_VALID)
 					break;
 			}
-			if (tmp == 0)
+			if (tmp == 0) {
+				u32 entry = (iopte - iommu->page_table);
+
+				if (entry < iommu->lowest_consistent_map)
+					iommu->lowest_consistent_map = entry;
 				return iopte;
+			}
 		}
 	}
 	return NULL;
@@ -182,7 +237,7 @@
 	struct pcidev_cookie *pcp;
 	struct pci_iommu *iommu;
 	iopte_t *iopte;
-	unsigned long flags, order, npages, i;
+	unsigned long flags, order, npages, i, ctx;
 
 	npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	pcp = pdev->sysdata;
@@ -192,15 +247,45 @@
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
+	if ((iopte - iommu->page_table) ==
+	    iommu->lowest_consistent_map) {
+		iopte_t *walk = iopte + npages;
+		iopte_t *limit;
+
+		limit = (iommu->page_table +
+			 (1 << (iommu->page_table_sz_bits - PBM_LOGCLUSTERS)));
+		while (walk < limit) {
+			if (iopte_val(*walk) != IOPTE_INVALID)
+				break;
+			walk++;
+		}
+		iommu->lowest_consistent_map =
+			(walk - iommu->page_table);
+	}
+
 	/* Data for consistent mappings cannot enter the streaming
-	 * buffers, so we only need to update the TSB.  Flush of the
-	 * IOTLB is done later when these ioptes are used for a new
-	 * allocation.
+	 * buffers, so we only need to update the TSB.  We flush
+	 * the IOMMU here as well to prevent conflicts with the
+	 * streaming mapping deferred tlb flush scheme.
 	 */
 
+	ctx = 0;
+	if (iommu->iommu_ctxflush)
+		ctx = (iopte_val(*iopte) & IOPTE_CONTEXT) >> 47UL;
+
 	for (i = 0; i < npages; i++, iopte++)
 		iopte_val(*iopte) = IOPTE_INVALID;
 
+	if (iommu->iommu_ctxflush) {
+		pci_iommu_write(iommu->iommu_ctxflush, ctx);
+	} else {
+		for (i = 0; i < npages; i++) {
+			u32 daddr = dvma + (i << PAGE_SHIFT);
+
+			pci_iommu_write(iommu->iommu_flush, daddr);
+		}
+	}
+
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	order = get_order(size);
@@ -253,14 +338,6 @@
 	for (i = 0; i < npages; i++, base++, base_paddr += PAGE_SIZE)
 		iopte_val(*base) = iopte_protection | base_paddr;
 
-	/* Flush the IOMMU TLB. */
-	if (iommu->iommu_ctxflush) {
-		pci_iommu_write(iommu->iommu_ctxflush, ctx);
-	} else {
-		for (i = 0; i < npages; i++, bus_addr += PAGE_SIZE)
-			pci_iommu_write(iommu->iommu_flush, bus_addr);
-	}
-
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return ret;
@@ -294,15 +371,15 @@
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
+	/* Record the context, if any. */
+	ctx = 0;
+	if (iommu->iommu_ctxflush)
+		ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+
 	/* Step 1: Kick data out of streaming buffers if necessary. */
 	if (strbuf->strbuf_enabled) {
 		u32 vaddr = bus_addr;
 
-		/* Record the context, if any. */
-		ctx = 0;
-		if (iommu->iommu_ctxflush)
-			ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
-
 		PCI_STC_FLUSHFLAG_INIT(strbuf);
 		if (strbuf->strbuf_ctxflush &&
 		    iommu->iommu_ctxflush) {
@@ -327,10 +404,8 @@
 	/* Step 2: Clear out first TSB entry. */
 	iopte_val(*base) = IOPTE_INVALID;
 
-	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages);
-
-	/* Step 3: Ensure completion of previous PIO writes. */
-	(void) pci_iommu_read(iommu->write_complete_reg);
+	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
+			       npages, ctx);
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
@@ -415,7 +490,7 @@
 	struct pcidev_cookie *pcp;
 	struct pci_iommu *iommu;
 	struct pci_strbuf *strbuf;
-	unsigned long flags, ctx, i, npages, iopte_protection;
+	unsigned long flags, ctx, npages, iopte_protection;
 	iopte_t *base;
 	u32 dma_base;
 	struct scatterlist *sgtmp;
@@ -474,14 +549,6 @@
 	verify_sglist(sglist, nelems, base, npages);
 #endif
 
-	/* Step 6: Flush the IOMMU TLB. */
-	if (iommu->iommu_ctxflush) {
-		pci_iommu_write(iommu->iommu_ctxflush, ctx);
-	} else {
-		for (i = 0; i < npages; i++, dma_base += PAGE_SIZE)
-			pci_iommu_write(iommu->iommu_flush, dma_base);
-	}
-
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return used;
@@ -522,15 +589,15 @@
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
+	/* Record the context, if any. */
+	ctx = 0;
+	if (iommu->iommu_ctxflush)
+		ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+
 	/* Step 1: Kick data out of streaming buffers if necessary. */
 	if (strbuf->strbuf_enabled) {
 		u32 vaddr = bus_addr;
 
-		/* Record the context, if any. */
-		ctx = 0;
-		if (iommu->iommu_ctxflush)
-			ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
-
 		PCI_STC_FLUSHFLAG_INIT(strbuf);
 		if (strbuf->strbuf_ctxflush &&
 		    iommu->iommu_ctxflush) {
@@ -555,10 +622,8 @@
 	/* Step 2: Clear out first TSB entry. */
 	iopte_val(*base) = IOPTE_INVALID;
 
-	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base, npages);
-
-	/* Step 3: Ensure completion of previous PIO writes. */
-	(void) pci_iommu_read(iommu->write_complete_reg);
+	free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
+			       npages, ctx);
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.3.50/linux/arch/sparc64/kernel/pci_psycho.c	Sun Feb 20 21:12:38 2000
+++ linux/arch/sparc64/kernel/pci_psycho.c	Fri Mar 10 09:43:04 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.13 2000/02/18 13:48:54 davem Exp $
+/* $Id: pci_psycho.c,v 1.14 2000/03/10 02:42:15 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1246,11 +1246,14 @@
 	control = psycho_read(p->controller_regs + PSYCHO_IOMMU_CONTROL);
 	control |= PSYCHO_IOMMU_CTRL_DENAB;
 	psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
-	for(i = 0; i < 16; i++)
+	for(i = 0; i < 16; i++) {
+		psycho_write(p->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0);
 		psycho_write(p->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0);
+	}
 
-	control &= ~(PSYCHO_IOMMU_CTRL_DENAB);
-	psycho_write(p->controller_regs + PSYCHO_IOMMU_CONTROL, control);
+	/* Leave diag mode enabled for full-flushing done
+	 * in pci_iommu.c
+	 */
 
 	/* Using assumed page size 8K with 128K entries we need 1MB iommu page
 	 * table (128K ioptes * 8 bytes per iopte).  This is
@@ -1267,9 +1270,14 @@
 	p->iommu.dma_addr_mask = 0xffffffff;
 	memset((char *)tsbbase, 0, PAGE_SIZE << 7);
 
-	/* Make sure DMA address 0 is never returned just to allow catching
-	   of buggy drivers.  */
-	p->iommu.lowest_free[0] = 1;
+	/* We start with no consistent mappings. */
+	p->iommu.lowest_consistent_map =
+		1 << (p->iommu.page_table_sz_bits - PBM_LOGCLUSTERS);
+
+	for (i = 0; i < PBM_NCLUSTERS; i++) {
+		p->iommu.alloc_info[i].flush = 0;
+		p->iommu.alloc_info[i].next = 0;
+	}
 
 	psycho_write(p->controller_regs + PSYCHO_IOMMU_TSBBASE, __pa(tsbbase));
 
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.3.50/linux/arch/sparc64/kernel/pci_sabre.c	Sun Feb 20 21:12:38 2000
+++ linux/arch/sparc64/kernel/pci_sabre.c	Fri Mar 10 09:43:04 2000
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.14 2000/02/18 13:48:55 davem Exp $
+/* $Id: pci_sabre.c,v 1.15 2000/03/10 02:42:16 davem Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1128,11 +1128,14 @@
 	control |= SABRE_IOMMUCTRL_DENAB;
 	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
 
-	for(i = 0; i < 16; i++)
+	for(i = 0; i < 16; i++) {
+		sabre_write(p->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
 		sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
+	}
 
-	control &= ~(SABRE_IOMMUCTRL_DENAB);
-	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+	/* Leave diag mode enabled for full-flushing done
+	 * in pci_iommu.c
+	 */
 
 	tsbbase = __get_free_pages(GFP_KERNEL, order = get_order(tsbsize * 1024 * 8));
 	if (!tsbbase) {
@@ -1144,10 +1147,6 @@
 	p->iommu.dma_addr_mask = dma_mask;
 	memset((char *)tsbbase, 0, PAGE_SIZE << order);
 
-	/* Make sure DMA address 0 is never returned just to allow catching
-	   of buggy drivers.  */
-	p->iommu.lowest_free[0] = 1;
-
 	sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
 
 	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
@@ -1168,6 +1167,15 @@
 		break;
 	}
 	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+
+	/* We start with no consistent mappings. */
+	p->iommu.lowest_consistent_map =
+		1 << (p->iommu.page_table_sz_bits - PBM_LOGCLUSTERS);
+
+	for (i = 0; i < PBM_NCLUSTERS; i++) {
+		p->iommu.alloc_info[i].flush = 0;
+		p->iommu.alloc_info[i].next = 0;
+	}
 }
 
 static void __init pbm_register_toplevel_resources(struct pci_controller_info *p,
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c
--- v2.3.50/linux/arch/sparc64/kernel/sbus.c	Sun Feb 20 21:12:38 2000
+++ linux/arch/sparc64/kernel/sbus.c	Fri Mar 10 09:43:04 2000
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.9 2000/02/18 13:48:57 davem Exp $
+/* $Id: sbus.c,v 1.10 2000/03/10 07:52:08 davem Exp $
  * sbus.c: UltraSparc SBUS controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -53,13 +53,18 @@
 	 * you must increase the size of the type of
 	 * these counters.  You have been duly warned. -DaveM
 	 */
-/*0x30*/u16			lowest_free[NCLUSTERS];
+/*0x30*/struct {
+		u16	next;
+		u16	flush;
+	} alloc_info[NCLUSTERS];
+
+	/* The lowest used consistent mapping entry.  Since
+	 * we allocate consistent maps out of cluster 0 this
+	 * is relative to the beginning of closter 0.
+	 */
+/*0x50*/u32		lowest_consistent_map;
 };
 
-/* Flushing heuristics */
-#define IOMMU_DIAG_LIM	16
-#define STRBUF_DIAG_LIM	32
-
 /* Offsets from iommu_regs */
 #define SYSIO_IOMMUREG_BASE	0x2400UL
 #define IOMMU_CONTROL	(0x2400UL - 0x2400UL)	/* IOMMU control register */
@@ -73,49 +78,29 @@
 
 #define IOMMU_DRAM_VALID	(1UL << 30UL)
 
-static void __iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+static void __iommu_flushall(struct sbus_iommu *iommu)
 {
-	int hit = 0;
+	unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG;
+	int entry;
 
-	if (npages <= IOMMU_DIAG_LIM) {
-		while (npages--)
-			upa_writeq(base + (npages << PAGE_SHIFT),
-				   iommu->iommu_regs + IOMMU_FLUSH);
-		hit = 1;
-	} else {
-		u32 limit = base + ((npages << PAGE_SHIFT) - 1UL);
-		unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG;
-		unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG;
-		int entry;
+	for (entry = 0; entry < 16; entry++) {
+		upa_writeq(0, tag);
+		tag += 8UL;
+	}
+	upa_readq(iommu->sbus_control_reg);
 
-		for (entry = 0; entry < 16; entry++, dram += 8, tag += 8) {
-			u32 addr = ((u32)upa_readq(tag) << PAGE_SHIFT);
-			if (addr >= base && addr <= limit) {
-				u64 val = upa_readq(dram);
-
-				if (val & IOMMU_DRAM_VALID) {
-					upa_writeq(addr,
-						   iommu->iommu_regs + IOMMU_FLUSH);
-					hit = 1;
-				}
-			}
-		}
+	for (entry = 0; entry < NCLUSTERS; entry++) {
+		iommu->alloc_info[entry].flush =
+			iommu->alloc_info[entry].next;
 	}
-	if (hit != 0)
-		upa_readq(iommu->sbus_control_reg);
 }
 
-/* In an effort to keep latency under control, we special
- * case single page IOMMU flushes.
- */
-static __inline__ void iommu_flush(struct sbus_iommu *iommu,
-				   u32 base, unsigned long npages)
+static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
 {
-	if (npages == 1) {
-		upa_writeq(base, iommu->iommu_regs + IOMMU_FLUSH);
-		upa_readq(iommu->sbus_control_reg);
-	} else
-		__iommu_flush(iommu, base, npages);
+	while (npages--)
+		upa_writeq(base + (npages << PAGE_SHIFT),
+			   iommu->iommu_regs + IOMMU_FLUSH);
+	upa_readq(iommu->sbus_control_reg);
 }
 
 /* Offsets from strbuf_regs */
@@ -132,65 +117,57 @@
 
 static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
 {
-	int hit = 0;
-
 	iommu->strbuf_flushflag = 0UL;
-	if (npages <= STRBUF_DIAG_LIM) {
-		while (npages--)
-			upa_writeq(base + (npages << PAGE_SHIFT),
-				   iommu->strbuf_regs + STRBUF_PFLUSH);
-		hit = 1;
-	} else {
-		u32 limit = base + ((npages << PAGE_SHIFT) - 1UL);
-		unsigned long tag = iommu->strbuf_regs + STRBUF_PTAGDIAG;
-		int entry;
-
-		for (entry = 0; entry < 16; entry++, tag += 8) {
-			u64 val = upa_readq(tag);
-
-			if (val & STRBUF_TAG_VALID) {
-				u32 addr = ((u32)(val & ~3UL)) << (PAGE_SHIFT - 2UL);
-				if (addr >= base && addr <= limit) {
-					upa_writeq(addr,
-						   iommu->strbuf_regs + STRBUF_PFLUSH);
-					hit = 1;
-				}
-			}
-		}
-	}
-	if (hit != 0) {
-		/* Whoopee cushion! */
-		upa_writeq(__pa(&iommu->strbuf_flushflag),
-			   iommu->strbuf_regs + STRBUF_FSYNC);
-		upa_readq(iommu->sbus_control_reg);
-		while (iommu->strbuf_flushflag == 0UL)
-			membar("#LoadLoad");
-	}
+	while (npages--)
+		upa_writeq(base + (npages << PAGE_SHIFT),
+			   iommu->strbuf_regs + STRBUF_PFLUSH);
+
+	/* Whoopee cushion! */
+	upa_writeq(__pa(&iommu->strbuf_flushflag),
+		   iommu->strbuf_regs + STRBUF_FSYNC);
+	upa_readq(iommu->sbus_control_reg);
+	while (iommu->strbuf_flushflag == 0UL)
+		membar("#LoadLoad");
 }
 
 static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
 {
-	iopte_t *iopte;
-	unsigned long cnum, ent;
+	iopte_t *iopte, *limit;
+	unsigned long cnum, ent, flush_point;
 
 	cnum = 0;
 	while ((1UL << cnum) < npages)
 		cnum++;
 	iopte  = iommu->page_table + (cnum * CLUSTER_NPAGES);
-	iopte += ((ent = iommu->lowest_free[cnum]) << cnum);
-
-	if (iopte_val(iopte[(1UL << cnum)]) == 0UL) {
-		/* Fast path. */
-		iommu->lowest_free[cnum] = ent + 1;
-	} else {
-		unsigned long pte_off = 1;
 
-		ent += 1;
-		do {
-			pte_off++;
-			ent++;
-		} while (iopte_val(iopte[(pte_off << cnum)]) != 0UL);
-		iommu->lowest_free[cnum] = ent;
+	if (cnum == 0)
+		limit = (iommu->page_table +
+			 iommu->lowest_consistent_map);
+	else
+		limit = (iopte + CLUSTER_NPAGES);
+
+	iopte += ((ent = iommu->alloc_info[cnum].next) << cnum);
+	flush_point = iommu->alloc_info[cnum].flush;
+
+	for (;;) {
+		if (iopte_val(*iopte) == 0UL) {
+			if ((iopte + (1 << cnum)) >= limit)
+				ent = 0;
+			else
+				ent = ent + 1;
+			iommu->alloc_info[cnum].next = ent;
+			if (ent == flush_point)
+				__iommu_flushall(iommu);
+			break;
+		}
+		iopte += (1 << cnum);
+		ent++;
+		if (iopte >= limit) {
+			iopte = (iommu->page_table + (cnum * CLUSTER_NPAGES));
+			ent = 0;
+		}
+		if (ent == flush_point)
+			__iommu_flushall(iommu);
 	}
 
 	/* I've got your streaming cluster right here buddy boy... */
@@ -208,8 +185,15 @@
 	ent = (base & CLUSTER_MASK) >> (PAGE_SHIFT + cnum);
 	iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT);
 	iopte_val(*iopte) = 0UL;
-	if (ent < iommu->lowest_free[cnum])
-		iommu->lowest_free[cnum] = ent;
+
+	/* If the global flush might not have caught this entry,
+	 * adjust the flush point such that we will flush before
+	 * ever trying to reuse it.
+	 */
+#define between(X,Y,Z)	(((Z) - (Y)) >= ((X) - (Y)))
+	if (between(ent, iommu->alloc_info[cnum].next, iommu->alloc_info[cnum].flush))
+		iommu->alloc_info[cnum].flush = ent;
+#undef between
 }
 
 /* We allocate consistent mappings from the end of cluster zero. */
@@ -228,8 +212,13 @@
 				if (iopte_val(*iopte) & IOPTE_VALID)
 					break;
 			}
-			if (tmp == 0)
+			if (tmp == 0) {
+				u32 entry = (iopte - iommu->page_table);
+
+				if (entry < iommu->lowest_consistent_map)
+					iommu->lowest_consistent_map = entry;
 				return iopte;
+			}
 		}
 	}
 	return NULL;
@@ -239,6 +228,20 @@
 {
 	iopte_t *iopte = iommu->page_table + ((base - MAP_BASE) >> PAGE_SHIFT);
 
+	if ((iopte - iommu->page_table) == iommu->lowest_consistent_map) {
+		iopte_t *walk = iopte + npages;
+		iopte_t *limit;
+
+		limit = iommu->page_table + CLUSTER_NPAGES;
+		while (walk < limit) {
+			if (iopte_val(*walk) != 0UL)
+				break;
+			walk++;
+		}
+		iommu->lowest_consistent_map =
+			(walk - iommu->page_table);
+	}
+
 	while (npages--)
 		*iopte++ = __iopte(0UL);
 }
@@ -301,6 +304,7 @@
 
 	spin_lock_irq(&iommu->lock);
 	free_consistent_cluster(iommu, dvma, npages);
+	iommu_flush(iommu, dvma, npages);
 	spin_unlock_irq(&iommu->lock);
 
 	order = get_order(size);
@@ -337,7 +341,6 @@
 		phys_base += PAGE_SIZE;
 	}
 	npages = size >> PAGE_SHIFT;
-	iommu_flush(iommu, dma_base, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return (dma_base | offset);
@@ -472,7 +475,6 @@
 #ifdef VERIFY_SG
 	verify_sglist(sg, nents, iopte, npages);
 #endif
-	iommu_flush(iommu, dma_base, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return used;
@@ -1061,9 +1063,13 @@
 
 	memset(iommu, 0, sizeof(*iommu));
 
-	/* Make sure DMA address 0 is never returned just to allow catching
-	   of buggy drivers.  */
-	iommu->lowest_free[0] = 1;
+	/* We start with no consistent mappings. */
+	iommu->lowest_consistent_map = CLUSTER_NPAGES;
+
+	for (i = 0; i < NCLUSTERS; i++) {
+		iommu->alloc_info[i].flush = 0;
+		iommu->alloc_info[i].next = 0;
+	}
 
 	/* Setup spinlock. */
 	spin_lock_init(&iommu->lock);
@@ -1110,9 +1116,12 @@
 	 */
 	for (i = 0; i < 16; i++) {
 		unsigned long dram = iommu->iommu_regs + IOMMU_DRAMDIAG;
+		unsigned long tag = iommu->iommu_regs + IOMMU_TAGDIAG;
 
 		dram += (unsigned long)i * 8UL;
+		tag += (unsigned long)i * 8UL;
 		upa_writeq(0, dram);
+		upa_writeq(0, tag);
 	}
 	upa_readq(iommu->sbus_control_reg);
 
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- v2.3.50/linux/arch/sparc64/kernel/smp.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/sparc64/kernel/smp.c	Thu Mar  9 06:57:17 2000
@@ -328,6 +328,7 @@
 	stxa	%6, [%0+%8] %3
 	membar	#Sync
 	stxa	%%g0, [%7] %3
+	membar	#Sync
 	mov	0x20, %%g1
 	ldxa	[%%g1] 0x7f, %%g0
 	membar	#Sync"
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.3.50/linux/arch/sparc64/kernel/sys_sparc32.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Thu Mar  9 06:57:17 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.133 2000/03/01 02:53:33 davem Exp $
+/* $Id: sys_sparc32.c,v 1.134 2000/03/07 22:27:30 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.3.50/linux/arch/sparc64/kernel/sys_sunos32.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Thu Mar  9 06:57:17 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.39 2000/02/16 07:31:37 davem Exp $
+/* $Id: sys_sunos32.c,v 1.40 2000/03/07 22:27:31 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.3.50/linux/arch/sparc64/mm/init.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/sparc64/mm/init.c	Thu Mar  9 06:57:17 2000
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.147 2000/03/03 23:48:44 davem Exp $
+/*  $Id: init.c,v 1.148 2000/03/07 07:08:31 anton Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -824,7 +824,7 @@
 			sp_banks[i].num_bytes;
 		if (cmdline_memory_size) {
 			if (end_of_phys_memory > cmdline_memory_size) {
-				if (cmdline_memory_size > sp_banks[i].base_addr) {
+				if (cmdline_memory_size < sp_banks[i].base_addr) {
 					end_of_phys_memory =
 						sp_banks[i-1].base_addr +
 						sp_banks[i-1].num_bytes;
diff -u --recursive --new-file v2.3.50/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c
--- v2.3.50/linux/arch/sparc64/solaris/fs.c	Fri Jan 21 18:19:16 2000
+++ linux/arch/sparc64/solaris/fs.c	Fri Mar 10 09:43:04 2000
@@ -1,4 +1,4 @@
-/* $Id: fs.c,v 1.16 2000/01/12 02:59:27 davem Exp $
+/* $Id: fs.c,v 1.17 2000/03/10 04:43:30 davem Exp $
  * fs.c: fs related syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -410,17 +410,10 @@
 static int report_statvfs(struct inode *inode, u32 buf)
 {
 	struct statfs s;
-	mm_segment_t old_fs = get_fs();
 	int error;
 	struct sol_statvfs *ss = (struct sol_statvfs *)A(buf);
 
-	if (!inode->i_sb)
-		return -ENODEV;
-	if (!inode->i_sb->s_op->statfs)
-		return -ENOSYS;
-	set_fs (KERNEL_DS);
-	error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs));
-	set_fs (old_fs);
+	error = vfs_statfs(inode->i_sb, &s);
 	if (!error) {
 		const char *p = inode->i_sb->s_type->name;
 		int i = 0;
@@ -451,17 +444,10 @@
 static int report_statvfs64(struct inode *inode, u32 buf)
 {
 	struct statfs s;
-	mm_segment_t old_fs = get_fs();
 	int error;
 	struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf);
 			
-	if (!inode->i_sb)
-		return -ENODEV;
-	if (!inode->i_sb->s_op->statfs)
-		return -ENOSYS;
-	set_fs (KERNEL_DS);
-	error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs));
-	set_fs (old_fs);
+	error = vfs_statfs(inode->i_sb, &s);
 	if (!error) {
 		const char *p = inode->i_sb->s_type->name;
 		int i = 0;
diff -u --recursive --new-file v2.3.50/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.3.50/linux/drivers/block/DAC960.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/block/DAC960.c	Thu Mar  9 07:08:50 2000
@@ -1051,20 +1051,23 @@
 	int max_segments;
 	DAC960_Controller_T * Controller = q->queuedata;
 	int total_segments = req->nr_segments + next->nr_segments;
+       int same_segment;
 
 	max_segments = Controller->MaxSegmentsPerRequest[MINOR(req->rq_dev)];
 	if (__max_segments < max_segments)
 		max_segments = __max_segments;
 
+       same_segment = 0;
 	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data)
 	{
 		total_segments--;
-		q->nr_segments--;
+               same_segment = 1;
 	}
     
 	if (total_segments > max_segments)
 		return 0;
 
+       q->nr_segments -= same_segment;
 	req->nr_segments = total_segments;
 	return 1;
 }
diff -u --recursive --new-file v2.3.50/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.3.50/linux/drivers/block/Makefile	Thu Mar  2 14:36:22 2000
+++ linux/drivers/block/Makefile	Wed Mar  8 11:40:25 2000
@@ -182,6 +182,10 @@
 IDE_OBJS += ide-pci.o
 endif
 
+ifeq ($(CONFIG_BLK_DEV_ISAPNP),y)
+IDE_OBJS += ide-pnp.o
+endif
+
 ifeq ($(CONFIG_BLK_DEV_IDE_PMAC),y)
 IDE_OBJS += ide-pmac.o
 endif
diff -u --recursive --new-file v2.3.50/linux/drivers/block/aec6210.c linux/drivers/block/aec6210.c
--- v2.3.50/linux/drivers/block/aec6210.c	Sat Feb 26 22:31:43 2000
+++ linux/drivers/block/aec6210.c	Wed Mar  8 11:40:25 2000
@@ -54,9 +54,9 @@
 
 #include "ide_modes.h"
 
-#define ACARD_DEBUG_DRIVE_INFO 1
+#define ACARD_DEBUG_DRIVE_INFO		0
 
-#define DISPLAY_AEC6210_TIMINGS
+#undef DISPLAY_AEC6210_TIMINGS
 
 #if defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS)
 #include <linux/stat.h>
diff -u --recursive --new-file v2.3.50/linux/drivers/block/cmd64x.c linux/drivers/block/cmd64x.c
--- v2.3.50/linux/drivers/block/cmd64x.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/block/cmd64x.c	Wed Mar  8 11:40:25 2000
@@ -21,8 +21,11 @@
 #include <asm/io.h>
 #include "ide_modes.h"
 
+#ifndef SPLIT_BYTE
+#define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
+#endif
+
 #define CMD_DEBUG 0
-#undef NO_WRITE
 
 #if CMD_DEBUG
 #define cmdprintk(x...)	printk(##x)
@@ -47,14 +50,25 @@
 #define ARTTIM23	0x57
 #define   ARTTIM23_DIS_RA2	0x04
 #define   ARTTIM23_DIS_RA3	0x08
+#define ARTTIM2		0x57
+#define ARTTIM3		0x57
 #define DRWTIM23	0x58
 #define DRWTIM2		0x58
 #define BRST		0x59
 #define DRWTIM3		0x5b
 
+#define BMIDECR0	0x70
 #define MRDMODE		0x71
+#define BMIDESR0	0x72
+#define UDIDETCR0	0x73
+#define DTPR0		0x74
+#define BMIDECR1	0x78
+#define BMIDECSR	0x79
+#define BMIDESR1	0x7A
+#define UDIDETCR1	0x7B
+#define DTPR1		0x7C
 
-#define DISPLAY_CMD64X_TIMINGS
+#undef DISPLAY_CMD64X_TIMINGS
 
 #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS)
 #include <linux/stat.h>
@@ -68,8 +82,11 @@
 static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
 {
 	char *p = buffer;
-	u32 bibma = bmide_dev->resource[4].start;
-	u8  c0 = 0, c1 = 0;
+	u8 reg53 = 0, reg54 = 0, reg55 = 0, reg56 = 0;	/* primary */
+	u8 reg57 = 0, reg58 = 0, reg5b;			/* secondary */
+	u8 reg72 = 0, reg73 = 0;			/* primary */
+	u8 reg7a = 0, reg7b = 0;			/* secondary */
+	u8 hi_byte = 0, lo_byte = 0;
 
 	switch(bmide_dev->device) {
 		case PCI_DEVICE_ID_CMD_648:
@@ -85,26 +102,57 @@
 			p += sprintf(p, "\n                                CMD64? Chipse.\n");
 			break;
 	}
+	(void) pci_read_config_byte(bmide_dev, ARTTIM0,   &reg53);
+	(void) pci_read_config_byte(bmide_dev, DRWTIM0,   &reg54);
+	(void) pci_read_config_byte(bmide_dev, ARTTIM1,   &reg55);
+	(void) pci_read_config_byte(bmide_dev, DRWTIM1,   &reg56);
+	(void) pci_read_config_byte(bmide_dev, ARTTIM2,   &reg57);
+	(void) pci_read_config_byte(bmide_dev, DRWTIM2,   &reg58);
+	(void) pci_read_config_byte(bmide_dev, DRWTIM3,   &reg5b);
+	(void) pci_read_config_byte(bmide_dev, BMIDESR0,  &reg72);
+	(void) pci_read_config_byte(bmide_dev, UDIDETCR0, &reg73);
+	(void) pci_read_config_byte(bmide_dev, BMIDESR1,  &reg7a);
+	(void) pci_read_config_byte(bmide_dev, UDIDETCR1, &reg7b);
 
-	/*
-	 * at that point bibma+0x2 et bibma+0xa are byte registers
-	 * to investigate:
-	 */
-	c0 = inb_p((unsigned short)bibma + 0x02);
-	c1 = inb_p((unsigned short)bibma + 0x0a);
 	p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
 	p += sprintf(p, "                %sabled                         %sabled\n",
-			(c0&0x80) ? "dis" : " en",
-			(c1&0x80) ? "dis" : " en");
+			(reg72&0x80) ? "dis" : " en", (reg7a&0x80) ? "dis" : " en");
 	p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
 	p += sprintf(p, "DMA enabled:    %s              %s             %s               %s\n",
-			(c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
-			(c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
-
-	p += sprintf(p, "UDMA\n");
-	p += sprintf(p, "DMA\n");
+			(reg72&0x20) ? "yes" : "no ", (reg72&0x40) ? "yes" : "no ", (reg7a&0x20) ? "yes" : "no ", (reg7a&0x40) ? "yes" : "no " );
+	p += sprintf(p, "UDMA enabled:   %s              %s             %s               %s\n",
+			(reg73&0x01) ? "yes" : "no ", (reg73&0x02) ? "yes" : "no ", (reg7b&0x01) ? "yes" : "no ", (reg7b&0x02) ? "yes" : "no " );
+	p += sprintf(p, "UDMA enabled:   %s                %s               %s                 %s\n",
+			(reg73&0x15) ? "4" : (reg73&0x25) ? "3" : (reg73&0x11) ? "2" : (reg73&0x21) ? "1" : (reg73&0x31) ? "0" : "X",
+			(reg73&0x4A) ? "4" : (reg73&0x8A) ? "3" : (reg73&0x42) ? "2" : (reg73&0x82) ? "1" : (reg73&0xC2) ? "0" : "X",
+			(reg7b&0x15) ? "4" : (reg7b&0x25) ? "3" : (reg7b&0x11) ? "2" : (reg7b&0x21) ? "1" : (reg7b&0x31) ? "0" : "X",
+			(reg7b&0x4A) ? "4" : (reg7b&0x8A) ? "3" : (reg7b&0x42) ? "2" : (reg7b&0x82) ? "1" : (reg7b&0xC2) ? "0" : "X" );
+	p += sprintf(p, "DMA enabled:    %s                %s               %s                 %s\n",
+			(reg73&0x10) ? "2" : (reg73&0x20) ? "1" : (reg73&0x30) ? "0" : "X",
+			(reg73&0x40) ? "2" : (reg73&0x80) ? "1" : (reg73&0xC0) ? "0" : "X",
+			(reg7b&0x10) ? "2" : (reg7b&0x20) ? "1" : (reg7b&0x30) ? "0" : "X",
+			(reg7b&0x40) ? "2" : (reg7b&0x80) ? "1" : (reg7b&0xC0) ? "0" : "X" );
 	p += sprintf(p, "PIO\n");
 
+	SPLIT_BYTE(reg53, hi_byte, lo_byte);
+	p += sprintf(p, "ARTTIM0   = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg53, hi_byte, lo_byte);
+	SPLIT_BYTE(reg54, hi_byte, lo_byte);
+	p += sprintf(p, "DRWTIM0   = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg54, hi_byte, lo_byte);
+	SPLIT_BYTE(reg55, hi_byte, lo_byte);
+	p += sprintf(p, "ARTTIM1   = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg55, hi_byte, lo_byte);
+	SPLIT_BYTE(reg56, hi_byte, lo_byte);
+	p += sprintf(p, "DRWTIM1   = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg56, hi_byte, lo_byte);
+	SPLIT_BYTE(reg57, hi_byte, lo_byte);
+	p += sprintf(p, "ARTTIM23  = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg57, hi_byte, lo_byte);
+	SPLIT_BYTE(reg58, hi_byte, lo_byte);
+	p += sprintf(p, "DRWTIM2   = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg58, hi_byte, lo_byte);
+	SPLIT_BYTE(reg5b, hi_byte, lo_byte);
+	p += sprintf(p, "DRWTIM3   = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg5b, hi_byte, lo_byte);
+	SPLIT_BYTE(reg73, hi_byte, lo_byte);
+	p += sprintf(p, "UDIDETCR0 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg73, hi_byte, lo_byte);
+	SPLIT_BYTE(reg7b, hi_byte, lo_byte);
+	p += sprintf(p, "UDIDETCR1 = 0x%02x, HI = 0x%02x, LOW = 0x%02x\n", reg7b, hi_byte, lo_byte);
+
 	return p-buffer;	/* => must be less than 4k! */
 }
 #endif	/* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */
@@ -176,12 +224,10 @@
 	 * and then the active/recovery counts into the DRWTIM reg
 	 */
 	(void) pci_read_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave], &temp_b);
-#ifndef NO_WRITE
 	(void) pci_write_config_byte(HWIF(drive)->pci_dev, arttim_regs[channel][slave],
 		((byte) setup_count) | (temp_b & 0x3f));
 	(void) pci_write_config_byte(HWIF(drive)->pci_dev, drwtim_regs[channel][slave],
 		(byte) ((active_count << 4) | recovery_count));
-#endif
 	cmdprintk ("Write %x to %x\n", ((byte) setup_count) | (temp_b & 0x3f), arttim_regs[channel][slave]);
 	cmdprintk ("Write %x to %x\n", (byte) ((active_count << 4) | recovery_count), drwtim_regs[channel][slave]);
 	__restore_flags(flags);
@@ -212,7 +258,7 @@
 			return;
 	}
 
-	(void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d);
+	mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d);
 	pio_mode = d.pio_mode;
 	cycle_time = d.cycle_time;
 
@@ -253,12 +299,84 @@
 	 */
 	program_drive_counts (drive, setup_count, active_count, recovery_count);
 
-	printk ("%s: selected cmd646 PIO mode%d (%dns)%s, clocks=%d/%d/%d\n",
-		drive->name, pio_mode, cycle_time,
+	cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, clocks=%d/%d/%d\n",
+		drive->name, pio_mode, mode_wanted, cycle_time,
 		d.overridden ? " (overriding vendor mode)" : "",
 		setup_count, active_count, recovery_count);
 }
 
+static int tune_chipset_for_dma (ide_drive_t *drive, byte speed)
+{
+#if 0
+	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);
+
+	u8 reg72 = 0, reg73 = 0;	/* primary */
+	u8 reg7a = 0, reg7b = 0;	/* secondary */
+	u8 pciU = (hwif->channel) ? UDIDETCR1 : UDIDETCR0;
+	u8 pciD = (hwif->channel) ? BMIDESR1 : BMIDESR0;
+	u8 regU = (hwif->channel) ? 2 : 0;
+	u8 regD = (hwif->channel) ? 2 : 0;
+
+	(void) pci_read_config_byte(dev, BMIDESR0,  &reg72);
+	(void) pci_read_config_byte(dev, UDIDETCR0, &reg73);
+	(void) pci_read_config_byte(dev, BMIDESR1,  &reg7a);
+	(void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
+
+	switch(speed) {
+		case XFER_UDMA_4:
+			pciU = unit ? 0x4A : 0x15;
+		case XFER_UDMA_3:
+			pciU = unit ? 0x8A : 0x25;
+		case XFER_UDMA_2:
+			pciU = unit ? 0x42 : 0x11;
+		case XFER_UDMA_1:
+			pciU = unit ? 0x82 : 0x21;
+		case XFER_UDMA_0:
+			pciU = unit ? 0xC2 : 0x31
+(reg73&0x15)?"4":(reg73&0x25)?"3":(reg73&0x11)?"2":(reg73&0x21)?"1":(reg73&0x31)?"0":"X",
+(reg73&0x4A)?"4":(reg73&0x8A)?"3":(reg73&0x42)?"2":(reg73&0x82)?"1":(reg73&0xC2)?"0":"X",
+(reg7b&0x15)?"4":(reg7b&0x25)?"3":(reg7b&0x11)?"2":(reg7b&0x21)?"1":(reg7b&0x31)?"0":"X",
+(reg7b&0x4A)?"4":(reg7b&0x8A)?"3":(reg7b&0x42)?"2":(reg7b&0x82)?"1":(reg7b&0xC2)?"0":"X",
+
+		case XFER_MW_DMA_2:
+			pciD = unit ? 0x40 : 0x10;
+		case XFER_MW_DMA_1:
+			pciD = unit ? 0x80 : 0x20;
+		case XFER_MW_DMA_0:
+			pciD = unit ? 0xC0 : 0x30;
+		case XFER_SW_DMA_2:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+(reg73&0x10)?"2":(reg73&0x20)?"1":(reg73&0x30)?"0":"X",
+(reg73&0x40)?"2":(reg73&0x80)?"1":(reg73&0xC0)?"0":"X",
+(reg7b&0x10)?"2":(reg7b&0x20)?"1":(reg7b&0x30)?"0":"X",
+(reg7b&0x40)?"2":(reg7b&0x80)?"1":(reg7b&0xC0)?"0":"X" );
+
+		default:
+			return 1;
+	}
+
+	(void) ide_config_drive_speed(drive, speed);
+	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
+#endif
+	return 0;
+}
+
+static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
+{
+	byte speed	= 0x00;
+	byte set_pio	= ide_get_best_pio_mode(drive, 4, 5, NULL);	
+
+	cmd64x_tuneproc(drive, set_pio);
+	speed = XFER_PIO_0 + set_pio;
+	if (set_speed)
+		(void) ide_config_drive_speed(drive, speed);
+}
+
 static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
 {
 	struct hd_driveid *id	= drive->id;
@@ -268,6 +386,7 @@
 
  	byte unit		= (drive->select.b.unit & 0x01);
 	byte speed		= 0x00;
+	byte set_pio		= 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;
@@ -326,9 +445,19 @@
 	} else if (id->dma_1word & 0x0001) {
 		speed = XFER_SW_DMA_0;
 	} else {
-		return ((int) ide_dma_off_quietly);
+		set_pio = 1;
 	}
 
+	config_chipset_for_pio(drive, set_pio);
+
+	if (set_pio)
+		return ((int) ide_dma_off_quietly);
+
+#if 1
+	/*
+	 * This the alternate access method. :-(
+	 * The correct method is to directly setup the pci-config space.
+	 */ 
 	(void) ide_config_drive_speed(drive, speed);
 	outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
 
@@ -343,6 +472,10 @@
 		udma_ctrl |=  (udma_timing_bits << (unit * 2));
 		outb(udma_ctrl, dma_base+3);
 	}
+#endif
+
+	if (tune_chipset_for_dma(drive, speed))
+		return ((int) ide_dma_off);
 
 	rval = (int)(	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
 			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
@@ -353,11 +486,6 @@
 	return rval;
 }
 
-static void config_chipset_for_pio (ide_drive_t *drive, unsigned int rev)
-{
-	cmd64x_tuneproc(drive, 5);
-}
-
 static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
 {
 	struct hd_driveid *id	= drive->id;
@@ -428,7 +556,7 @@
 fast_ata_pio:
 		dma_func = ide_dma_off_quietly;
 no_dma_set:
-		config_chipset_for_pio(drive, class_rev);
+		config_chipset_for_pio(drive, 1);
 	}
 	return HWIF(drive)->dmaproc(dma_func, drive);
 }
@@ -476,6 +604,11 @@
 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
 	class_rev &= 0xff;
 
+#if 0
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+#endif
+
 	switch(dev->device) {
 		case PCI_DEVICE_ID_CMD_643:
 			break;
@@ -520,18 +653,19 @@
 	 *       this point.
 	 */
 	(void) pci_write_config_byte(dev, MRDMODE, mrdmode | 0x02);
-#if 0
+
 	/* Set reasonable active/recovery/address-setup values. */
 	(void) pci_write_config_byte(dev, ARTTIM0,  0x40);
 	(void) pci_write_config_byte(dev, DRWTIM0,  0x3f);
 	(void) pci_write_config_byte(dev, ARTTIM1,  0x40);
 	(void) pci_write_config_byte(dev, DRWTIM1,  0x3f);
+#ifdef __i386__
+	(void) pci_write_config_byte(dev, ARTTIM23, 0x1c);
+#else
 	(void) pci_write_config_byte(dev, ARTTIM23, 0x5c);
+#endif
 	(void) pci_write_config_byte(dev, DRWTIM23, 0x3f);
 	(void) pci_write_config_byte(dev, DRWTIM3,  0x3f);
-#else
-	(void) pci_write_config_byte(dev, ARTTIM23, 0x1c);
-#endif
 
 #if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS)
 	cmd64x_proc = 1;
@@ -547,7 +681,7 @@
 	byte ata66 = 0;
 	byte mask = (hwif->channel) ? 0x02 : 0x01;
 
-	pci_read_config_byte(hwif->pci_dev, 0x79, &ata66);
+	pci_read_config_byte(hwif->pci_dev, BMIDECSR, &ata66);
 	return (ata66 & mask) ? 1 : 0;
 }
 
@@ -560,12 +694,11 @@
 	class_rev &= 0xff;
 
 	hwif->tuneproc = &cmd64x_tuneproc;
+	hwif->drives[0].autotune = 1;
+	hwif->drives[0].autotune = 1;
 
-	if (!hwif->dma_base) {
-		hwif->drives[0].autotune = 1;
-		hwif->drives[1].autotune = 1;
+	if (!hwif->dma_base)
 		return;
-	}
 
 	switch(dev->device) {
 		case PCI_DEVICE_ID_CMD_643:
diff -u --recursive --new-file v2.3.50/linux/drivers/block/hpt34x.c linux/drivers/block/hpt34x.c
--- v2.3.50/linux/drivers/block/hpt34x.c	Sat Feb 26 22:31:43 2000
+++ linux/drivers/block/hpt34x.c	Wed Mar  8 11:40:25 2000
@@ -46,9 +46,10 @@
 #define SPLIT_BYTE(B,H,L)	((H)=(B>>4), (L)=(B-((B>>4)<<4)))
 #endif
 
-#define HPT343_DEBUG_DRIVE_INFO		1
+#define HPT343_DEBUG_DRIVE_INFO		0
+
+#undef DISPLAY_HPT34X_TIMINGS
 
-#define DISPLAY_HPT34X_TIMINGS
 #if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS)
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.3.50/linux/drivers/block/hpt366.c linux/drivers/block/hpt366.c
--- v2.3.50/linux/drivers/block/hpt366.c	Sat Feb 26 22:31:43 2000
+++ linux/drivers/block/hpt366.c	Wed Mar  8 11:40:25 2000
@@ -30,7 +30,7 @@
 
 #include "ide_modes.h"
 
-#define DISPLAY_HPT366_TIMINGS
+#undef DISPLAY_HPT366_TIMINGS
 
 #if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS)
 #include <linux/stat.h>
@@ -241,6 +241,11 @@
 	/*
 	 * Disable on-chip PIO FIFO/buffer (to avoid problems handling I/O errors later)
 	 */
+	if (speed >= XFER_MW_DMA_0) {
+		reg2 = (reg2 & ~0xc0000000) | (reg1 & 0xc0000000);
+	} else {
+		reg2 = (reg2 & ~0x30070000) | (reg1 & 0x30070000);
+	}	
 	reg2 &= ~0x80000000;
 
 	pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
@@ -270,7 +275,6 @@
 	struct hd_driveid *id	= drive->id;
 	byte speed		= 0x00;
 	byte reg51h		= 0;
-	unsigned int reg40	= 0;
 	int  rval;
 
 	if ((id->dma_ultra & 0x0010) &&
@@ -326,13 +330,6 @@
 	if (reg51h & 0x80)
 		pci_write_config_byte(HWIF(drive)->pci_dev, 0x51, reg51h & ~0x80);
 #endif /* CONFIG_HPT366_FIP */
-
-	/*
-	 * Preserve existing PIO settings:
-	 */
-	pci_read_config_dword(HWIF(drive)->pci_dev, 0x40, &reg40);
-	speed = (speed & ~0xc0000000) | (reg40 & 0xc0000000);
-
 #if HPT366_DEBUG_DRIVE_INFO
 	printk("%s: config_chipset_for_dma:  speed=0x%04x\n", drive->name, speed);
 #endif /* HPT366_DEBUG_DRIVE_INFO */
@@ -355,7 +352,6 @@
 	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;
-	unsigned int reg40 = 0;
 
 #if HPT366_DEBUG_DRIVE_INFO
 	printk("%s: config_chipset_for_pio\n", drive->name);
@@ -389,11 +385,6 @@
 			speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
 			break;
 	}
-	/*
-	 * Preserve existing DMA settings:
-	 */
-	pci_read_config_dword(HWIF(drive)->pci_dev, 0x40, &reg40);
-	speed = (speed & ~0x30070000) | (reg40 & 0x30070000);
 #if HPT366_DEBUG_DRIVE_INFO
 	printk("%s: config_chipset_for_pio:  speed=0x%04x\n", drive->name, speed);
 #endif /* HPT366_DEBUG_DRIVE_INFO */
diff -u --recursive --new-file v2.3.50/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
--- v2.3.50/linux/drivers/block/ide-disk.c	Sat Feb 26 22:31:43 2000
+++ linux/drivers/block/ide-disk.c	Thu Mar  9 17:39:10 2000
@@ -105,8 +105,11 @@
 	 * The ATA spec tells large drives to return
 	 * C/H/S = 16383/16/63 independent of their size.
 	 * Some drives can be jumpered to use 15 heads instead of 16.
+	 * Some drives can be jumpered to use 4092 cyls instead of 16383.
 	 */
-	if (id->cyls == 16383 && id->sectors == 63 &&
+	if ((id->cyls == 16383
+	     || (id->cyls == 4092 && id->cur_cyls == 16383)) &&
+	    id->sectors == 63 &&
 	    (id->heads == 15 || id->heads == 16) &&
 	    id->lba_capacity >= 16383*63*id->heads)
 		return 1;
diff -u --recursive --new-file v2.3.50/linux/drivers/block/ide-geometry.c linux/drivers/block/ide-geometry.c
--- v2.3.50/linux/drivers/block/ide-geometry.c	Fri Jan 21 18:19:16 2000
+++ linux/drivers/block/ide-geometry.c	Thu Mar  9 17:39:10 2000
@@ -2,6 +2,8 @@
  * linux/drivers/block/ide-geometry.c
  */
 #include <linux/config.h>
+
+#ifdef CONFIG_BLK_DEV_IDE
 #include <linux/ide.h>
 
 #include <asm/io.h>
@@ -60,15 +62,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;
-			drive->head  = drive->bios_head = *(BIOS+2);
-			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;
@@ -83,7 +77,7 @@
 				printk("hd%d: C/H/S=%d/%d/%d from BIOS ignored\n", unit, cyl, head, sect);
 			}
 		}
-#endif
+
 		BIOS += 16;
 	}
 #endif
@@ -98,13 +92,15 @@
 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;
+	unsigned long total;
 
 	/*
 	 * The specs say: take geometry as obtained from Identify,
 	 * compute total capacity C*H*S from that, and truncate to
 	 * 1024*255*63. Now take S=63, H the first in the sequence
 	 * 4, 8, 16, 32, 64, 128, 255 such that 63*H*1024 >= total.
+	 * [Please tell aeb@cwi.nl in case this computes a
+	 * geometry different from what OnTrack uses.]
 	 */
 	total = DRIVER(drive)->capacity(drive);
 
@@ -116,32 +112,10 @@
 		return;
 	}
 
-#if 0
 	while (63 * headp[0] * 1024 < total && headp[1] != 0)
 		 headp++;
 	*h = headp[0];
 	*c = total / (63 * headp[0]);
-#else
-	/* The code below differs in two aspects:
-	   (i) It will not produce geometries like C/H/S = 1024/64/63
-		because of the `>='. This follows OnTracks text (which
-		claims that 512 <= C <= 1023), but not OnTracks code.
-	   (ii) It starts dividing by 63, so that a rounding down occurs.
-		For example, with C=11159, H=10, S=37 we find total=4128830
-		and DM would make C=512, H=128, S=63, but we make 1024/64/63
-		if `>=' is replaced by `>'.
-	   The reason we use this code is mainly that we have done so for
-	   a long time without getting complaints.
-	*/
-
-	tracks = total / 63;
-	while (*c >= 1024) {
-		*h = *headp;
-		*c = tracks / *h;
-		if (*++headp == 0)
-			break;
-	}
-#endif
 }
 
 /*
@@ -237,3 +211,4 @@
 		       drive->bios_cyl, drive->bios_head, drive->bios_sect);
 	return ret;
 }
+#endif /* CONFIG_BLK_DEV_IDE */
diff -u --recursive --new-file v2.3.50/linux/drivers/block/ide-pnp.c linux/drivers/block/ide-pnp.c
--- v2.3.50/linux/drivers/block/ide-pnp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/ide-pnp.c	Thu Mar  9 23:31:43 2000
@@ -0,0 +1,158 @@
+/*
+ * linux/drivers/block/ide-pnp.c
+ *
+ * This file provides autodetection for ISA PnP IDE interfaces.
+ * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
+ *
+ * Copyright (C) 2000 Andrey Panin <pazke@orbita.don.sitek.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 Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+ */
+
+#include <linux/ide.h>
+#include <linux/isapnp.h>
+
+#ifndef PREPARE_FUNC
+#define PREPARE_FUNC(dev)  (dev->prepare)
+#define ACTIVATE_FUNC(dev)  (dev->activate)
+#define DEACTIVATE_FUNC(dev)  (dev->deactivate)
+#endif
+
+#define DEV_IO(dev, index) (dev->resource[index].start)
+#define DEV_IRQ(dev, index) (dev->irq_resource[index].start)
+
+#define DEV_NAME(dev) (dev->bus->name ? dev->bus->name : "ISA PnP")
+
+#define GENERIC_HD_DATA		0
+#define GENERIC_HD_ERROR	1
+#define GENERIC_HD_NSECTOR	2
+#define GENERIC_HD_SECTOR	3
+#define GENERIC_HD_LCYL		4
+#define GENERIC_HD_HCYL		5
+#define GENERIC_HD_SELECT	6
+#define GENERIC_HD_STATUS	7
+
+static int generic_ide_offsets[IDE_NR_PORTS] __initdata = {
+	GENERIC_HD_DATA, GENERIC_HD_ERROR, GENERIC_HD_NSECTOR, 
+	GENERIC_HD_SECTOR, GENERIC_HD_LCYL, GENERIC_HD_HCYL,
+	GENERIC_HD_SELECT, GENERIC_HD_STATUS, -1, -1
+};
+
+/* ISA PnP device table entry */
+struct pnp_dev_t {
+	unsigned int vendor, device;
+	int (*init_fn)(struct pci_dev *dev, int enable);
+};
+
+/* Generic initialisation function for ISA PnP IDE interface */
+static int __init pnpide_generic_init(struct pci_dev *dev, int enable)
+{
+	hw_regs_t hw;
+	int index;
+
+	if (!enable)
+		return 0;
+
+	if (!(DEV_IO(dev, 0) && DEV_IO(dev, 1) && DEV_IRQ(dev, 0)))
+		return 1;
+
+	ide_setup_ports(&hw, (ide_ioreg_t) DEV_IO(dev, 0),
+			generic_ide_offsets, (ide_ioreg_t) DEV_IO(dev, 1),
+			0, NULL, DEV_IRQ(dev, 0));
+
+	index = ide_register_hw(&hw, NULL);
+
+	if (index != -1) {
+	    	printk("ide%d: %s IDE interface\n", index, DEV_NAME(dev));
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Add your devices here :)) */
+struct pnp_dev_t idepnp_devices[] __initdata = {
+	/* Generic ESDI/IDE/ATA compatible hard disk controller
 */
+	{	ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0600),
+		pnpide_generic_init },
+	{	0 }
+};
+
+#ifdef MODULE
+#define NR_PNP_DEVICES 8
+struct pnp_dev_inst {
+	struct pci_dev *dev;
+	struct pnp_dev_t *dev_type;
+};
+static struct pnp_dev_inst devices[NR_PNP_DEVICES];
+static int pnp_ide_dev_idx = 0;
+#endif
+
+/*
+ * Probe for ISA PnP IDE interfaces.
+ */
+void pnpide_init(int enable)
+{
+	struct pci_dev *dev = NULL;
+	struct pnp_dev_t *dev_type;
+
+	if (!isapnp_present())
+		return;
+
+#ifdef MODULE
+	/* Module unload, deactivate all registered devices. */
+	if (!enable) {
+		int i;
+		for (i = 0; i < pnp_ide_dev_idx; i++) {
+			devices[i].dev_type->init_fn(dev, 0);
+
+			if (DEACTIVATE_FUNC(devices[i].dev))
+				DEACTIVATE_FUNC(devices[i].dev)(devices[i].dev);
+		}
+		return;
+	}
+#endif
+	for (dev_type = idepnp_devices; dev_type->vendor; dev_type++) {
+		while ((dev = isapnp_find_dev(NULL, dev_type->vendor,
+			dev_type->device, dev))) {
+
+			if (dev->active)
+				continue;
+
+       			if (PREPARE_FUNC(dev) && (PREPARE_FUNC(dev))(dev) < 0) {
+				printk("ide: %s prepare failed\n", DEV_NAME(dev));
+				continue;
+			}
+
+			if (ACTIVATE_FUNC(dev) && (ACTIVATE_FUNC(dev))(dev) < 0) {
+				printk("ide: %s activate failed\n", DEV_NAME(dev));
+				continue;
+			}
+
+			/* Call device initialization function */
+			if (dev_type->init_fn(dev, 1)) {
+				if (DEACTIVATE_FUNC(dev))
+					DEACTIVATE_FUNC(dev)(dev);
+			} else {
+#ifdef MODULE
+				/*
+				 * Register device in the array to
+				 * deactivate it on a module unload.
+				 */
+				if (pnp_ide_dev_idx >= NR_PNP_DEVICES)
+					return;
+				devices[pnp_ide_dev_idx].dev = dev;
+				devices[pnp_ide_dev_idx].dev_type = dev_type;
+				pnp_ide_dev_idx++;
+#endif
+			}
+		}
+	}
+}
diff -u --recursive --new-file v2.3.50/linux/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
--- v2.3.50/linux/drivers/block/ide-probe.c	Tue Mar  7 14:32:25 2000
+++ linux/drivers/block/ide-probe.c	Wed Mar  8 11:40:25 2000
@@ -404,6 +404,7 @@
 {
 	int region_errors = 0;
 
+	hwif->straight8 = 0;
 	region_errors  = ide_check_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
 	region_errors += ide_check_region(hwif->io_ports[IDE_ERROR_OFFSET], 1);
 	region_errors += ide_check_region(hwif->io_ports[IDE_NSECTOR_OFFSET], 1);
@@ -412,16 +413,28 @@
 	region_errors += ide_check_region(hwif->io_ports[IDE_HCYL_OFFSET], 1);
 	region_errors += ide_check_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
 	region_errors += ide_check_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
+
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
 		region_errors += ide_check_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
+
 	if (hwif->io_ports[IDE_IRQ_OFFSET])
 		region_errors += ide_check_region(hwif->io_ports[IDE_IRQ_OFFSET], 1);
 
+	/*
+	 * If any errors are return, we drop the hwif interface.
+	 */
 	return(region_errors);
 }
 
 static void hwif_register (ide_hwif_t *hwif)
 {
+	if ((hwif->io_ports[IDE_DATA_OFFSET] | 7) ==
+	    (hwif->io_ports[IDE_STATUS_OFFSET])) {
+		ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name);
+		hwif->straight8 = 1;
+		goto jump_straight8;
+	}
+
 	if (hwif->io_ports[IDE_DATA_OFFSET])
 		ide_request_region(hwif->io_ports[IDE_DATA_OFFSET], 1, hwif->name);
 	if (hwif->io_ports[IDE_ERROR_OFFSET])
@@ -438,6 +451,8 @@
 		ide_request_region(hwif->io_ports[IDE_SELECT_OFFSET], 1, hwif->name);
 	if (hwif->io_ports[IDE_STATUS_OFFSET])
 		ide_request_region(hwif->io_ports[IDE_STATUS_OFFSET], 1, hwif->name);
+
+jump_straight8:
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
 		ide_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);
 	if (hwif->io_ports[IDE_IRQ_OFFSET])
diff -u --recursive --new-file v2.3.50/linux/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
--- v2.3.50/linux/drivers/block/ide-proc.c	Tue Mar  7 14:32:25 2000
+++ linux/drivers/block/ide-proc.c	Thu Mar  9 17:39:10 2000
@@ -51,7 +51,7 @@
  * be updated someday soon to use this mechanism.
  *
  * Feel free to develop and distribute fancy GUI configuration
- * utilities for you favorite PCI chipsets.  I'll be working on
+ * utilities for your favorite PCI chipsets.  I'll be working on
  * one for the Promise 20246 someday soon.  -ml
  *
  */
@@ -798,7 +798,7 @@
 
 	create_proc_ide_interfaces();
 
-	create_proc_read_entry("drivers",0,proc_ide_root,
+	create_proc_read_entry("drivers", 0, proc_ide_root,
 				proc_ide_read_drivers, NULL);
 
 #ifdef CONFIG_BLK_DEV_AEC6210
@@ -823,11 +823,11 @@
 #endif /* CONFIG_BLK_DEV_CS5530 */
 #ifdef CONFIG_BLK_DEV_HPT34X
 	if ((hpt34x_display_info) && (hpt34x_proc))
-		create_proc_info_entry("", 0, proc_ide_root, hpt34x_display_info);
+		create_proc_info_entry("hpt34x", 0, proc_ide_root, hpt34x_display_info);
 #endif /* CONFIG_BLK_DEV_HPT34X */
 #ifdef CONFIG_BLK_DEV_HPT366
 	if ((hpt366_display_info) && (hpt366_proc))
-		create_proc_info_entry("", 0, proc_ide_root, hpt366_display_info);
+		create_proc_info_entry("hpt366", 0, proc_ide_root, hpt366_display_info);
 #endif /* CONFIG_BLK_DEV_HPT366 */
 #ifdef CONFIG_BLK_DEV_PDC202XX
 	if ((pdc202xx_display_info) && (pdc202xx_proc))
diff -u --recursive --new-file v2.3.50/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.3.50/linux/drivers/block/ide.c	Tue Mar  7 14:32:25 2000
+++ linux/drivers/block/ide.c	Wed Mar  8 11:40:25 2000
@@ -161,18 +161,14 @@
 extern byte fifoconfig;		/* defined in via82cxxx.c used by ide_setup() */
 #endif /* CONFIG_BLK_DEV_VIA82CXXX */
 
-static const byte	ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
-						IDE2_MAJOR, IDE3_MAJOR,
-						IDE4_MAJOR, IDE5_MAJOR,
-						IDE6_MAJOR, IDE7_MAJOR,
-						IDE8_MAJOR, IDE9_MAJOR };
+static const byte ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR };
 
-static int	idebus_parameter; /* holds the "idebus=" parameter */
-static int	system_bus_speed; /* holds what we think is VESA/PCI bus speed */
+static int	idebus_parameter = 0; /* holds the "idebus=" parameter */
+static int	system_bus_speed = 0; /* 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!! */
+static int	ide_scan_direction = 0;	/* THIS was formerly 2.2.x pci=reverse */
 #endif /* CONFIG_BLK_DEV_IDEPCI */
 
 #if defined(__mc68000__) || defined(CONFIG_APUS)
@@ -186,8 +182,8 @@
 /*
  * ide_modules keeps track of the available IDE chipset/probe/driver modules.
  */
-ide_module_t *ide_modules = NULL;
-ide_module_t *ide_probe = NULL;
+ide_module_t *ide_modules	= NULL;
+ide_module_t *ide_probe		= NULL;
 
 /*
  * This is declared extern in ide.h, for access by other IDE modules:
@@ -1922,6 +1918,10 @@
  */
 void hwif_unregister (ide_hwif_t *hwif)
 {
+	if (hwif->straight8) {
+		ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 8);
+		goto jump_eight;
+	}
 	if (hwif->io_ports[IDE_DATA_OFFSET])
 		ide_release_region(hwif->io_ports[IDE_DATA_OFFSET], 1);
 	if (hwif->io_ports[IDE_ERROR_OFFSET])
@@ -1938,6 +1938,7 @@
 		ide_release_region(hwif->io_ports[IDE_SELECT_OFFSET], 1);
 	if (hwif->io_ports[IDE_STATUS_OFFSET])
 		ide_release_region(hwif->io_ports[IDE_STATUS_OFFSET], 1);
+jump_eight:
 	if (hwif->io_ports[IDE_CONTROL_OFFSET])
 		ide_release_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1);
 	if (hwif->io_ports[IDE_IRQ_OFFSET])
@@ -2102,6 +2103,7 @@
 	hwif->pci_dev		= old_hwif.pci_dev;
 	hwif->pci_devid		= old_hwif.pci_devid;
 #endif /* CONFIG_BLK_DEV_IDEPCI */
+	hwif->straight8		= old_hwif.straight8;
 
 abort:
 	restore_flags(flags);	/* all CPUs */
@@ -2535,6 +2537,11 @@
 			err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
 
 			if (!err && set_transfer(drive, args[0], args[1], args[2])) {
+#if 0
+				/* active-retuning-calls future */
+				if (HWIF(drive)->tune2proc)
+					HWIF(drive)->tune2proc(drive, args[1]);
+#endif
 				ide_driveid_update(drive);
 			}
 		abort:
@@ -2796,6 +2803,7 @@
 	const char max_hwif  = '0' + (MAX_HWIFS - 1);
 
 	printk("ide_setup: %s", s);
+	init_ide_data ();
 
 #ifdef CONFIG_BLK_DEV_IDEDOUBLER
 	if (!strcmp(s, "ide=doubler")) {
@@ -2815,10 +2823,6 @@
 	}
 #endif /* CONFIG_BLK_DEV_IDEPCI */
 
-#ifndef CONFIG_BLK_DEV_IDEPCI
-	init_ide_data ();
-#endif /* CONFIG_BLK_DEV_IDEPCI */
-
 	/*
 	 * Look for drive options:  "hdx="
 	 */
@@ -2971,9 +2975,9 @@
 	if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') {
 		if (match_parm(&s[6], NULL, vals, 1) != 1)
 			goto bad_option;
-		if (vals[0] >= 20 && vals[0] <= 66)
+		if (vals[0] >= 20 && vals[0] <= 66) {
 			idebus_parameter = vals[0];
-		else
+		} else
 			printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
 		goto done;
 	}
@@ -3216,6 +3220,12 @@
 		buddha_init();
 	}
 #endif /* CONFIG_BLK_DEV_BUDDHA */
+#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP)
+	{
+		extern void pnpide_init(int enable);
+		pnpide_init(1);
+	}
+#endif /* CONFIG_BLK_DEV_ISAPNP */
 }
 
 void __init ide_init_builtin_drivers (void)
@@ -3407,6 +3417,9 @@
 		restore_flags(flags);	/* all CPUs */
 		return 1;
 	}
+#if defined(CONFIG_BLK_DEV_ISAPNP) && defined(CONFIG_ISAPNP) && defined(MODULE)
+	pnpide_init(0);
+#endif /* CONFIG_BLK_DEV_ISAPNP */
 #ifdef CONFIG_PROC_FS
 	ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
 	ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
@@ -3550,6 +3563,7 @@
 	if (!banner_printed) {
 		printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
 		ide_devfs_handle = devfs_mk_dir (NULL, "ide", 3, NULL);
+		(void) ide_system_bus_speed();
 		banner_printed = 1;
 	}
 
@@ -3578,6 +3592,7 @@
  		if ((next = strchr(line,' ')) != NULL)
 			*next++ = 0;
 		if (!strncmp(line,"ide",3) ||
+		    !strncmp(line,"idebus",6) ||
 #ifdef CONFIG_BLK_DEV_VIA82CXXX
 		    !strncmp(line,"splitfifo",9) ||
 #endif /* CONFIG_BLK_DEV_VIA82CXXX */
diff -u --recursive --new-file v2.3.50/linux/drivers/block/ide_modes.h linux/drivers/block/ide_modes.h
--- v2.3.50/linux/drivers/block/ide_modes.h	Sat Feb 26 22:31:44 2000
+++ linux/drivers/block/ide_modes.h	Fri Mar 10 14:31:31 2000
@@ -197,6 +197,10 @@
 			}
 		}
 
+#if 0
+		if (drive->id->major_rev_num & 0x0004) printf("ATA-2 ");
+#endif
+
 		/*
 		 * Conservative "downgrade" for all pre-ATA2 drives
 		 */
diff -u --recursive --new-file v2.3.50/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.3.50/linux/drivers/block/ll_rw_blk.c	Sat Feb 26 22:31:44 2000
+++ linux/drivers/block/ll_rw_blk.c	Thu Mar  9 07:08:50 2000
@@ -212,15 +212,18 @@
 				struct request *next, int max_segments)
 {
 	int total_segments = req->nr_segments + next->nr_segments;
+       int same_segment;
 
+       same_segment = 0;
 	if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) {
 		total_segments--;
-		q->nr_segments--;
+               same_segment = 1;
 	}
     
 	if (total_segments > max_segments)
 		return 0;
 
+       q->nr_segments -= same_segment;
 	req->nr_segments = total_segments;
 	return 1;
 }
@@ -472,14 +475,8 @@
 	int sequence = elevator_sequence(&q->elevator, latency);
 	if (after)
 		sequence -= req->nr_segments;
-	if (elevator_sequence_before(sequence, req->elevator_sequence)) {
-		if (!after)
-			printk(KERN_WARNING __FUNCTION__
-			       ": req latency %d req latency %d\n",
-			       req->elevator_sequence - q->elevator.sequence,
-			       sequence - q->elevator.sequence);
+	if (elevator_sequence_before(sequence, req->elevator_sequence))
 		req->elevator_sequence = sequence;
-	}
 }
 
 static inline void elevator_queue(request_queue_t * q,
diff -u --recursive --new-file v2.3.50/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.3.50/linux/drivers/block/nbd.c	Tue Mar  7 14:32:25 2000
+++ linux/drivers/block/nbd.c	Fri Mar 10 09:44:44 2000
@@ -4,7 +4,7 @@
  * Note that you can not swap over this thing, yet. Seems to work but
  * deadlocks sometimes - you can not swap over TCP in general.
  * 
- * Copyright 1997 Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
+ * Copyright 1997-2000 Pavel Machek <pavel@ucw.cz>
  * 
  * (part of code stolen from loop.c)
  *
@@ -24,6 +24,7 @@
  *          structure with userland
  */
 
+#undef	NBD_PLUGGABLE
 #define PARANOIA
 #include <linux/major.h>
 
@@ -62,10 +63,11 @@
 static int requests_out;
 #endif
 
+static void nbd_plug_device(request_queue_t *q, kdev_t dev) { }
+
 static int nbd_open(struct inode *inode, struct file *file)
 {
 	int dev;
-	struct nbd_device *nbdev;
 
 	if (!inode)
 		return -EINVAL;
@@ -73,13 +75,7 @@
 	if (dev >= MAX_NBD)
 		return -ENODEV;
 
-	nbdev = &nbd_dev[dev];
 	nbd_dev[dev].refcnt++;
-	if (!(nbdev->flags & NBD_INITIALISED)) {
-		init_MUTEX(&nbdev->queue_lock);
-		INIT_LIST_HEAD(&nbdev->queue_head);
-		nbdev->flags |= NBD_INITIALISED;
-	}
 	MOD_INC_USE_COUNT;
 	return 0;
 }
@@ -216,12 +212,18 @@
 void nbd_do_it(struct nbd_device *lo)
 {
 	struct request *req;
+	int dequeued;
 
 	down (&lo->queue_lock);
-	while (!list_empty(&lo->queue_head)) {
+	while (1) {
+		up (&lo->queue_lock);
 		req = nbd_read_stat(lo);
-		if (!req)
+		down (&lo->queue_lock);
+
+		if (!req) {
+			printk(KERN_ALERT "req should never be null\n" );
 			goto out;
+		}
 #ifdef PARANOIA
 		if (req != blkdev_entry_prev_request(&lo->queue_head)) {
 			printk(KERN_ALERT "NBD: I have problem...\n");
@@ -238,9 +240,11 @@
 		list_del(&req->queue);
 		up (&lo->queue_lock);
 		
-		nbd_end_request(req);
+		dequeued = nbd_end_request(req);
 
 		down (&lo->queue_lock);
+		if (!dequeued)
+			list_add(&req->queue, &lo->queue_head);
 	}
  out:
 	up (&lo->queue_lock);
@@ -249,26 +253,36 @@
 void nbd_clear_que(struct nbd_device *lo)
 {
 	struct request *req;
+	int dequeued;
+
+#ifdef PARANOIA
+	if (lo->magic != LO_MAGIC) {
+		printk(KERN_ERR "NBD: nbd_dev[] corrupted: Not enough magic when clearing!\n");
+		return;
+	}
+#endif
 
 	while (!list_empty(&lo->queue_head)) {
 		req = blkdev_entry_prev_request(&lo->queue_head);
 #ifdef PARANOIA
+		if (!req) {
+			printk( KERN_ALERT "NBD: panic, panic, panic\n" );
+			break;
+		}
 		if (lo != &nbd_dev[MINOR(req->rq_dev)]) {
 			printk(KERN_ALERT "NBD: request corrupted when clearing!\n");
 			continue;
 		}
-		if (lo->magic != LO_MAGIC) {
-			printk(KERN_ERR "NBD: nbd_dev[] corrupted: Not enough magic when clearing!\n");
-			return;
-		}
 #endif
 		req->errors++;
 		list_del(&req->queue);
 		up(&lo->queue_lock);
 
-		nbd_end_request(req);
+		dequeued = nbd_end_request(req);
 
 		down(&lo->queue_lock);
+		if (!dequeued)
+			list_add(&req->queue, &lo->queue_head);
 	}
 }
 
@@ -290,6 +304,10 @@
 
 	while (!QUEUE_EMPTY) {
 		req = CURRENT;
+#ifdef PARANOIA
+		if (!req)
+			FAIL("que not empty but no request?");
+#endif
 		dev = MINOR(req->rq_dev);
 #ifdef PARANOIA
 		if (dev >= MAX_NBD)
@@ -470,12 +488,17 @@
 	blksize_size[MAJOR_NR] = nbd_blksizes;
 	blk_size[MAJOR_NR] = nbd_sizes;
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_nbd_request);
+#ifndef NBD_PLUGGABLE
+	blk_queue_pluggable(BLK_DEFAULT_QUEUE(MAJOR_NR), nbd_plug_device);
+#endif
 	blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
 	for (i = 0; i < MAX_NBD; i++) {
 		nbd_dev[i].refcnt = 0;
 		nbd_dev[i].file = NULL;
 		nbd_dev[i].magic = LO_MAGIC;
 		nbd_dev[i].flags = 0;
+		INIT_LIST_HEAD(&nbd_dev[i].queue_head);
+		init_MUTEX(&nbd_dev[i].queue_lock);
 		nbd_blksizes[i] = 1024;
 		nbd_blksize_bits[i] = 10;
 		nbd_bytesizes[i] = 0x7ffffc00; /* 2GB */
diff -u --recursive --new-file v2.3.50/linux/drivers/block/pdc202xx.c linux/drivers/block/pdc202xx.c
--- v2.3.50/linux/drivers/block/pdc202xx.c	Sat Feb 26 22:31:44 2000
+++ linux/drivers/block/pdc202xx.c	Wed Mar  8 11:40:25 2000
@@ -100,7 +100,8 @@
 #define PDC202XX_DEBUG_DRIVE_INFO		0
 #define PDC202XX_DECODE_REGISTER_INFO		0
 
-#define DISPLAY_PDC202XX_TIMINGS
+#undef DISPLAY_PDC202XX_TIMINGS
+
 #if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS)
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.3.50/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.3.50/linux/drivers/block/rd.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/block/rd.c	Thu Mar  9 07:04:49 2000
@@ -99,6 +99,7 @@
 static int rd_blocksizes[NUM_RAMDISKS];		/* Size of 1024 byte blocks :)  */
 static int rd_kbsize[NUM_RAMDISKS];		/* Size in blocks of 1024 bytes */
 static devfs_handle_t devfs_handle = NULL;
+static struct inode *rd_inode[NUM_RAMDISKS];		/* Protected device inodes */
 
 /*
  * Parameters for the boot-loading of the RAM disk.  These are set by
@@ -169,11 +170,18 @@
 	return ramdisk_size(str);
 }
 
+static int __init ramdisk_blocksize(char *str)
+{
+	rd_blocksize = simple_strtol(str,NULL,0);
+	return 1;
+}
+
 __setup("ramdisk_start=", ramdisk_start_setup);
 __setup("load_ramdisk=", load_ramdisk);
 __setup("prompt_ramdisk=", prompt_ramdisk);
 __setup("ramdisk=", ramdisk_size);
 __setup("ramdisk_size=", ramdisk_size2);
+__setup("ramdisk_blocksize=", ramdisk_blocksize);
 
 #endif
 
@@ -216,67 +224,16 @@
 		goto repeat;
 	}
 
-	/*
-	 * This has become somewhat more complicated with the addition of
-	 * the page cache.  The problem is that in some cases the furnished
-	 * buffer is "real", i.e., part of the existing ramdisk, while in
-	 * others it is "unreal", e.g., part of a page.  In the first case
-	 * not much needs to be done, while in the second, some kind of
-	 * transfer is needed.
- 	 *
-	 * The two cases are distinguished here by checking whether the
-	 * real buffer is already in the buffer cache, and whether it is
-	 * the same as the one supplied.
-	 *
-	 * There are three cases with read/write to consider:
-	 *
-	 * 1. Supplied buffer matched one in the buffer cache:
-	 *    Read - Clear the buffer, as it wasn't already valid.
-	 *    Write - Mark the buffer as "Protected".
-	 *
-	 * 2. Supplied buffer mismatched one in the buffer cache:
-	 *    Read - Copy the data from the buffer cache entry.
-	 *    Write - Copy the data to the buffer cache entry.
-	 *
-	 * 3  No buffer cache entry existed:
-	 *    Read - Clear the supplied buffer, but do not create a real
-	 *    one.
-	 *    Write - Create a real buffer, copy the data to it, and mark
-	 *    it as "Protected".
-	 *
-	 * NOTE: There seems to be some schizophrenia here - the logic
-	 * using "len" seems to assume arbitrary request lengths, while
-	 * the "protect" logic assumes a single buffer cache entry.
-	 * This seems to be left over from the ancient contiguous ramdisk
-	 * logic.
-	 */
-
 	sbh = CURRENT->bh;
-	rbh = get_hash_table(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
-	if (sbh == rbh) {
-		if (CURRENT->cmd == READ) 
-			memset(CURRENT->buffer, 1, len);
-	} else if (rbh) {
-		if (CURRENT->cmd == READ)
+	rbh = getblk(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
+	if (CURRENT->cmd == READ) {
+		if (sbh != rbh)
 			memcpy(CURRENT->buffer, rbh->b_data, rbh->b_size);
-		else
+	} else
+		if (sbh != rbh)
 			memcpy(rbh->b_data, CURRENT->buffer, rbh->b_size);
-	} else { /* !rbh */
-		if (CURRENT->cmd == READ)
-			memset(sbh->b_data, 2, len);
-		else {
-			rbh = getblk(sbh->b_dev, sbh->b_blocknr, sbh->b_size);
-			if (rbh)
-				memcpy(rbh->b_data, CURRENT->buffer,
-				    rbh->b_size);
-			else
-				BUG();	/* No buffer, what to do here? */
-		}
-	}
-	if (rbh) {
-		mark_buffer_protected(rbh);
-		brelse(rbh);
-	}
+	mark_buffer_protected(rbh);
+	brelse(rbh);
 
 	end_request(1);
 	goto repeat;
@@ -372,6 +329,14 @@
 	if (DEVICE_NR(inode->i_rdev) >= NUM_RAMDISKS)
 		return -ENXIO;
 
+	/*
+	 * Immunize device against invalidate_buffers() and prune_icache().
+	 */
+	if (rd_inode[DEVICE_NR(inode->i_rdev)] == NULL) {
+		if((rd_inode[DEVICE_NR(inode->i_rdev)] = igrab(inode)) != NULL)
+			atomic_inc(&rd_inode[DEVICE_NR(inode->i_rdev)]->i_bdev->bd_openers);
+	}
+
 	MOD_INC_USE_COUNT;
 
 	return 0;
@@ -389,24 +354,31 @@
 	ioctl:		rd_ioctl,
 };
 
+#ifdef MODULE
 /* Before freeing the module, invalidate all of the protected buffers! */
 static void __exit rd_cleanup (void)
 {
 	int i;
 
 	for (i = 0 ; i < NUM_RAMDISKS; i++) {
-		struct block_device *bdev;
-		bdev = bdget(kdev_t_to_nr(MKDEV(MAJOR_NR,i)));
-		atomic_dec(&bdev->bd_openers);
+		if (rd_inode[i]) {
+			/* withdraw invalidate_buffers() and prune_icache() immunity */
+			atomic_dec(&rd_inode[i]->i_bdev->bd_openers);
+			/* remove stale pointer to module address space */
+			rd_inode[i]->i_bdev->bd_op = NULL;
+			iput(rd_inode[i]);
+		}
 		destroy_buffers(MKDEV(MAJOR_NR, i));
 	}
 
 	devfs_unregister (devfs_handle);
 	unregister_blkdev( MAJOR_NR, "ramdisk" );
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
+	hardsect_size[MAJOR_NR] = NULL;
 	blksize_size[MAJOR_NR] = NULL;
 	blk_size[MAJOR_NR] = NULL;
 }
+#endif
 
 /* This is the registration and initialization section of the RAM disk driver */
 int __init rd_init (void)
@@ -441,21 +413,16 @@
 			       S_IFBLK | S_IRUSR | S_IWUSR, 0, 0,
 			       &fd_fops, NULL);
 
-	hardsect_size[MAJOR_NR] = rd_hardsec;		/* Size of the RAM disk blocks */
-	blksize_size[MAJOR_NR] = rd_blocksizes;		/* Avoid set_blocksize() check */
-
-	for (i = 0; i < NUM_RAMDISKS; i++) {
-		struct block_device *bdev;
+	for (i = 0; i < NUM_RAMDISKS; i++)
 		register_disk(NULL, MKDEV(MAJOR_NR,i), 1, &fd_fops, rd_size<<1);
-		bdev = bdget(kdev_t_to_nr(MKDEV(MAJOR_NR,i)));
-		atomic_inc(&bdev->bd_openers);  /* avoid invalidate_buffers() */
-	}
 
 #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
 
+	hardsect_size[MAJOR_NR] = rd_hardsec;		/* Size of the RAM disk blocks */
+	blksize_size[MAJOR_NR] = rd_blocksizes;		/* Avoid set_blocksize() check */
 	blk_size[MAJOR_NR] = rd_kbsize;			/* Size of the RAM disk in kB  */
 
 		/* rd_size is given in kB */
@@ -468,8 +435,8 @@
 
 #ifdef MODULE
 module_init(rd_init);
-#endif
 module_exit(rd_cleanup);
+#endif
 
 /* loadable module support */
 MODULE_PARM     (rd_size, "1i");
diff -u --recursive --new-file v2.3.50/linux/drivers/block/via82cxxx.c linux/drivers/block/via82cxxx.c
--- v2.3.50/linux/drivers/block/via82cxxx.c	Sat Feb 26 22:31:44 2000
+++ linux/drivers/block/via82cxxx.c	Wed Mar  8 11:40:25 2000
@@ -43,6 +43,38 @@
  *  Note that by default (if no command line is provided) and if a channel
  *  has been disabled in Bios, all the fifo is given to the active channel,
  *  and its threshold is set to 3/4.
+ *
+ *  VT82c586B
+ *
+ *    Offset 4B-48 - Drive Timing Control
+ *             | pio0 | pio1 | pio2 | pio3 | pio4
+ *    25.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20 
+ *    33.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20
+ *    37.5 MHz | 0xA9 | 0x76 | 0x76 | 0x32 | 0x21
+ *
+ *    Offset 53-50 - UltraDMA Extended Timing Control
+ *      UDMA   |  NO  |   0  |   1  |   2
+ *             | 0x03 | 0x62 | 0x61 | 0x60
+ *
+ *  VT82c596B & VT82c686A
+ *
+ *    Offset 4B-48 - Drive Timing Control
+ *             | pio0 | pio1 | pio2 | pio3 | pio4
+ *    25.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20
+ *    33.0 MHz | 0xA8 | 0x65 | 0x65 | 0x31 | 0x20
+ *    37.5 MHz | 0xDB | 0x87 | 0x87 | 0x42 | 0x31
+ *    41.5 MHz | 0xFE | 0xA8 | 0xA8 | 0x53 | 0x32
+ *
+ *    Offset 53-50 - UltraDMA Extended Timing Control
+ *      UDMA   |  NO  |   0  |   1  |   2
+ *    33.0 MHz | 0x03 | 0xE2 | 0xE1 | 0xE0
+ *    37.5 MHz | 0x03 | 0xE2 | 0xE2 | 0xE1   (1)
+ *
+ *    Offset 53-50 - UltraDMA Extended Timing Control
+ *      UDMA   |  NO  |   0  |   1  |   2  |   3  |   4
+ *    33.0 MHz |  (2) | 0xE6 | 0xE4 | 0xE2 | 0xE1 | 0xE0
+ *    37.5 MHz |  (2) | 0xE6 | 0xE6 | 0xE4 | 0xE2 | 0xE1   (1)
+ *
  */
 
 #include <linux/config.h>
@@ -76,6 +108,8 @@
 	{ "VT 82C691 Apollo Pro",	PCI_DEVICE_ID_VIA_82C691, },
 	{ "VT 82C693 Apollo Pro Plus",	PCI_DEVICE_ID_VIA_82C693, },
 	{ "Apollo MVP4",		PCI_DEVICE_ID_VIA_8501_0, },
+	{ "VT 8371",			PCI_DEVICE_ID_VIA_8371_0, },
+	{ "VT 8601",			PCI_DEVICE_ID_VIA_8601_0, },
 };
 
 #define NUM_APOLLO_ISA_CHIP_DEVICES	2
@@ -96,6 +130,8 @@
 	{ PCI_DEVICE_ID_VIA_82C691,	PCI_DEVICE_ID_VIA_82C596,	0 },
 	{ PCI_DEVICE_ID_VIA_82C693,	PCI_DEVICE_ID_VIA_82C596,	0 },
 	{ PCI_DEVICE_ID_VIA_8501_0,	PCI_DEVICE_ID_VIA_82C686,	VIA_FLAG_ATA_66 },
+	{ PCI_DEVICE_ID_VIA_8371_0,	PCI_DEVICE_ID_VIA_82C686,	VIA_FLAG_ATA_66 },
+	{ PCI_DEVICE_ID_VIA_8601_0,	PCI_DEVICE_ID_VIA_8231,		VIA_FLAG_ATA_66 },
 };
 
 #define arraysize(x)	(sizeof(x)/sizeof(*(x)))
@@ -477,6 +513,220 @@
 	return 0;
 }
 
+#ifdef CONFIG_VIA82CXXX_TUNING
+
+static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	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);
+	int drive_number	= ((hwif->channel ? 2 : 0) + unit);
+
+	byte ata2_pci		= 0x00;
+	byte ata3_pci		= 0x00;
+	byte timing		= 0x00;
+	byte ultra		= 0x00;
+	int			err;
+
+	int bus_speed		= ide_system_bus_speed();
+
+	switch(drive_number) {
+		case 0: ata2_pci = 0x48; ata3_pci = 0x50; break;
+		case 1: ata2_pci = 0x49; ata3_pci = 0x51; break;
+		case 2: ata2_pci = 0x4a; ata3_pci = 0x52; break;
+		case 3: ata2_pci = 0x4b; ata3_pci = 0x53; break;
+		default:
+			return err;
+	}
+
+	pci_read_config_byte(dev, ata2_pci, &timing);
+	pci_read_config_byte(dev, ata3_pci, &ultra);
+
+	switch(speed) {
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:
+		case XFER_MW_DMA_0:
+		case XFER_SW_DMA_2:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+		case XFER_PIO_4:
+		case XFER_PIO_3:
+		case XFER_PIO_2:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+		case XFER_PIO_SLOW:
+		default:
+			break;
+	}
+
+	pci_write_config_byte(dev, ata2_pci, timing);
+	pci_write_config_byte(dev, ata3_pci, ultra);
+
+	err = ide_config_drive_speed(drive, speed);
+
+	return(err);
+}
+
+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) via82cxxx_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) via82cxxx_tune_chipset(drive, speed);
+}
+
+static void via82cxxx_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) via82cxxx_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);
+}
+
+int via82cxxx_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 */
+}
+#endif /* CONFIG_VIA82CXXX_TUNING */
+
 unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name)
 {
 	struct pci_dev *host;
@@ -501,7 +751,7 @@
 				continue;
 
 			isa = pci_find_device (PCI_VENDOR_ID_VIA,
-					ApolloISAChipInfo[i].isa_id,
+					ApolloISAChipInfo[j].isa_id,
 					NULL);
 			if (!isa)
 				continue;
@@ -511,10 +761,10 @@
 			ata33 = 1;
 			ata66 = 0;
 
-			if (ApolloISAChipInfo[i].flags & VIA_FLAG_CHECK_REV) {
+			if (ApolloISAChipInfo[j].flags & VIA_FLAG_CHECK_REV) {
 				pci_read_config_byte(isa_dev, 0x0d, &revision);
 				ata33 = (revision >= 0x20) ? 1 : 0;
-			} else if (ApolloISAChipInfo[i].flags & VIA_FLAG_ATA_66) {
+			} else if (ApolloISAChipInfo[j].flags & VIA_FLAG_ATA_66) {
 				ata33 = 0;
 				ata66 = 1;
 			}
@@ -543,7 +793,8 @@
 void __init ide_init_via82cxxx (ide_hwif_t *hwif)
 {
 	set_via_timings(hwif);
-#if 0
+
+#ifdef CONFIG_VIA82CXXX_TUNING
 	hwif->tuneproc = &via82cxxx_tune_drive;
 	if (hwif->dma_base) {
 		hwif->dmaproc = &via82cxxx_dmaproc;
@@ -552,7 +803,7 @@
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
 	}
-#endif
+#endif /* CONFIG_VIA82CXXX_TUNING */
 }
 
 /*
diff -u --recursive --new-file v2.3.50/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.3.50/linux/drivers/char/Config.in	Tue Mar  7 14:32:25 2000
+++ linux/drivers/char/Config.in	Fri Mar 10 10:56:48 2000
@@ -140,7 +140,9 @@
 
 tristate '/dev/nvram support' CONFIG_NVRAM
 tristate 'Enhanced Real Time Clock Support' CONFIG_RTC
-bool 'EFI Real Time Clock Services' CONFIG_EFI_RTC
+if [ "$CONFIG_IA64" = "y" ]; then
+   bool 'EFI Real Time Clock Services' CONFIG_EFI_RTC
+fi
 if [ "$CONFIG_OBSOLETE" = "y" -a "$CONFIG_ALPHA_BOOK1" = "y" ]; then
    bool 'Tadpole ANA H8 Support'  CONFIG_H8
 fi
@@ -207,8 +209,8 @@
 	 dep_tristate '  QuickCam Colour Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
       fi
    fi
-   dep_tristate '  SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
-   dep_tristate '  SAB3036 tuner' CONFIG_TUNER_3036 $CONFIG_VIDEO_DEV
+   dep_tristate '  SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV $CONFIG_I2C
+   dep_tristate '  SAB3036 tuner' CONFIG_TUNER_3036 $CONFIG_VIDEO_DEV $CONFIG_I2C
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
       if [ "$CONFIG_SGI" = "y" ]; then
          dep_tristate '  SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV $CONFIG_SGI
diff -u --recursive --new-file v2.3.50/linux/drivers/char/README.epca linux/drivers/char/README.epca
--- v2.3.50/linux/drivers/char/README.epca	Thu Mar  2 14:36:22 2000
+++ linux/drivers/char/README.epca	Fri Mar 10 10:48:47 2000
@@ -523,3 +523,10 @@
 Files affected        : epca.c
 Release version       : 1.3.0.1-LK
 -----------------------------------------------------------------------
+Programmer            : Arjan van de Ven <adve@oce.nl>
+Date                  : March 10, 2000
+Description (Verbose) : Fixed includes to make it actually compile
+			for kernel 2.3.51
+Files affected        : epca.c
+Release version       : 1.3.0.2-LK
+-----------------------------------------------------------------------
diff -u --recursive --new-file v2.3.50/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.3.50/linux/drivers/char/bttv.c	Tue Mar  7 14:32:25 2000
+++ linux/drivers/char/bttv.c	Thu Mar  9 23:31:43 2000
@@ -20,7 +20,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.3.50/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c
--- v2.3.50/linux/drivers/char/dsp56k.c	Wed Feb 16 17:03:51 2000
+++ linux/drivers/char/dsp56k.c	Fri Mar 10 09:43:04 2000
@@ -1,9 +1,9 @@
 /*
  * The DSP56001 Device Driver, saviour of the Free World(tm)
  *
- * Authors: Fredrik Noring   <noring@lysator.liu.se>
- *          lars brinkhoff   <f93labr@dd.chalmers.se>
- *          Tomas Berndtsson <tobe@lysator.liu.se>
+ * Authors: Fredrik Noring   <noring@nocrew.org>
+ *          lars brinkhoff   <lars@nocrew.org>
+ *          Tomas Berndtsson <tomas@nocrew.org>
  *
  * First version May 1996
  *
diff -u --recursive --new-file v2.3.50/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.3.50/linux/drivers/char/epca.c	Tue Mar  7 14:32:25 2000
+++ linux/drivers/char/epca.c	Fri Mar 10 10:48:47 2000
@@ -38,7 +38,10 @@
 #include <linux/ctype.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
 #include <asm/uaccess.h>
+#include <asm/io.h>
 
 #ifdef CONFIG_PCI
 #define ENABLE_PCI
diff -u --recursive --new-file v2.3.50/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.3.50/linux/drivers/char/mem.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/char/mem.c	Wed Mar  8 14:00:08 2000
@@ -52,6 +52,7 @@
 #endif
 #ifdef CONFIG_FB
 extern void fbmem_init(void);
+extern void fbconsole_init(void);
 #endif
 #ifdef CONFIG_PROM_CONSOLE
 extern void prom_con_init(void);
@@ -617,6 +618,7 @@
 #endif
 #if defined (CONFIG_FB)
 	fbmem_init();
+	fbconsole_init();
 #endif
 #if defined (CONFIG_PROM_CONSOLE)
 	prom_con_init();
diff -u --recursive --new-file v2.3.50/linux/drivers/char/radio-miropcm20.c linux/drivers/char/radio-miropcm20.c
--- v2.3.50/linux/drivers/char/radio-miropcm20.c	Mon Oct  4 15:49:29 1999
+++ linux/drivers/char/radio-miropcm20.c	Fri Mar 10 10:54:10 2000
@@ -10,7 +10,7 @@
 #include <linux/init.h>			/* Initdata			*/
 #include <asm/uaccess.h>		/* copy to/from user		*/
 #include <linux/videodev.h>		/* kernel radio structs		*/
-#include "../sound/lowlevel/miroaci.h"	/* ACI Control by acimixer	*/
+#include "../sound/miroaci.h"		/* ACI Control by acimixer      */
 
 static int users = 0;
 
diff -u --recursive --new-file v2.3.50/linux/drivers/char/raw.c linux/drivers/char/raw.c
--- v2.3.50/linux/drivers/char/raw.c	Sat Feb 26 22:31:45 2000
+++ linux/drivers/char/raw.c	Thu Mar  9 21:12:27 2000
@@ -197,14 +197,17 @@
 			raw_device_bindings[minor] = 
 				bdget(kdev_t_to_nr(MKDEV(rq.block_major, rq.block_minor)));
 		} else {
+			struct block_device *bdev;
 			kdev_t dev;
-			if (!raw_device_bindings[minor]) {
-				err = -ENODEV;
-				break;
+
+			bdev = raw_device_bindings[minor];
+			if (bdev) {
+				dev = to_kdev_t(bdev->bd_dev);
+				rq.block_major = MAJOR(dev);
+				rq.block_minor = MINOR(dev);
+			} else {
+				rq.block_major = rq.block_minor = 0;
 			}
-			dev = to_kdev_t(raw_device_bindings[minor]->bd_dev);
-			rq.block_major = MAJOR(dev);
-			rq.block_minor = MINOR(dev);
 			err = copy_to_user((void *) arg, &rq, sizeof(rq));
 		}
 		break;
@@ -304,7 +307,12 @@
 		err = map_user_kiobuf(rw, iobuf, (unsigned long) buf, iosize);
 		if (err)
 			break;
-		
+#if 0
+		err = lock_kiovec(1, &iobuf, 1);
+		if (err) 
+			break;
+#endif
+	
 		for (i=0; i < blocks; i++) 
 			b[i] = blocknr++;
 		
@@ -316,7 +324,7 @@
 			buf += err;
 		}
 
-		unmap_kiobuf(iobuf);
+		unmap_kiobuf(iobuf); /* The unlock_kiobuf is implicit here */
 
 		if (err != iosize)
 			break;
diff -u --recursive --new-file v2.3.50/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.3.50/linux/drivers/net/3c509.c	Sat Feb 12 11:22:10 2000
+++ linux/drivers/net/3c509.c	Thu Mar  9 17:39:10 2000
@@ -186,8 +186,10 @@
 	{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
 	{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}
 };
-#endif
+#endif /* CONFIG_ISAPNP */
+#if defined(CONFIG_ISAPNP) || defined(MODULE)
 static int nopnp = 0;
+#endif
 
 int el3_probe(struct net_device *dev)
 {
@@ -195,8 +197,10 @@
 	int ioaddr, irq, if_port;
 	u16 phys_addr[3];
 	static int current_tag = 0;
-	static int pnp_cards = 0;
 	int mca_slot = -1;
+#ifdef CONFIG_ISAPNP
+	static int pnp_cards = 0;
+#endif
 
 	/* First check all slots of the EISA bus.  The next slot address to
 	   probe is kept in 'eisa_addr' to support multiple probe() calls. */
diff -u --recursive --new-file v2.3.50/linux/drivers/net/aironet4500.h linux/drivers/net/aironet4500.h
--- v2.3.50/linux/drivers/net/aironet4500.h	Thu Mar  2 14:36:22 2000
+++ linux/drivers/net/aironet4500.h	Fri Mar 10 09:43:04 2000
@@ -66,8 +66,8 @@
 };
 
 
-/* timeout for transmit watchdog timer */
-#define TX_TIMEOUT			(HZ * 3)
+/* timeout for transmit watchdog timer, AP default is 8 sec */
+#define AWC_TX_TIMEOUT			(HZ * 8) 
 
 
 
@@ -454,7 +454,7 @@
 };
 
 
-extern inline void
+extern  void
 awc_fid_queue_init(struct awc_fid_queue * queue){
 
 	unsigned long flags;
@@ -1429,10 +1429,10 @@
 
 
 struct awc_private {
-	dev_node_t node;
-
-
-	int dummy_test;
+	dev_node_t node; // somewhere back in times PCMCIA needed that
+	
+	int dummy_test; // left for cleanup
+	// card rid inmemory copy
 	struct awc_config 		config; // card RID mirrors
 	struct awc_config 		general_config; // 
 	struct awc_SSIDs  		SSIDs;
@@ -1452,6 +1452,7 @@
 	struct awc_wep_key		wep_nonvolatile;
 	struct awc_modulation		modulation;
 
+	// here are just references to rids
 	struct awc_rid_dir		rid_dir[AWC_NOF_RIDS];
 	int	rids_read;
 	
@@ -1493,12 +1494,14 @@
 	
 	// Command serialize stuff
 //changed to spinlock        struct semaphore 	command_semaphore;
-	my_spinlock_t		both_bap_spinlock;
+	my_spinlock_t		both_bap_spinlock; // on SMP, card should theorethically live without that
 	unsigned long		both_bap_spinlock_flags;
-	my_spinlock_t		bap_setup_spinlock;
+	my_spinlock_t		bap_setup_spinlock; // on SMP, card should theoretically live without that
 	unsigned long		bap_setup_spinlock_flags;
 	my_spinlock_t		command_issuing_spinlock;
 	unsigned long		command_issuing_spinlock_flags;
+	my_spinlock_t		interrupt_spinlock;
+
         volatile int		unlock_command_postponed;
         struct awc_command	cmd;
         long long		async_command_start;
@@ -1511,6 +1514,13 @@
 	int			p2p_uc;
 	int			p2p_found;
 	int			p802_11_send;
+	int			simple_bridge;
+	int			force_rts_on_shorter;
+	int			force_tx_rate;
+	int			ip_tos_reliability_rts;
+	int			ip_tos_troughput_no_retries;
+	int 			full_stats;
+	int 			debug;
 	
 	struct enet_statistics  stats;
 	
diff -u --recursive --new-file v2.3.50/linux/drivers/net/aironet4500_card.c linux/drivers/net/aironet4500_card.c
--- v2.3.50/linux/drivers/net/aironet4500_card.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/net/aironet4500_card.c	Fri Mar 10 09:43:04 2000
@@ -188,9 +188,8 @@
     	dev->base_addr = ioaddr;
     	dev->irq = pci_irq_line;
 	dev->tx_timeout = &awc_tx_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->watchdog_timeo = AWC_TX_TIMEOUT;
 	
-	netif_start_queue (dev);
 
 	request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT ,"Aironet 4X00",dev);
 
@@ -377,7 +376,7 @@
 	    	dev->base_addr = isa_ioaddr;
 	    	dev->irq = isa_irq_line;
 		dev->tx_timeout = &awc_tx_timeout;
-		dev->watchdog_timeo = TX_TIMEOUT;
+		dev->watchdog_timeo = AWC_TX_TIMEOUT;
 		
 		netif_start_queue (dev);
 		
@@ -498,7 +497,7 @@
 
 	if (! io[0] || ! irq[0]){
 	
-		printk("       Both irq and io params must be supplied  for ISA mode !!!\n");
+//		printk("       Both irq and io params must be supplied  for ISA mode !!!\n");
 		return -ENODEV;
 	}
 
@@ -538,10 +537,8 @@
 	    	dev->base_addr = isa_ioaddr;
 	    	dev->irq = isa_irq_line;
 		dev->tx_timeout = &awc_tx_timeout;
-		dev->watchdog_timeo = TX_TIMEOUT;
+		dev->watchdog_timeo = AWC_TX_TIMEOUT;
 		
-		netif_start_queue (dev);
-
 		request_irq(dev->irq,awc_interrupt ,SA_INTERRUPT ,"Aironet 4X00",dev);
 
 		awc_private_init( dev);
@@ -815,9 +812,8 @@
     	dev->irq = s->irq;
     	dev->base_addr = s->io;
 	dev->tx_timeout = &awc_tx_timeout;
-	dev->watchdog_timeo = TX_TIMEOUT;
+	dev->watchdog_timeo = AWC_TX_TIMEOUT;
 
-	netif_start_queue (dev);
 
 	awc_private_init( dev);
 
@@ -946,37 +942,40 @@
 		
 #ifdef CONFIG_AIRONET4500_PCI
 	if (awc4500_pci_probe(NULL) == -ENODEV){
-		printk("PCI 4X00 aironet cards not found\n");
+//		printk("PCI 4X00 aironet cards not found\n");
 	} else {
 		found++;
-		printk("PCI 4X00 found some cards \n");
+//		printk("PCI 4X00 found some cards \n");
 	}
 #endif
 #ifdef CONFIG_AIRONET4500_PNP
 	if (awc4500_pnp_probe(NULL) == -ENODEV){
-		printk("PNP 4X00 aironet cards not found\n");
+//		printk("PNP 4X00 aironet cards not found\n");
 	} else {
 		found++;
-		printk("PNP 4X00 found some cards \n");
+//		printk("PNP 4X00 found some cards \n");
 	}
 #endif
 #ifdef CONFIG_AIRONET4500_365
 	if ( awc_i365_probe() == -1) {
-		printk("PCMCIA 4X00 aironet cards not found for i365(without card services) initialization\n");
+//		printk("PCMCIA 4X00 aironet cards not found for i365(without card services) initialization\n");
 	} else {
 		 found++ ;
-		 printk("PCMCIA 4X00 found some cards, take care, this code is not supposed to work yet \n");
+//		 printk("PCMCIA 4X00 found some cards, take care, this code is not supposed to work yet \n");
 	}
 #endif
 #ifdef CONFIG_AIRONET4500_ISA
 	if (awc4500_isa_probe(NULL) == -ENODEV){
-		printk("ISA 4X00 aironet ISA-bus non-PNP-mode cards not found\n");
+//		printk("ISA 4X00 aironet ISA-bus non-PNP-mode cards not found\n");
 	} else {
 		found++;
-		printk("ISA 4X00 found some cards \n");
+//		printk("ISA 4X00 found some cards \n");
 	}
 #endif
-	if (!found) return -1;
+	if (!found) {
+		printk(KERN_ERR "No Aironet 4X00 cards were found. Note that for ISA \n cards you should use either automatic PNP mode or \n ISA mode with both io and irq param \n Aironet is also afraid of: being second PNP controller(by slot), having anything(brandname bios weirdnesses) in range 0x100-0x180 and maybe around  0xd0000\n If you PNP type card does not get found, try non-PNP switch before complainig. \n");
+		return -1;
+	}
 	return 0;
 	
 
diff -u --recursive --new-file v2.3.50/linux/drivers/net/aironet4500_core.c linux/drivers/net/aironet4500_core.c
--- v2.3.50/linux/drivers/net/aironet4500_core.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/net/aironet4500_core.c	Fri Mar 10 09:43:04 2000
@@ -15,6 +15,7 @@
  	november 99, integration with 2.3
 	17.12.99: finally, got SMP near-correct. 
 		timing issues remain- on SMP box its 15% slower on tcp	
+	10.03.00 looks like softnet take us back to normal on SMP
  */
 
 #include <linux/module.h>
@@ -36,6 +37,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include "aironet4500.h"
+#include <linux/ip.h>
 
 
 int bap_sleep = 10 ;
@@ -371,7 +373,7 @@
 
 /******************************** 	BAP	*************************/
 
-inline 
+// inline // too long for inline
 int awc_bap_setup(struct awc_command * cmd) {
 
 	int status;
@@ -1524,6 +1526,8 @@
 	rx_buff->skb = NULL;
 	rx_buff->u.rx.payload = NULL;
 	priv->stats.rx_packets++;
+	priv->stats.rx_bytes++;
+	
 	netif_rx(skb);
 	AWC_ENTRY_EXIT_DEBUG("exit\n");
 	return ;
@@ -1577,11 +1581,12 @@
 	struct awc_fid * fid = NULL;
 //	u16 saved_fid ;
 	u16 p2p_direct =priv->p2p_found;
-//	struct iphdr * ip_hdr;
+	struct iphdr * ip_hdr;
 	//buffer = skb->data;
 
 	AWC_ENTRY_EXIT_DEBUG("awc_802_11_tx_find_path_and_post");	
 
+	// netif_stop_queue(dev);
 	DOWN(&priv->tx_buff_semaphore);
 	if (len  > dev->mtu + 16 ) {
 		printk(KERN_ERR "%s packet size too large %d \n",dev->name, len);
@@ -1644,28 +1649,33 @@
 			}	
 	};
 
-	if (tx_rate == 2 || tx_rate == 4 || tx_rate== 20 || tx_rate == 22)
-		fid->u.tx.radio_tx.tx_bit_rate  = tx_rate;
+	if (priv->force_tx_rate == 2 || priv->force_tx_rate == 4 || 
+		priv->force_tx_rate== 11 || priv->force_tx_rate == 22){
+			fid->u.tx.radio_tx.tx_bit_rate  = priv->force_tx_rate;
+	} else if (priv->force_tx_rate != 0 ) {
+		printk(KERN_ERR "wrong force_tx_rate=%d changed to default \n",	priv->force_tx_rate);
+		priv->force_tx_rate = 0;
+	};
 	fid->u.tx.radio_tx.TX_Control = 
 		aironet4500_tx_control_tx_ok_event_enable |
 		aironet4500_tx_control_tx_fail_event_enable |
 		aironet4500_tx_control_no_release;
 
-/*	if (len < 100){
+	if (len < priv->force_rts_on_shorter){
 		fid->u.tx.radio_tx.TX_Control |=
 			aironet4500_tx_control_use_rts;
 	};
-*/
-/*	ip_hdr = skb->data + 14;
+
+	ip_hdr = (struct iphdr * ) ((( char * ) skb->data) + 14);
 	if (ip_hdr && skb->data[12] == 0x80 ){
-		if (ip_hdr->tos & IPTOS_RELIABILITY)
+		if (ip_hdr->tos & IPTOS_RELIABILITY && priv->ip_tos_reliability_rts)
 			fid->u.tx.radio_tx.TX_Control |=
 			    aironet4500_tx_control_use_rts;
-		if (ip_hdr->tos & IPTOS_THROUGHPUT)
+		if (ip_hdr->tos & IPTOS_THROUGHPUT && priv->ip_tos_troughput_no_retries)
 			fid->u.tx.radio_tx.TX_Control |=
 			    aironet4500_tx_control_no_retries;
 	};
-*/	
+
 	if (priv->p802_11_send ||  memcmp(dev->dev_addr, skb->data +6, 6)  ){
 		fid->u.tx.radio_tx.TX_Control |=
 			aironet4500_tx_control_header_type_802_11;	
@@ -1683,7 +1693,7 @@
 			fid->pkt_len = len -12;
 			fid->u.tx.payload = skb->data +12;
 
-			if (!memcmp(dev->dev_addr, skb->data +6, 6)){	
+			if (priv->simple_bridge){	
 				memcpy(fid->u.tx.ieee_802_11.mac1,skb->data,6);
 				memcpy(fid->u.tx.ieee_802_11.mac2,skb->data +6,6);
 				memcpy(fid->u.tx.ieee_802_11.mac3,priv->status.CurrentBssid ,6);
@@ -1691,14 +1701,12 @@
 				fid->u.tx.ieee_802_11.frame_control = 0x8;
 				fid->u.tx.ieee_802_11.gapLen=6;
 			} else {
-
 				memcpy(fid->u.tx.ieee_802_11.mac1,skb->data,6);
 				memcpy(fid->u.tx.ieee_802_11.mac2,dev->dev_addr,6);
 				memcpy(fid->u.tx.ieee_802_11.mac3,skb->data +6 ,6);
 				memset(fid->u.tx.ieee_802_11.mac4,0 ,6);
 				fid->u.tx.ieee_802_11.frame_control = 0x108;
 				fid->u.tx.ieee_802_11.gapLen=6;                 
-
 			}
 		} else { // plain old 802.3, with hdr copied
 			fid->u.tx.radio_tx.PayloadLength 	= len -12;
@@ -1745,11 +1753,20 @@
 		
 	};
 	
+	priv->stats.tx_bytes += fid->u.tx.ieee_802_3.payload_length;
+	priv->stats.tx_packets++;
 	
 	
 	awc_fid_queue_push_tail(&priv->tx_in_transmit,fid);
 	udelay(1);
 	awc_transmit_packet(dev,fid);
+	if (priv->tx_large_ready.size <= 2 || priv->tx_small_ready.size <= 2 ){
+		if (netif_running(dev))
+			netif_stop_queue(dev);
+	} else {
+	  	if (netif_running(dev)) 
+			netif_wake_queue(dev);
+	}
 	UP(&priv->tx_buff_semaphore);
 	AWC_ENTRY_EXIT_DEBUG("exit\n");
 	return 0;
@@ -1768,6 +1785,8 @@
   final:
 	priv->stats.tx_errors++;
 	UP(&priv->tx_buff_semaphore);
+	if (!netif_running(dev)) 
+		netif_start_queue(dev);
 	dev_kfree_skb(skb);
 	AWC_ENTRY_EXIT_DEBUG("BADExit\n");
 	return -1;
@@ -1797,7 +1816,6 @@
 		dev_kfree_skb(tx_buff->skb);
 		tx_buff->skb = NULL;
 	}
-	netif_wake_queue (dev);
 
 	AWC_ENTRY_EXIT_DEBUG("exit\n");
 };
@@ -1839,7 +1857,7 @@
 
 };
                                          
-void 
+inline void 
 awc_802_11_after_tx_complete(struct net_device * dev, struct awc_fid * tx_buff){
 
         struct awc_private * priv = (struct awc_private *)dev->priv;
@@ -1861,7 +1879,7 @@
 	}
 
 	tx_buff->busy = 0;
-	netif_wake_queue (dev);
+//	netif_wake_queue (dev);
 
 	AWC_ENTRY_EXIT_DEBUG("exit\n");
 };
@@ -2294,7 +2312,8 @@
 
 //	save_flags(flags);
 //	cli();
-//	disable_irq(dev->irq);
+	// here we need it, because on 2.3 SMP there are truly parallel irqs 	
+	disable_irq(dev->irq);
 
 	DEBUG(2," entering interrupt handler %s ",dev->name);
 
@@ -2503,14 +2522,14 @@
 
 //end_here:
 
-//	enable_irq(dev->irq);
+	enable_irq(dev->irq);
 //  	restore_flags(flags);
 
         return 0;
 
 bad_end:
         AWC_ENTRY_EXIT_DEBUG(" bad_end exit \n"); 	
-//	enable_irq(dev->irq);
+	enable_irq(dev->irq);
 //	restore_flags(flags);
 	return -1;
 
@@ -2528,16 +2547,17 @@
 static int awc_process_tx_results = 0;
 int tx_queue_len = 10;
 int tx_rate = 0;
-static int channel = 5;
+int channel = 5;
 //static int tx_full_rate = 0;
-static int max_mtu = 2312;
-static int adhoc = 0;
-static int large_buff_mem = 1700 * 10;
-static int small_buff_no	= 20;
-static int awc_full_stats = 0;
-static char SSID[33] = {0};
-static int master= 0;
-static int slave = 0;
+int max_mtu = 2312;
+int adhoc = 0;
+int large_buff_mem = 1700 * 10;
+int small_buff_no	= 20;
+int awc_full_stats = 0;
+char SSID[33] = {0};
+int master= 0;
+int slave = 0;
+int awc_simple_bridge = 0;
 // int debug =0;
 
 #if LINUX_VERSION_CODE >= 0x20100
@@ -2550,6 +2570,7 @@
 MODULE_PARM(adhoc,"i");
 MODULE_PARM(master,"i");
 MODULE_PARM(slave,"i");
+MODULE_PARM(awc_simple_bridge,"i");
 MODULE_PARM(max_mtu,"i");
 MODULE_PARM(large_buff_mem,"i");
 MODULE_PARM(small_buff_no,"i");
@@ -2572,7 +2593,7 @@
 EXPORT_SYMBOL(awc_private_init);
 EXPORT_SYMBOL(awc_tx_timeout);
 EXPORT_SYMBOL(awc_start_xmit);
-EXPORT_SYMBOL(awc_rx);
+//EXPORT_SYMBOL(awc_rx);
 EXPORT_SYMBOL(awc_interrupt);
 EXPORT_SYMBOL(awc_get_stats);
 EXPORT_SYMBOL(awc_change_mtu);
@@ -2674,7 +2695,7 @@
 		i++;
 	}
 	
-	// following MUST be consistent with awc_rids !!!
+	// following MUST be consistent with awc_rids in count and ordrering !!!
  	priv->rid_dir[0].buff = &priv->config; // card RID mirrors
 	priv->rid_dir[1].buff = &priv->SSIDs;
 	priv->rid_dir[2].buff = &priv->fixed_APs;
@@ -2726,6 +2747,7 @@
 	if (!adhoc)
 	        priv->config.OperatingMode = MODE_STA_ESS;
 //        priv->config.OperatingMode = MODE_AP;
+// Setting rates does not work with new hardware, use force_tx_rate via proc
 //	priv->config.Rates[0]	=0x82;
 //	priv->config.Rates[1]	=0x4;
 //	priv->config.Rates[2]	=tx_full_rate;
@@ -2738,7 +2760,9 @@
 	if (adhoc && master){
 		priv->config.JoinNetTimeout	= 0x1;//0 is facotry default
 	} else if (adhoc && slave){
-		priv->config.JoinNetTimeout	= 0xffff;
+		// by spec 0xffff, but, this causes immediate bad behaviour
+		// firmware behvaiour changed somehere around ver 2??
+		priv->config.JoinNetTimeout	= 0x7fff;
 	};	
 //	priv->config.AuthenticationType = 1;
 	priv->config.Stationary	=1;
@@ -2761,6 +2785,7 @@
 	// here we go, bad aironet
 	memset(&priv->SSIDs,0,sizeof(priv->SSIDs));
 
+	my_spin_lock_init(&priv->queues_lock);
         priv->SSIDs.ridLen		=0;
         if (!SSID) {
 	        priv->SSIDs.SSID[0].SSID[0] 	='a';
@@ -2839,6 +2864,7 @@
 	my_spin_lock_init(&priv->command_issuing_spinlock);
 	my_spin_lock_init(&priv->both_bap_spinlock);
 	my_spin_lock_init(&priv->bap_setup_spinlock);
+	my_spin_lock_init(&priv->interrupt_spinlock);
 	
 	priv->command_semaphore_on = 0;
 	priv->unlock_command_postponed = 0;
@@ -2877,7 +2903,12 @@
 	priv->p2p_found		=0;
 
 	priv->p802_11_send	=p802_11_send;
-	
+	priv->full_stats	= awc_full_stats;
+	priv->simple_bridge	= awc_simple_bridge;
+	priv->force_rts_on_shorter = 0;
+	priv->force_tx_rate	= tx_rate;
+	priv->ip_tos_reliability_rts = 0;
+	priv->ip_tos_troughput_no_retries = 0 ;	
 
 	priv->ejected		=0;	
 	priv->interrupt_count	=0;
@@ -2960,6 +2991,7 @@
 	struct awc_private *priv = (struct awc_private *) dev->priv;
 	struct awc_fid * fid;
 	int cnt;
+	unsigned long flags;
 
 	DEBUG (2, "%s: awc_tx_timeout \n", dev->name);
 
@@ -2969,11 +3001,11 @@
 		priv->tx_large_ready.size, priv->tx_small_ready.size);
 	priv->stats.tx_errors++;
 
-	// save_flags(flags);
-	// cli();
+	save_flags(flags);
+	cli();
 	fid = priv->tx_in_transmit.head;
 	cnt = 0;
-	while (fid) {
+	while (fid) { // removing all fids older that that
 		if (jiffies - fid->transmit_start_time > (HZ)) {
 			//      printk(KERN_ERR "%s staled tx_buff found, age %uld jiffies\n",dev->name,
 			//              jiffies - fid->transmit_start_time );
@@ -2986,14 +3018,12 @@
 		fid = fid->next;
 		if (cnt++ > 200) {
 			printk ("bbb in awc_fid_queue\n");
-			//              restore_flags(flags);
+			restore_flags(flags);
 			return;
 		};
 
 	}
-	//restore_flags(flags);
-	//debug =0x8;
-
+	restore_flags(flags);
 	dev->trans_start = jiffies;
 	netif_start_queue (dev);
 }
@@ -3002,7 +3032,7 @@
 long long last_tx_q_hack = 0;
 int direction = 1;
 
- int awc_start_xmit(struct sk_buff *skb, struct net_device *dev) {
+int awc_start_xmit(struct sk_buff *skb, struct net_device *dev) {
 
 	struct awc_private *priv = (struct awc_private *)dev->priv;
 	int retval = 0;
@@ -3021,10 +3051,10 @@
 		return -1;
 	};
 	
-	if (test_and_set_bit( 0, (void *) &priv->tx_chain_active) ) {
-		netif_start_queue (dev);
-		return 1;
-	}
+//	if (test_and_set_bit( 0, (void *) &priv->tx_chain_active) ) {
+//		netif_start_queue (dev);
+//		return 1;
+//	}
 
 	dev->trans_start = jiffies;
 	retval = awc_802_11_tx_find_path_and_post(dev,skb);
@@ -3035,7 +3065,7 @@
 	return retval;
 }
 
-int awc_rx(struct net_device *dev, struct awc_fid * rx_fid) {
+inline int awc_rx(struct net_device *dev, struct awc_fid * rx_fid) {
 
 //	struct awc_private *lp = (struct awc_private *)dev->priv;
 
@@ -3062,20 +3092,23 @@
  void awc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-//	struct awc_private *lp;
-//	unsigned long flags;
+	struct awc_private *priv;
+	unsigned long flags;
 
 //	if ((dev == NULL)) return;
 
-//	lp = (struct awc_private *)dev->priv;
+	priv = (struct awc_private *)dev->priv;
 
 
 	
 
 	DEBUG(2, "%s: awc_interrupt \n",  dev->name);
-	
+	my_spin_lock_irqsave(&priv->interrupt_spinlock, flags);	  
+
 	awc_interrupt_process(dev);
 
+	my_spin_unlock_irqrestore(&priv->interrupt_spinlock, flags);	  
+
 	return;
 }
 
@@ -3105,6 +3138,8 @@
 
 	// the very following is the very wrong very probably
 	if (awc_full_stats){
+		priv->stats.rx_bytes		= priv->statistics.HostRxBytes;
+		priv->stats.tx_bytes		= priv->statistics.HostTxBytes;
 		priv->stats.rx_fifo_errors 	= priv->statistics.RxOverrunErr ;
 		priv->stats.rx_crc_errors 	= priv->statistics.RxPlcpCrcErr + priv->statistics.RxMacCrcErr ;
 		priv->stats.rx_frame_errors 	= priv->statistics.RxPlcpFormat ;
@@ -3130,7 +3165,7 @@
 int awc_change_mtu(struct net_device *dev, int new_mtu){
 
 //	struct awc_private *priv = (struct awc_private *)dev->priv;
-//        unsigned long flags;
+        unsigned long flags;
 
        if ((new_mtu < 256 ) || (new_mtu > 2312) || (max_mtu && new_mtu > max_mtu) )
                 return -EINVAL;
@@ -3140,14 +3175,17 @@
 
 	};
 	if (dev->mtu != new_mtu) {
-//		save_flags(flags);
-//		cli();
-		awc_disable_MAC(dev);
+		save_flags(flags);
+		cli();
+		 netif_stop_queue(dev);
+		 awc_disable_MAC(dev);
+		restore_flags(flags); 
+				
 		awc_tx_dealloc(dev);
 		dev->mtu = new_mtu;
 		awc_tx_alloc(dev);
 		awc_enable_MAC(dev);
-//		restore_flags(flags);
+		netif_start_queue(dev);
 
 		printk("%s mtu has been changed to %d \n ",dev->name,dev->mtu);
 
diff -u --recursive --new-file v2.3.50/linux/drivers/net/aironet4500_proc.c linux/drivers/net/aironet4500_proc.c
--- v2.3.50/linux/drivers/net/aironet4500_proc.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/net/aironet4500_proc.c	Fri Mar 10 09:43:04 2000
@@ -43,7 +43,7 @@
 #endif
 
 
-
+#include "aironet4500.h"
 #include "aironet4500_rid.c"
 
 
@@ -247,8 +247,9 @@
 
 	DEBUG(0x20000,"awc proc int data %x \n",val);
 	
+// both of them are crazy
 //	*lenp = sizeof(int);
- 	*lenp += 1;
+// 	*lenp += 1;
  	
   	AWC_ENTRY_EXIT_DEBUG("exit");
 	return 0;
@@ -385,6 +386,18 @@
         {0}
 };
 
+ctl_table awc_driver_level_ctable[] = {
+        {1, "force_rts_on_shorter"	, NULL, sizeof(int), 0600,NULL, proc_dointvec},
+        {2, "force_tx_rate"		, NULL, sizeof(int), 0600,NULL, proc_dointvec},
+        {3, "ip_tos_reliability_rts"	, NULL, sizeof(int), 0600,NULL, proc_dointvec},
+        {4, "ip_tos_troughput_no_retries", NULL, sizeof(int), 0600,NULL, proc_dointvec},
+        {5, "debug"			, NULL, sizeof(int), 0600,NULL, proc_dointvec},
+        {6, "simple_bridge"		, NULL, sizeof(int), 0600,NULL, proc_dointvec},
+        {7, "p802_11_send"		, NULL, sizeof(int), 0600,NULL, proc_dointvec},
+        {8, "full_stats"		, NULL, sizeof(int), 0600,NULL, proc_dointvec},
+        {0}
+};
+
 ctl_table awc_root_table[] = {
         {254, "aironet4500", NULL, 0, 0555, awc_driver_proc_table},
         {0}
@@ -398,12 +411,12 @@
 int awc_proc_set_device(int device_number){
   int group =0;
   int rid = 0;
-  struct awc_priv * priv;
-
+  struct awc_private * priv;
+  ctl_table * tmp_table_ptr;
  
   AWC_ENTRY_EXIT_DEBUG("awc_proc_set_device");  
   if (!aironet4500_devices[device_number] || (awc_nof_rids <=0 )) return -1 ;
-  priv = (struct awc_priv * )aironet4500_devices[device_number]->priv;
+  priv = (struct awc_private * )aironet4500_devices[device_number]->priv;
 
   awc_rids_setup(aironet4500_devices[device_number]);
 
@@ -413,7 +426,7 @@
   awc_proc_priv[device_number].proc_table_device_root[0].ctl_name = device_number+1;
 
   awc_proc_priv[device_number].proc_table_sys_root->child = awc_proc_priv[device_number].proc_table_device_root;
-  memcpy(awc_proc_priv[device_number].proc_name,(struct awc_priv * )aironet4500_devices[device_number]->name,5);
+  memcpy(awc_proc_priv[device_number].proc_name,(struct NET_DEVICE * )aironet4500_devices[device_number]->name,5);
   awc_proc_priv[device_number].proc_name[4]=0;
  // awc_proc_priv[device_number].proc_name[3]=48+device_number;
   awc_proc_priv[device_number].proc_table_device_root[0].procname = &(awc_proc_priv[device_number].proc_name[0]);
@@ -484,6 +497,40 @@
   	group++;
 
   };
+// here are driver-level params dir  
+  	awc_proc_priv[device_number].proc_table[group].ctl_name = group +1;
+  	awc_proc_priv[device_number].proc_table[group+1].ctl_name = 0;
+  	awc_proc_priv[device_number].proc_table[group].procname = "driver-level";
+  	awc_proc_priv[device_number].proc_table[group].data	= awc_proc_buff;
+  	awc_proc_priv[device_number].proc_table[group].maxlen  = sizeof(awc_proc_buff) -1;
+  	awc_proc_priv[device_number].proc_table[group].mode	= 0600;
+  	awc_proc_priv[device_number].proc_table[group].child	= kmalloc(sizeof(awc_driver_level_ctable) , GFP_KERNEL);
+  	awc_proc_priv[device_number].proc_table[group].proc_handler = NULL;
+  	awc_proc_priv[device_number].proc_table[group].strategy = NULL;
+  	awc_proc_priv[device_number].proc_table[group].de	= NULL;
+  	awc_proc_priv[device_number].proc_table[group].extra1	= NULL;
+  	awc_proc_priv[device_number].proc_table[group].extra2	= NULL;
+  	if (!awc_proc_priv[device_number].proc_table[group].child) {
+  		awc_proc_priv[device_number].proc_table[group].ctl_name = 0;
+   		printk(KERN_CRIT "Out of memory on aironet4500_proc huge table alloc \n");
+  		return 0;
+  	}
+
+	
+	tmp_table_ptr = awc_proc_priv[device_number].proc_table[group].child;
+	memcpy(tmp_table_ptr,awc_driver_level_ctable,sizeof(awc_driver_level_ctable));
+
+
+        tmp_table_ptr[0].data = 
+         &(priv->force_rts_on_shorter);
+        tmp_table_ptr[1].data =   &priv->force_tx_rate;
+        tmp_table_ptr[2].data = (void *) &priv->ip_tos_reliability_rts;
+        tmp_table_ptr[3].data = (void *) &priv->ip_tos_troughput_no_retries;
+        tmp_table_ptr[4].data = (void *) &priv->debug;
+        tmp_table_ptr[5].data = (void *) &priv->simple_bridge;
+        tmp_table_ptr[6].data = (void *) &priv->p802_11_send;
+        tmp_table_ptr[7].data = (void *) &priv->full_stats;
+
 
 	awc_proc_priv[device_number].sysctl_header = 
 		register_sysctl_table(awc_proc_priv[device_number].proc_table_sys_root,0);
diff -u --recursive --new-file v2.3.50/linux/drivers/net/aironet4500_rid.c linux/drivers/net/aironet4500_rid.c
--- v2.3.50/linux/drivers/net/aironet4500_rid.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/net/aironet4500_rid.c	Fri Mar 10 09:43:04 2000
@@ -58,14 +58,14 @@
 #define awc_RID_gen_BasicRate_11Mbps 			{&aironet4500_RID_Select_General_Config,0x0010, 8,1,1,0,1,0xff,0x96,"BasicRate 11Mbps"}
 
 
-#define awc_RID_gen_Long_retry_limit 			{&aironet4500_RID_Select_General_Config,0x0018,16, 1,1,0,0,0,0,"Short Retry Limit"}
-#define awc_RID_gen_Short_retry_limit 			{&aironet4500_RID_Select_General_Config,0x001A,16, 1,1,0,0,0,0,"Long Retry Limit"}
-#define awc_RID_gen_Tx_MSDU_lifetime 			{&aironet4500_RID_Select_General_Config,0x001C,16, 1,1000,0,0,0,0,"TX MSDU Lifetime"}
-#define awc_RID_gen_Rx_MSDU_lifetime 			{&aironet4500_RID_Select_General_Config,0x001E,16, 1,1000,0,0,0,0,"RX MSDU Lifetime"}
-#define awc_RID_gen_Stationary 				{&aironet4500_RID_Select_General_Config,0x0020,16, 1,1,0,0,0,0,"Stationary"}
-#define awc_RID_gen_BC_MC_Ordering 			{&aironet4500_RID_Select_General_Config,0x0022,16, 1,1,0,0,0,0,"Strictly order Bcast and Mcast"}
-#define awc_RID_gen_Device_type 			{&aironet4500_RID_Select_General_Config,0x0024,16, 1,1,1,0,0xffff,0x0065,"Radio Type PC4500"}
-#define awc_RID_gen_Reserved_0x0026 			{&aironet4500_RID_Select_General_Config,0x0026, 8,10,1,0,0,0,0,"Reserved 0x0028"}
+#define awc_RID_gen_Long_retry_limit 			{&aironet4500_RID_Select_General_Config,0x0018,16, 1,1,0,0,0xffff,0,"Short Retry Limit"}
+#define awc_RID_gen_Short_retry_limit 			{&aironet4500_RID_Select_General_Config,0x001A,16, 1,1,0,0,0xffff,0,"Long Retry Limit"}
+#define awc_RID_gen_Tx_MSDU_lifetime 			{&aironet4500_RID_Select_General_Config,0x001C,16, 1,1000,0,0,0xffff,0,"TX MSDU Lifetime"}
+#define awc_RID_gen_Rx_MSDU_lifetime 			{&aironet4500_RID_Select_General_Config,0x001E,16, 1,1000,0,0,0xffff,0,"RX MSDU Lifetime"}
+#define awc_RID_gen_Stationary 				{&aironet4500_RID_Select_General_Config,0x0020,16, 1,1,0,0,0xffff,0,"Stationary"}
+#define awc_RID_gen_BC_MC_Ordering 			{&aironet4500_RID_Select_General_Config,0x0022,16, 1,1,0,0,0xffff,0,"Strictly order Bcast and Mcast"}
+#define awc_RID_gen_Device_type 			{&aironet4500_RID_Select_General_Config,0x0024,16, 1,1,1,0,0xffff,0x00,"Radio Type"}
+#define awc_RID_gen_Reserved_0x0026 			{&aironet4500_RID_Select_General_Config,0x0026, 8,10,1,0,0,0xff,0,"Reserved0x28"}
 
 
 //SCANNING/ASSOCIATING
@@ -101,7 +101,7 @@
 #define awc_RID_gen_FastListenInterval 		awc_def_gen_RID(0x0056,"FastListenInterval",	16,0xffff,0,"msek")     // 0 default    100 kus    The listen interval to be used immediately after
 #define awc_RID_gen_ListenDecay 			awc_def_gen_RID(0x0058,"ListenDecay",		16,0xffff,0,"times")	//      0 default    2Number of times to use the current listen interval
 #define awc_RID_gen_FastListenDelay 		awc_def_gen_RID(0x005A,"FastListenDelay",	16,0xffff,0,"msek")	//      0 default    200 kus    Time interval to delay before going to fast listen
-#define awc_RID_gen_Reserved0x005C 			awc_def_gen_RID(0x005C,"Reserved0x005C",	32,0,0,"")	//
+#define awc_RID_gen_Reserved0x005C 			awc_def_gen_RID(0x005C,"Reserved0x005C",	32,0xffffffff,0,"")	//
 //ADHOC (or AP) OPERATION
 #define awc_RID_gen_BeaconPeriod 			awc_def_gen_RID(0x0060,"BeaconPeriod",		16,0xffff,0,"msek")	//      0 default    100        0 selects the factory default of [~100 ms].  (kus)
 #define awc_RID_gen_AtimDuration 			awc_def_gen_RID(0x0062,"AtimDuration",		16,0xffff,0,"msek")	//      0 default    5 kus      The time period reserved for ATIMs immediately after (kus)      the beacon. 0xFFFF will disable the ATIM window; power save mode will not operate.This parameter only applies to adhoc/IBSS.
@@ -136,7 +136,7 @@
 #define awc_RID_gen_ARLThreshold 			awc_def_gen_RID(0x0090,"ARLThreshold",		16,0xffff,0,"times")	//       0 default    0xFFFF    0 selects the factory defaults. (which for now is
 #define awc_RID_gen_ARLDecay 			awc_def_gen_RID(0x0092,"ARLDecay",		16,0xffff,0,"times")	//       0 default    0xFFFF    0 selects the factory defaults. (which for now is
 #define awc_RID_gen_ARLDelay 			awc_def_gen_RID(0x0094,"ARLDelay",		16,0xffff,0,"times")	//       0 default    0xFFFF    0 selects the factory defaults. (which for now is
-#define awc_RID_gen_Unused0x0096 			awc_def_gen_RID(0x0096,"Unused",		16,0,0,"")	//
+#define awc_RID_gen_Unused0x0096 			awc_def_gen_RID(0x0096,"Reserved0x96",		16,0xffff,0,"")	//
 #define awc_RID_gen_MagicPacketAction 		awc_def_gen_RID(0x0098,"MagicPacketAction",	8,0xff,0," hell knows what")	//        0  0         0 selects no action to be taken on a magic packet and"
 #define awc_RID_gen_MagicPacketControl 		awc_def_gen_RID(0x0099,"MagicPacketControl",	8,0xff,0," hell know what")	//        0  0         0 will disable the magic packet mode command"
 
@@ -182,14 +182,14 @@
 #define awc_RID_act_BasicRate_11Mbps 			{&aironet4500_RID_Select_Active_Config,0x0010, 8,1,1,0,1,0xff,0x96,"BasicRate 11Mbps"}
 
 
-#define awc_RID_act_Long_retry_limit 		{&aironet4500_RID_Select_Active_Config,0x0018,16, 1,1,0,0,0,0,"Short Retry Limit"}
-#define awc_RID_act_Short_retry_limit 		{&aironet4500_RID_Select_Active_Config,0x001A,16, 1,1,0,0,0,0,"Long Retry Limit"}
-#define awc_RID_act_Tx_MSDU_lifetime 		{&aironet4500_RID_Select_Active_Config,0x001C,16, 1,1000,0,0,0,0,"TX MSDU Lifetime"}
-#define awc_RID_act_Rx_MSDU_lifetime 		{&aironet4500_RID_Select_Active_Config,0x001E,16, 1,1000,0,0,0,0,"RX MSDU Lifetime"}
-#define awc_RID_act_Stationary 			{&aironet4500_RID_Select_Active_Config,0x0020,16, 1,1,0,0,0,0,"Stationary"}
-#define awc_RID_act_BC_MC_Ordering 			{&aironet4500_RID_Select_Active_Config,0x0022,16, 1,1,0,0,0,0,"Strictly order Bcast and Mcast"}
+#define awc_RID_act_Long_retry_limit 		{&aironet4500_RID_Select_Active_Config,0x0018,16, 1,1,0,0,0xffff,0,"Short Retry Limit"}
+#define awc_RID_act_Short_retry_limit 		{&aironet4500_RID_Select_Active_Config,0x001A,16, 1,1,0,0,0xffff,0,"Long Retry Limit"}
+#define awc_RID_act_Tx_MSDU_lifetime 		{&aironet4500_RID_Select_Active_Config,0x001C,16, 1,1000,0,0,0xffff,0,"TX MSDU Lifetime"}
+#define awc_RID_act_Rx_MSDU_lifetime 		{&aironet4500_RID_Select_Active_Config,0x001E,16, 1,1000,0,0,0xffff,0,"RX MSDU Lifetime"}
+#define awc_RID_act_Stationary 			{&aironet4500_RID_Select_Active_Config,0x0020,16, 1,1,0,0,0xffff,0,"Stationary"}
+#define awc_RID_act_BC_MC_Ordering 			{&aironet4500_RID_Select_Active_Config,0x0022,16, 1,1,0,0,0xffff,0,"Strictly order Bcast and Mcast"}
 #define awc_RID_act_Device_type 			{&aironet4500_RID_Select_Active_Config,0x0024,16, 1,1,1,0,0xffff,0x0065,"Radio Type PC4500"}
-#define awc_RID_act_Reserved_0x0026 			{&aironet4500_RID_Select_Active_Config,0x0026, 8,10,1,0,0,0,0,"Reserved 0x0028"}
+#define awc_RID_act_Reserved_0x0026 			{&aironet4500_RID_Select_Active_Config,0x0026, 8,10,1,0,0,0xff,0,"Reserved0x28"}
 
 
 //SCANNING/ASSOCIATING
@@ -260,7 +260,7 @@
 #define awc_RID_act_ARLThreshold 		awc_def_act_RID(0x0090,"ARLThreshold",		16,0xffff,0,"times")	//       0 default    0xFFFF    0 selects the factory defaults. (which for now is
 #define awc_RID_act_ARLDecay 			awc_def_act_RID(0x0092,"ARLDecay",		16,0xffff,0,"times")	//       0 default    0xFFFF    0 selects the factory defaults. (which for now is
 #define awc_RID_act_ARLDelay 			awc_def_act_RID(0x0094,"ARLDelay",		16,0xffff,0,"times")	//       0 default    0xFFFF    0 selects the factory defaults. (which for now is
-#define awc_RID_act_Unused0x0096 		awc_def_act_RID(0x0096,"Unused",		16,0,0,"")	//
+#define awc_RID_act_Unused0x0096 		awc_def_act_RID(0x0096,"Reserved0x96",		16,0xffff,0,"")	//
 #define awc_RID_act_MagicPacketAction 		awc_def_act_RID(0x0098,"MagicPacketAction",	8,0xff,0," hell knows what")	//        0  0         0 selects no action to be taken on a magic packet and"
 #define awc_RID_act_MagicPacketControl 		awc_def_act_RID(0x0099,"MagicPacketControl",	8,0xff,0," hell know what")	//        0  0         0 will disable the magic packet mode command"
 
@@ -275,9 +275,12 @@
 #define awc_RID_SSIDlen1 			awc_def_SSID_RID(0x0002,"SSIDlen1",		16,0xffff,0,"")	//      7      The length of the SSID1 byte string.
 #define awc_RID_SSID1 				awc_def_SSID_RID(0x0004,"SSID1",		255,0,0,"")	//    "tsunami"        The identifier uniquely identifying the wireless system.
 #define awc_RID_SSIDlen2 			awc_def_SSID_RID(0x0024,"SSIDlen2",		16,0xffff,0,"")	//      0      The length of the SSID2 byte string.
-#define awc_RID_SSID2 				awc_def_SSID_RID(0x0026,"SSID2",		255,0,0,"") 	//   0's    The identifier uniquely identifying the wireless system.
+#define awc_RID_SSID2 				awc_def_SSID_RID(0x0026,"SSID2",		255,0,0,"") 	//   
 #define awc_RID_SSIDlen3 			awc_def_SSID_RID(0x0046,"SSIDlen3",		16,0xffff,0,"")	//      0      The length of the SSID3 byte string.
-#define awc_RID_SSID3 				awc_def_SSID_RID(0x0048,"SSID3",		255,0,0,"")	//    0's    The identifier uniquely identifying the wireless system.
+#define awc_RID_SSID3 				awc_def_SSID_RID(0x0048,"SSID3",		255,0,0,"")	//    
+#define awc_RID_SSID1hex 				awc_def_SSID_RID(0x0004,"SSID1hex",		255,0xff,0,"")	
+#define awc_RID_SSID2hex 				awc_def_SSID_RID(0x0026,"SSID2hex",		255,0xff,0,"") 	
+#define awc_RID_SSID3hex 				awc_def_SSID_RID(0x0048,"SSID3hex",		255,0xff,0,"")	
 
 // AP list
 
@@ -1304,6 +1307,9 @@
 	awc_RID_SSID2,
 	awc_RID_SSIDlen3,
 	awc_RID_SSID3,
+	awc_RID_SSID1hex,
+	awc_RID_SSID2hex,
+	awc_RID_SSID3hex,
 	{0}
 };
 
diff -u --recursive --new-file v2.3.50/linux/drivers/net/arlan.c linux/drivers/net/arlan.c
--- v2.3.50/linux/drivers/net/arlan.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/net/arlan.c	Fri Mar 10 09:43:04 2000
@@ -1,6 +1,6 @@
 /*
  *  Copyright (C) 1997 Cullen Jennings
- *  Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500        
+ *  Copyright (C) 1998 Elmer Joandiu, elmer@ylenurme.ee
  *  Gnu Public License applies
  * This module provides support for the Arlan 655 card made by Aironet
  */
@@ -638,15 +638,20 @@
 		priv->registrationLastSeen = jiffies;
 		priv->registrationLostCount = 0;
 		priv->reRegisterExp = 1;
-		if (!netif_running(dev))
+		if (!netif_running(dev) )
 			netif_wake_queue(dev);
+		if (priv->tx_last_sent > priv->tx_last_cleared &&
+			jiffies - priv->tx_last_sent > 5*HZ ){
+			arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);		
+			priv->tx_last_cleared = jiffies;
+		};
 	}
 
 
 	if (!registrationBad(dev) && priv->ReTransmitRequested)
 	{
 		IFDEBUG(ARLAN_DEBUG_TX_CHAIN)
-			printk(KERN_ERR "Retranmit from timer \n");
+			printk(KERN_ERR "Retransmit from timer \n");
 		priv->ReTransmitRequested = 0;
 		arlan_retransmit_now(dev);
 	}
@@ -1335,8 +1340,8 @@
 	printk(KERN_ERR "%s: arlan transmit timed out, kernel decided\n", dev->name);
 	/* Try to restart the adaptor. */
 	arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET);
-	dev->trans_start = jiffies;
-	netif_start_queue (dev);
+	// dev->trans_start = jiffies;
+	// netif_start_queue (dev);
 }
 
 
@@ -1348,12 +1353,6 @@
 
 	ARLAN_DEBUG_ENTRY("arlan_tx");
 	
-	/*
-	 * If some higher layer thinks we've missed an tx-done interrupt
-	 * we are passed NULL. Caution: dev_tint() handles the cli()/sti()
-	 * itself.
-	 */
-
 	length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 	buf = skb->data;
 
diff -u --recursive --new-file v2.3.50/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in
--- v2.3.50/linux/drivers/net/pcmcia/Config.in	Wed Feb 16 17:03:52 2000
+++ linux/drivers/net/pcmcia/Config.in	Fri Mar 10 09:43:04 2000
@@ -14,7 +14,6 @@
    dep_tristate '  New Media PCMCIA support' CONFIG_PCMCIA_NMCLAN $CONFIG_PCMCIA
    dep_tristate '  SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA
    dep_tristate '  Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA
-   dep_tristate '  Aironet 4500/4800 PCMCIA support' CONFIG_AIRONET4500_CS $CONFIG_AIRONET4500 $CONFIG_PCMCIA
    dep_tristate '  COM20020 ARCnet PCMCIA support' CONFIG_ARCNET_COM20020_CS $CONFIG_ARCNET_COM20020 $CONFIG_ARCNET $CONFIG_PCMCIA
 
    if [ "$CONFIG_CARDBUS" = "y" ]; then
@@ -27,6 +26,7 @@
       dep_tristate '  Aviator/Raytheon 2.4MHz wireless support' CONFIG_PCMCIA_RAYCS $CONFIG_PCMCIA
       dep_tristate '  Xircom Netwave AirSurfer wireless support' CONFIG_PCMCIA_NETWAVE $CONFIG_PCMCIA
       dep_tristate '  AT&T/Lucent Wavelan wireless support' CONFIG_PCMCIA_WAVELAN $CONFIG_PCMCIA
+      dep_tristate '  Aironet 4500/4800 PCMCIA support' CONFIG_AIRONET4500_CS $CONFIG_AIRONET4500 $CONFIG_PCMCIA
    fi
 fi
 
diff -u --recursive --new-file v2.3.50/linux/drivers/net/pcmcia/aironet4500_cs.c linux/drivers/net/pcmcia/aironet4500_cs.c
--- v2.3.50/linux/drivers/net/pcmcia/aironet4500_cs.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/net/pcmcia/aironet4500_cs.c	Fri Mar 10 09:43:04 2000
@@ -230,7 +230,6 @@
 	dev->init = &awc_pcmcia_init;
 	dev->open = &awc_pcmcia_open;
 	dev->stop = &awc_pcmcia_close;
-	netif_start_queue (dev);
 	
 	link->priv = dev;
 #if CS_RELEASE_CODE > 0x2911
diff -u --recursive --new-file v2.3.50/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c
--- v2.3.50/linux/drivers/net/ppp_generic.c	Wed Feb 16 17:03:52 2000
+++ linux/drivers/net/ppp_generic.c	Thu Mar  9 17:39:10 2000
@@ -558,7 +558,9 @@
 {
 	int err;
 #ifndef MODULE
+#ifdef CONFIG_PPP_DEFLATE
 	extern struct compressor ppp_deflate, ppp_deflate_draft;
+#endif
 	extern int ppp_async_init(void);
 	extern int ppp_sync_init(void);
 #endif
diff -u --recursive --new-file v2.3.50/linux/drivers/net/setup.c linux/drivers/net/setup.c
--- v2.3.50/linux/drivers/net/setup.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/net/setup.c	Thu Mar  9 07:08:04 2000
@@ -227,7 +227,7 @@
 		extern int sb1000_probe(struct net_device *dev);
 		static struct net_device sb1000_dev = 
 		{
-			"cm0 __PAD3", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, sb1000_probe 
+			"cm0" __PAD3, 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NULL, sb1000_probe 
 		};
 		register_netdev(&sb1000_dev);
 	}
diff -u --recursive --new-file v2.3.50/linux/drivers/net/tokenring/Makefile linux/drivers/net/tokenring/Makefile
--- v2.3.50/linux/drivers/net/tokenring/Makefile	Tue Mar  7 14:32:26 2000
+++ linux/drivers/net/tokenring/Makefile	Wed Mar  8 09:18:02 2000
@@ -14,7 +14,7 @@
 obj-n   :=
 obj-m   :=
 obj-    :=
-export-objs :=
+export-objs := tms380tr.o
 
 obj-$(CONFIG_IBMTR) 	+= ibmtr.o
 obj-$(CONFIG_IBMOL) 	+= olympic.o
diff -u --recursive --new-file v2.3.50/linux/drivers/net/tokenring/tms380tr.c linux/drivers/net/tokenring/tms380tr.c
--- v2.3.50/linux/drivers/net/tokenring/tms380tr.c	Sat Feb 12 11:22:11 2000
+++ linux/drivers/net/tokenring/tms380tr.c	Wed Mar  8 09:18:02 2000
@@ -72,7 +72,6 @@
 #endif
 
 #ifdef MODULE
-#define EXPORT_SYMTAB
 #include <linux/module.h>
 #include <linux/version.h>
 #endif
diff -u --recursive --new-file v2.3.50/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- v2.3.50/linux/drivers/net/tulip/tulip_core.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/net/tulip/tulip_core.c	Wed Mar  8 09:07:31 2000
@@ -420,8 +420,6 @@
 	tp->timer.data = (unsigned long)dev;
 	tp->timer.function = tulip_tbl[tp->chip_id].media_timer;
 	add_timer(&tp->timer);
-
-	netif_device_attach(dev);
 }
 
 
@@ -439,6 +437,8 @@
 	
 	tulip_up (dev);
 	
+	netif_start_queue (dev);
+	
 	return 0;
 }
 
@@ -652,8 +652,6 @@
 	struct tulip_private *tp = (struct tulip_private *) dev->priv;
 	unsigned long flags;
 
-	netif_device_detach (dev);
-
 	del_timer (&tp->timer);
 
 	spin_lock_irqsave (&tp->lock, flags);
@@ -686,6 +684,8 @@
 	long ioaddr = dev->base_addr;
 	struct tulip_private *tp = (struct tulip_private *) dev->priv;
 	int i;
+	
+	netif_stop_queue (dev);
 
 	tulip_down (dev);
 
@@ -1338,8 +1338,10 @@
 {
 	struct net_device *dev = pdev->driver_data;
 
-	if (dev && netif_device_present (dev))
+	if (dev && netif_device_present (dev)) {
+		netif_device_detach (dev);
 		tulip_down (dev);
+	}
 }
 
 
@@ -1347,8 +1349,10 @@
 {
 	struct net_device *dev = pdev->driver_data;
 
-	if (dev && !netif_device_present (dev))
+	if (dev && !netif_device_present (dev)) {
 		tulip_up (dev);
+		netif_device_attach (dev);
+	}
 }
 
 
diff -u --recursive --new-file v2.3.50/linux/drivers/net/wan/Config.in linux/drivers/net/wan/Config.in
--- v2.3.50/linux/drivers/net/wan/Config.in	Fri Jan 28 15:09:07 2000
+++ linux/drivers/net/wan/Config.in	Fri Mar 10 16:11:58 2000
@@ -51,12 +51,8 @@
 
 	# X.25 network drivers
 
-	if [ "$CONFIG_X25" != "n" ]; then
-	   if [ "$CONFIG_LAPB" != "n" ]; then
-	      dep_tristate 'LAPB over Ethernet driver' CONFIG_LAPBETHER $CONFIG_LAPB
-	      dep_tristate 'X.25 async driver' CONFIG_X25_ASY $CONFIG_LAPB
-	   fi
-	fi
+	dep_tristate 'LAPB over Ethernet driver' CONFIG_LAPBETHER $CONFIG_LAPB $CONFIG_X25
+	dep_tristate 'X.25 async driver' CONFIG_X25_ASY $CONFIG_LAPB $CONFIG_X25
 
 	tristate 'SBNI12-xx support' CONFIG_SBNI
 fi
diff -u --recursive --new-file v2.3.50/linux/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c
--- v2.3.50/linux/drivers/net/wan/cosa.c	Sat Feb 26 22:31:47 2000
+++ linux/drivers/net/wan/cosa.c	Wed Mar  8 10:18:25 2000
@@ -1,4 +1,4 @@
-/* $Id: cosa.c,v 1.30 2000/02/21 15:19:49 kas Exp $ */
+/* $Id: cosa.c,v 1.31 2000/03/08 17:47:16 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -373,7 +373,7 @@
 {
 	int i;
 
-	printk(KERN_INFO "cosa v1.07 (c) 1997-2000 Jan Kasprzak <kas@fi.muni.cz>\n");
+	printk(KERN_INFO "cosa v1.08 (c) 1997-2000 Jan Kasprzak <kas@fi.muni.cz>\n");
 #ifdef __SMP__
 	printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
 #endif
@@ -584,6 +584,7 @@
 	struct net_device *d;
 	chan->if_ptr = &chan->pppdev;
 	chan->pppdev.dev = kmalloc(sizeof(struct net_device), GFP_KERNEL);
+	memset(chan->pppdev.dev, 0, sizeof(struct net_device));
 	sppp_attach(&chan->pppdev);
 	d=chan->pppdev.dev;
 	d->name = chan->name;
@@ -599,7 +600,6 @@
 	d->get_stats = cosa_net_stats;
 	d->tx_timeout = cosa_sppp_timeout;
 	d->watchdog_timeo = TX_TIMEOUT;
-	dev_init_buffers(d);
 	if (register_netdev(d) == -1) {
 		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
 		sppp_detach(chan->pppdev.dev);
@@ -757,7 +757,7 @@
 		chan->stats.tx_aborted_errors++;
 		return 1;
 	}
-	dev_kfree_skb(chan->tx_skb);
+	dev_kfree_skb_irq(chan->tx_skb);
 	chan->tx_skb = 0;
 	chan->stats.tx_packets++;
 	chan->stats.tx_bytes += size;
diff -u --recursive --new-file v2.3.50/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v2.3.50/linux/drivers/net/wavelan.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/net/wavelan.c	Wed Mar  8 09:20:15 2000
@@ -1805,6 +1805,7 @@
 	mm_t m;
 	unsigned long flags;
 	int ret = 0;
+	int err = 0;
 
 #ifdef DEBUG_IOCTL_TRACE
 	printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name,
@@ -1813,8 +1814,6 @@
 
 	/* Disable interrupts and save flags. */
 	wv_splhi(lp, &flags);
-	/* FIXME: can't copy*user when cli this is broken! */
-	/* Note : is it still valid ? Jean II */
 	
 	/* Look what is the request */
 	switch (cmd) {
@@ -1945,10 +1944,12 @@
 			}
 
 			/* Copy the key in the driver */
-			if (copy_from_user
-			    (psa.psa_encryption_key,
-			     wrq->u.encoding.pointer,
-			     wrq->u.encoding.length)) {
+			wv_splx(lp, &flags);
+			err = copy_from_user(psa.psa_encryption_key,
+					     wrq->u.encoding.pointer,
+					     wrq->u.encoding.length);
+			wv_splhi(lp, &flags);
+			if (err) {
 				ret = -EFAULT;
 				break;
 			}
@@ -2018,9 +2019,11 @@
 
 			/* Copy the key to the user buffer */
 			wrq->u.encoding.length = 8;
-			if (copy_to_user
-			    (wrq->u.encoding.pointer,
-			     psa.psa_encryption_key, 8)) ret = -EFAULT;
+			wv_splx(lp, &flags);
+			if (copy_to_user(wrq->u.encoding.pointer,
+					 psa.psa_encryption_key, 8))
+				ret = -EFAULT;
+			wv_splhi(lp, &flags);
 		}
 		break;
 
@@ -2067,38 +2070,51 @@
 			}
 
 			/* Copy structure to the user buffer. */
-			if (copy_to_user
-			    (wrq->u.data.pointer, &range,
-			     sizeof(struct iw_range))) ret = -EFAULT;
+			wv_splx(lp, &flags);
+			if (copy_to_user(wrq->u.data.pointer,
+					 &range,
+					 sizeof(struct iw_range)))
+				ret = -EFAULT;
+			wv_splhi(lp, &flags);
 		}
 		break;
 
 	case SIOCGIWPRIV:
 		/* Basic checking */
 		if (wrq->u.data.pointer != (caddr_t) 0) {
-			struct iw_priv_args priv[] = {	/* cmd,         set_args,       get_args,       name */
-				
-				    {SIOCSIPQTHR,
-				 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED |
-				     1, 0, "setqualthr"},
-				{SIOCGIPQTHR, 0,
-				 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED |
-				 1, "getqualthr"},
-
-				
-				    {SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16,
-				 0, "sethisto"},
-				{SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16,
-				 "gethisto"},
+			struct iw_priv_args priv[] = {
+				/* { cmd,
+				     set_args,
+				     get_args,
+				     name } */
+				{ SIOCSIPQTHR,
+				  IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
+				  0,
+				  "setqualthr" },
+				{ SIOCGIPQTHR,
+				  0,
+				  IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
+				  "getqualthr" },
+				{ SIOCSIPHISTO,
+				  IW_PRIV_TYPE_BYTE | 16,
+				  0,
+				  "sethisto" },
+				{ SIOCGIPHISTO,
+				  0,
+				  IW_PRIV_TYPE_INT | 16,
+				 "gethisto" },
 			};
 
 			/* Set the number of available ioctls. */
 			wrq->u.data.length = 4;
 
 			/* Copy structure to the user buffer. */
-			if (copy_to_user
-			    (wrq->u.data.pointer, (u8 *) priv,
-			     sizeof(priv))) ret = -EFAULT;
+			wv_splx(lp, &flags);
+			if (copy_to_user(wrq->u.data.pointer,
+					      (u8 *) priv,
+					      sizeof(priv)))
+				ret = -EFAULT;
+			wv_splhi(lp, &flags);
 		}
 		break;
 
@@ -2119,9 +2135,13 @@
 			int i;
 
 			/* Copy addresses to the driver. */
-			if (copy_from_user
-			    (address, wrq->u.data.pointer,
-			     sizeof(struct sockaddr) * lp->spy_number)) {
+			wv_splx(lp, &flags);
+			err = copy_from_user(address,
+					     wrq->u.data.pointer,
+					     sizeof(struct sockaddr)
+					     * lp->spy_number);
+			wv_splhi(lp, &flags);
+			if (err) {
 				ret = -EFAULT;
 				break;
 			}
@@ -2175,18 +2195,20 @@
 			}
 
 			/* Copy addresses to the user buffer. */
-			if (copy_to_user
-			    (wrq->u.data.pointer, address,
-			     sizeof(struct sockaddr) * lp->spy_number)) {
-				ret = -EFAULT;
-				break;
-			}
+			wv_splx(lp, &flags);
+			err = copy_to_user(wrq->u.data.pointer,
+					   address,
+					   sizeof(struct sockaddr)
+					   * lp->spy_number);
 
 			/* Copy stats to the user buffer (just after). */
-			if (copy_to_user(wrq->u.data.pointer +
-					 (sizeof(struct sockaddr) *
-					  lp->spy_number), lp->spy_stat,
-					 sizeof(iw_qual) * lp->spy_number)) {
+			err |= copy_to_user(wrq->u.data.pointer
+					    + (sizeof(struct sockaddr)
+					       * lp->spy_number),
+					    lp->spy_stat,
+					    sizeof(iw_qual) * lp->spy_number);
+			wv_splhi(lp, &flags);
+			if (err) {
 				ret = -EFAULT;
 				break;
 			}
@@ -2241,9 +2263,12 @@
 		/* Are there addresses to copy? */
 		if (lp->his_number > 0) {
 			/* Copy interval ranges to the driver */
-			if (copy_from_user
-			    (lp->his_range, wrq->u.data.pointer,
-			     sizeof(char) * lp->his_number)) {
+			wv_splx(lp, &flags);
+			err = copy_from_user(lp->his_range,
+					     wrq->u.data.pointer,
+					     sizeof(char) * lp->his_number);
+			wv_splhi(lp, &flags);
+			if (err) {
 				ret = -EFAULT;
 				break;
 			}
@@ -2261,10 +2286,12 @@
 		if ((lp->his_number > 0)
 		    && (wrq->u.data.pointer != (caddr_t) 0)) {
 			/* Copy data to the user buffer. */
-			if (copy_to_user
-			    (wrq->u.data.pointer, lp->his_sum,
-			     sizeof(long) * lp->his_number))
+			wv_splx(lp, &flags);
+			if (copy_to_user(wrq->u.data.pointer,
+					 lp->his_sum,
+					 sizeof(long) * lp->his_number);
 				ret = -EFAULT;
+			wv_splhi(lp, &flags);
 
 		}		/* if(pointer != NULL) */
 		break;
@@ -2274,7 +2301,7 @@
 
 	default:
 		ret = -EOPNOTSUPP;
-	}
+	}	/* switch (cmd) */
 
 	/* Enable interrupts and restore flags. */
 	wv_splx(lp, &flags);
diff -u --recursive --new-file v2.3.50/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- v2.3.50/linux/drivers/parport/ChangeLog	Wed Dec 31 16:00:00 1969
+++ linux/drivers/parport/ChangeLog	Fri Mar 10 10:48:47 2000
@@ -0,0 +1,10 @@
+2000-03-10    <twaugh@redhat.com>
+
+	* parport_pc.c (decode_winbond): Use correct 83877ATF chip ID.
+	(decode_winbond): Fix typo.
+
+2000-03-09    <twaugh@redhat.com>
+
+	* parport_pc.c: Integrate SuperIO PCI probe with normal PCI card
+	probe, so that the MODULE_DEVICE_TABLE is complete.
+
diff -u --recursive --new-file v2.3.50/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.3.50/linux/drivers/parport/parport_pc.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/parport/parport_pc.c	Fri Mar 10 10:48:47 2000
@@ -1175,11 +1175,11 @@
 	else if ((id & ~0x0f) == 0x5210) type="83627";
 	else if ((id & ~0x0f) == 0x6010) type="83697HF";
 	else if ((oldid &0x0f ) == 0x0c) { type="83877TF"; progif=1;}
-	else if ((oldid &0x0f ) == 0x0c) { type="83877ATF"; progif=1;}
+	else if ((oldid &0x0f ) == 0x0d) { type="83877ATF"; progif=1;}
 	else progif=0;
 
 	if(type==NULL) 
-		printk("Winbond unkown chip type\n");
+		printk("Winbond unknown chip type\n");
 	else	
 	 	printk("Winbond chip type %s\n",type);
 
@@ -2161,9 +2161,9 @@
 
 enum parport_pc_sio_types {
 	sio_via_686a = 0,	/* Via VT82C686A motherboard Super I/O */
+	last_sio
 };
 
-
 /* each element directly indexed from enum list, above */
 static struct parport_pc_superio {
 	int (*probe) (struct pci_dev *pdev);
@@ -2172,195 +2172,180 @@
 };
 
 
+enum parport_pc_pci_cards {
+	siig_1s1p_10x_550 = last_sio,
+	siig_1s1p_10x_650,
+	siig_1s1p_10x_850,
+	siig_1p_10x,
+	siig_2p_10x,
+	siig_2s1p_10x_550,
+	siig_2s1p_10x_650,
+	siig_2s1p_10x_850,
+	siig_1p_20x,
+	siig_2p_20x,
+	siig_2p1s_20x_550,
+	siig_2p1s_20x_650,
+	siig_2p1s_20x_850,
+	siig_1s1p_20x_550,
+	siig_1s1p_20x_650,
+	siig_1s1p_20x_850,
+	siig_2s1p_20x_550,
+	siig_2s1p_20x_650,
+	siig_2s1p_20x_850,
+	lava_parallel,
+	lava_parallel_dual_a,
+	lava_parallel_dual_b,
+	boca_ioppar,
+	plx_9050,
+	afavlab_tk9902,
+};
+
+
+/* each element directly indexed from enum list, above 
+ * (but offset by last_sio) */
+static struct parport_pc_pci {
+	int numports;
+	struct {
+		int lo;
+		int hi; /* -ve if not there */
+	} addr[4];
+} cards[] __devinitdata = {
+	/* siig_1s1p_10x_550 */		{ 1, { { 3, 4 }, } },
+	/* siig_1s1p_10x_650 */		{ 1, { { 3, 4 }, } },
+	/* siig_1s1p_10x_850 */		{ 1, { { 3, 4 }, } },
+	/* siig_1p_10x */		{ 1, { { 2, 3 }, } },
+	/* siig_2p_10x */		{ 2, { { 2, 3 }, { 4, 5 }, } },
+	/* siig_2s1p_10x_550 */		{ 1, { { 4, 5 }, } },
+	/* siig_2s1p_10x_650 */		{ 1, { { 4, 5 }, } },
+	/* siig_2s1p_10x_850 */		{ 1, { { 4, 5 }, } },
+	/* siig_1p_20x */		{ 1, { { 0, 1 }, } },
+	/* siig_2p_20x */		{ 2, { { 0, 1 }, { 2, 3 }, } },
+	/* siig_2p1s_20x_550 */		{ 2, { { 1, 2 }, { 3, 4 }, } },
+	/* siig_2p1s_20x_650 */		{ 2, { { 1, 2 }, { 3, 4 }, } },
+	/* siig_2p1s_20x_850 */		{ 2, { { 1, 2 }, { 3, 4 }, } },
+	/* siig_1s1p_20x_550 */		{ 1, { { 1, 2 }, } },
+	/* siig_1s1p_20x_650 */		{ 1, { { 1, 2 }, } },
+	/* siig_1s1p_20x_850 */		{ 1, { { 1, 2 }, } },
+	/* siig_2s1p_20x_550 */		{ 1, { { 2, 3 }, } },
+	/* siig_2s1p_20x_650 */		{ 1, { { 2, 3 }, } },
+	/* siig_2s1p_20x_850 */		{ 1, { { 2, 3 }, } },
+	/* lava_parallel */		{ 1, { { 0, -1 }, } },
+	/* lava_parallel_dual_a */	{ 1, { { 0, -1 }, } },
+	/* lava_parallel_dual_b */	{ 1, { { 0, -1 }, } },
+	/* boca_ioppar */		{ 1, { { 0, -1 }, } },
+	/* plx_9050 */			{ 2, { { 4, -1 }, { 5, -1 }, } },
+	/* afavlab_tk9902 */		{ 1, { { 0, 1 }, } },
+};
+
 static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
+	/* Super-IO onboard chips */
 	{ 0x1106, 0x0686, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sio_via_686a },
+
+	/* PCI cards */
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x_550 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x_650 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_10x_850 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_10x,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_10x,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p_10x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x_550 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x_650 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_10x_850 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_20x,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_20x,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p_20x },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x_550 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x_650 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2p1s_20x_850 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x_550 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x_650 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_1s1p_20x_850 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x_550 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x_650 },
+	{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, siig_2s1p_20x_850 },
+	{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PARALLEL,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, lava_parallel },
+	{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_A,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, lava_parallel_dual_a },
+	{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_B,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, lava_parallel_dual_b },
+	{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_BOCA_IOPPAR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, boca_ioppar },
+	{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+	  PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0,0, plx_9050 },
+	{ PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_TK9902,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, afavlab_tk9902 },
 	{ 0, }, /* terminate list */
 };
+MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
+
+static int __devinit parport_pc_pci_probe (struct pci_dev *dev,
+					   const struct pci_device_id *id)
+{
+	int count, n, i = id->driver_data;
+	if (i < last_sio)
+		/* This is an onboard Super-IO and has already been probed */
+		return 0;
 
+	/* This is a PCI card */
+	i -= last_sio;
+	count = 0;
+	for (n = 0; n < cards[i].numports; n++) {
+		int lo = cards[i].addr[n].lo;
+		int hi = cards[i].addr[n].hi;
+		unsigned long io_lo, io_hi;
+		io_lo = pci_resource_start (dev, lo);
+		io_hi = 0;
+		if (hi >= 0)
+			io_hi = pci_resource_start (dev, hi);
+		/* TODO: test if sharing interrupts works */
+		if (parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
+					   PARPORT_DMA_NONE, dev))
+			count++;
+	}
 
-static int __devinit parport_pc_init_superio(void)
+	return count;
+}
+
+static struct pci_driver parport_pc_pci_driver = {
+	name:		"parport_pc",
+	id_table:	parport_pc_pci_tbl,
+	probe:		parport_pc_pci_probe,
+};
+
+static int __devinit parport_pc_init_superio (void)
 {
 #ifdef CONFIG_PCI
 	const struct pci_device_id *id;
 	struct pci_dev *pdev;
-	
+
 	pci_for_each_dev(pdev) {
 		id = pci_match_device (parport_pc_pci_tbl, pdev);
-		if (id == NULL)
+		if (id == NULL || id->driver_data >= last_sio)
 			continue;
-		
+
 		return parport_pc_superio_info[id->driver_data].probe (pdev);
 	}
 #endif /* CONFIG_PCI */
-	
-	return 0; /* zero devices found */
-}
 
-/* Look for PCI parallel port cards. */
-static int __init parport_pc_init_pci (int irq, int dma)
-{
-#ifndef PCI_VENDOR_ID_AFAVLAB
-#define PCI_VENDOR_ID_AFAVLAB		0x14db
-#define PCI_DEVICE_ID_AFAVLAB_TK9902	0x2120
-#endif
-
-	struct {
-		unsigned int vendor;
-		unsigned int device;
-		unsigned int subvendor;
-		unsigned int subdevice;
-		unsigned int numports;
-		struct {
-			unsigned long lo;
-			unsigned long hi; /* -ve if not there */
-		} addr[4];
-	} cards[] = {
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 3, 4 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 3, 4 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 3, 4 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_10x,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 2, 3 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_10x,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  2, { { 2, 3 }, { 4, 5 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 4, 5 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 4, 5 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 4, 5 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1P_20x,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 0, 1 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P_20x,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  2, { { 0, 1 }, { 2, 3 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  2, { { 1, 2 }, { 3, 4 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  2, { { 1, 2 }, { 3, 4 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  2, { { 1, 2 }, { 3, 4 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 1, 2 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 1, 2 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 1, 2 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 2, 3 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 2, 3 }, } },
-		{ PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 2, 3 }, } },
-		{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PARALLEL,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 0, -1 }, } },
-		{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_A,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 0, -1 }, } },
-		{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DUAL_PAR_B,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 0, -1 }, } },
-		{ PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_BOCA_IOPPAR,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 0, -1 }, } },
-		{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
-		  PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014,
-		  2, { { 4, -1 }, { 5, -1 }, } },
-		{ PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_TK9902,
-		  PCI_ANY_ID, PCI_ANY_ID,
-		  1, { { 0, 1 }, } },
-		{ 0, }
-	};
-
-	struct pci_dev *pcidev;
-	int count = 0;
-	int i;
-
-	if (!pci_present ())
-		return 0;
-
-	for (i = 0; cards[i].vendor; i++) {
-		pcidev = NULL;
-		while ((pcidev = pci_find_device (cards[i].vendor,
-						  cards[i].device,
-						  pcidev)) != NULL) {
-			int n;
-
-			if (cards[i].subvendor != PCI_ANY_ID &&
-			    cards[i].subvendor != pcidev->subsystem_vendor)
-				continue;
-
-			if (cards[i].subdevice != PCI_ANY_ID &&
-			    cards[i].subdevice != pcidev->subsystem_device)
-				continue;
-
-			for (n = 0; n < cards[i].numports; n++) {
-				unsigned long lo = cards[i].addr[n].lo;
-				unsigned long hi = cards[i].addr[n].hi;
-				unsigned long io_lo, io_hi;
-				io_lo = pcidev->resource[lo].start;
-				io_hi = ((hi < 0) ? 0 :
-					 pcidev->resource[hi].start);
-				if (irq == PARPORT_IRQ_AUTO) {
-					if (parport_pc_probe_port (io_lo,
-								   io_hi,
-								   pcidev->irq,
-								   dma,
-								   pcidev))
-						count++;
-				} else if (parport_pc_probe_port (io_lo, io_hi,
-								  irq, dma,
-								  pcidev))
-					count++;
-			}
-		}
-	}
-
-#ifdef CONFIG_PCI
-	/* Look for parallel controllers that we don't know about. */
-	pci_for_each_dev(pcidev) {
-		const int class_noprogif = pcidev->class & ~0xff;
-		if (class_noprogif != (PCI_CLASS_COMMUNICATION_PARALLEL << 8))
-			continue;
-
-		for (i = 0; cards[i].vendor; i++)
-			if ((cards[i].vendor == pcidev->vendor) &&
-			    (cards[i].device == pcidev->device))
-				break;
-		if (cards[i].vendor)
-			/* We know about this one. */
-			continue;
-
-		printk (KERN_INFO
-			"Unknown PCI parallel I/O card (%04x/%04x)\n"
-			"Please send 'lspci' output to "
-			"tim@cyberelk.demon.co.uk\n",
-			pcidev->vendor, pcidev->device);
-	}
-#endif
-
-	return count;
+	return 0; /* zero devices found */
 }
 
 /* Exported symbols. */
@@ -2401,7 +2386,7 @@
 {	
 	/* Work out how many ports we have, then get parport_share to parse
 	   the irq values. */
-	unsigned int i;
+	unsigned int i, n;
 	if (superio) {
 		detect_and_report_winbond ();
 		detect_and_report_smsc ();
@@ -2430,12 +2415,18 @@
 			}
 	}
 
-	return (parport_pc_init(io, io_hi, irqval, dmaval)?0:1);
+	n = parport_pc_init_superio ();
+	n += parport_pc_init (io, io_hi, irqval, dmaval);
+	i = pci_register_driver (&parport_pc_pci_driver);
+
+	if (i > 0) n += i;
+	return !n;
 }
 
 void cleanup_module(void)
 {
 	struct parport *p = parport_enumerate(), *tmp;
+	pci_unregister_driver (&parport_pc_pci_driver);
 	while (p) {
 		tmp = p->next;
 		if (p->modes & PARPORT_MODE_PCSPP) { 
diff -u --recursive --new-file v2.3.50/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- v2.3.50/linux/drivers/pci/pci.ids	Thu Mar  2 14:36:22 2000
+++ linux/drivers/pci/pci.ids	Thu Mar  9 07:08:04 2000
@@ -4,7 +4,7 @@
 #	Maintained by Martin Mares <pci-ids@ucw.cz>
 #	If you have any new entries, send them to the maintainer.
 #
-#	$Id: pci.ids,v 1.50 2000/01/23 05:57:06 mj Exp $
+#	$Id: pci.ids,v 1.53 2000/03/09 08:19:20 mj Exp $
 #
 
 # Vendors, devices and subsystems. Please keep sorted.
@@ -258,6 +258,8 @@
 	0026  DECchip 21154
 	0045  DECchip 21553
 	0046  DECchip 21554
+		9005 1364  Dell PowerEdge RAID Controller 2
+		9005 1365  Dell PowerEdge RAID Controller 2
 1012  Micronics Computers Inc
 1013  Cirrus Logic
 	0038  GD 7548
@@ -411,20 +413,35 @@
 	1489  M1489
 	1511  M1511
 	1513  M1513
-	1531  M1531
-	1533  M1533
+	1531  M1531 Northbridge [Aladdin IV/IV+]
+	1533  M1533 PCI-to-ISA Bridge
+	1535  M1535 PCI Bridge + Super I/O + FIR
+	1541  M1541 Northbridge [Aladdin V]
+	1542  M1542 Northbridge [Aladdin V]
+	1543  M1543 PCI-to-ISA Bridge + Super I/O + FIR
+	1561  M1561 Northbridge [Aladdin 7]
+	1621  M1621 Northbridge [Aladdin-Pro II]
+	1631  M1631 Northbridge+3D Graphics [Aladdin TNT2]
+	1641  M1641 Northbridge [Aladdin-Pro IV]
 	3141  M3141
 	3143  M3143
 	3145  M3145
 	3147  M3147
 	3149  M3149
 	3151  M3151
+	3307  M3307 MPEG-I Video Controller
+	3309  M3309 MPEG-II Video w/ Software Audio Decoder
+	3321  M3321 MPEG-II Audio/Video Decoder
 	5217  M5217H
 	5219  M5219
 	5225  M5225
 	5229  M5229
 	5235  M5235
+	5251  M5251 P1394 OHCI Controller
 1028  Dell Computer Corporation
+	0001  PowerEdge Expandable RAID Controller 2/Si
+	0002  PowerEdge Expandable RAID Controller 3/Di
+	0003  PowerEdge Expandable RAID Controller 3/Si
 1029  Siemens Nixdorf IS
 102a  LSI Logic
 	0000  HYDRA
@@ -1000,9 +1017,30 @@
 10a8  Sierra Semiconductor
 	0000  STB Horizon 64
 10a9  Silicon Graphics, Inc.
-	0003  IOC3
+	0001  Crosstalk to PCI Bridge
+	0002  Linc I/O controller
+	0003  IOC3 I/O controller
+	0004  O2 MACE
 	0005  RAD Audio
+	0006  HPCEX
+	0007  RPCEX
+	0008  DiVO VIP
 	0009  Alteon Gigabit Ethernet
+	0010  AMP Video I/O
+	0011  GRIP
+	0012  SGH PSHAC GSN
+	1001  Magic Carpet
+	1002  Lithium
+	1003  Dual JPEG 1
+	1004  Dual JPEG 2
+	1005  Dual JPEG 3
+	1006  Dual JPEG 4
+	1007  Dual JPEG 5
+	1008  Cesium
+	2001  Fibre Channel
+	2002  ASDE
+	8001  O2 1394
+	8002  G-net NT
 10aa  ACC Microelectronics
 	0000  ACCM 2188
 10ab  Digicom
@@ -1031,6 +1069,23 @@
 	1077  VScom 400 4 port serial adaptor
 	9036  9036
 	9050  PCI <-> IOBus Bridge
+		d84d 4006  EX-4006 1P
+		d84d 4008  EX-4008 1P EPP/ECP
+		d84d 4014  EX-4014 2P
+		d84d 4018  EX-4018 3P EPP/ECP
+		d84d 4025  EX-4025 1S(16C550) RS-232
+		d84d 4027  EX-4027 1S(16C650) RS-232
+		d84d 4028  EX-4028 1S(16C850) RS-232
+		d84d 4036  EX-4036 2S(16C650) RS-232
+		d84d 4037  EX-4037 2S(16C650) RS-232
+		d84d 4038  EX-4038 2S(16C850) RS-232
+		d84d 4052  EX-4052 1S(16C550) RS-422/485
+		d84d 4053  EX-4053 2S(16C550) RS-422/485
+		d84d 4055  EX-4055 4S(16C550) RS-232
+		d84d 4058  EX-4055 4S(16C650) RS-232
+		d84d 4065  EX-4065 8S(16C550) RS-232
+		d84d 4068  EX-4068 8S(16C650) RS-232
+		d84d 4078  EX-4078 2S(16C552) RS-232+1P
 	9060  9060
 	906d  9060SD
 		125c 0640  Aries 16000P
@@ -1193,9 +1248,10 @@
 	10dc  ATT2C15-3 FPGA
 10dd  Evans & Sutherland
 10de  nVidia Corporation
-	0008  NV1 EDGE 3D
-	0009  NV1 EDGE 3D
-	0020  Riva TNT 128
+	0008  EDGE 3D [NV1]
+	0009  EDGE 3D [NV1]
+	0010  Mutara V08 [NV2]
+	0020  Riva TnT 128 [NV04]
 		1043 0200  V3400 TNT
 		1092 0550  Viper V550
 		1092 0552  Viper V550
@@ -1210,7 +1266,7 @@
 		1092 4904  Viper V550 
 		1092 4914  Viper V550 
 		1092 8225  Viper V550
-	0028  Riva TNT2
+	0028  Riva TnT2 [NV5]
 		1043 0200  AGP-V3800 SGRAM
 		1092 4804  Viper V770
 		1092 4a00  Viper V770
@@ -1219,16 +1275,20 @@
 		1092 7a02  Viper V770 Ultra
 		1102 1020  3D Blaster RIVA TNT2
 		14af 5810  Maxi Gamer Xentor
-	0029  Riva TNT2 Ultra
+	0029  Riva TnT2 Ultra [NV5]
 		1043 0200  AGP-V3800 Deluxe
 		1102 1021  3D Blaster RIVA TNT2 Ultra
 		14af 5820  Maxi Gamer Xentor 32
-	002c  Vanta
+	002a  Riva TnT2 [NV5]
+	002b  Riva TnT2 [NV5]
+	002c  Vanta [NV6]
 		1043 0200  AGP-V3800 Combat SDRAM
 		1092 6820  Viper V730
 		14af 5008  Maxi Gamer Phoenix 2
-	002d  Riva TNT2 Model 64
+	002d  Vanta [NV6]
 		1043 0200  AGP-V3800M
+	002e  Vanta [NV6]
+	002f  Vanta [NV6]
 	00a0  Riva TNT2
 		14af 5810  Maxi Gamer Xentor
 10df  Emulex Corporation
@@ -1279,14 +1339,14 @@
 	0101  3GA
 	8111  Twist3 Frame Grabber
 10ec  Realtek Semiconductor Co., Ltd.
-	8029  RT8029(AS)
+	8029  RTL-8029(AS)
 		10b8 2011  EZ-Card
 		10ec 8029  RT8029(AS)
 		1113 1208  EN1208
 		1186 0300  DE-528
 		1259 2400  AT-2400
-	8129  RT8129
-	8139  RT8139
+	8129  RTL-8129
+	8139  RTL-8139
 		1025 8920  ALN-325
 		1025 8921  ALN-325
 		10bd 0320  EP-320X-R
@@ -1304,9 +1364,14 @@
 		2646 0001  EtheRx
 		8e2e 7000  KF-230TX
 		8e2e 7100  KF-230TX/2
+		a0a0 0007  ALN-325C
 10ed  Ascii Corporation
 	7310  V7310
 10ee  Xilinx, Inc.
+	3fc0  RME Digi96
+	3fc1  RME Digi96/8
+	3fc2  RME Digi96/8 Pro
+	3fc3  RME Digi96/8 Pad
 10ef  Racore Computer Products, Inc.
 	8154  M815x Token Ring Adapter
 10f0  Peritek Corporation
@@ -1329,6 +1394,7 @@
 10ff  NCube
 1100  Jazz Multimedia
 1101  Initio Corporation
+	1060  INI-A100U2W
 	9100  INI-9100/9100W
 	9400  INI-940
 	9401  INI-950
@@ -1353,7 +1419,9 @@
 1105  Sigma Designs, Inc.
 	8300  REALmagic Hollywood Plus DVD Decoder
 1106  VIA Technologies, Inc.
+	0391  VT8371 [KX133]
 	0501  VT8501
+	0601  VT8601
 	0505  VT82C505
 	0561  VT82C561
 	0571  VT82C586 IDE [Apollo]
@@ -1385,11 +1453,14 @@
 	3068  VT82C686 [Apollo Super AC97/Modem]
 	5030  VT82C596 ACPI [Apollo PRO]
 	6100  VT85C100A [Rhine II]
+	8231  VT8231 [PCI-to-ISA Bridge]
+	8391  VT8371 [PCI-PCI Bridge]
 	8501  VT8501
 	8596  VT82C596 [Apollo PRO AGP]
 	8597  VT82C597 [Apollo VP3 AGP]
 	8598  VT82C598 [Apollo MVP3 AGP]
 	8691  VT82C691 [Apollo Pro]
+	8601  VT8601
 1107  Stratus Computers
 	0576  VIA VT82C570MV [Apollo] (Wrong vendor ID!)
 1108  Proteon, Inc.
@@ -1491,7 +1562,7 @@
 	0000  155P-MF1 (FPGA)
 	0002  155P-MF1 (ASIC)
 	0003  ENI-25P ATM Adapter
-	0005  ENI-25P ATM Adapter
+	0005  Speedstream 30xx ATM Adapter
 111b  Teledyne Electronic Systems
 111c  Tricord Systems Inc.
 	0001  Powerbis Bridge
@@ -2185,6 +2256,7 @@
 	1968  ES1968 Maestro 2
 	1969  ES1969 Solo-1 Audiodrive
 	1978  ES1978 Maestro 2E
+	1988  ES1988 Allegro-1
 	2808  ES336H Fax Modem (Later Model)
 	2898  ES2898 Modem
 125e  Specialvideo Engineering SRL
@@ -2741,6 +2813,7 @@
 	0100  CM8338A
 	0101  CM8338B
 	0111  CM8738
+	0211  CM8738
 13f7  Wildfire Communications
 13f8  Ad Lib Multimedia Inc
 13f9  NTT Advanced Technology Corp.
@@ -2848,6 +2921,7 @@
 145d  Gallant Computer Inc
 145e  Aashima Technology B.V.
 145f  Baldor Electric Company
+	0001  NextMove PCI
 1460  DYNARC INC
 1461  Avermedia Technologies Inc
 1462  Micro-star International Co Ltd
@@ -2932,6 +3006,7 @@
 14b1  Nextcom K.K.
 14b2  ENNOVATE Networks Inc
 14b3  XPEED Inc
+	0000  DSL NIC
 14b4  PHILIPS Business Electronics B.V.
 14b5  Creamware GmBH
 14b6  Quantum Data Corp.
@@ -2974,7 +3049,18 @@
 14d9  Alpha Processor Inc
 14da  National Aerospace Laboratories
 14db  AFAVLAB Technology Inc
+	2120  TK9902
 14dc  Amplicon Liveline Ltd
+	0000  PCI230
+	0001  PCI242
+	0002  PCI244
+	0003  PCI247
+	0004  PCI248
+	0005  PCI249
+	0006  PCI260
+	0007  PCI224
+	0008  PCI234
+	0009  PCI236
 14dd  Boulder Design Labs Inc
 14de  Applied Integration Corporation
 14df  ASIC Communications Corp
@@ -3115,6 +3201,7 @@
 1d44  DPT
 	a400  PM2x24/PM3224
 1de1  Tekram Technology Co.,Ltd.
+	0391  TRM-S1040
 	2020  DC-390
 	690c  690c
 	dc29  DC290
@@ -3571,6 +3658,7 @@
 cafe  Chrysalis-ITS
 cccc  Catapult Communications
 d4d4  Dy4 Systems Inc
+d84d  Exsys
 e000  Winbond
 	e000  W89C940
 e159  Tiger Jet Network Inc.
diff -u --recursive --new-file v2.3.50/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- v2.3.50/linux/drivers/pcmcia/i82365.c	Sat Feb 26 22:31:47 2000
+++ linux/drivers/pcmcia/i82365.c	Fri Mar 10 10:44:14 2000
@@ -1336,7 +1336,6 @@
 
 static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
 {
-#ifdef CONFIG_PROC_FS
     socket_info_t *s = &socket[sock];
 
     if (s->flags & IS_ALIVE)
@@ -1345,7 +1344,6 @@
     create_proc_read_entry("info", 0, base, proc_read_info, s);
     create_proc_read_entry("exca", 0, base, proc_read_exca, s);
     s->proc = base;
-#endif
 }
 
 static void pcic_proc_remove(u_short sock)
@@ -1355,6 +1353,10 @@
     remove_proc_entry("info", base);
     remove_proc_entry("exca", base);
 }
+
+#else
+
+#define pcic_proc_setup NULL
 
 #endif /* CONFIG_PROC_FS */
 
diff -u --recursive --new-file v2.3.50/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- v2.3.50/linux/drivers/pcmcia/yenta.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/pcmcia/yenta.c	Fri Mar 10 11:08:59 2000
@@ -555,6 +555,30 @@
 	}
 }
 
+/*
+ * Many chipsets (all TI chips?) seem to have
+ * problems sensing the power state of the card
+ * that was inserted at chip init time, so force
+ * it if necessary..
+ */
+static void yenta_power_sense(pci_socket_t *socket)
+{
+	u32 status = config_readl(socket, CB_SOCKET_STATE);
+
+	/*
+	 * Nothing inserted, nothing to sense..
+	 * ..or sense status already available.
+	 */
+	if (status & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD))
+		return;
+
+	/*
+	 * Ho humm. It reports a card, but it doesn't report
+	 * any voltages. Need to redo the VS test..
+	 */
+	cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);
+}
+
 /* Called at resume and initialization events */
 static int yenta_init(pci_socket_t *socket)
 {
@@ -594,6 +618,8 @@
 
 	exca_writeb(socket, I365_GBLCTL, 0x00);
 	exca_writeb(socket, I365_GENCTL, 0x00);
+
+	yenta_power_sense(socket);
 
 	yenta_clear_maps(socket);
 	return 0;
diff -u --recursive --new-file v2.3.50/linux/drivers/pnp/quirks.c linux/drivers/pnp/quirks.c
--- v2.3.50/linux/drivers/pnp/quirks.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/pnp/quirks.c	Tue Mar  7 14:36:51 2000
@@ -48,6 +48,25 @@
 	printk(KERN_INFO "isapnp: AWE32 quirk - adding two ports\n");
 }
 
+static void __init quirk_cmi8330_resources(struct pci_dev *dev)
+{
+	struct isapnp_resources *res = dev->sysdata;
+
+	for ( ; res ; res = res->alt ) {
+
+		struct isapnp_irq *irq;
+		struct isapnp_dma *dma;
+	
+		for( irq = res->irq; irq; irq = irq->next )	// Valid irqs are 5, 7, 10
+			irq->map = 0x04A0;						// 0000 0100 1010 0000
+
+		for( dma = res->dma; dma; dma = dma->next ) // Valid 8bit dma channels are 1,3
+			if( ( dma->flags & IORESOURCE_DMA_TYPE_MASK ) == IORESOURCE_DMA_8BIT )
+				dma->map = 0x000A;
+	}
+	printk(KERN_INFO "isapnp: CMI8330 quirk - fixing interrupts and dma\n");
+}
+
 
 /*
  *  ISAPnP Quirks
@@ -61,6 +80,8 @@
 		quirk_awe32_resources },
 	{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0023),
 		quirk_awe32_resources },
+	{ ISAPNP_VENDOR('@','X','@'), ISAPNP_DEVICE(0x0001), // CMI8330 
+		quirk_cmi8330_resources },
 	{ 0 }
 };
 
diff -u --recursive --new-file v2.3.50/linux/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c
--- v2.3.50/linux/drivers/scsi/3w-xxxx.c	Sat Feb 26 22:31:48 2000
+++ linux/drivers/scsi/3w-xxxx.c	Wed Mar  8 11:40:25 2000
@@ -85,7 +85,7 @@
 static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
 
 /* Globals */
-char *tw_driver_version="1.0.000";
+char *tw_driver_version="1.1.000";
 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
 int tw_device_extension_count = 0;
 
@@ -2051,7 +2051,7 @@
 	command_packet->status = 0;
 	command_packet->flags = 0;
 
-	if ((srb->cmnd[0] == WRITE_6) || (srb->cmnd[0] == WRITE_10)) {
+	if (srb->cmnd[0] == WRITE_10) {
 		if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))
 			command_packet->flags = 1;
 	}
diff -u --recursive --new-file v2.3.50/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.3.50/linux/drivers/scsi/Config.in	Sat Feb 26 22:31:48 2000
+++ linux/drivers/scsi/Config.in	Wed Mar  8 11:40:25 2000
@@ -44,8 +44,8 @@
    dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII $CONFIG_SCSI
 fi
 
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   dep_tristate '3ware Hardware ATA-RAID support (EXPERIMENTAL)' CONFIG_BLK_DEV_3W_XXXX_RAID $CONFIG_SCSI
+if [ "$CONFIG_PCI" = "y" ]; then
+   dep_tristate '3ware Hardware ATA-RAID support' CONFIG_BLK_DEV_3W_XXXX_RAID $CONFIG_SCSI
 fi
 dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
 dep_tristate 'ACARD SCSI support' CONFIG_SCSI_ACARD $CONFIG_SCSI
diff -u --recursive --new-file v2.3.50/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.3.50/linux/drivers/scsi/aic7xxx.c	Sun Feb 20 21:12:39 2000
+++ linux/drivers/scsi/aic7xxx.c	Fri Mar 10 15:24:02 2000
@@ -956,7 +956,7 @@
   unsigned char  numscbs;          /* current number of scbs */
   unsigned char  maxhscbs;         /* hardware scbs */
   unsigned char  maxscbs;          /* max scbs including pageable scbs */
-  unsigned int   hscbs_dma;	   /* DMA handle to hscbs */
+  dma_addr_t	 hscbs_dma;	   /* DMA handle to hscbs */
   unsigned int   hscbs_dma_len;    /* length of the above DMA area */
   void          *hscb_kmalloc_ptr;
 } scb_data_type;
diff -u --recursive --new-file v2.3.50/linux/drivers/scsi/scsi_dma.c linux/drivers/scsi/scsi_dma.c
--- v2.3.50/linux/drivers/scsi/scsi_dma.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/scsi_dma.c	Fri Mar 10 15:24:02 2000
@@ -147,7 +147,7 @@
 			nbits = len >> 9;
 			mask = (1 << nbits) - 1;
 
-			if ((mask << sector) >= (1 << SECTORS_PER_PAGE))
+			if (sector + nbits > SECTORS_PER_PAGE)
 				panic("scsi_free:Bad memory alignment");
 
 			if ((dma_malloc_freelist[page] &
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.3.50/linux/drivers/sound/Config.in	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/Config.in	Thu Mar  9 17:23:22 2000
@@ -86,6 +86,7 @@
    fi
 
    dep_tristate '    Aztech Sound Galaxy (non-PnP) cards' CONFIG_SOUND_SGALAXY $CONFIG_SOUND_OSS
+   dep_tristate '    ACI mixer (miroPCM12)' CONFIG_SOUND_ACI_MIXER $CONFIG_SOUND_OSS
    dep_tristate '    Crystal CS4232 based (PnP) cards' CONFIG_SOUND_CS4232 $CONFIG_SOUND_OSS
    dep_tristate '    Ensoniq SoundScape support' CONFIG_SOUND_SSCAPE $CONFIG_SOUND_OSS
    dep_tristate '    Gravis Ultrasound support' CONFIG_SOUND_GUS $CONFIG_SOUND_OSS
@@ -115,10 +116,10 @@
    dep_tristate '    PSS (AD1848, ADSP-2115, ESC614) support' CONFIG_SOUND_PSS $CONFIG_SOUND_OSS
    if [ "$CONFIG_SOUND_PSS" = "y" -o "$CONFIG_SOUND_PSS" = "m" ]; then
       bool '      Enable PSS mixer (Beethoven ADSP-16 and other compatibile)' CONFIG_PSS_MIXER
-   fi
-   bool '      Have DSPxxx.LD firmware file' CONFIG_PSS_HAVE_BOOT
-   if [ "$CONFIG_PSS_HAVE_BOOT" = "y" ]; then
-      string '  Full pathname of DSPxxx.LD firmware file' CONFIG_PSS_BOOT_FILE /etc/sound/dsp001.ld
+      bool '      Have DSPxxx.LD firmware file' CONFIG_PSS_HAVE_BOOT
+      if [ "$CONFIG_PSS_HAVE_BOOT" = "y" ]; then
+         string '        Full pathname of DSPxxx.LD firmware file' CONFIG_PSS_BOOT_FILE /etc/sound/dsp001.ld
+      fi
    fi
 
    dep_tristate '    SoftOSS software wave table engine' CONFIG_SOUND_SOFTOSS $CONFIG_SOUND_OSS
@@ -128,6 +129,7 @@
    fi
   
    dep_tristate '    100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support' CONFIG_SOUND_SB $CONFIG_SOUND_OSS
+   dep_tristate '    AWE32 synth' CONFIG_SOUND_AWE32_SYNTH $CONFIG_SOUND_OSS
    dep_tristate '    Full support for Turtle Beach WaveFront (Tropez Plus, Tropez, Maui) synth/soundcards' CONFIG_SOUND_WAVEFRONT $CONFIG_SOUND_OSS m
    dep_tristate '    Limited support for Turtle Beach Wave Front (Maui, Tropez) synthesizers' CONFIG_SOUND_MAUI $CONFIG_SOUND_OSS
    if [ "$CONFIG_SOUND_MAUI" = "y" ]; then
@@ -143,20 +145,33 @@
    dep_tristate '    Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
    dep_tristate '    6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS
   
+   dep_tristate '    Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_SOUND_AEDSP16 $CONFIG_SOUND_OSS
+   if [ "$CONFIG_SOUND_AEDSP16" = "y" -o "$CONFIG_SOUND_AEDSP16" = "m" ]; then
+      bool '      SC-6600 based audio cards (new Audio Excel DSP 16)' CONFIG_SC6600
+      if [ "$CONFIG_SC6600" = "y" ]; then
+         bool '        Activate SC-6600 Joystick Interface' CONFIG_SC6600_JOY
+         int '        SC-6600 CDROM Interface (4=None, 3=IDE, 1=Panasonic, 0=?Sony?)' CONFIG_SC6600_CDROM 4
+         hex '        SC-6600 CDROM Interface I/O Address' CONFIG_SC6600_CDROMBASE 0
+      fi
+      if [ "$CONFIG_SOUND_SB" = "y" -o "$CONFIG_SOUND_SB" = "m" ]; then
+         if [ "$CONFIG_AEDSP16_MSS" != "y" ]; then
+            bool '      Audio Excel DSP 16 (SBPro emulation)' CONFIG_AEDSP16_SBPRO
+         fi
+      fi
+      if [ "$CONFIG_SOUND_MSS" = "y" -o "$CONFIG_SOUND_MSS" = "m" ]; then
+         if [ "$CONFIG_AEDSP16_SBPRO" != "y" ]; then
+            bool '      Audio Excel DSP 16 (MSS emulation)' CONFIG_AEDSP16_MSS
+         fi
+      fi
+      if [ "$CONFIG_SOUND_MPU401" = "y" -o "$CONFIG_SOUND_MPU401" = "m" ]; then
+         bool '      Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
+      fi
+   fi
+	 
    if [ "$CONFIG_ARM" = "y" ]; then
       dep_tristate '    VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
       dep_tristate '    Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS
    fi
-  
-  
-   # Additional low level drivers.
-  
-   mainmenu_option next_comment
-   comment 'Additional low level sound drivers'
-   bool 'Additional low level sound drivers' CONFIG_LOWLEVEL_SOUND $CONFIG_SOUND_OSS
-   if [ "$CONFIG_LOWLEVEL_SOUND" = "y" ]; then
-      source drivers/sound/lowlevel/Config.in
-   fi
-   endmenu
+
 fi
 
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.3.50/linux/drivers/sound/Makefile	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/Makefile	Thu Mar  9 17:23:22 2000
@@ -10,13 +10,7 @@
 SUB_DIRS	:= 
 MOD_SUB_DIRS	:=
 MOD_IN_SUB_DIRS	:=
-ALL_SUB_DIRS	:= $(SUB_DIRS) lowlevel
-
-ifeq ($(CONFIG_LOWLEVEL_SOUND),y)
-    SUB_DIRS		+= lowlevel
-    MOD_IN_SUB_DIRS	+= lowlevel
-endif
-
+ALL_SUB_DIRS	:= $(SUB_DIRS)
 
 
 # All of the (potential) objects that export symbols.
@@ -47,6 +41,7 @@
 
 # Please leave it as is, cause the link order is significant !
 
+obj-$(CONFIG_SOUND_AEDSP16)	+= aedsp16.o
 obj-$(CONFIG_SOUND_PSS)		+= pss.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_TRIX)	+= trix.o ad1848.o sb_lib.o uart401.o
 obj-$(CONFIG_SOUND_OPL3SA1)     += opl3sa.o ad1848.o uart401.o
@@ -69,6 +64,8 @@
 obj-$(CONFIG_SOUND_WAVEARTIST)  += waveartist.o
 obj-$(CONFIG_SOUND_SGALAXY)     += sgalaxy.o ad1848.o
 obj-$(CONFIG_SOUND_AD1816)      += ad1816.o
+obj-$(CONFIG_SOUND_ACI_MIXER)	+= aci.o
+obj-$(CONFIG_SOUND_AWE32_SYNTH)	+= awe_wave.o
 
 obj-$(CONFIG_SOUND_VIA82CXXX)	+= via82cxxx_audio.o sb_lib.o uart401.o ac97.o
 obj-$(CONFIG_SOUND_MSNDCLAS)	+= msnd.o msnd_classic.o
@@ -85,7 +82,7 @@
 
 # Declare multi-part drivers.
 
-list-multi	:= sound.o gus.o pas2.o sb.o softoss2.o vidc_mod.o \
+list-multi	:= sound.o gus.o pas2.o sb.o sb_lib.o softoss2.o vidc_mod.o \
     soundcore.o wavefront.o
 
 sound-objs	:= 							\
@@ -137,8 +134,8 @@
 OX_OBJS		:= $(filter     $(export-objs), $(obj-y))
 M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
 MX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-m)))
-#MI_OBJS		:= $(sort $(filter-out $(export-objs), $(int-m)))
-#MIX_OBJS	:= $(sort $(filter     $(export-objs), $(int-m)))
+MI_OBJS		:= $(sort $(filter-out $(export-objs), $(int-m)))
+MIX_OBJS	:= $(sort $(filter     $(export-objs), $(int-m)))
 
 ifeq ($(CONFIG_LOWLEVEL_SOUND),y)
     O_OBJS	+= lowlevel/lowlevel.o
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/aci.c linux/drivers/sound/aci.c
--- v2.3.50/linux/drivers/sound/aci.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/aci.c	Wed Mar  8 11:37:03 2000
@@ -0,0 +1,718 @@
+/*
+ * Audio Command Interface (ACI) driver (sound/aci.c)
+ *
+ * ACI is a protocol used to communicate with the microcontroller on
+ * some sound cards produced by miro, e.g. the miroSOUND PCM12 and
+ * PCM20. The ACI has been developed for miro by Norberto Pellicci
+ * <pellicci@home.com>. Special thanks to both him and miro for
+ * providing the ACI specification.
+ *
+ * The main function of the ACI is to control the mixer and to get a
+ * product identification. On the PCM20, ACI also controls the radio
+ * tuner on this card, this is supported in the Video for Linux 
+ * radio-miropcm20 driver.
+ * 
+ * This Voxware ACI driver currently only supports the ACI functions
+ * on the miroSOUND PCM12 and PCM20 card. Support for miro sound cards 
+ * with additional ACI functions can easily be added later.
+ *
+ * / NOTE / When compiling as a module, make sure to load the module 
+ * after loading the mad16 module. The initialisation code expects the
+ * MAD16 default mixer to be already available.
+ *
+ * Revision history:
+ *
+ *   1995-11-10  Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
+ *        First version written.
+ *   1995-12-31  Markus Kuhn
+ *        Second revision, general code cleanup.
+ *   1996-05-16	 Hannu Savolainen
+ *	  Integrated with other parts of the driver.
+ *   1996-05-28  Markus Kuhn
+ *        Initialize CS4231A mixer, make ACI first mixer,
+ *        use new private mixer API for solo mode.
+ *   1998-08-18  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
+ *	  Small modification to export ACI functions and 
+ *	  complete modularisation.
+ */
+
+/*
+ * Some driver specific information and features:
+ *
+ * This mixer driver identifies itself to applications as "ACI" in
+ * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
+ *
+ * Proprietary mixer features that go beyond the standard OSS mixer
+ * interface are:
+ * 
+ * Full duplex solo configuration:
+ *
+ *   int solo_mode;
+ *   ioctl(fd, SOUND_MIXER_PRIVATE1, &solo_mode);
+ *
+ *   solo_mode = 0: deactivate solo mode (default)
+ *   solo_mode > 0: activate solo mode
+ *                  With activated solo mode, the PCM input can not any
+ *                  longer hear the signals produced by the PCM output.
+ *                  Activating solo mode is important in duplex mode in order
+ *                  to avoid feedback distortions.
+ *   solo_mode < 0: do not change solo mode (just retrieve the status)
+ *
+ *   When the ioctl() returns 0, solo_mode contains the previous
+ *   status (0 = deactivated, 1 = activated). If solo mode is not
+ *   implemented on this card, ioctl() returns -1 and sets errno to
+ *   EINVAL.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h> 
+
+#include "sound_config.h"
+
+#undef  DEBUG		/* if defined, produce a verbose report via syslog */
+
+int aci_port = 0x354;	/* as determined by bit 4 in the OPTi 929 MC4 register */
+unsigned char aci_idcode[2] = {0, 0};	/* manufacturer and product ID */
+unsigned char aci_version = 0;		/* ACI firmware version	*/
+int aci_solo;		/* status bit of the card that can't be		*
+			 * checked with ACI versions prior to 0xb0	*/
+
+static int aci_present = 0;
+
+#ifdef MODULE                  /* Whether the aci mixer is to be reset.    */
+int aci_reset = 0;             /* Default: don't reset if the driver is a  */
+MODULE_PARM(aci_reset,"i");
+#else                          /* module; use "insmod aci.o aci_reset=1" */
+int aci_reset = 1;             /* to override.                             */
+#endif
+
+
+#define COMMAND_REGISTER    (aci_port)
+#define STATUS_REGISTER     (aci_port + 1)
+#define BUSY_REGISTER       (aci_port + 2)
+
+/*
+ * Wait until the ACI microcontroller has set the READYFLAG in the
+ * Busy/IRQ Source Register to 0. This is required to avoid
+ * overrunning the sound card microcontroller. We do a busy wait here,
+ * because the microcontroller is not supposed to signal a busy
+ * condition for more than a few clock cycles. In case of a time-out,
+ * this function returns -1.
+ *
+ * This busy wait code normally requires less than 15 loops and
+ * practically always less than 100 loops on my i486/DX2 66 MHz.
+ *
+ * Warning: Waiting on the general status flag after reseting the MUTE
+ * function can take a VERY long time, because the PCM12 does some kind
+ * of fade-in effect. For this reason, access to the MUTE function has
+ * not been implemented at all.
+ */
+
+static int busy_wait(void)
+{
+	long timeout;
+
+	for (timeout = 0; timeout < 10000000L; timeout++)
+		if ((inb_p(BUSY_REGISTER) & 1) == 0)
+			return 0;
+
+#ifdef DEBUG
+	printk("ACI: READYFLAG timed out.\n");
+#endif
+
+	return -1;
+}
+
+
+/*
+ * Read the GENERAL STATUS register.
+ */
+
+static int read_general_status(void)
+{
+	unsigned long flags;
+	int status;
+
+	save_flags(flags);
+	cli();
+	
+	if (busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+	
+	status = (unsigned) inb_p(STATUS_REGISTER);
+	restore_flags(flags);
+	return status;
+}
+
+
+/*
+ * The four ACI command types (implied, write, read and indexed) can
+ * be sent to the microcontroller using the following four functions.
+ * If a problem occurred, they return -1.
+ */
+
+int aci_implied_cmd(unsigned char opcode)
+{
+	unsigned long flags;
+
+#ifdef DEBUG
+	printk("ACI: aci_implied_cmd(0x%02x)\n", opcode);
+#endif
+
+	save_flags(flags);
+	cli();
+  
+  	if (read_general_status() < 0 || busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+	
+	outb_p(opcode, COMMAND_REGISTER);
+
+	restore_flags(flags);
+	return 0;
+}
+
+
+int aci_write_cmd(unsigned char opcode, unsigned char parameter)
+{
+	unsigned long flags;
+	int status;
+
+#ifdef DEBUG
+	printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
+#endif
+
+	save_flags(flags);
+	cli();
+	
+	if (read_general_status() < 0 || busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+
+	outb_p(opcode, COMMAND_REGISTER);
+	if (busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+
+	outb_p(parameter, COMMAND_REGISTER);
+
+	if ((status = read_general_status()) < 0) {
+		restore_flags(flags);
+		return -1;
+	}
+
+	/* polarity of the INVALID flag depends on ACI version */
+	if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
+	  (aci_version >= 0xb0 && (status & 0x40) == 0)) {
+	  	restore_flags(flags);
+		printk("ACI: invalid write command 0x%02x, 0x%02x.\n",
+			opcode, parameter);
+		return -1;
+	}
+
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * This write command send 2 parameters instead of one.
+ * Only used in PCM20 radio frequency tuning control
+ */
+
+int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2)
+{
+	unsigned long flags;
+	int status;
+
+#ifdef DEBUG
+	printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode, parameter, parameter2);
+#endif
+
+	save_flags(flags);
+	cli();
+	
+	if (read_general_status() < 0 || busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+
+	outb_p(opcode, COMMAND_REGISTER);
+	if (busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+
+	outb_p(parameter, COMMAND_REGISTER);
+	if (busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+	
+	outb_p(parameter2, COMMAND_REGISTER);
+	
+	if ((status = read_general_status()) < 0) {
+		restore_flags(flags);
+		return -1;
+	}
+	
+	/* polarity of the INVALID flag depends on ACI version */
+	if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
+	  (aci_version >= 0xb0 && (status & 0x40) == 0)) {
+		restore_flags(flags);
+#if 0	/* Frequency tuning works, but the INVALID flag is set ??? */
+		printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n",
+			opcode, parameter, parameter2);
+#endif
+		return -1;
+  	}
+	
+	restore_flags(flags);
+	return 0;
+}
+
+int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter)
+{
+	unsigned long flags;
+	int i = 0;
+	
+	save_flags(flags);
+	cli();
+ 
+ 	if (read_general_status() < 0) {
+		restore_flags(flags);
+		return -1;
+	}
+	while (i < length) {
+		if (busy_wait()) {
+			restore_flags(flags);
+			return -1;
+		}
+			
+		outb_p(opcode, COMMAND_REGISTER);
+		if (busy_wait()) {
+			restore_flags(flags);
+			return -1;
+		}
+			
+		parameter[i++] = inb_p(STATUS_REGISTER);
+#ifdef DEBUG
+		if (i == 1)
+			printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n",
+				opcode, length, parameter[i-1]);
+		else
+			printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter[i-1]);
+#endif
+	}
+
+	restore_flags(flags);
+	return 0;
+}
+
+
+int aci_indexed_cmd(unsigned char opcode, unsigned char index,
+		       unsigned char *parameter)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+  
+	if (read_general_status() < 0 || busy_wait()) {
+	  	restore_flags(flags);
+		return -1;
+	}
+	
+	outb_p(opcode, COMMAND_REGISTER);
+	if (busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+	
+	outb_p(index, COMMAND_REGISTER);
+	if (busy_wait()) {
+		restore_flags(flags);
+		return -1;
+	}
+	
+	*parameter = inb_p(STATUS_REGISTER);
+#ifdef DEBUG
+	printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
+		*parameter);
+#endif
+
+	restore_flags(flags);
+	return 0;
+}
+
+
+/*
+ * The following macro SCALE can be used to scale one integer volume
+ * value into another one using only integer arithmetic. If the input
+ * value x is in the range 0 <= x <= xmax, then the result will be in
+ * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
+ *
+ * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
+ * following nice properties:
+ *
+ * - SCALE(xmax,ymax,xmax) = ymax
+ * - SCALE(xmax,ymax,0) = 0
+ * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
+ *
+ * In addition, the rounding error is minimal and nicely distributed.
+ * The proofs are left as an exercise to the reader.
+ */
+
+#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
+
+
+static int getvolume(caddr_t arg,
+		     unsigned char left_index, unsigned char right_index)
+{
+	int vol;
+	unsigned char buf;
+
+	/* left channel */
+	if (aci_indexed_cmd(0xf0, left_index, &buf))
+		return -EIO;
+	vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
+	
+	/* right channel */
+	if (aci_indexed_cmd(0xf0, right_index, &buf))
+		return -EIO;
+	vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
+
+	return (*(int *) arg = vol);
+}
+
+
+static int setvolume(caddr_t arg, 
+		     unsigned char left_index, unsigned char right_index)
+{
+	int vol, ret;
+
+	/* left channel */
+	vol = *(int *)arg & 0xff;
+	if (vol > 100)
+		vol = 100;
+	vol = SCALE(100, 0x20, vol);
+	if (aci_write_cmd(left_index, 0x20 - vol))
+		return -EIO;
+	ret = SCALE(0x20, 100, vol);
+
+
+	/* right channel */
+	vol = (*(int *)arg >> 8) & 0xff;
+	if (vol > 100)
+		vol = 100;
+	vol = SCALE(100, 0x20, vol);
+	if (aci_write_cmd(right_index, 0x20 - vol))
+		return -EIO;
+	ret |= SCALE(0x20, 100, vol) << 8;
+ 
+	return (*(int *) arg = ret);
+}
+
+
+static int
+aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+	int status, vol;
+	unsigned char buf;
+
+	/* handle solo mode control */
+	if (cmd == SOUND_MIXER_PRIVATE1) {
+		if (*(int *) arg >= 0) {
+			aci_solo = !!*(int *) arg;
+			if (aci_write_cmd(0xd2, aci_solo))
+				return -EIO;
+		} else if (aci_version >= 0xb0) {
+			if ((status = read_general_status()) < 0)
+				return -EIO;
+			return (*(int *) arg = (status & 0x20) == 0);
+		}
+		
+		return (*(int *) arg = aci_solo);
+	}
+	
+	if (((cmd >> 8) & 0xff) == 'M') {
+		if (cmd & IOC_IN)
+			/* read and write */
+			switch (cmd & 0xff) {
+				case SOUND_MIXER_VOLUME:
+					return setvolume(arg, 0x01, 0x00);
+				case SOUND_MIXER_CD:
+					return setvolume(arg, 0x3c, 0x34);
+				case SOUND_MIXER_MIC:
+					return setvolume(arg, 0x38, 0x30);
+				case SOUND_MIXER_LINE:
+					return setvolume(arg, 0x39, 0x31);
+				case SOUND_MIXER_SYNTH:
+					return setvolume(arg, 0x3b, 0x33);
+				case SOUND_MIXER_PCM:
+					return setvolume(arg, 0x3a, 0x32);
+				case SOUND_MIXER_LINE1:  /* AUX1 */
+					return setvolume(arg, 0x3d, 0x35);
+				case SOUND_MIXER_LINE2:  /* AUX2 */
+					return setvolume(arg, 0x3e, 0x36);
+				case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
+					vol = *(int *) arg & 0xff;
+					if (vol > 100)
+						vol = 100;
+					vol = SCALE(100, 3, vol);
+					if (aci_write_cmd(0x03, vol))
+						return -EIO;
+					vol = SCALE(3, 100, vol);
+					return (*(int *) arg = vol | (vol << 8));
+				case SOUND_MIXER_RECSRC:
+					return (*(int *) arg = 0);
+					break;
+				default:
+					return -EINVAL;
+			}
+		else
+			/* only read */
+			switch (cmd & 0xff) {
+				case SOUND_MIXER_DEVMASK:
+					return (*(int *) arg =
+				 SOUND_MASK_VOLUME | SOUND_MASK_CD    |
+				 SOUND_MASK_MIC    | SOUND_MASK_LINE  |
+				 SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
+#if 0
+				 SOUND_MASK_IGAIN  |
+#endif
+				 SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
+				 	break;
+				case SOUND_MIXER_STEREODEVS:
+					return (*(int *) arg =
+				 SOUND_MASK_VOLUME | SOUND_MASK_CD   |
+				 SOUND_MASK_MIC    | SOUND_MASK_LINE |
+				 SOUND_MASK_SYNTH  | SOUND_MASK_PCM  |
+				 SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
+				 	break;
+				case SOUND_MIXER_RECMASK:
+					return (*(int *) arg = 0);
+					break;
+				case SOUND_MIXER_RECSRC:
+					return (*(int *) arg = 0);
+					break;
+				case SOUND_MIXER_CAPS:
+					return (*(int *) arg = 0);
+					break;
+				case SOUND_MIXER_VOLUME:
+					return getvolume(arg, 0x04, 0x03);
+				case SOUND_MIXER_CD:
+					return getvolume(arg, 0x0a, 0x09);
+				case SOUND_MIXER_MIC:
+					return getvolume(arg, 0x06, 0x05);
+				case SOUND_MIXER_LINE:
+					return getvolume(arg, 0x08, 0x07);
+				case SOUND_MIXER_SYNTH:
+					return getvolume(arg, 0x0c, 0x0b);
+				case SOUND_MIXER_PCM:
+					return getvolume(arg, 0x0e, 0x0d);
+				case SOUND_MIXER_LINE1:  /* AUX1 */
+					return getvolume(arg, 0x11, 0x10);
+				case SOUND_MIXER_LINE2:  /* AUX2 */
+					return getvolume(arg, 0x13, 0x12);
+				case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
+					if (aci_indexed_cmd(0xf0, 0x21, &buf))
+						return -EIO;
+					vol = SCALE(3, 100, buf <= 3 ? buf : 3);
+					vol |= vol << 8;
+					return (*(int *) arg = vol);
+				default:
+					return -EINVAL;
+			}
+	}
+	
+	return -EINVAL;
+}
+
+
+static struct mixer_operations aci_mixer_operations =
+{
+	"ACI",
+	"ACI mixer",
+	aci_mixer_ioctl,
+	NULL
+};
+
+static unsigned char
+mad_read (int port)
+{
+	outb (0xE3, 0xf8f); /* Write MAD16 password */
+	return inb (port);  /* Read from port */
+}
+
+
+/*
+ * Check, whether there actually is any ACI port operational and if
+ * one was found, then initialize the ACI interface, reserve the I/O
+ * addresses and attach the new mixer to the relevant VoxWare data
+ * structures.
+ *
+ * Returns:  1   ACI mixer detected
+ *           0   nothing there
+ *
+ * There is also an internal mixer in the codec (CS4231A or AD1845),
+ * that deserves no purpose in an ACI based system which uses an
+ * external ACI controlled stereo mixer. Make sure that this codec
+ * mixer has the AUX1 input selected as the recording source, that the
+ * input gain is set near maximum and that the other channels going
+ * from the inputs to the codec output are muted.
+ */
+
+static int __init attach_aci(void)
+{
+	char *boardname = "unknown";
+	int volume;
+
+#define MC4_PORT	0xf90
+
+	aci_port =
+		(mad_read(MC4_PORT) & 0x10) ? 0x344 : 0x354;
+
+	if (check_region(aci_port, 3)) {
+#ifdef DEBUG
+		printk("ACI: I/O area 0x%03x-0x%03x already used.\n",
+			aci_port, aci_port+2);
+#endif
+		return 0;
+	}
+	
+	if (aci_read_cmd(0xf2, 2, aci_idcode)) {
+#ifdef DEBUG
+		printk("ACI: Failed to read idcode.\n");
+#endif
+		return 0;
+	}
+	
+	if (aci_read_cmd(0xf1, 1, &aci_version)) {
+#ifdef DEBUG
+		printk("ACI: Failed to read version.\n");
+#endif
+		return 0;
+	}
+
+	if (aci_idcode[0] == 0x6d) {
+		/* It looks like a miro sound card. */
+		switch (aci_idcode[1]) {
+			case 0x41:
+				boardname = "PCM1 pro / early PCM12";
+				break;
+			case 0x42:
+				boardname = "PCM12";
+				break;
+			case 0x43:
+				boardname = "PCM20";
+				break;
+			default:
+				boardname = "unknown miro";
+		}
+	} else
+#ifndef DEBUG
+	return 0;
+#endif
+  
+  	printk("<ACI %02x, id %02x %02x (%s)> at 0x%03x\n",
+		aci_version, aci_idcode[0], aci_idcode[1], boardname, aci_port);
+
+	if (aci_reset) {
+		/* initialize ACI mixer */
+		aci_implied_cmd(0xff);
+		aci_solo = 0;
+	}
+
+	/* attach the mixer */
+	request_region(aci_port, 3, "sound mixer (ACI)");
+	if (num_mixers < MAX_MIXER_DEV) {
+		if (num_mixers > 0 &&
+		  !strncmp("MAD16 WSS", mixer_devs[num_mixers-1]->name, 9)) {
+			/*
+			 * The previously registered mixer device is the CS4231A which
+			 * has no function on an ACI card. Make the ACI mixer the first
+			 * of the two mixer devices.
+			 */
+			mixer_devs[num_mixers] = mixer_devs[num_mixers-1];
+			mixer_devs[num_mixers-1] = &aci_mixer_operations;
+			/*
+			 * Initialize the CS4231A mixer with reasonable values. It is
+			 * unlikely that the user ever will want to change these as all
+			 * channels can be mixed via ACI.
+			 */
+			volume = 0x6464;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_PCM, (caddr_t) &volume);
+			volume = 0x6464;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_IGAIN,   (caddr_t) &volume);
+			volume = 0;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_SPEAKER, (caddr_t) &volume);
+			volume = 0;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_MIC, (caddr_t) &volume);
+			volume = 0;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_IMIX, (caddr_t) &volume);
+			volume = 0;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_LINE1, (caddr_t) &volume);
+			volume = 0;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_LINE2, (caddr_t) &volume);
+			volume = 0;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_LINE3, (caddr_t) &volume);
+			volume = SOUND_MASK_LINE1;
+			mixer_devs[num_mixers]->ioctl(num_mixers,
+				SOUND_MIXER_WRITE_RECSRC, (caddr_t) &volume);
+			num_mixers++;
+		} else
+			mixer_devs[num_mixers++] = &aci_mixer_operations;
+	}
+
+	/* Just do something; otherwise the first write command fails, at
+	 * least with my PCM20.
+	 */
+	aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_READ_VOLUME, (caddr_t) &volume);
+	
+	if (aci_reset) {
+		/* Initialize ACI mixer with reasonable power-up values */
+		volume = 0x3232;
+		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_VOLUME, (caddr_t) &volume);
+		volume = 0x3232;
+		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_SYNTH,  (caddr_t) &volume);
+		volume = 0x3232;
+		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_PCM,    (caddr_t) &volume);
+		volume = 0x3232;
+		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE,   (caddr_t) &volume);
+		volume = 0x3232;
+		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_MIC,    (caddr_t) &volume);
+		volume = 0x3232;
+		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_CD,     (caddr_t) &volume);
+		volume = 0x3232;
+		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE1,  (caddr_t) &volume);
+		volume = 0x3232;
+		aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE2,  (caddr_t) &volume);
+	}
+
+	aci_present = 1;
+
+	return 1;
+}
+
+static void __exit unload_aci(void)
+{
+	if (aci_present)
+		release_region(aci_port, 3);
+}
+
+module_init(attach_aci);
+module_exit(unload_aci);
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c
--- v2.3.50/linux/drivers/sound/ad1816.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/ad1816.c	Wed Mar  8 11:37:03 2000
@@ -1386,7 +1386,7 @@
 	io	= ints[1];
 	irq	= ints[2];
 	dma	= ints[3];
-	dma16	= ints[4];
+	dma2	= ints[4];
 
 	return 1;
 }
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.3.50/linux/drivers/sound/ad1848.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/ad1848.c	Fri Mar 10 10:55:44 2000
@@ -2502,11 +2502,6 @@
 	int dma = hw_config->dma;
 	int dma2 = hw_config->dma2;
 
-	if(hw_config->io_base != -1 || hw_config->irq == -1 || hw_config->dma == -1) {
-		printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n");
-		return;
-	}
-
 	if (hw_config->card_subtype == 1)	/* Has no IRQ/DMA registers */
 	{
 		hw_config->slots[0] = ad1848_init("MS Sound System", hw_config->io_base + 4,
@@ -2573,9 +2568,6 @@
 					  dma2, 0,
 					  hw_config->osp);
 	request_region(hw_config->io_base, 4, "WSS config");
-
-	SOUND_LOCK;
-	loaded = 1;
 }
 
 void unload_ms_sound(struct address_info *hw_config)
@@ -2710,15 +2702,6 @@
 EXPORT_SYMBOL(attach_ms_sound);
 EXPORT_SYMBOL(unload_ms_sound);
 
-MODULE_PARM(io, "i");			/* I/O for a raw AD1848 card */
-MODULE_PARM(irq, "i");			/* IRQ to use */
-MODULE_PARM(dma, "i");			/* First DMA channel */
-MODULE_PARM(dma2, "i");			/* Second DMA channel */
-MODULE_PARM(type, "i");			/* Card type */
-MODULE_PARM(deskpro_xl, "i");		/* Special magic for Deskpro XL boxen */
-MODULE_PARM(deskpro_m, "i");		/* Special magic for Deskpro M box */
-MODULE_PARM(soundpro, "i");		/* More special magic for SoundPro chips */
-
 static int __initdata io = -1;
 static int __initdata irq = -1;
 static int __initdata dma = -1;
@@ -2727,21 +2710,41 @@
 
 static struct address_info cfg;
 
+MODULE_PARM(io, "i");                   /* I/O for a raw AD1848 card */
+MODULE_PARM(irq, "i");                  /* IRQ to use */
+MODULE_PARM(dma, "i");                  /* First DMA channel */
+MODULE_PARM(dma2, "i");                 /* Second DMA channel */
+MODULE_PARM(type, "i");                 /* Card type */
+MODULE_PARM(deskpro_xl, "i");           /* Special magic for Deskpro XL boxen
+*/
+MODULE_PARM(deskpro_m, "i");            /* Special magic for Deskpro M box */
+MODULE_PARM(soundpro, "i");             /* More special magic for SoundPro
+chips */
+
 static int __init init_ad1848(void)
 {
 	printk(KERN_INFO "ad1848/cs4248 codec driver Copyright (C) by Hannu Savolainen 1993-1996\n");
 
-	cfg.irq = irq;
-	cfg.io_base = io;
-	cfg.dma = dma;
-	cfg.dma2 = dma2;
-	cfg.card_subtype = type;
+	if(io != -1) {
+		if(irq == -1 || dma == -1) {
+			printk(KERN_WARNING "ad1848: must give I/O , IRQ and DMA.\n");
+			return -EINVAL;
+		}
+
+		cfg.irq = irq;
+		cfg.io_base = io;
+		cfg.dma = dma;
+		cfg.dma2 = dma2;
+		cfg.card_subtype = type;
 
-	if(probe_ms_sound(&cfg)) {
+		if(!probe_ms_sound(&cfg))
+			return -ENODEV;
 		attach_ms_sound(&cfg);
-		return 0;
-	} else
-		return -ENODEV;
+		loaded = 1;
+	}
+	
+	SOUND_LOCK;
+	return 0;
 }
 
 static void __exit cleanup_ad1848(void)
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c
--- v2.3.50/linux/drivers/sound/aedsp16.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/aedsp16.c	Wed Mar  8 11:37:03 2000
@@ -0,0 +1,1389 @@
+/*
+   drivers/sound/lowlevel/aedsp16.c
+
+   Audio Excel DSP 16 software configuration routines
+   Copyright (C) 1995,1996,1997,1998  Riccardo Facchetti (fizban@tin.it)
+
+   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.
+
+ */
+/*
+ * Include the main OSS Lite header file. It include all the os, OSS Lite, etc
+ * headers needed by this source.
+ */
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include "sound_config.h"
+#include "soundmodule.h"
+
+/*
+ * Sanity checks
+ */
+
+#if defined(CONFIG_SOUND_AEDSP16_SBPRO) && defined(CONFIG_SOUND_AEDSP16_MSS)
+#error You have to enable only one of the MSS and SBPRO emulations.
+#endif
+
+/*
+
+   READ THIS
+
+   This module started to configure the Audio Excel DSP 16 Sound Card.
+   Now works with the SC-6000 (old aedsp16) and new SC-6600 based cards.
+
+   NOTE: I have NO idea about Audio Excel DSP 16 III. If someone owns this
+   audio card and want to see the kernel support for it, please contact me.
+
+   Audio Excel DSP 16 is an SB pro II, Microsoft Sound System and MPU-401
+   compatible card.
+   It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq),
+   so before this module, the only way to configure the DSP under linux was
+   boot the MS-DOS loading the sound.sys device driver (this driver soft-
+   configure the sound board hardware by massaging someone of its registers),
+   and then ctrl-alt-del to boot linux with the DSP configured by the DOS
+   driver.
+
+   This module works configuring your Audio Excel DSP 16's irq, dma and
+   mpu-401-irq. The OSS Lite routines rely on the fact that if the
+   hardware is there, they can detect it. The problem with AEDSP16 is
+   that no hardware can be found by the probe routines if the sound card
+   is not configured properly. Sometimes the kernel probe routines can find
+   an SBPRO even when the card is not configured (this is the standard setup
+   of the card), but the SBPRO emulation don't work well if the card is not
+   properly initialized. For this reason
+
+   aedsp16_init_board()
+
+   routine is called before the OSS Lite probe routines try to detect the
+   hardware.
+
+   NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS)
+
+   NOTE: Now it works with SC-6000 and SC-6600 based audio cards. The new cards
+   have no jumper switch at all. No more WSS or MPU-401 I/O port switches. They
+   have to be configured by software.
+
+   NOTE: The driver is merged with the new OSS Lite sound driver. It works
+   as a lowlevel driver.
+
+   The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS;
+   the OSS Lite sound driver can be configured for SBPRO and MSS cards
+   at the same time, but the aedsp16 can't be two cards!!
+   When we configure it, we have to choose the SBPRO or the MSS emulation
+   for AEDSP16. We also can install a *REAL* card of the other type (see [1]).
+
+   NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO
+   please let me know if it works.
+
+   The MPU-401 support can be compiled in together with one of the other
+   two operating modes.
+
+   NOTE: This is something like plug-and-play: we have only to plug
+   the AEDSP16 board in the socket, and then configure and compile
+   a kernel that uses the AEDSP16 software configuration capability.
+   No jumper setting is needed!
+
+   For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3
+   you have just to make config the OSS Lite package, configuring
+   the AEDSP16 sound card, then activating the SBPro emulation mode
+   and at last configuring IRQ and DMA.
+   Compile the kernel and run it.
+
+   NOTE: This means for SC-6000 cards that you can choose irq and dma,
+   but not the I/O addresses. To change I/O addresses you have to set
+   them with jumpers. For SC-6600 cards you have no jumpers so you have
+   to set up your full card configuration in the make config.
+
+   You can change the irq/dma/mirq settings WITHOUT THE NEED to open
+   your computer and massage the jumpers (there are no irq/dma/mirq
+   jumpers to be configured anyway, only I/O BASE values have to be
+   configured with jumpers)
+
+   For some ununderstandable reason, the card default of irq 7, dma 1,
+   don't work for me. Seems to be an IRQ or DMA conflict. Under heavy
+   HDD work, the kernel start to erupt out a lot of messages like:
+
+   'Sound: DMA timed out - IRQ/DRQ config error?'
+
+   For what I can say, I have NOT any conflict at irq 7 (under linux I'm
+   using the lp polling driver), and dma line 1 is unused as stated by
+   /proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so
+   I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows!
+   Anyway a setting of irq 10, dma 3 works really fine.
+
+   NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know
+   the emulation mode, all the installed hardware and the hardware
+   configuration (irq and dma settings of all the hardware).
+
+   This init module should work with SBPRO+MSS, when one of the two is
+   the AEDSP16 emulation and the other the real card. (see [1])
+   For example:
+
+   AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other
+   AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other
+
+   MPU401 should work. (see [2])
+
+   [1]
+       ---
+       Date: Mon, 29 Jul 1997 08:35:40 +0100
+       From: Mr S J Greenaway <sjg95@unixfe.rl.ac.uk>
+
+       [...]
+       Just to let you know got my Audio Excel (emulating a MSS) working
+       with my original SB16, thanks for the driver!
+       [...]
+       ---
+
+   [2] Not tested by me for lack of hardware.
+
+   TODO, WISHES AND TECH
+
+   - About I/O ports allocation -
+
+   Request the 2x0h region (port base) in any case if we are using this card.
+
+   NOTE: the "aedsp16 (base)" string with which we are requesting the aedsp16
+   port base region (see code) does not mean necessarily that we are emulating
+   sbpro.  Even if this region is the sbpro I/O ports region, we use this
+   region to access the control registers of the card, and if emulating
+   sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro
+   registers are not used, in no way, to emulate an sbpro: they are
+   used only for configuration purposes.
+
+   Started Fri Mar 17 16:13:18 MET 1995
+
+   v0.1 (ALPHA, was an user-level program called AudioExcelDSP16.c)
+   - Initial code.
+   v0.2 (ALPHA)
+   - Cleanups.
+   - Integrated with Linux voxware v 2.90-2 kernel sound driver.
+   - SoundBlaster Pro mode configuration.
+   - Microsoft Sound System mode configuration.
+   - MPU-401 mode configuration.
+   v0.3 (ALPHA)
+   - Cleanups.
+   - Rearranged the code to let aedsp16_init_board be more general.
+   - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
+   inclusion too. We rely on os.h
+   - Used the  to get a variable
+   len string (we are not sure about the len of Copyright string).
+   This works with any SB and compatible.
+   - Added the code to request_region at device init (should go in
+   the main body of voxware).
+   v0.4 (BETA)
+   - Better configure.c patch for aedsp16 configuration (better
+   logic of inclusion of AEDSP16 support)
+   - Modified the conditional compilation to better support more than
+   one sound card of the emulated type (read the NOTES above)
+   - Moved the sb init routine from the attach to the very first
+   probe in sb_card.c
+   - Rearrangements and cleanups
+   - Wiped out some unnecessary code and variables: this is kernel
+   code so it is better save some TEXT and DATA
+   - Fixed the request_region code. We must allocate the aedsp16 (sbpro)
+   I/O ports in any case because they are used to access the DSP
+   configuration registers and we can not allow anyone to get them.
+   v0.5
+   - cleanups on comments
+   - prep for diffs against v3.0-proto-950402
+   v0.6
+   - removed the request_region()s when compiling the MODULE sound.o
+   because we are not allowed (by the actual voxware structure) to
+   release_region()
+   v0.7 (pre ALPHA, not distributed)
+   - started porting this module to kernel 1.3.84. Dummy probe/attach
+   routines.
+   v0.8 (ALPHA)
+   - attached all the init routines.
+   v0.9 (BETA)
+   - Integrated with linux-pre2.0.7
+   - Integrated with configuration scripts.
+   - Cleaned up and beautyfied the code.
+   v0.9.9 (BETA)
+   - Thanks to Piercarlo Grandi: corrected the conditonal compilation code.
+     Now only the code configured is compiled in, with some memory saving.
+   v0.9.10
+   - Integration into the sound/lowlevel/ section of the sound driver.
+   - Re-organized the code.
+   v0.9.11 (not distributed)
+   - Rewritten the init interface-routines to initialize the AEDSP16 in
+     one shot.
+   - More cosmetics.
+   - SC-6600 support.
+   - More soft/hard configuration.
+   v0.9.12
+   - Refined the v0.9.11 code with conditional compilation to distinguish
+     between SC-6000 and SC-6600 code.
+   v1.0.0
+   - Prep for merging with OSS Lite and Linux kernel 2.1.13
+   - Corrected a bug in request/check/release region calls (thanks to the
+     new kernel exception handling).
+   v1.1
+   - Revamped for integration with new modularized sound drivers: to enhance
+     the flexibility of modular version, I have removed all the conditional
+     compilation for SBPRO, MPU and MSS code. Now it is all managed with
+     the ae_config structure.
+   v1.2
+   - Module informations added.
+   - Removed aedsp16_delay_10msec(), now using mdelay(10)
+   - All data and funcs moved to .*.init section.
+
+   Known Problems:
+   - Audio Excel DSP 16 III don't work with this driver.
+
+   Credits:
+   Many thanks to Gerald Britton <gbritton@CapAccess.org>. He helped me a
+   lot in testing the 0.9.11 and 0.9.12 versions of this driver.
+
+ */
+
+
+#define VERSION "1.2"		/* Version of Audio Excel DSP 16 driver */
+
+#undef	AEDSP16_DEBUG 1		/* Define this to enable debug code     */
+#undef	AEDSP16_DEBUG_MORE 1	/* Define this to enable more debug     */
+#undef	AEDSP16_INFO  1		/* Define this to enable info code      */
+
+#if defined(AEDSP16_DEBUG)
+# define DBG(x)  printk x
+# if defined(AEDSP16_DEBUG_MORE)
+#  define DBG1(x) printk x
+# else
+#  define DBG1(x)
+# endif
+#else
+# define DBG(x)
+# define DBG1(x)
+#endif
+
+/*
+ * Misc definitions
+ */
+#define TRUE	1
+#define FALSE	0
+
+/*
+ * Region Size for request/check/release region.
+ */
+#define IOBASE_REGION_SIZE	0x10
+
+/*
+ * Hardware related defaults
+ */
+#define DEF_AEDSP16_IOB 0x220   /* 0x220(default) 0x240                 */
+#define DEF_AEDSP16_IRQ 7	/* 5 7(default) 9 10 11                 */
+#define DEF_AEDSP16_MRQ 0	/* 5 7 9 10 0(default), 0 means disable */
+#define DEF_AEDSP16_DMA 1	/* 0 1(default) 3                       */
+
+/*
+ * Commands of AEDSP16's DSP (SBPRO+special).
+ * Some of them are COMMAND_xx, in the future they may change.
+ */
+#define WRITE_MDIRQ_CFG   0x50	/* Set M&I&DRQ mask (the real config)   */
+#define COMMAND_52        0x52	/*                                      */
+#define READ_HARD_CFG     0x58	/* Read Hardware Config (I/O base etc)  */
+#define COMMAND_5C        0x5c	/*                                      */
+#define COMMAND_60        0x60	/*                                      */
+#define COMMAND_66        0x66	/*                                      */
+#define COMMAND_6C        0x6c	/*                                      */
+#define COMMAND_6E        0x6e	/*                                      */
+#define COMMAND_88        0x88	/*                                      */
+#define DSP_INIT_MSS      0x8c	/* Enable Microsoft Sound System mode   */
+#define COMMAND_C5        0xc5	/*                                      */
+#define GET_DSP_VERSION   0xe1	/* Get DSP Version                      */
+#define GET_DSP_COPYRIGHT 0xe3	/* Get DSP Copyright                    */
+
+/*
+ * Offsets of AEDSP16 DSP I/O ports. The offset is added to base I/O port
+ * to have the actual I/O port.
+ * Register permissions are:
+ * (wo) == Write Only
+ * (ro) == Read  Only
+ * (w-) == Write
+ * (r-) == Read
+ */
+#define DSP_RESET    0x06	/* offset of DSP RESET             (wo) */
+#define DSP_READ     0x0a	/* offset of DSP READ              (ro) */
+#define DSP_WRITE    0x0c	/* offset of DSP WRITE             (w-) */
+#define DSP_COMMAND  0x0c	/* offset of DSP COMMAND           (w-) */
+#define DSP_STATUS   0x0c	/* offset of DSP STATUS            (r-) */
+#define DSP_DATAVAIL 0x0e	/* offset of DSP DATA AVAILABLE    (ro) */
+
+
+#define RETRY           10	/* Various retry values on I/O opera-   */
+#define STATUSRETRY   1000	/* tions. Sometimes we have to          */
+#define HARDRETRY   500000	/* wait for previous cmd to complete    */
+
+/*
+ * Size of character arrays that store name and version of sound card
+ */
+#define CARDNAMELEN 15		/* Size of the card's name in chars     */
+#define CARDVERLEN  2		/* Size of the card's version in chars  */
+
+#if defined(CONFIG_SC6600)
+/*
+ * Bitmapped flags of hard configuration
+ */
+/*
+ * Decode macros (xl == low byte, xh = high byte)
+ */
+#define IOBASE(xl)		((xl & 0x01)?0x240:0x220)
+#define JOY(xl)  		(xl & 0x02)
+#define MPUADDR(xl)		( 			\
+				(xl & 0x0C)?0x330:	\
+				(xl & 0x08)?0x320:	\
+				(xl & 0x04)?0x310:	\
+						0x300)
+#define WSSADDR(xl)		((xl & 0x10)?0xE80:0x530)
+#define CDROM(xh)		(xh & 0x20)
+#define CDROMADDR(xh)		(((xh & 0x1F) << 4) + 0x200)
+/*
+ * Encode macros
+ */
+#define BLDIOBASE(xl, val) {		\
+	xl &= ~0x01; 			\
+	if (val == 0x240)		\
+		xl |= 0x01;		\
+	}
+#define BLDJOY(xl, val) {		\
+	xl &= ~0x02; 			\
+	if (val == 1)			\
+		xl |= 0x02;		\
+	}
+#define BLDMPUADDR(xl, val) {		\
+	xl &= ~0x0C;			\
+	switch (val) {			\
+		case 0x330:		\
+			xl |= 0x0C;	\
+			break;		\
+		case 0x320:		\
+			xl |= 0x08;	\
+			break;		\
+		case 0x310:		\
+			xl |= 0x04;	\
+			break;		\
+		case 0x300:		\
+			xl |= 0x00;	\
+			break;		\
+		default:		\
+			xl |= 0x00;	\
+			break;		\
+		}			\
+	}
+#define BLDWSSADDR(xl, val) {		\
+	xl &= ~0x10; 			\
+	if (val == 0xE80)		\
+		xl |= 0x10;		\
+	}
+#define BLDCDROM(xh, val) {		\
+	xh &= ~0x20; 			\
+	if (val == 1)			\
+		xh |= 0x20;		\
+	}
+#define BLDCDROMADDR(xh, val) {		\
+	int tmp = val;			\
+	tmp -= 0x200;			\
+	tmp >>= 4;			\
+	tmp &= 0x1F;			\
+	xh |= tmp;			\
+	xh &= 0x7F;			\
+	xh |= 0x40;			\
+	}
+#endif /* CONFIG_SC6600 */
+
+/*
+ * Bit mapped flags for calling aedsp16_init_board(), and saving the current
+ * emulation mode.
+ */
+#define INIT_NONE   (0   )
+#define INIT_SBPRO  (1<<0)
+#define INIT_MSS    (1<<1)
+#define INIT_MPU401 (1<<2)
+
+static int      soft_cfg __initdata = 0;	/* bitmapped config */
+static int      soft_cfg_mss __initdata = 0;	/* bitmapped mss config */
+static int      ver[CARDVERLEN] __initdata = {0, 0};	/* DSP Ver:
+						   hi->ver[0] lo->ver[1] */
+
+#if defined(CONFIG_SC6600)
+static int	hard_cfg[2]     /* lo<-hard_cfg[0] hi<-hard_cfg[1]      */
+                     __initdata = { 0, 0};
+#endif /* CONFIG_SC6600 */
+
+#if defined(CONFIG_SC6600)
+/* Decoded hard configuration */
+struct	d_hcfg {
+	int iobase;
+	int joystick;
+	int mpubase;
+	int wssbase;
+	int cdrom;
+	int cdrombase;
+};
+
+struct d_hcfg decoded_hcfg __initdata = {0, };
+
+#endif /* CONFIG_SC6600 */
+
+/* orVals contain the values to be or'ed       				*/
+struct orVals {
+	int	val;		/* irq|mirq|dma                         */
+	int	or;		/* soft_cfg |= TheStruct.or             */
+};
+
+/* aedsp16_info contain the audio card configuration                  */
+struct aedsp16_info {
+	int base_io;            /* base I/O address for accessing card  */
+	int irq;                /* irq value for DSP I/O                */
+	int mpu_irq;            /* irq for mpu401 interface I/O         */
+	int dma;                /* dma value for DSP I/O                */
+	int mss_base;           /* base I/O for Microsoft Sound System  */
+	int mpu_base;           /* base I/O for MPU-401 emulation       */
+	int init;               /* Initialization status of the card    */
+};
+
+/*
+ * Magic values that the DSP will eat when configuring irq/mirq/dma
+ */
+/* DSP IRQ conversion array             */
+static struct orVals orIRQ[] __initdata = {
+	{0x05, 0x28},
+	{0x07, 0x08},
+	{0x09, 0x10},
+	{0x0a, 0x18},
+	{0x0b, 0x20},
+	{0x00, 0x00}
+};
+
+/* MPU-401 IRQ conversion array         */
+static struct orVals orMIRQ[] __initdata = {
+	{0x05, 0x04},
+	{0x07, 0x44},
+	{0x09, 0x84},
+	{0x0a, 0xc4},
+	{0x00, 0x00}
+};
+
+/* DMA Channels conversion array        */
+static struct orVals orDMA[] __initdata = {
+	{0x00, 0x01},
+	{0x01, 0x02},
+	{0x03, 0x03},
+	{0x00, 0x00}
+};
+
+static struct aedsp16_info ae_config __initdata = {
+	DEF_AEDSP16_IOB,
+	DEF_AEDSP16_IRQ,
+	DEF_AEDSP16_MRQ,
+	DEF_AEDSP16_DMA,
+	-1,
+	-1,
+	INIT_NONE
+};
+
+/*
+ * Buffers to store audio card informations
+ */
+static char     DSPCopyright[CARDNAMELEN + 1] __initdata = {0, };
+static char     DSPVersion[CARDVERLEN + 1] __initdata = {0, };
+
+static int __init aedsp16_wait_data(int port)
+{
+	int             loop = STATUSRETRY;
+	unsigned char   ret = 0;
+
+	DBG1(("aedsp16_wait_data (0x%x): ", port));
+
+	do {
+		  ret = inb(port + DSP_DATAVAIL);
+	/*
+	 * Wait for data available (bit 7 of ret == 1)
+	 */
+	  } while (!(ret & 0x80) && loop--);
+
+	if (ret & 0x80) {
+		DBG1(("success.\n"));
+		return TRUE;
+	}
+
+	DBG1(("failure.\n"));
+	return FALSE;
+}
+
+static int __init aedsp16_read(int port)
+{
+	int inbyte;
+
+	DBG(("    Read DSP Byte (0x%x): ", port));
+
+	if (aedsp16_wait_data(port) == FALSE) {
+		DBG(("failure.\n"));
+		return -1;
+	}
+
+	inbyte = inb(port + DSP_READ);
+
+	DBG(("read [0x%x]/{%c}.\n", inbyte, inbyte));
+
+	return inbyte;
+}
+
+static int __init aedsp16_test_dsp(int port)
+{
+	return ((aedsp16_read(port) == 0xaa) ? TRUE : FALSE);
+}
+
+static int __init aedsp16_dsp_reset(int port)
+{
+	/*
+	 * Reset DSP
+	 */
+
+	DBG(("Reset DSP:\n"));
+
+	outb(1, (port + DSP_RESET));
+	udelay(10);
+	outb(0, (port + DSP_RESET));
+	udelay(10);
+	udelay(10);
+	if (aedsp16_test_dsp(port) == TRUE) {
+		DBG(("success.\n"));
+		return TRUE;
+	} else
+		DBG(("failure.\n"));
+	return FALSE;
+}
+
+static int __init aedsp16_write(int port, int cmd)
+{
+	unsigned char   ret;
+	int             loop = HARDRETRY;
+
+	DBG(("    Write DSP Byte (0x%x) [0x%x]: ", port, cmd));
+
+	do {
+		ret = inb(port + DSP_STATUS);
+		/*
+		 * DSP ready to receive data if bit 7 of ret == 0
+		 */
+		if (!(ret & 0x80)) {
+			outb(cmd, port + DSP_COMMAND);
+			DBG(("success.\n"));
+			return 0;
+		}
+	} while (loop--);
+
+	DBG(("timeout.\n"));
+	printk("[AEDSP16] DSP Command (0x%x) timeout.\n", cmd);
+
+	return -1;
+}
+
+#if defined(CONFIG_SC6600)
+
+#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
+void __init aedsp16_pinfo(void) {
+	DBG(("\n Base address:  %x\n", decoded_hcfg.iobase));
+	DBG((" Joystick    : %s present\n", decoded_hcfg.joystick?"":" not"));
+	DBG((" WSS addr    :  %x\n", decoded_hcfg.wssbase));
+	DBG((" MPU-401 addr:  %x\n", decoded_hcfg.mpubase));
+	DBG((" CDROM       : %s present\n", (decoded_hcfg.cdrom!=4)?"":" not"));
+	DBG((" CDROMADDR   :  %x\n\n", decoded_hcfg.cdrombase));
+}
+#endif
+
+void __init aedsp16_hard_decode(void) {
+
+	DBG((" aedsp16_hard_decode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
+
+/*
+ * Decode Cfg Bytes.
+ */
+	decoded_hcfg.iobase	= IOBASE(hard_cfg[0]);
+	decoded_hcfg.joystick	= JOY(hard_cfg[0]);
+	decoded_hcfg.wssbase	= WSSADDR(hard_cfg[0]);
+	decoded_hcfg.mpubase	= MPUADDR(hard_cfg[0]);
+	decoded_hcfg.cdrom	= CDROM(hard_cfg[1]);
+	decoded_hcfg.cdrombase	= CDROMADDR(hard_cfg[1]);
+
+#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
+	printk(" Original sound card configuration:\n");
+	aedsp16_pinfo();
+#endif
+
+/*
+ * Now set up the real kernel configuration.
+ */
+	decoded_hcfg.iobase	= ae_config.base_io;
+	decoded_hcfg.wssbase	= ae_config.mss_base;
+	decoded_hcfg.mpubase	= ae_config.mpu_base;
+
+#if defined(CONFIG_SC6600_JOY)
+ 	decoded_hcfg.joystick	= CONFIG_SC6600_JOY; /* Enable */
+#endif
+#if defined(CONFIG_SC6600_CDROM)
+	decoded_hcfg.cdrom	= CONFIG_SC6600_CDROM; /* 4:N-3:I-2:G-1:P-0:S */
+#endif
+#if defined(CONFIG_SC6600_CDROMBASE)
+	decoded_hcfg.cdrombase	= CONFIG_SC6600_CDROMBASE; /* 0 Disable */
+#endif
+
+#if defined(AEDSP16_DEBUG)
+	DBG((" New Values:\n"));
+	aedsp16_pinfo();
+#endif
+
+	DBG(("success.\n"));
+}
+
+void __init aedsp16_hard_encode(void) {
+
+	DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
+
+	hard_cfg[0] = 0;
+	hard_cfg[1] = 0;
+
+	hard_cfg[0] |= 0x20;
+
+	BLDIOBASE (hard_cfg[0], decoded_hcfg.iobase);
+	BLDWSSADDR(hard_cfg[0], decoded_hcfg.wssbase);
+	BLDMPUADDR(hard_cfg[0], decoded_hcfg.mpubase);
+	BLDJOY(hard_cfg[0], decoded_hcfg.joystick);
+	BLDCDROM(hard_cfg[1], decoded_hcfg.cdrom);
+	BLDCDROMADDR(hard_cfg[1], decoded_hcfg.cdrombase);
+
+#if defined(AEDSP16_DEBUG)
+	aedsp16_pinfo();
+#endif
+
+	DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
+	DBG(("success.\n"));
+
+}
+
+static int __init aedsp16_hard_write(int port) {
+
+	DBG(("aedsp16_hard_write:\n"));
+
+	if (aedsp16_write(port, COMMAND_6C)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6C);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+	if (aedsp16_write(port, COMMAND_5C)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+	if (aedsp16_write(port, hard_cfg[0])) {
+		printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[0]);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+	if (aedsp16_write(port, hard_cfg[1])) {
+		printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[1]);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+	if (aedsp16_write(port, COMMAND_C5)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_C5);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+
+	DBG(("success.\n"));
+
+	return TRUE;
+}
+
+static int __init aedsp16_hard_read(int port) {
+
+	DBG(("aedsp16_hard_read:\n"));
+
+	if (aedsp16_write(port, READ_HARD_CFG)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", READ_HARD_CFG);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+
+	if ((hard_cfg[0] = aedsp16_read(port)) == -1) {
+		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
+			READ_HARD_CFG);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+	if ((hard_cfg[1] = aedsp16_read(port)) == -1) {
+		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
+			READ_HARD_CFG);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+	if (aedsp16_read(port) == -1) {
+		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
+			READ_HARD_CFG);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+
+	DBG(("success.\n"));
+
+	return TRUE;
+}
+
+static int __init aedsp16_ext_cfg_write(int port) {
+
+	int extcfg, val;
+
+	if (aedsp16_write(port, COMMAND_66)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_66);
+		return FALSE;
+	}
+
+	extcfg = 7;
+	if (decoded_hcfg.cdrom != 2)
+		extcfg = 0x0F;
+	if ((decoded_hcfg.cdrom == 4) ||
+	    (decoded_hcfg.cdrom == 3))
+		extcfg &= ~2;
+	if (decoded_hcfg.cdrombase == 0)
+		extcfg &= ~2;
+	if (decoded_hcfg.mpubase == 0)
+		extcfg &= ~1;
+
+	if (aedsp16_write(port, extcfg)) {
+		printk("[AEDSP16] Write extcfg: failed!\n");
+		return FALSE;
+	}
+	if (aedsp16_write(port, 0)) {
+		printk("[AEDSP16] Write extcfg: failed!\n");
+		return FALSE;
+	}
+	if (decoded_hcfg.cdrom == 3) {
+		if (aedsp16_write(port, COMMAND_52)) {
+			printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52);
+			return FALSE;
+		}
+		if ((val = aedsp16_read(port)) == -1) {
+			printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n"
+					, COMMAND_52);
+			return FALSE;
+		}
+		val &= 0x7F;
+		if (aedsp16_write(port, COMMAND_60)) {
+			printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60);
+			return FALSE;
+		}
+		if (aedsp16_write(port, val)) {
+			printk("[AEDSP16] Write val: failed!\n");
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+#endif /* CONFIG_SC6600 */
+
+static int __init aedsp16_cfg_write(int port) {
+	if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
+		return FALSE;
+	}
+	if (aedsp16_write(port, soft_cfg)) {
+		printk("[AEDSP16] Initialization of (M)IRQ and DMA: failed!\n");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static int __init aedsp16_init_mss(int port)
+{
+	DBG(("aedsp16_init_mss:\n"));
+
+	mdelay(10);
+
+	if (aedsp16_write(port, DSP_INIT_MSS)) {
+		printk("[AEDSP16] aedsp16_init_mss [0x%x]: failed!\n",
+				DSP_INIT_MSS);
+		DBG(("failure.\n"));
+		return FALSE;
+	}
+	
+	mdelay(10);
+
+	if (aedsp16_cfg_write(port) == FALSE)
+		return FALSE;
+
+	outb(soft_cfg_mss, ae_config.mss_base);
+
+	DBG(("success.\n"));
+
+	return TRUE;
+}
+
+static int __init aedsp16_setup_board(int port) {
+	int	loop = RETRY;
+
+#if defined(CONFIG_SC6600)
+	int	val = 0;
+
+	if (aedsp16_hard_read(port) == FALSE) {
+		printk("[AEDSP16] aedsp16_hard_read: failed!\n");
+		return FALSE;
+	}
+
+	if (aedsp16_write(port, COMMAND_52)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52);
+		return FALSE;
+	}
+
+	if ((val = aedsp16_read(port)) == -1) {
+		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
+				COMMAND_52);
+		return FALSE;
+	}
+#endif
+
+	do {
+		if (aedsp16_write(port, COMMAND_88)) {
+			printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_88);
+			return FALSE;
+		}
+		mdelay(10);
+	} while ((aedsp16_wait_data(port) == FALSE) && loop--);
+
+	if (aedsp16_read(port) == -1) {
+		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
+				COMMAND_88);
+		return FALSE;
+	}
+
+#if !defined(CONFIG_SC6600)
+	if (aedsp16_write(port, COMMAND_5C)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
+		return FALSE;
+	}
+#endif
+
+	if (aedsp16_cfg_write(port) == FALSE)
+		return FALSE;
+
+#if defined(CONFIG_SC6600)
+	if (aedsp16_write(port, COMMAND_60)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60);
+		return FALSE;
+	}
+	if (aedsp16_write(port, val)) {
+		printk("[AEDSP16] DATA 0x%x: failed!\n", val);
+		return FALSE;
+	}
+	if (aedsp16_write(port, COMMAND_6E)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6E);
+		return FALSE;
+	}
+	if (aedsp16_write(port, ver[0])) {
+		printk("[AEDSP16] DATA 0x%x: failed!\n", ver[0]);
+		return FALSE;
+	}
+	if (aedsp16_write(port, ver[1])) {
+		printk("[AEDSP16] DATA 0x%x: failed!\n", ver[1]);
+		return FALSE;
+	}
+
+	if (aedsp16_hard_write(port) == FALSE) {
+		printk("[AEDSP16] aedsp16_hard_write: failed!\n");
+		return FALSE;
+	}
+
+	if (aedsp16_write(port, COMMAND_5C)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
+		return FALSE;
+	}
+
+#if defined(THIS_IS_A_THING_I_HAVE_NOT_TESTED_YET)
+	if (aedsp16_cfg_write(port) == FALSE)
+		return FALSE;
+#endif
+
+#endif
+
+	return TRUE;
+}
+
+static int __init aedsp16_stdcfg(int port) {
+	if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
+		return FALSE;
+	}
+	/*
+	 * 0x0A == (IRQ 7, DMA 1, MIRQ 0)
+	 */
+	if (aedsp16_write(port, 0x0A)) {
+		printk("[AEDSP16] aedsp16_stdcfg: failed!\n");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+static int __init aedsp16_dsp_version(int port)
+{
+	int             len = 0;
+	int             ret;
+
+	DBG(("Get DSP Version:\n"));
+
+	if (aedsp16_write(ae_config.base_io, GET_DSP_VERSION)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_VERSION);
+		DBG(("failed.\n"));
+		return FALSE;
+	}
+
+	do {
+		if ((ret = aedsp16_read(port)) == -1) {
+			DBG(("failed.\n"));
+			return FALSE;
+		}
+	/*
+	 * We already know how many int are stored (2), so we know when the
+	 * string is finished.
+	 */
+		ver[len++] = ret;
+	  } while (len < CARDVERLEN);
+	sprintf(DSPVersion, "%d.%d", ver[0], ver[1]);
+
+	DBG(("success.\n"));
+
+	return TRUE;
+}
+
+static int __init aedsp16_dsp_copyright(int port)
+{
+	int             len = 0;
+	int             ret;
+
+	DBG(("Get DSP Copyright:\n"));
+
+	if (aedsp16_write(ae_config.base_io, GET_DSP_COPYRIGHT)) {
+		printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_COPYRIGHT);
+		DBG(("failed.\n"));
+		return FALSE;
+	}
+
+	do {
+		if ((ret = aedsp16_read(port)) == -1) {
+	/*
+	 * If no more data available, return to the caller, no error if len>0.
+	 * We have no other way to know when the string is finished.
+	 */
+			if (len)
+				break;
+			else {
+				DBG(("failed.\n"));
+				return FALSE;
+			}
+		}
+
+		DSPCopyright[len++] = ret;
+
+	  } while (len < CARDNAMELEN);
+
+	DBG(("success.\n"));
+
+	return TRUE;
+}
+
+static void __init aedsp16_init_tables(void)
+{
+	int i = 0;
+
+	memset(DSPCopyright, 0, CARDNAMELEN + 1);
+	memset(DSPVersion, 0, CARDVERLEN + 1);
+
+	for (i = 0; orIRQ[i].or; i++)
+		if (orIRQ[i].val == ae_config.irq) {
+			soft_cfg |= orIRQ[i].or;
+			soft_cfg_mss |= orIRQ[i].or;
+		}
+
+	for (i = 0; orMIRQ[i].or; i++)
+		if (orMIRQ[i].or == ae_config.mpu_irq)
+			soft_cfg |= orMIRQ[i].or;
+
+	for (i = 0; orDMA[i].or; i++)
+		if (orDMA[i].val == ae_config.dma) {
+			soft_cfg |= orDMA[i].or;
+			soft_cfg_mss |= orDMA[i].or;
+		}
+}
+
+static int __init aedsp16_init_board(void)
+{
+	aedsp16_init_tables();
+
+	if (aedsp16_dsp_reset(ae_config.base_io) == FALSE) {
+		printk("[AEDSP16] aedsp16_dsp_reset: failed!\n");
+		return FALSE;
+	}
+	if (aedsp16_dsp_copyright(ae_config.base_io) == FALSE) {
+		printk("[AEDSP16] aedsp16_dsp_copyright: failed!\n");
+		return FALSE;
+	}
+
+	/*
+	 * My AEDSP16 card return SC-6000 in DSPCopyright, so
+	 * if we have something different, we have to be warned.
+	 */
+	if (strcmp("SC-6000", DSPCopyright))
+		printk("[AEDSP16] Warning: non SC-6000 audio card!\n");
+
+	if (aedsp16_dsp_version(ae_config.base_io) == FALSE) {
+		printk("[AEDSP16] aedsp16_dsp_version: failed!\n");
+		return FALSE;
+	}
+
+	if (aedsp16_stdcfg(ae_config.base_io) == FALSE) {
+		printk("[AEDSP16] aedsp16_stdcfg: failed!\n");
+		return FALSE;
+	}
+
+#if defined(CONFIG_SC6600)
+	if (aedsp16_hard_read(ae_config.base_io) == FALSE) {
+		printk("[AEDSP16] aedsp16_hard_read: failed!\n");
+		return FALSE;
+	}
+
+	aedsp16_hard_decode();
+
+	aedsp16_hard_encode();
+
+	if (aedsp16_hard_write(ae_config.base_io) == FALSE) {
+		printk("[AEDSP16] aedsp16_hard_write: failed!\n");
+		return FALSE;
+	}
+
+	if (aedsp16_ext_cfg_write(ae_config.base_io) == FALSE) {
+		printk("[AEDSP16] aedsp16_ext_cfg_write: failed!\n");
+		return FALSE;
+	}
+#endif /* CONFIG_SC6600 */
+
+	if (aedsp16_setup_board(ae_config.base_io) == FALSE) {
+		printk("[AEDSP16] aedsp16_setup_board: failed!\n");
+		return FALSE;
+	}
+
+	if (ae_config.mss_base != -1) {
+		if (ae_config.init & INIT_MSS) {
+			if (aedsp16_init_mss(ae_config.base_io) == FALSE) {
+				printk("[AEDSP16] Can not initialize"
+				       "Microsoft Sound System mode.\n");
+				return FALSE;
+			}
+		}
+	}
+
+#if !defined(MODULE) || defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
+
+	printk("Audio Excel DSP 16 init v%s (%s %s) [",
+		VERSION, DSPCopyright,
+		DSPVersion);
+
+	if (ae_config.mpu_base != -1) {
+		if (ae_config.init & INIT_MPU401) {
+			printk("MPU401");
+			if ((ae_config.init & INIT_MSS) ||
+			    (ae_config.init & INIT_SBPRO))
+				printk(" ");
+		}
+	}
+
+	if (ae_config.mss_base == -1) {
+		if (ae_config.init & INIT_SBPRO) {
+			printk("SBPro");
+			if (ae_config.init & INIT_MSS)
+				printk(" ");
+		}
+	}
+
+	if (ae_config.mss_base != -1)
+		if (ae_config.init & INIT_MSS)
+			printk("MSS");
+
+	printk("]\n");
+#endif /* MODULE || AEDSP16_INFO || AEDSP16_DEBUG */
+
+	mdelay(10);
+
+	return TRUE;
+}
+
+static int __init init_aedsp16_sb(void)
+{
+	DBG(("init_aedsp16_sb: "));
+
+/*
+ * If the card is already init'ed MSS, we can not init it to SBPRO too
+ * because the board can not emulate simultaneously MSS and SBPRO.
+ */
+	if (ae_config.init & INIT_MSS)
+		return FALSE;
+	if (ae_config.init & INIT_SBPRO)
+		return FALSE;
+
+	ae_config.init |= INIT_SBPRO;
+
+	DBG(("done.\n"));
+
+	return TRUE;
+}
+
+static void __init uninit_aedsp16_sb(void)
+{
+	DBG(("uninit_aedsp16_sb: "));
+
+	ae_config.init &= ~INIT_SBPRO;
+
+	DBG(("done.\n"));
+}
+
+static int __init init_aedsp16_mss(void)
+{
+	DBG(("init_aedsp16_mss: "));
+
+/*
+ * If the card is already init'ed SBPRO, we can not init it to MSS too
+ * because the board can not emulate simultaneously MSS and SBPRO.
+ */
+	if (ae_config.init & INIT_SBPRO)
+		return FALSE;
+	if (ae_config.init & INIT_MSS)
+		return FALSE;
+/*
+ * We must check the CONFIG_AEDSP16_BASE region too because these are the I/O 
+ * ports to access card's control registers.
+ */
+	if (!(ae_config.init & INIT_MPU401)) {
+		if (check_region(ae_config.base_io, IOBASE_REGION_SIZE)) {
+			printk(
+			"AEDSP16 BASE I/O port region is already in use.\n");
+			return FALSE;
+		}
+	}
+
+/*
+ * We must allocate the CONFIG_AEDSP16_BASE region too because these are the 
+ * I/O ports to access card's control registers.
+ */
+	if (!(ae_config.init & INIT_MPU401))
+		request_region(ae_config.base_io, IOBASE_REGION_SIZE,
+				"aedsp16 (base)");
+
+	ae_config.init |= INIT_MSS;
+
+	DBG(("done.\n"));
+
+	return TRUE;
+}
+
+static void __init uninit_aedsp16_mss(void)
+{
+	DBG(("uninit_aedsp16_mss: "));
+
+	if ((!(ae_config.init & INIT_MPU401)) &&
+	   (ae_config.init & INIT_MSS)) {
+		release_region(ae_config.base_io, IOBASE_REGION_SIZE);
+		DBG(("AEDSP16 base region released.\n"));
+	}
+
+	ae_config.init &= ~INIT_MSS;
+	DBG(("done.\n"));
+}
+
+static int __init init_aedsp16_mpu(void)
+{
+	DBG(("init_aedsp16_mpu: "));
+
+	if (ae_config.init & INIT_MPU401)
+		return FALSE;
+
+/*
+ * We must check the CONFIG_AEDSP16_BASE region too because these are the I/O 
+ * ports to access card's control registers.
+ */
+	if (!(ae_config.init & (INIT_MSS | INIT_SBPRO))) {
+		if (check_region(ae_config.base_io, IOBASE_REGION_SIZE)) {
+			printk(
+			"AEDSP16 BASE I/O port region is already in use.\n");
+			return FALSE;
+		}
+	}
+
+	if (!(ae_config.init & (INIT_MSS | INIT_SBPRO)))
+		request_region(ae_config.base_io, IOBASE_REGION_SIZE,
+				"aedsp16 (base)");
+
+	ae_config.init |= INIT_MPU401;
+
+	DBG(("done.\n"));
+
+	return TRUE;
+}
+
+static void __init uninit_aedsp16_mpu(void)
+{
+	DBG(("uninit_aedsp16_mpu: "));
+
+	if ((!(ae_config.init & (INIT_MSS | INIT_SBPRO))) &&
+	   (ae_config.init & INIT_MPU401)) {
+		release_region(ae_config.base_io, IOBASE_REGION_SIZE);
+		DBG(("AEDSP16 base region released.\n"));
+	}
+
+	ae_config.init &= ~INIT_MPU401;
+
+	DBG(("done.\n"));
+}
+
+int __init init_aedsp16(void)
+{
+	int initialized = FALSE;
+
+	DBG(("Initializing BASE[0x%x] IRQ[%d] DMA[%d] MIRQ[%d]\n",
+	     ae_config.base_io,ae_config.irq,ae_config.dma,ae_config.mpu_irq));
+
+	if (ae_config.mss_base == -1) {
+		if (init_aedsp16_sb() == FALSE) {
+			uninit_aedsp16_sb();
+		} else {
+			initialized = TRUE;
+		}
+	}
+
+	if (ae_config.mpu_base != -1) {
+		if (init_aedsp16_mpu() == FALSE) {
+			uninit_aedsp16_mpu();
+		} else {
+			initialized = TRUE;
+		}
+	}
+
+/*
+ * In the sequence of init routines, the MSS init MUST be the last!
+ * This because of the special register programming the MSS mode needs.
+ * A board reset would disable the MSS mode restoring the default SBPRO
+ * mode.
+ */
+	if (ae_config.mss_base != -1) {
+		if (init_aedsp16_mss() == FALSE) {
+			uninit_aedsp16_mss();
+		} else {
+			initialized = TRUE;
+		}
+	}
+
+	if (initialized)
+		initialized = aedsp16_init_board();
+	return initialized;
+}
+
+void __init uninit_aedsp16(void)
+{
+	if (ae_config.mss_base != -1)
+		uninit_aedsp16_mss();
+	else
+		uninit_aedsp16_sb();
+	if (ae_config.mpu_base != -1)
+		uninit_aedsp16_mpu();
+}
+
+static int __initdata io = -1;
+static int __initdata irq = -1;
+static int __initdata dma = -1;
+static int __initdata mpu_irq = -1;
+static int __initdata mss_base = -1;
+static int __initdata mpu_base = -1;
+
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)");
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)");
+MODULE_PARM(dma, "i");
+MODULE_PARM_DESC(dma, "dma line (0 1 3)");
+MODULE_PARM(mpu_irq, "i");
+MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)");
+MODULE_PARM(mss_base, "i");
+MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)");
+MODULE_PARM(mpu_base, "i");
+MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)");
+MODULE_AUTHOR("Riccardo Facchetti <fizban@tin.it>");
+MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION);
+
+static int __init do_init_aedsp16(void) {
+	printk("Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98\n");
+	if (io == -1 || dma == -1 || irq == -1) {
+		printk(KERN_INFO "aedsp16: I/O, IRQ and DMA are mandatory\n");
+		return -EINVAL;
+	}
+
+	ae_config.base_io = io;
+	ae_config.irq = irq;
+	ae_config.dma = dma;
+
+	ae_config.mss_base = mss_base;
+	ae_config.mpu_base = mpu_base;
+	ae_config.mpu_irq = mpu_irq;
+
+	if (init_aedsp16() == FALSE) {
+		printk(KERN_ERR "aedsp16: initialization failed\n");
+		/*
+		 * XXX
+		 * What error should we return here ?
+		 */
+		return -EINVAL;
+	}
+	SOUND_LOCK;
+	return 0;
+}
+
+static void __exit cleanup_aedsp16(void) {
+	uninit_aedsp16();
+	SOUND_LOCK_END;
+}
+
+module_init(do_init_aedsp16);
+module_exit(cleanup_aedsp16);
+
+#ifndef MODULE
+static int __init setup_aedsp16(char *str)
+{
+	/* io, irq, dma, mss_io, mpu_io, mpu_irq */
+	int ints[7];
+	
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+
+	io	 = ints[1];
+	irq	 = ints[2];
+	dma	 = ints[3];
+	mss_base = ints[4];
+	mpu_base = ints[5];
+	mpu_irq	 = ints[6];
+}
+
+__setup("aedsp16=", setup_aedsp16);
+#endif
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/awe_hw.h linux/drivers/sound/awe_hw.h
--- v2.3.50/linux/drivers/sound/awe_hw.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/awe_hw.h	Wed Mar  8 11:37:03 2000
@@ -0,0 +1,99 @@
+/*
+ * sound/awe_hw.h
+ *
+ * Access routines and definitions for the low level driver for the 
+ * Creative AWE32/SB32/AWE64 wave table synth.
+ *   version 0.4.3; Mar. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * 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 AWE_HW_H_DEF
+#define AWE_HW_H_DEF
+
+/*
+ * Emu-8000 control registers
+ * name(channel)	reg, port
+ */
+
+#define awe_cmd_idx(reg,ch)	(((reg)<< 5) | (ch))
+
+#define Data0    0		/* 0x620: doubleword r/w */
+#define Data1    1		/* 0xA20: doubleword r/w */
+#define Data2    2		/* 0xA22: word r/w */
+#define Data3    3		/* 0xE20: word r/w */
+#define Pointer  4		/* 0xE22 register pointer r/w */
+
+#define AWE_CPF(ch)	awe_cmd_idx(0,ch), Data0	/* DW: current pitch and fractional address */
+#define AWE_PTRX(ch)	awe_cmd_idx(1,ch), Data0	/* DW: pitch target and reverb send */
+#define AWE_CVCF(ch)	awe_cmd_idx(2,ch), Data0	/* DW: current volume and filter cutoff */
+#define AWE_VTFT(ch)	awe_cmd_idx(3,ch), Data0	/* DW: volume and filter cutoff targets */
+#define AWE_0080(ch)	awe_cmd_idx(4,ch), Data0	/* DW: ?? */
+#define AWE_00A0(ch)	awe_cmd_idx(5,ch), Data0	/* DW: ?? */
+#define AWE_PSST(ch)	awe_cmd_idx(6,ch), Data0	/* DW: pan send and loop start address */
+#define AWE_CSL(ch)	awe_cmd_idx(7,ch), Data0	/* DW: chorus send and loop end address */
+#define AWE_CCCA(ch)	awe_cmd_idx(0,ch), Data1	/* DW: Q, control bits, and current address */
+#define AWE_HWCF4	awe_cmd_idx(1,9),  Data1	/* DW: config dw 4 */
+#define AWE_HWCF5	awe_cmd_idx(1,10), Data1	/* DW: config dw 5 */
+#define AWE_HWCF6	awe_cmd_idx(1,13), Data1	/* DW: config dw 6 */
+#define AWE_HWCF7	awe_cmd_idx(1,14), Data1	/* DW: config dw 7? (not documented) */
+#define AWE_SMALR	awe_cmd_idx(1,20), Data1	/* DW: sound memory address for left read */
+#define AWE_SMARR	awe_cmd_idx(1,21), Data1	/* DW:    for right read */
+#define AWE_SMALW	awe_cmd_idx(1,22), Data1	/* DW: sound memory address for left write */
+#define AWE_SMARW	awe_cmd_idx(1,23), Data1	/* DW:    for right write */
+#define AWE_SMLD	awe_cmd_idx(1,26), Data1	/* W: sound memory left data */
+#define AWE_SMRD	awe_cmd_idx(1,26), Data2	/* W:    right data */
+#define AWE_WC		awe_cmd_idx(1,27), Data2	/* W: sample counter */
+#define AWE_WC_Cmd	awe_cmd_idx(1,27)
+#define AWE_WC_Port	Data2
+#define AWE_HWCF1	awe_cmd_idx(1,29), Data1	/* W: config w 1 */
+#define AWE_HWCF2	awe_cmd_idx(1,30), Data1	/* W: config w 2 */
+#define AWE_HWCF3	awe_cmd_idx(1,31), Data1	/* W: config w 3 */
+#define AWE_INIT1(ch)	awe_cmd_idx(2,ch), Data1	/* W: init array 1 */
+#define AWE_INIT2(ch)	awe_cmd_idx(2,ch), Data2	/* W: init array 2 */
+#define AWE_INIT3(ch)	awe_cmd_idx(3,ch), Data1	/* W: init array 3 */
+#define AWE_INIT4(ch)	awe_cmd_idx(3,ch), Data2	/* W: init array 4 */
+#define AWE_ENVVOL(ch)	awe_cmd_idx(4,ch), Data1	/* W: volume envelope delay */
+#define AWE_DCYSUSV(ch)	awe_cmd_idx(5,ch), Data1	/* W: volume envelope sustain and decay */
+#define AWE_ENVVAL(ch)	awe_cmd_idx(6,ch), Data1	/* W: modulation envelope delay */
+#define AWE_DCYSUS(ch)	awe_cmd_idx(7,ch), Data1	/* W: modulation envelope sustain and decay */
+#define AWE_ATKHLDV(ch)	awe_cmd_idx(4,ch), Data2	/* W: volume envelope attack and hold */
+#define AWE_LFO1VAL(ch)	awe_cmd_idx(5,ch), Data2	/* W: LFO#1 Delay */
+#define AWE_ATKHLD(ch)	awe_cmd_idx(6,ch), Data2	/* W: modulation envelope attack and hold */
+#define AWE_LFO2VAL(ch)	awe_cmd_idx(7,ch), Data2	/* W: LFO#2 Delay */
+#define AWE_IP(ch)	awe_cmd_idx(0,ch), Data3	/* W: initial pitch */
+#define AWE_IFATN(ch)	awe_cmd_idx(1,ch), Data3	/* W: initial filter cutoff and attenuation */
+#define AWE_PEFE(ch)	awe_cmd_idx(2,ch), Data3	/* W: pitch and filter envelope heights */
+#define AWE_FMMOD(ch)	awe_cmd_idx(3,ch), Data3	/* W: vibrato and filter modulation freq */
+#define AWE_TREMFRQ(ch)	awe_cmd_idx(4,ch), Data3	/* W: LFO#1 tremolo amount and freq */
+#define AWE_FM2FRQ2(ch)	awe_cmd_idx(5,ch), Data3	/* W: LFO#2 vibrato amount and freq */
+
+/* used during detection (returns ROM version?; not documented in ADIP) */
+#define AWE_U1		0xE0, Data3	  /* (R)(W) used in initialization */
+#define AWE_U2(ch)	0xC0+(ch), Data3  /* (W)(W) used in init envelope  */
+
+
+#define AWE_MAX_VOICES		32
+#define AWE_NORMAL_VOICES	30	/*30&31 are reserved for DRAM refresh*/
+
+#define AWE_MAX_CHANNELS	32	/* max midi channels (must >= voices) */
+#define AWE_MAX_LAYERS	AWE_MAX_VOICES	/* maximum number of multiple layers */
+
+#define AWE_DRAM_OFFSET		0x200000
+#define AWE_MAX_DRAM_SIZE	(28 * 1024)	/* 28 MB is max onboard memory */
+
+#endif
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/awe_wave.c linux/drivers/sound/awe_wave.c
--- v2.3.50/linux/drivers/sound/awe_wave.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/awe_wave.c	Wed Mar  8 11:37:03 2000
@@ -0,0 +1,6118 @@
+/*
+ * sound/awe_wave.c
+ *
+ * The low level driver for the AWE32/SB32/AWE64 wave table synth.
+ *   version 0.4.3; Feb. 1, 1999
+ *
+ * Copyright (C) 1996-1999 Takashi Iwai
+ *
+ * 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.
+ */
+
+#include <linux/awe_voice.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#include "sound_config.h"
+#include "soundmodule.h"
+
+#include "awe_wave.h"
+#include "awe_hw.h"
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+#include "tuning.h"
+#include <linux/ultrasound.h>
+#endif
+
+/*
+ * debug message
+ */
+
+/* do not allocate buffer at beginning */
+#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
+
+#ifdef AWE_DEBUG_ON
+#define DEBUG(LVL,XXX)	{if (ctrls[AWE_MD_DEBUG_MODE] > LVL) { XXX; }}
+#define ERRMSG(XXX)	{if (ctrls[AWE_MD_DEBUG_MODE]) { XXX; }}
+#define FATALERR(XXX)	XXX
+#else
+#define DEBUG(LVL,XXX) /**/
+#define ERRMSG(XXX)	XXX
+#define FATALERR(XXX)	XXX
+#endif
+
+/*
+ * bank and voice record
+ */
+
+/* soundfont record */
+typedef struct _sf_list {
+	unsigned short sf_id;
+	unsigned short type;
+	int num_info;		/* current info table index */
+	int num_sample;		/* current sample table index */
+	int mem_ptr;		/* current word byte pointer */
+	int infos;
+	int samples;
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	int shared;		/* shared index */
+	unsigned char name[AWE_PATCH_NAME_LEN];
+#endif
+} sf_list;
+
+/* bank record */
+typedef struct _awe_voice_list {
+	int next;	/* linked list with same sf_id */
+	unsigned char bank, instr;	/* preset number information */
+	char type, disabled;	/* type=normal/mapped, disabled=boolean */
+	awe_voice_info v;	/* voice information */
+	int next_instr;	/* preset table list */
+	int next_bank;	/* preset table list */
+} awe_voice_list;
+
+/* voice list type */
+#define V_ST_NORMAL	0
+#define V_ST_MAPPED	1
+
+typedef struct _awe_sample_list {
+	int next;	/* linked list with same sf_id */
+	awe_sample_info v;	/* sample information */
+} awe_sample_list;
+
+/* sample and information table */
+static int current_sf_id = 0;
+static int locked_sf_id = 0;
+static int max_sfs;
+static sf_list *sflists = NULL;
+
+#define awe_free_mem_ptr() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].mem_ptr)
+#define awe_free_info() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].num_info)
+#define awe_free_sample() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].num_sample)
+
+static int max_samples;
+static awe_sample_list *samples = NULL;
+
+static int max_infos;
+static awe_voice_list *infos = NULL;
+
+
+#define AWE_MAX_PRESETS		256
+#define AWE_DEFAULT_PRESET	0
+#define AWE_DEFAULT_BANK	0
+#define AWE_DEFAULT_DRUM	0
+#define AWE_DRUM_BANK		128
+
+#define MAX_LAYERS	AWE_MAX_VOICES
+
+/* preset table index */
+static int preset_table[AWE_MAX_PRESETS];
+
+/*
+ * voice table
+ */
+
+/* effects table */
+typedef	struct FX_Rec { /* channel effects */
+	unsigned char flags[AWE_FX_END];
+	short val[AWE_FX_END];
+} FX_Rec;
+
+
+/* channel parameters */
+typedef struct _awe_chan_info {
+	int channel;		/* channel number */
+	int bank;		/* current tone bank */
+	int instr;		/* current program */
+	int bender;		/* midi pitchbend (-8192 - 8192) */
+	int bender_range;	/* midi bender range (x100) */
+	int panning;		/* panning (0-127) */
+	int main_vol;		/* channel volume (0-127) */
+	int expression_vol;	/* midi expression (0-127) */
+	int chan_press;		/* channel pressure */
+	int vrec;		/* instrument list */
+	int def_vrec;		/* default instrument list */
+	int sustained;		/* sustain status in MIDI */
+	FX_Rec fx;		/* effects */
+	FX_Rec fx_layer[MAX_LAYERS]; /* layer effects */
+} awe_chan_info;
+
+/* voice parameters */
+typedef struct _voice_info {
+	int state;
+#define AWE_ST_OFF		(1<<0)	/* no sound */
+#define AWE_ST_ON		(1<<1)	/* playing */
+#define AWE_ST_STANDBY		(1<<2)	/* stand by for playing */
+#define AWE_ST_SUSTAINED	(1<<3)	/* sustained */
+#define AWE_ST_MARK		(1<<4)	/* marked for allocation */
+#define AWE_ST_DRAM		(1<<5)	/* DRAM read/write */
+#define AWE_ST_FM		(1<<6)	/* reserved for FM */
+#define AWE_ST_RELEASED		(1<<7)	/* released */
+
+	int ch;			/* midi channel */
+	int key;		/* internal key for search */
+	int layer;		/* layer number (for channel mode only) */
+	int time;		/* allocated time */
+	awe_chan_info	*cinfo;	/* channel info */
+
+	int note;		/* midi key (0-127) */
+	int velocity;		/* midi velocity (0-127) */
+	int sostenuto;		/* sostenuto on/off */
+	awe_voice_info *sample;	/* assigned voice */
+
+	/* EMU8000 parameters */
+	int apitch;		/* pitch parameter */
+	int avol;		/* volume parameter */
+	int apan;		/* panning parameter */
+	int acutoff;		/* cutoff parameter */
+	short aaux;		/* aux word */
+} voice_info;
+
+/* voice information */
+static voice_info voices[AWE_MAX_VOICES];
+
+#define IS_NO_SOUND(v)	(voices[v].state & (AWE_ST_OFF|AWE_ST_RELEASED|AWE_ST_STANDBY|AWE_ST_SUSTAINED))
+#define IS_NO_EFFECT(v)	(voices[v].state != AWE_ST_ON)
+#define IS_PLAYING(v)	(voices[v].state & (AWE_ST_ON|AWE_ST_SUSTAINED|AWE_ST_RELEASED))
+#define IS_EMPTY(v)	(voices[v].state & (AWE_ST_OFF|AWE_ST_MARK|AWE_ST_DRAM|AWE_ST_FM))
+
+
+/* MIDI channel effects information (for hw control) */
+static awe_chan_info channels[AWE_MAX_CHANNELS];
+
+
+/*----------------------------------------------------------------
+ * global variables
+ *----------------------------------------------------------------*/
+
+#ifndef AWE_DEFAULT_BASE_ADDR
+#define AWE_DEFAULT_BASE_ADDR	0	/* autodetect */
+#endif
+
+#ifndef AWE_DEFAULT_MEM_SIZE
+#define AWE_DEFAULT_MEM_SIZE	-1	/* autodetect */
+#endif
+
+#define awe_port	io
+#define awe_mem_size	memsize
+int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */
+int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */
+
+MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>");
+MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "base i/o port of Emu8000");
+MODULE_PARM(memsize, "i");
+MODULE_PARM_DESC(memsize, "onboard DRAM size in Kbytes");
+EXPORT_NO_SYMBOLS;
+
+/* DRAM start offset */
+static int awe_mem_start = AWE_DRAM_OFFSET;
+
+/* maximum channels for playing */
+static int awe_max_voices = AWE_MAX_VOICES;
+
+static int patch_opened = 0;		/* sample already loaded? */
+
+static char atten_relative = FALSE;
+static short atten_offset = 0;
+
+static int awe_present = FALSE;		/* awe device present? */
+static int awe_busy = FALSE;		/* awe device opened? */
+
+static int my_dev = -1;			
+
+#define DEFAULT_DRUM_FLAGS	((1 << 9) | (1 << 25))
+#define IS_DRUM_CHANNEL(c)	(drum_flags & (1 << (c)))
+#define DRUM_CHANNEL_ON(c)	(drum_flags |= (1 << (c)))
+#define DRUM_CHANNEL_OFF(c)	(drum_flags &= ~(1 << (c)))
+static unsigned int drum_flags = DEFAULT_DRUM_FLAGS; /* channel flags */
+
+static int playing_mode = AWE_PLAY_INDIRECT;
+#define SINGLE_LAYER_MODE()	(playing_mode == AWE_PLAY_INDIRECT || playing_mode == AWE_PLAY_DIRECT)
+#define MULTI_LAYER_MODE()	(playing_mode == AWE_PLAY_MULTI || playing_mode == AWE_PLAY_MULTI2)
+
+static int current_alloc_time = 0;	/* voice allocation index for channel mode */
+
+static struct synth_info awe_info = {
+	"AWE32 Synth",		/* name */
+	0,			/* device */
+	SYNTH_TYPE_SAMPLE,	/* synth_type */
+	SAMPLE_TYPE_AWE32,	/* synth_subtype */
+	0,			/* perc_mode (obsolete) */
+	AWE_MAX_VOICES,		/* nr_voices */
+	0,			/* nr_drums (obsolete) */
+	AWE_MAX_INFOS		/* instr_bank_size */
+};
+
+
+static struct voice_alloc_info *voice_alloc;	/* set at initialization */
+
+
+/*
+ * function prototypes
+ */
+
+static int awe_check_port(void);
+static void awe_request_region(void);
+static void awe_release_region(void);
+
+static void awe_reset_samples(void);
+/* emu8000 chip i/o access */
+static void setup_ports(int p1, int p2, int p3);
+static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data);
+static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data);
+static unsigned short awe_peek(unsigned short cmd, unsigned short port);
+static unsigned int awe_peek_dw(unsigned short cmd, unsigned short port);
+static void awe_wait(unsigned short delay);
+
+/* initialize emu8000 chip */
+static int _attach_awe(void);
+static void _unload_awe(void);
+static void awe_initialize(void);
+
+/* set voice parameters */
+static void awe_init_ctrl_parms(int init_all);
+static void awe_init_voice_info(awe_voice_info *vp);
+static void awe_init_voice_parm(awe_voice_parm *pp);
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+static int freq_to_note(int freq);
+static int calc_rate_offset(int Hz);
+/*static int calc_parm_delay(int msec);*/
+static int calc_parm_hold(int msec);
+static int calc_parm_attack(int msec);
+static int calc_parm_decay(int msec);
+static int calc_parm_search(int msec, short *table);
+#endif /* gus compat */
+
+/* turn on/off note */
+static void awe_note_on(int voice);
+static void awe_note_off(int voice);
+static void awe_terminate(int voice);
+static void awe_exclusive_off(int voice);
+static void awe_note_off_all(int do_sustain);
+
+/* calculate voice parameters */
+typedef void (*fx_affect_func)(int voice, int forced);
+static void awe_set_pitch(int voice, int forced);
+static void awe_set_voice_pitch(int voice, int forced);
+static void awe_set_volume(int voice, int forced);
+static void awe_set_voice_vol(int voice, int forced);
+static void awe_set_pan(int voice, int forced);
+static void awe_fx_fmmod(int voice, int forced);
+static void awe_fx_tremfrq(int voice, int forced);
+static void awe_fx_fm2frq2(int voice, int forced);
+static void awe_fx_filterQ(int voice, int forced);
+static void awe_calc_pitch(int voice);
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+static void awe_calc_pitch_from_freq(int voice, int freq);
+#endif
+static void awe_calc_volume(int voice);
+static void awe_update_volume(void);
+static void awe_change_master_volume(short val);
+static void awe_voice_init(int voice, int init_all);
+static void awe_channel_init(int ch, int init_all);
+static void awe_fx_init(int ch);
+static void awe_send_effect(int voice, int layer, int type, int val);
+static void awe_modwheel_change(int voice, int value);
+
+/* sequencer interface */
+static int awe_open(int dev, int mode);
+static void awe_close(int dev);
+static int awe_ioctl(int dev, unsigned int cmd, caddr_t arg);
+static int awe_kill_note(int dev, int voice, int note, int velocity);
+static int awe_start_note(int dev, int v, int note_num, int volume);
+static int awe_set_instr(int dev, int voice, int instr_no);
+static int awe_set_instr_2(int dev, int voice, int instr_no);
+static void awe_reset(int dev);
+static void awe_hw_control(int dev, unsigned char *event);
+static int awe_load_patch(int dev, int format, const char *addr,
+			  int offs, int count, int pmgr_flag);
+static void awe_aftertouch(int dev, int voice, int pressure);
+static void awe_controller(int dev, int voice, int ctrl_num, int value);
+static void awe_panning(int dev, int voice, int value);
+static void awe_volume_method(int dev, int mode);
+static void awe_bender(int dev, int voice, int value);
+static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc);
+static void awe_setup_voice(int dev, int voice, int chn);
+
+#define awe_key_pressure(dev,voice,key,press) awe_start_note(dev,voice,(key)+128,press)
+
+/* hardware controls */
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+static void awe_hw_gus_control(int dev, int cmd, unsigned char *event);
+#endif
+static void awe_hw_awe_control(int dev, int cmd, unsigned char *event);
+static void awe_voice_change(int voice, fx_affect_func func);
+static void awe_sostenuto_on(int voice, int forced);
+static void awe_sustain_off(int voice, int forced);
+static void awe_terminate_and_init(int voice, int forced);
+
+/* voice search */
+static int awe_search_instr(int bank, int preset);
+static int awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist);
+static void awe_alloc_multi_voices(int ch, int note, int velocity, int key);
+static void awe_alloc_one_voice(int voice, int note, int velocity);
+static int awe_clear_voice(void);
+
+/* load / remove patches */
+static int awe_open_patch(awe_patch_info *patch, const char *addr, int count);
+static int awe_close_patch(awe_patch_info *patch, const char *addr, int count);
+static int awe_unload_patch(awe_patch_info *patch, const char *addr, int count);
+static int awe_load_info(awe_patch_info *patch, const char *addr, int count);
+static int awe_load_data(awe_patch_info *patch, const char *addr, int count);
+static int awe_replace_data(awe_patch_info *patch, const char *addr, int count);
+static int awe_load_map(awe_patch_info *patch, const char *addr, int count);
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag);
+#endif
+/*static int awe_probe_info(awe_patch_info *patch, const char *addr, int count);*/
+static int awe_probe_data(awe_patch_info *patch, const char *addr, int count);
+static int check_patch_opened(int type, char *name);
+static int awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels);
+static void add_sf_info(int rec);
+static void add_sf_sample(int rec);
+static void purge_old_list(int rec, int next);
+static void add_info_list(int rec);
+static void awe_remove_samples(int sf_id);
+static void rebuild_preset_list(void);
+static short awe_set_sample(awe_voice_info *vp);
+static int search_sample_index(int sf, int sample, int level);
+
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+static int is_identical_id(int id1, int id2);
+static int is_identical_name(unsigned char *name, int id);
+static int is_shared_sf(unsigned char *name);
+static int info_duplicated(awe_voice_list *rec);
+#endif /* allow sharing */
+
+/* lowlevel functions */
+static void awe_init_audio(void);
+static void awe_init_dma(void);
+static void awe_init_array(void);
+static void awe_send_array(unsigned short *data);
+static void awe_tweak_voice(int voice);
+static void awe_tweak(void);
+static void awe_init_fm(void);
+static int awe_open_dram_for_write(int offset, int channels);
+static void awe_open_dram_for_check(void);
+static void awe_close_dram(void);
+static void awe_write_dram(unsigned short c);
+static int awe_detect_base(int addr);
+static int awe_detect(void);
+static void awe_check_dram(void);
+static int awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count);
+static void awe_set_chorus_mode(int mode);
+static void awe_update_chorus_mode(void);
+static int awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count);
+static void awe_set_reverb_mode(int mode);
+static void awe_update_reverb_mode(void);
+static void awe_equalizer(int bass, int treble);
+static void awe_update_equalizer(void);
+
+#ifdef CONFIG_AWE32_MIXER
+static void attach_mixer(void);
+static void unload_mixer(void);
+#endif
+
+#ifdef CONFIG_AWE32_MIDIEMU
+static void attach_midiemu(void);
+static void unload_midiemu(void);
+#endif
+
+#define limitvalue(x, a, b) if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b)
+
+/*
+ * control parameters
+ */
+
+
+#ifdef AWE_USE_NEW_VOLUME_CALC
+#define DEF_VOLUME_CALC	TRUE
+#else
+#define DEF_VOLUME_CALC	FALSE
+#endif /* new volume */
+
+#define DEF_ZERO_ATTEN		32	/* 12dB below */
+#define DEF_MOD_SENSE		18
+#define DEF_CHORUS_MODE		2
+#define DEF_REVERB_MODE		4
+#define DEF_BASS_LEVEL		5
+#define DEF_TREBLE_LEVEL	9
+
+static struct CtrlParmsDef {
+	int value;
+	int init_each_time;
+	void (*update)(void);
+} ctrl_parms[AWE_MD_END] = {
+	{0,0, NULL}, {0,0, NULL}, /* <-- not used */
+	{AWE_VERSION_NUMBER, FALSE, NULL},
+	{TRUE, FALSE, NULL}, /* exclusive */
+	{TRUE, FALSE, NULL}, /* realpan */
+	{AWE_DEFAULT_BANK, FALSE, NULL}, /* gusbank */
+	{FALSE, TRUE, NULL}, /* keep effect */
+	{DEF_ZERO_ATTEN, FALSE, awe_update_volume}, /* zero_atten */
+	{FALSE, FALSE, NULL}, /* chn_prior */
+	{DEF_MOD_SENSE, FALSE, NULL}, /* modwheel sense */
+	{AWE_DEFAULT_PRESET, FALSE, NULL}, /* def_preset */
+	{AWE_DEFAULT_BANK, FALSE, NULL}, /* def_bank */
+	{AWE_DEFAULT_DRUM, FALSE, NULL}, /* def_drum */
+	{FALSE, FALSE, NULL}, /* toggle_drum_bank */
+	{DEF_VOLUME_CALC, FALSE, awe_update_volume}, /* new_volume_calc */
+	{DEF_CHORUS_MODE, FALSE, awe_update_chorus_mode}, /* chorus mode */
+	{DEF_REVERB_MODE, FALSE, awe_update_reverb_mode}, /* reverb mode */
+	{DEF_BASS_LEVEL, FALSE, awe_update_equalizer}, /* bass level */
+	{DEF_TREBLE_LEVEL, FALSE, awe_update_equalizer}, /* treble level */
+	{0, FALSE, NULL},	/* debug mode */
+	{FALSE, FALSE, NULL}, /* pan exchange */
+};
+
+static int ctrls[AWE_MD_END];
+
+
+/*----------------------------------------------------------------
+ * synth operation table
+ *----------------------------------------------------------------*/
+
+static struct synth_operations awe_operations =
+{
+	"EMU8K",
+	&awe_info,
+	0,
+	SYNTH_TYPE_SAMPLE,
+	SAMPLE_TYPE_AWE32,
+	awe_open,
+	awe_close,
+	awe_ioctl,
+	awe_kill_note,
+	awe_start_note,
+	awe_set_instr_2,
+	awe_reset,
+	awe_hw_control,
+	awe_load_patch,
+	awe_aftertouch,
+	awe_controller,
+	awe_panning,
+	awe_volume_method,
+	awe_bender,
+	awe_alloc,
+	awe_setup_voice
+};
+
+
+/*================================================================
+ * General attach / unload interface
+ *================================================================*/
+
+static int _attach_awe(void)
+{
+	if (awe_present) return 0; /* for OSS38.. called twice? */
+
+	/* check presence of AWE32 card */
+	if (! awe_detect()) {
+		printk(KERN_WARNING "AWE32: not detected\n");
+		return 0;
+	}
+
+	/* check AWE32 ports are available */
+	if (awe_check_port()) {
+		printk(KERN_WARNING "AWE32: I/O area already used.\n");
+		return 0;
+	}
+
+	/* set buffers to NULL */
+	sflists = NULL;
+	samples = NULL;
+	infos = NULL;
+
+	/* allocate sample tables */
+	INIT_TABLE(sflists, max_sfs, AWE_MAX_SF_LISTS, sf_list);
+	INIT_TABLE(samples, max_samples, AWE_MAX_SAMPLES, awe_sample_list);
+	INIT_TABLE(infos, max_infos, AWE_MAX_INFOS, awe_voice_list);
+
+	my_dev = sound_alloc_synthdev();
+	if (my_dev == -1) {
+		printk(KERN_WARNING "AWE32 Error: too many synthesizers\n");
+		return 0;
+	}
+
+	voice_alloc = &awe_operations.alloc;
+	voice_alloc->max_voice = awe_max_voices;
+	synth_devs[my_dev] = &awe_operations;
+
+#ifdef CONFIG_AWE32_MIXER
+	attach_mixer();
+#endif
+#ifdef CONFIG_AWE32_MIDIEMU
+	attach_midiemu();
+#endif
+
+	/* reserve I/O ports for awedrv */
+	awe_request_region();
+
+	/* clear all samples */
+	awe_reset_samples();
+
+	/* intialize AWE32 hardware */
+	awe_initialize();
+
+	sprintf(awe_info.name, "AWE32-%s (RAM%dk)",
+		AWEDRV_VERSION, awe_mem_size/1024);
+	printk("<SoundBlaster EMU8000 (RAM%dk)>\n", awe_mem_size/1024);
+
+	awe_present = TRUE;
+
+	SOUND_LOCK;
+
+	return 1;
+}
+
+
+static void free_tables(void)
+{
+	if(sflists)
+		vfree(sflists);
+	sflists = NULL; max_sfs = 0;
+	if (samples)
+		vfree(samples);
+	samples = NULL; max_samples = 0;
+	if (infos)
+		vfree(infos);
+	infos = NULL; max_infos = 0;
+}
+
+static void *realloc_block(void *buf, int oldsize, int size)
+{
+	void *ptr;
+	if (oldsize == size)
+		return buf;
+	if ((ptr = vmalloc(size)) == NULL)
+		return NULL;
+	if (oldsize && size)
+		memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) );
+	if (buf)
+		vfree(buf);
+	return ptr;
+}
+
+
+static void _unload_awe(void)
+{
+	if (awe_present) {
+		awe_reset_samples();
+		awe_release_region();
+		free_tables();
+#ifdef CONFIG_AWE32_MIXER
+		unload_mixer();
+#endif
+#ifdef CONFIG_AWE32_MIDIEMU
+		unload_midiemu();
+#endif
+		sound_unload_synthdev(my_dev);
+		awe_present = FALSE;
+		SOUND_LOCK_END;
+	}
+}
+
+/*
+ * Linux PnP driver support
+ */
+
+#ifdef CONFIG_PNP_DRV
+
+#include <linux/pnp.h>
+
+static int pnp = 1;	/* use PnP as default */
+
+#define AWE_NUM_CHIPS	3
+static unsigned int pnp_ids[AWE_NUM_CHIPS] = {
+	PNP_EISAID('C','T','L',0x0021),
+	PNP_EISAID('C','T','L',0x0022),
+	PNP_EISAID('C','T','L',0x0023),
+};
+static struct pnp_driver pnp_awe[AWE_NUM_CHIPS];
+static int awe_pnp_ok = 0;
+
+static void awe_pnp_config(struct pnp_device *d)
+{
+	struct pnp_resource *r;
+	int port[3];
+	int nio = 0;
+
+	port[0] = port[1] = port[2] = 0;
+	for (r = d->res; r != NULL; r = r->next) {
+		if (r->type == PNP_RES_IO) {
+			if (nio >= 0 && nio < 3)
+				port[nio] = r->start;
+			nio++;
+		}
+	}
+	setup_ports(port[0], port[1], port[2]);
+	DEBUG(0,printk("AWE32: PnP setup ports: %x:%x:%x\n", port[0], port[1], port[2]));
+}
+
+static int awe_pnp_event (struct pnp_device *d, struct pnp_drv_event *e)
+{
+	struct pnp_driver *drv = d->l.k.driver;
+
+	switch (e->type) {
+	case PNP_DRV_ALLOC:
+		drv->flags |= PNP_DRV_INUSE;
+		awe_pnp_ok = 1;
+		awe_pnp_config(d);
+		_attach_awe();
+		break;
+
+	case PNP_DRV_DISABLE:
+	case PNP_DRV_EMERGSTOP:
+		drv->flags &= ~PNP_DRV_INUSE;
+		awe_pnp_ok = 0;
+		_unload_awe();
+		break;
+
+	case PNP_DRV_CONFIG:
+		if (awe_busy) return 1; /* used now */
+		awe_release_region();
+		awe_pnp_config(d);
+		awe_request_region();
+		break;
+		
+	case PNP_DRV_RECONFIG:
+		break;
+	}
+	return 0;
+}
+
+static int awe_initpnp (void)
+{
+	int i;
+	for (i = 0; i < AWE_NUM_CHIPS; i++) {
+		pnp_awe[i].id.type = PNP_HDL_ISA;
+		pnp_awe[i].id.t.isa.id = pnp_ids[i];
+		pnp_awe[i].id.next = NULL;
+		pnp_awe[i].name = "Soundblaster AWE32/AWE64 PnP";
+		pnp_awe[i].event = awe_pnp_event;
+		pnp_register_driver(&pnp_awe[i], 1);
+	}
+	return 0;
+}
+
+static void awe_unload_pnp (void)
+{
+	int i;
+	for (i = 0; i < AWE_NUM_CHIPS; i++)
+		pnp_unregister_driver(&pnp_awe[i]);
+}
+#endif /* PnP support */
+
+/*
+ * clear sample tables 
+ */
+
+static void
+awe_reset_samples(void)
+{
+	int i;
+
+	/* free all bank tables */
+	for (i = 0; i < AWE_MAX_PRESETS; i++)
+		preset_table[i] = -1;
+
+	free_tables();
+
+	current_sf_id = 0;
+	locked_sf_id = 0;
+	patch_opened = 0;
+}
+
+
+/*
+ * EMU register access
+ */
+
+/* select a given AWE32 pointer */
+static int awe_ports[5];
+static int port_setuped = FALSE;
+static int awe_cur_cmd = -1;
+#define awe_set_cmd(cmd) \
+if (awe_cur_cmd != cmd) { outw(cmd, awe_ports[Pointer]); awe_cur_cmd = cmd; }
+
+/* store values to i/o port array */
+static void setup_ports(int port1, int port2, int port3)
+{
+	awe_ports[0] = port1;
+	if (port2 == 0)
+		port2 = port1 + 0x400;
+	awe_ports[1] = port2;
+	awe_ports[2] = port2 + 2;
+	if (port3 == 0)
+		port3 = port1 + 0x800;
+	awe_ports[3] = port3;
+	awe_ports[4] = port3 + 2;
+
+	port_setuped = TRUE;
+}
+
+/* write 16bit data */
+static inline void
+awe_poke(unsigned short cmd, unsigned short port, unsigned short data)
+{
+	awe_set_cmd(cmd);
+	outw(data, awe_ports[port]);
+}
+
+/* write 32bit data */
+static inline void
+awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data)
+{
+	unsigned short addr = awe_ports[port];
+	awe_set_cmd(cmd);
+	outw(data, addr);		/* write lower 16 bits */
+	outw(data >> 16, addr + 2);	/* write higher 16 bits */
+}
+
+/* read 16bit data */
+static inline unsigned short
+awe_peek(unsigned short cmd, unsigned short port)
+{
+	unsigned short k;
+	awe_set_cmd(cmd);
+	k = inw(awe_ports[port]);
+	return k;
+}
+
+/* read 32bit data */
+static inline unsigned int
+awe_peek_dw(unsigned short cmd, unsigned short port)
+{
+	unsigned int k1, k2;
+	unsigned short addr = awe_ports[port];
+	awe_set_cmd(cmd);
+	k1 = inw(addr);
+	k2 = inw(addr + 2);
+	k1 |= k2 << 16;
+	return k1;
+}
+
+/* wait delay number of AWE32 44100Hz clocks */
+#ifdef WAIT_BY_LOOP /* wait by loop -- that's not good.. */
+static void
+awe_wait(unsigned short delay)
+{
+	unsigned short clock, target;
+	unsigned short port = awe_ports[AWE_WC_Port];
+	int counter;
+  
+	/* sample counter */
+	awe_set_cmd(AWE_WC_Cmd);
+	clock = (unsigned short)inw(port);
+	target = clock + delay;
+	counter = 0;
+	if (target < clock) {
+		for (; (unsigned short)inw(port) > target; counter++)
+			if (counter > 65536)
+				break;
+	}
+	for (; (unsigned short)inw(port) < target; counter++)
+		if (counter > 65536)
+			break;
+}
+#else
+
+static void awe_wait(unsigned short delay)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout((HZ*(unsigned long)delay + 44099)/44100);
+}
+#endif /* wait by loop */
+
+/* write a word data */
+static inline void
+awe_write_dram(unsigned short c)
+{
+	awe_poke(AWE_SMLD, c);
+}
+
+
+/*
+ * port check / request
+ *  0x620-623, 0xA20-A23, 0xE20-E23
+ */
+
+static int
+awe_check_port(void)
+{
+	if (! port_setuped) return 0;
+	return (check_region(awe_ports[0], 4) ||
+		check_region(awe_ports[1], 4) ||
+		check_region(awe_ports[3], 4));
+}
+
+static void
+awe_request_region(void)
+{
+	if (! port_setuped) return;
+	request_region(awe_ports[0], 4, "sound driver (AWE32)");
+	request_region(awe_ports[1], 4, "sound driver (AWE32)");
+	request_region(awe_ports[3], 4, "sound driver (AWE32)");
+}
+
+static void
+awe_release_region(void)
+{
+	if (! port_setuped) return;
+	release_region(awe_ports[0], 4);
+	release_region(awe_ports[1], 4);
+	release_region(awe_ports[3], 4);
+}
+
+/*
+ * AWE32 initialization
+ */
+static void
+awe_initialize(void)
+{
+	DEBUG(0,printk("AWE32: initializing..\n"));
+
+	/* initialize hardware configuration */
+	awe_poke(AWE_HWCF1, 0x0059);
+	awe_poke(AWE_HWCF2, 0x0020);
+
+	/* disable audio; this seems to reduce a clicking noise a bit.. */
+	awe_poke(AWE_HWCF3, 0);
+
+	/* initialize audio channels */
+	awe_init_audio();
+
+	/* initialize DMA */
+	awe_init_dma();
+
+	/* initialize init array */
+	awe_init_array();
+
+	/* check DRAM memory size */
+	awe_check_dram();
+
+	/* initialize the FM section of the AWE32 */
+	awe_init_fm();
+
+	/* set up voice envelopes */
+	awe_tweak();
+
+	/* enable audio */
+	awe_poke(AWE_HWCF3, 0x0004);
+
+	/* set default values */
+	awe_init_ctrl_parms(TRUE);
+
+	/* set equalizer */
+	awe_update_equalizer();
+
+	/* set reverb & chorus modes */
+	awe_update_reverb_mode();
+	awe_update_chorus_mode();
+}
+
+
+/*
+ * AWE32 voice parameters
+ */
+
+/* initialize voice_info record */
+static void
+awe_init_voice_info(awe_voice_info *vp)
+{
+	vp->sf_id = 0; /* normal mode */
+	vp->sample = 0;
+	vp->rate_offset = 0;
+
+	vp->start = 0;
+	vp->end = 0;
+	vp->loopstart = 0;
+	vp->loopend = 0;
+	vp->mode = 0;
+	vp->root = 60;
+	vp->tune = 0;
+	vp->low = 0;
+	vp->high = 127;
+	vp->vellow = 0;
+	vp->velhigh = 127;
+
+	vp->fixkey = -1;
+	vp->fixvel = -1;
+	vp->fixpan = -1;
+	vp->pan = -1;
+
+	vp->exclusiveClass = 0;
+	vp->amplitude = 127;
+	vp->attenuation = 0;
+	vp->scaleTuning = 100;
+
+	awe_init_voice_parm(&vp->parm);
+}
+
+/* initialize voice_parm record:
+ * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
+ * Vibrato and Tremolo effects are zero.
+ * Cutoff is maximum.
+ * Chorus and Reverb effects are zero.
+ */
+static void
+awe_init_voice_parm(awe_voice_parm *pp)
+{
+	pp->moddelay = 0x8000;
+	pp->modatkhld = 0x7f7f;
+	pp->moddcysus = 0x7f7f;
+	pp->modrelease = 0x807f;
+	pp->modkeyhold = 0;
+	pp->modkeydecay = 0;
+
+	pp->voldelay = 0x8000;
+	pp->volatkhld = 0x7f7f;
+	pp->voldcysus = 0x7f7f;
+	pp->volrelease = 0x807f;
+	pp->volkeyhold = 0;
+	pp->volkeydecay = 0;
+
+	pp->lfo1delay = 0x8000;
+	pp->lfo2delay = 0x8000;
+	pp->pefe = 0;
+
+	pp->fmmod = 0;
+	pp->tremfrq = 0;
+	pp->fm2frq2 = 0;
+
+	pp->cutoff = 0xff;
+	pp->filterQ = 0;
+
+	pp->chorus = 0;
+	pp->reverb = 0;
+}	
+
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+
+/* convert frequency mHz to abstract cents (= midi key * 100) */
+static int
+freq_to_note(int mHz)
+{
+	/* abscents = log(mHz/8176) / log(2) * 1200 */
+	unsigned int max_val = (unsigned int)0xffffffff / 10000;
+	int i, times;
+	unsigned int base;
+	unsigned int freq;
+	int note, tune;
+
+	if (mHz == 0)
+		return 0;
+	if (mHz < 0)
+		return 12799; /* maximum */
+
+	freq = mHz;
+	note = 0;
+	for (base = 8176 * 2; freq >= base; base *= 2) {
+		note += 12;
+		if (note >= 128) /* over maximum */
+			return 12799;
+	}
+	base /= 2;
+
+	/* to avoid overflow... */
+	times = 10000;
+	while (freq > max_val) {
+		max_val *= 10;
+		times /= 10;
+		base /= 10;
+	}
+
+	freq = freq * times / base;
+	for (i = 0; i < 12; i++) {
+		if (freq < semitone_tuning[i+1])
+			break;
+		note++;
+	}
+
+	tune = 0;
+	freq = freq * 10000 / semitone_tuning[i];
+	for (i = 0; i < 100; i++) {
+		if (freq < cent_tuning[i+1])
+			break;
+		tune++;
+	}
+
+	return note * 100 + tune;
+}
+
+
+/* convert Hz to AWE32 rate offset:
+ * sample pitch offset for the specified sample rate
+ * rate=44100 is no offset, each 4096 is 1 octave (twice).
+ * eg, when rate is 22050, this offset becomes -4096.
+ */
+static int
+calc_rate_offset(int Hz)
+{
+	/* offset = log(Hz / 44100) / log(2) * 4096 */
+	int freq, base, i;
+
+	/* maybe smaller than max (44100Hz) */
+	if (Hz <= 0 || Hz >= 44100) return 0;
+
+	base = 0;
+	for (freq = Hz * 2; freq < 44100; freq *= 2)
+		base++;
+	base *= 1200;
+
+	freq = 44100 * 10000 / (freq/2);
+	for (i = 0; i < 12; i++) {
+		if (freq < semitone_tuning[i+1])
+			break;
+		base += 100;
+	}
+	freq = freq * 10000 / semitone_tuning[i];
+	for (i = 0; i < 100; i++) {
+		if (freq < cent_tuning[i+1])
+			break;
+		base++;
+	}
+	return -base * 4096 / 1200;
+}
+
+
+/*
+ * convert envelope time parameter to AWE32 raw parameter
+ */
+
+/* attack & decay/release time table (msec) */
+static short attack_time_tbl[128] = {
+32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
+707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
+361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
+180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
+90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
+45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
+22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
+11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
+};
+
+static short decay_time_tbl[128] = {
+32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
+2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
+1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
+691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
+345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
+172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
+86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
+43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
+};
+
+#define calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725);
+
+/* delay time = 0x8000 - msec/92 */
+static int
+calc_parm_hold(int msec)
+{
+	int val = (0x7f * 92 - msec) / 92;
+	if (val < 1) val = 1;
+	if (val > 127) val = 127;
+	return val;
+}
+
+/* attack time: search from time table */
+static int
+calc_parm_attack(int msec)
+{
+	return calc_parm_search(msec, attack_time_tbl);
+}
+
+/* decay/release time: search from time table */
+static int
+calc_parm_decay(int msec)
+{
+	return calc_parm_search(msec, decay_time_tbl);
+}
+
+/* search an index for specified time from given time table */
+static int
+calc_parm_search(int msec, short *table)
+{
+	int left = 1, right = 127, mid;
+	while (left < right) {
+		mid = (left + right) / 2;
+		if (msec < (int)table[mid])
+			left = mid + 1;
+		else
+			right = mid;
+	}
+	return left;
+}
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
+
+
+/*
+ * effects table
+ */
+
+/* set an effect value */
+#define FX_FLAG_OFF	0
+#define FX_FLAG_SET	1
+#define FX_FLAG_ADD	2
+
+#define FX_SET(rec,type,value) \
+	((rec)->flags[type] = FX_FLAG_SET, (rec)->val[type] = (value))
+#define FX_ADD(rec,type,value) \
+	((rec)->flags[type] = FX_FLAG_ADD, (rec)->val[type] = (value))
+#define FX_UNSET(rec,type) \
+	((rec)->flags[type] = FX_FLAG_OFF, (rec)->val[type] = 0)
+
+/* check the effect value is set */
+#define FX_ON(rec,type)	((rec)->flags[type])
+
+#define PARM_BYTE	0
+#define PARM_WORD	1
+#define PARM_SIGN	2
+
+static struct PARM_DEFS {
+	int type;	/* byte or word */
+	int low, high;	/* value range */
+	fx_affect_func realtime;	/* realtime paramater change */
+} parm_defs[] = {
+	{PARM_WORD, 0, 0x8000, NULL},	/* env1 delay */
+	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 attack */
+	{PARM_BYTE, 0, 0x7e, NULL},	/* env1 hold */
+	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 decay */
+	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 release */
+	{PARM_BYTE, 0, 0x7f, NULL},	/* env1 sustain */
+	{PARM_BYTE, 0, 0xff, NULL},	/* env1 pitch */
+	{PARM_BYTE, 0, 0xff, NULL},	/* env1 cutoff */
+
+	{PARM_WORD, 0, 0x8000, NULL},	/* env2 delay */
+	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 attack */
+	{PARM_BYTE, 0, 0x7e, NULL},	/* env2 hold */
+	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 decay */
+	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 release */
+	{PARM_BYTE, 0, 0x7f, NULL},	/* env2 sustain */
+
+	{PARM_WORD, 0, 0x8000, NULL},	/* lfo1 delay */
+	{PARM_BYTE, 0, 0xff, awe_fx_tremfrq},	/* lfo1 freq */
+	{PARM_SIGN, -128, 127, awe_fx_tremfrq},	/* lfo1 volume */
+	{PARM_SIGN, -128, 127, awe_fx_fmmod},	/* lfo1 pitch */
+	{PARM_BYTE, 0, 0xff, awe_fx_fmmod},	/* lfo1 cutoff */
+
+	{PARM_WORD, 0, 0x8000, NULL},	/* lfo2 delay */
+	{PARM_BYTE, 0, 0xff, awe_fx_fm2frq2},	/* lfo2 freq */
+	{PARM_SIGN, -128, 127, awe_fx_fm2frq2},	/* lfo2 pitch */
+
+	{PARM_WORD, 0, 0xffff, awe_set_voice_pitch},	/* initial pitch */
+	{PARM_BYTE, 0, 0xff, NULL},	/* chorus */
+	{PARM_BYTE, 0, 0xff, NULL},	/* reverb */
+	{PARM_BYTE, 0, 0xff, awe_set_volume},	/* initial cutoff */
+	{PARM_BYTE, 0, 15, awe_fx_filterQ},	/* initial resonance */
+
+	{PARM_WORD, 0, 0xffff, NULL},	/* sample start */
+	{PARM_WORD, 0, 0xffff, NULL},	/* loop start */
+	{PARM_WORD, 0, 0xffff, NULL},	/* loop end */
+	{PARM_WORD, 0, 0xffff, NULL},	/* coarse sample start */
+	{PARM_WORD, 0, 0xffff, NULL},	/* coarse loop start */
+	{PARM_WORD, 0, 0xffff, NULL},	/* coarse loop end */
+	{PARM_BYTE, 0, 0xff, awe_set_volume},	/* initial attenuation */
+};
+
+
+static unsigned char
+FX_BYTE(FX_Rec *rec, FX_Rec *lay, int type, unsigned char value)
+{
+	int effect = 0;
+	int on = 0;
+	if (lay && (on = FX_ON(lay, type)) != 0)
+		effect = lay->val[type];
+	if (!on && (on = FX_ON(rec, type)) != 0)
+		effect = rec->val[type];
+	if (on == FX_FLAG_ADD) {
+		if (parm_defs[type].type == PARM_SIGN) {
+			if (value > 0x7f)
+				effect += (int)value - 0x100;
+			else
+				effect += (int)value;
+		} else {
+			effect += (int)value;
+		}
+	}
+	if (on) {
+		if (effect < parm_defs[type].low)
+			effect = parm_defs[type].low;
+		else if (effect > parm_defs[type].high)
+			effect = parm_defs[type].high;
+		return (unsigned char)effect;
+	}
+	return value;
+}
+
+/* get word effect value */
+static unsigned short
+FX_WORD(FX_Rec *rec, FX_Rec *lay, int type, unsigned short value)
+{
+	int effect = 0;
+	int on = 0;
+	if (lay && (on = FX_ON(lay, type)) != 0)
+		effect = lay->val[type];
+	if (!on && (on = FX_ON(rec, type)) != 0)
+		effect = rec->val[type];
+	if (on == FX_FLAG_ADD)
+		effect += (int)value;
+	if (on) {
+		if (effect < parm_defs[type].low)
+			effect = parm_defs[type].low;
+		else if (effect > parm_defs[type].high)
+			effect = parm_defs[type].high;
+		return (unsigned short)effect;
+	}
+	return value;
+}
+
+/* get word (upper=type1/lower=type2) effect value */
+static unsigned short
+FX_COMB(FX_Rec *rec, FX_Rec *lay, int type1, int type2, unsigned short value)
+{
+	unsigned short tmp;
+	tmp = FX_BYTE(rec, lay, type1, (unsigned char)(value >> 8));
+	tmp <<= 8;
+	tmp |= FX_BYTE(rec, lay, type2, (unsigned char)(value & 0xff));
+	return tmp;
+}
+
+/* address offset */
+static int
+FX_OFFSET(FX_Rec *rec, FX_Rec *lay, int lo, int hi, int mode)
+{
+	int addr = 0;
+	if (lay && FX_ON(lay, hi))
+		addr = (short)lay->val[hi];
+	else if (FX_ON(rec, hi))
+		addr = (short)rec->val[hi];
+	addr = addr << 15;
+	if (lay && FX_ON(lay, lo))
+		addr += (short)lay->val[lo];
+	else if (FX_ON(rec, lo))
+		addr += (short)rec->val[lo];
+	if (!(mode & AWE_SAMPLE_8BITS))
+		addr /= 2;
+	return addr;
+}
+
+
+/*
+ * turn on/off sample
+ */
+
+/* table for volume target calculation */
+static unsigned short voltarget[16] = { 
+   0xEAC0, 0XE0C8, 0XD740, 0XCE20, 0XC560, 0XBD08, 0XB500, 0XAD58,
+   0XA5F8, 0X9EF0, 0X9830, 0X91C0, 0X8B90, 0X85A8, 0X8000, 0X7A90
+};
+
+static void
+awe_note_on(int voice)
+{
+	unsigned int temp;
+	int addr;
+	int vtarget, ftarget, ptarget, pitch;
+	awe_voice_info *vp;
+	awe_voice_parm_block *parm;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	/* A voice sample must assigned before calling */
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+
+	parm = (awe_voice_parm_block*)&vp->parm;
+
+	/* channel to be silent and idle */
+	awe_poke(AWE_DCYSUSV(voice), 0x0080);
+	awe_poke(AWE_VTFT(voice), 0x0000FFFF);
+	awe_poke(AWE_CVCF(voice), 0x0000FFFF);
+	awe_poke(AWE_PTRX(voice), 0);
+	awe_poke(AWE_CPF(voice), 0);
+
+	/* set pitch offset */
+	awe_set_pitch(voice, TRUE);
+
+	/* modulation & volume envelope */
+	if (parm->modatk >= 0x80 && parm->moddelay >= 0x8000) {
+		awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+		pitch = (parm->env1pit<<4) + voices[voice].apitch;
+		if (pitch > 0xffff) pitch = 0xffff;
+		/* calculate filter target */
+		ftarget = parm->cutoff + parm->env1fc;
+		limitvalue(ftarget, 0, 255);
+		ftarget <<= 8;
+	} else {
+		awe_poke(AWE_ENVVAL(voice),
+			 FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, parm->moddelay));
+		ftarget = parm->cutoff;
+		ftarget <<= 8;
+		pitch = voices[voice].apitch;
+	}
+
+	/* calcualte pitch target */
+	if (pitch != 0xffff) {
+		ptarget = 1 << (pitch >> 12);
+		if (pitch & 0x800) ptarget += (ptarget*0x102e)/0x2710;
+		if (pitch & 0x400) ptarget += (ptarget*0x764)/0x2710;
+		if (pitch & 0x200) ptarget += (ptarget*0x389)/0x2710;
+		ptarget += (ptarget>>1);
+		if (ptarget > 0xffff) ptarget = 0xffff;
+
+	} else ptarget = 0xffff;
+	if (parm->modatk >= 0x80)
+		awe_poke(AWE_ATKHLD(voice),
+			 FX_BYTE(fx, fx_lay, AWE_FX_ENV1_HOLD, parm->modhld) << 8 | 0x7f);
+	else
+		awe_poke(AWE_ATKHLD(voice),
+			 FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK,
+				 vp->parm.modatkhld));
+	awe_poke(AWE_DCYSUS(voice),
+		 FX_COMB(fx, fx_lay, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,
+			  vp->parm.moddcysus));
+
+	if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {
+		awe_poke(AWE_ENVVOL(voice), 0xBFFF);
+		vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);
+	} else {
+		awe_poke(AWE_ENVVOL(voice),
+			 FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
+		vtarget = 0;
+	}
+	if (parm->volatk >= 0x80)
+		awe_poke(AWE_ATKHLDV(voice),
+			 FX_BYTE(fx, fx_lay, AWE_FX_ENV2_HOLD, parm->volhld) << 8 | 0x7f);
+	else
+		awe_poke(AWE_ATKHLDV(voice),
+			 FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK,
+			 vp->parm.volatkhld));
+	/* decay/sustain parameter for volume envelope must be set at last */
+
+	/* cutoff and volume */
+	awe_set_volume(voice, TRUE);
+
+	/* modulation envelope heights */
+	awe_poke(AWE_PEFE(voice),
+		 FX_COMB(fx, fx_lay, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF,
+			 vp->parm.pefe));
+
+	/* lfo1/2 delay */
+	awe_poke(AWE_LFO1VAL(voice),
+		 FX_WORD(fx, fx_lay, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay));
+	awe_poke(AWE_LFO2VAL(voice),
+		 FX_WORD(fx, fx_lay, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay));
+
+	/* lfo1 pitch & cutoff shift */
+	awe_fx_fmmod(voice, TRUE);
+	/* lfo1 volume & freq */
+	awe_fx_tremfrq(voice, TRUE);
+	/* lfo2 pitch & freq */
+	awe_fx_fm2frq2(voice, TRUE);
+	/* pan & loop start */
+	awe_set_pan(voice, TRUE);
+
+	/* chorus & loop end (chorus 8bit, MSB) */
+	addr = vp->loopend - 1;
+	addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_END,
+			  AWE_FX_COARSE_LOOP_END, vp->mode);
+	temp = FX_BYTE(fx, fx_lay, AWE_FX_CHORUS, vp->parm.chorus);
+	temp = (temp <<24) | (unsigned int)addr;
+	awe_poke_dw(AWE_CSL(voice), temp);
+	DEBUG(4,printk("AWE32: [-- loopend=%x/%x]\n", vp->loopend, addr));
+
+	/* Q & current address (Q 4bit value, MSB) */
+	addr = vp->start - 1;
+	addr += FX_OFFSET(fx, fx_lay, AWE_FX_SAMPLE_START,
+			  AWE_FX_COARSE_SAMPLE_START, vp->mode);
+	temp = FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ);
+	temp = (temp<<28) | (unsigned int)addr;
+	awe_poke_dw(AWE_CCCA(voice), temp);
+	DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n", vp->start, addr));
+
+	/* clear unknown registers */
+	awe_poke_dw(AWE_00A0(voice), 0);
+	awe_poke_dw(AWE_0080(voice), 0);
+
+	/* reset volume */
+	awe_poke_dw(AWE_VTFT(voice), (vtarget<<16)|ftarget);
+	awe_poke_dw(AWE_CVCF(voice), (vtarget<<16)|ftarget);
+
+	/* turn on envelope */
+	awe_poke(AWE_DCYSUSV(voice),
+		 FX_COMB(fx, fx_lay, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY,
+			  vp->parm.voldcysus));
+	/* set reverb */
+	temp = FX_BYTE(fx, fx_lay, AWE_FX_REVERB, vp->parm.reverb);
+	temp = (temp << 8) | (ptarget << 16) | voices[voice].aaux;
+	awe_poke_dw(AWE_PTRX(voice), temp);
+	awe_poke_dw(AWE_CPF(voice), ptarget << 16);
+
+	voices[voice].state = AWE_ST_ON;
+
+	/* clear voice position for the next note on this channel */
+	if (SINGLE_LAYER_MODE()) {
+		FX_UNSET(fx, AWE_FX_SAMPLE_START);
+		FX_UNSET(fx, AWE_FX_COARSE_SAMPLE_START);
+	}
+}
+
+
+/* turn off the voice */
+static void
+awe_note_off(int voice)
+{
+	awe_voice_info *vp;
+	unsigned short tmp;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	if ((vp = voices[voice].sample) == NULL) {
+		voices[voice].state = AWE_ST_OFF;
+		return;
+	}
+
+	tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV1_RELEASE,
+			       (unsigned char)vp->parm.modrelease);
+	awe_poke(AWE_DCYSUS(voice), tmp);
+	tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV2_RELEASE,
+			       (unsigned char)vp->parm.volrelease);
+	awe_poke(AWE_DCYSUSV(voice), tmp);
+	voices[voice].state = AWE_ST_RELEASED;
+}
+
+/* force to terminate the voice (no releasing echo) */
+static void
+awe_terminate(int voice)
+{
+	awe_poke(AWE_DCYSUSV(voice), 0x807F);
+	awe_tweak_voice(voice);
+	voices[voice].state = AWE_ST_OFF;
+}
+
+/* turn off other voices with the same exclusive class (for drums) */
+static void
+awe_exclusive_off(int voice)
+{
+	int i, exclass;
+
+	if (voices[voice].sample == NULL)
+		return;
+	if ((exclass = voices[voice].sample->exclusiveClass) == 0)
+		return;	/* not exclusive */
+
+	/* turn off voices with the same class */
+	for (i = 0; i < awe_max_voices; i++) {
+		if (i != voice && IS_PLAYING(i) &&
+		    voices[i].sample && voices[i].ch == voices[voice].ch &&
+		    voices[i].sample->exclusiveClass == exclass) {
+			DEBUG(4,printk("AWE32: [exoff(%d)]\n", i));
+			awe_terminate(i);
+			awe_voice_init(i, TRUE);
+		}
+	}
+}
+
+
+/*
+ * change the parameters of an audible voice
+ */
+
+/* change pitch */
+static void
+awe_set_pitch(int voice, int forced)
+{
+	if (IS_NO_EFFECT(voice) && !forced) return;
+	awe_poke(AWE_IP(voice), voices[voice].apitch);
+	DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch));
+}
+
+/* calculate & change pitch */
+static void
+awe_set_voice_pitch(int voice, int forced)
+{
+	awe_calc_pitch(voice);
+	awe_set_pitch(voice, forced);
+}
+
+/* change volume & cutoff */
+static void
+awe_set_volume(int voice, int forced)
+{
+	awe_voice_info *vp;
+	unsigned short tmp2;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	if (!IS_PLAYING(voice) && !forced) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+
+	tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF,
+		       (unsigned char)voices[voice].acutoff);
+	tmp2 = (tmp2 << 8);
+	tmp2 |= FX_BYTE(fx, fx_lay, AWE_FX_ATTEN,
+			(unsigned char)voices[voice].avol);
+	awe_poke(AWE_IFATN(voice), tmp2);
+}
+
+/* calculate & change volume */
+static void
+awe_set_voice_vol(int voice, int forced)
+{
+	if (IS_EMPTY(voice))
+		return;
+	awe_calc_volume(voice);
+	awe_set_volume(voice, forced);
+}
+
+
+/* change pan; this could make a click noise.. */
+static void
+awe_set_pan(int voice, int forced)
+{
+	unsigned int temp;
+	int addr;
+	awe_voice_info *vp;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	if (IS_NO_EFFECT(voice) && !forced) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+
+	/* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
+	if (vp->fixpan > 0)	/* 0-127 */
+		temp = 255 - (int)vp->fixpan * 2;
+	else {
+		int pos = 0;
+		if (vp->pan >= 0) /* 0-127 */
+			pos = (int)vp->pan * 2 - 128;
+		pos += voices[voice].cinfo->panning; /* -128 - 127 */
+		temp = 127 - pos;
+	}
+	limitvalue(temp, 0, 255);
+	if (ctrls[AWE_MD_PAN_EXCHANGE]) {
+		temp = 255 - temp;
+	}
+	if (forced || temp != voices[voice].apan) {
+		voices[voice].apan = temp;
+		addr = vp->loopstart - 1;
+		addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_START,
+				  AWE_FX_COARSE_LOOP_START, vp->mode);
+		temp = (temp<<24) | (unsigned int)addr;
+		awe_poke_dw(AWE_PSST(voice), temp);
+		DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n", vp->loopstart, addr));
+		if (temp == 0) voices[voice].aaux = 0xff;
+		else voices[voice].aaux = (-temp)&0xff;
+	}
+}
+
+/* effects change during playing */
+static void
+awe_fx_fmmod(int voice, int forced)
+{
+	awe_voice_info *vp;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	if (IS_NO_EFFECT(voice) && !forced) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+	awe_poke(AWE_FMMOD(voice),
+		 FX_COMB(fx, fx_lay, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
+			 vp->parm.fmmod));
+}
+
+/* set tremolo (lfo1) volume & frequency */
+static void
+awe_fx_tremfrq(int voice, int forced)
+{
+	awe_voice_info *vp;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	if (IS_NO_EFFECT(voice) && !forced) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+	awe_poke(AWE_TREMFRQ(voice),
+		 FX_COMB(fx, fx_lay, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
+			 vp->parm.tremfrq));
+}
+
+/* set lfo2 pitch & frequency */
+static void
+awe_fx_fm2frq2(int voice, int forced)
+{
+	awe_voice_info *vp;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	if (IS_NO_EFFECT(voice) && !forced) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+	awe_poke(AWE_FM2FRQ2(voice),
+		 FX_COMB(fx, fx_lay, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
+			 vp->parm.fm2frq2));
+}
+
+
+/* Q & current address (Q 4bit value, MSB) */
+static void
+awe_fx_filterQ(int voice, int forced)
+{
+	unsigned int addr;
+	awe_voice_info *vp;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	if (IS_NO_EFFECT(voice) && !forced) return;
+	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
+		return;
+
+	addr = awe_peek_dw(AWE_CCCA(voice)) & 0xffffff;
+	addr |= (FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ) << 28);
+	awe_poke_dw(AWE_CCCA(voice), addr);
+}
+
+/*================================================================
+ * calculate pitch offset
+ *----------------------------------------------------------------
+ * 0xE000 is no pitch offset at 44100Hz sample.
+ * Every 4096 is one octave.
+ *================================================================*/
+
+static void
+awe_calc_pitch(int voice)
+{
+	voice_info *vp = &voices[voice];
+	awe_voice_info *ap;
+	awe_chan_info *cp = voices[voice].cinfo;
+	int offset;
+
+	/* search voice information */
+	if ((ap = vp->sample) == NULL)
+			return;
+	if (ap->index < 0) {
+		DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample));
+		if (awe_set_sample(ap) < 0)
+			return;
+	}
+
+	/* calculate offset */
+	if (ap->fixkey >= 0) {
+		DEBUG(3,printk("AWE32: p-> fixkey(%d) tune(%d)\n", ap->fixkey, ap->tune));
+		offset = (ap->fixkey - ap->root) * 4096 / 12;
+	} else {
+		DEBUG(3,printk("AWE32: p(%d)-> root(%d) tune(%d)\n", vp->note, ap->root, ap->tune));
+		offset = (vp->note - ap->root) * 4096 / 12;
+		DEBUG(4,printk("AWE32: p-> ofs=%d\n", offset));
+	}
+	offset = (offset * ap->scaleTuning) / 100;
+	DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset));
+	offset += ap->tune * 4096 / 1200;
+	DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset));
+	if (cp->bender != 0) {
+		DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, cp->bender));
+		/* (819200: 1 semitone) ==> (4096: 12 semitones) */
+		offset += cp->bender * cp->bender_range / 2400;
+	}
+
+	/* add initial pitch correction */
+	if (FX_ON(&cp->fx_layer[vp->layer], AWE_FX_INIT_PITCH))
+		offset += cp->fx_layer[vp->layer].val[AWE_FX_INIT_PITCH];
+	else if (FX_ON(&cp->fx, AWE_FX_INIT_PITCH))
+		offset += cp->fx.val[AWE_FX_INIT_PITCH];
+
+	/* 0xe000: root pitch */
+	vp->apitch = 0xe000 + ap->rate_offset + offset;
+	DEBUG(4,printk("AWE32: p-> sum aofs=%x, rate_ofs=%d\n", vp->apitch, ap->rate_offset));
+	if (vp->apitch > 0xffff)
+		vp->apitch = 0xffff;
+	if (vp->apitch < 0)
+		vp->apitch = 0;
+}
+
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+/* calculate MIDI key and semitone from the specified frequency */
+static void
+awe_calc_pitch_from_freq(int voice, int freq)
+{
+	voice_info *vp = &voices[voice];
+	awe_voice_info *ap;
+	FX_Rec *fx = &voices[voice].cinfo->fx;
+	FX_Rec *fx_lay = NULL;
+	int offset;
+	int note;
+
+	if (voices[voice].layer < MAX_LAYERS)
+		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
+
+	/* search voice information */
+	if ((ap = vp->sample) == NULL)
+		return;
+	if (ap->index < 0) {
+		DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample));
+		if (awe_set_sample(ap) < 0)
+			return;
+	}
+	note = freq_to_note(freq);
+	offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200;
+	offset = (offset * ap->scaleTuning) / 100;
+	if (fx_lay && FX_ON(fx_lay, AWE_FX_INIT_PITCH))
+		offset += fx_lay->val[AWE_FX_INIT_PITCH];
+	else if (FX_ON(fx, AWE_FX_INIT_PITCH))
+		offset += fx->val[AWE_FX_INIT_PITCH];
+	vp->apitch = 0xe000 + ap->rate_offset + offset;
+	if (vp->apitch > 0xffff)
+		vp->apitch = 0xffff;
+	if (vp->apitch < 0)
+		vp->apitch = 0;
+}
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
+
+
+/*================================================================
+ * calculate volume attenuation
+ *----------------------------------------------------------------
+ * Voice volume is controlled by volume attenuation parameter.
+ * So volume becomes maximum when avol is 0 (no attenuation), and
+ * minimum when 255 (-96dB or silence).
+ *================================================================*/
+
+static int vol_table[128] = {
+	255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
+	47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
+	31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
+	22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
+	15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
+	10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
+	6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
+	2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
+};
+
+/* tables for volume->attenuation calculation */
+static unsigned char voltab1[128] = {
+   0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+   0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
+   0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
+   0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
+   0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
+   0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
+   0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
+   0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
+   0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
+   0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
+   0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
+   0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+   0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char voltab2[128] = {
+   0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
+   0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
+   0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
+   0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
+   0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
+   0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
+   0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
+   0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
+   0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
+   0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+   0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
+   0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
+   0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char expressiontab[128] = {
+   0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
+   0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
+   0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
+   0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
+   0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
+   0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
+   0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
+   0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
+   0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
+   0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
+   0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
+   0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+   0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static void
+awe_calc_volume(int voice)
+{
+	voice_info *vp = &voices[voice];
+	awe_voice_info *ap;
+	awe_chan_info *cp = voices[voice].cinfo;
+	int vol;
+
+	/* search voice information */
+	if ((ap = vp->sample) == NULL)
+		return;
+
+	ap = vp->sample;
+	if (ap->index < 0) {
+		DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample));
+		if (awe_set_sample(ap) < 0)
+			return;
+	}
+	
+	if (ctrls[AWE_MD_NEW_VOLUME_CALC]) {
+		int main_vol = cp->main_vol * ap->amplitude / 127;
+		limitvalue(vp->velocity, 0, 127);
+		limitvalue(main_vol, 0, 127);
+		limitvalue(cp->expression_vol, 0, 127);
+
+		vol = voltab1[main_vol] + voltab2[vp->velocity];
+		vol = (vol * 8) / 3;
+		vol += ap->attenuation;
+		if (cp->expression_vol < 127)
+			vol += ((0x100 - vol) * expressiontab[cp->expression_vol])/128;
+		vol += atten_offset;
+		if (atten_relative)
+			vol += ctrls[AWE_MD_ZERO_ATTEN];
+		limitvalue(vol, 0, 255);
+		vp->avol = vol;
+		
+	} else {
+		/* 0 - 127 */
+		vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127);
+		vol = vol * ap->amplitude / 127;
+
+		if (vol < 0) vol = 0;
+		if (vol > 127) vol = 127;
+
+		/* calc to attenuation */
+		vol = vol_table[vol];
+		vol += (int)ap->attenuation;
+		vol += atten_offset;
+		if (atten_relative)
+			vol += ctrls[AWE_MD_ZERO_ATTEN];
+		if (vol > 255) vol = 255;
+
+		vp->avol = vol;
+	}
+	if (cp->bank !=  AWE_DRUM_BANK && ((awe_voice_parm_block*)(&ap->parm))->volatk < 0x7d) {
+		int atten;
+		if (vp->velocity < 70) atten = 70;
+		else atten = vp->velocity;
+		vp->acutoff = (atten * ap->parm.cutoff + 0xa0) >> 7;
+	} else {
+		vp->acutoff = ap->parm.cutoff;
+	}
+	DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol));
+}
+
+/* change master volume */
+static void
+awe_change_master_volume(short val)
+{
+	limitvalue(val, 0, 127);
+	atten_offset = vol_table[val];
+	atten_relative = TRUE;
+	awe_update_volume();
+}
+
+/* update volumes of all available channels */
+static void awe_update_volume(void)
+{
+	int i;
+	for (i = 0; i < awe_max_voices; i++)
+		awe_set_voice_vol(i, TRUE);
+}
+
+/* set sostenuto on */
+static void awe_sostenuto_on(int voice, int forced)
+{
+	if (IS_NO_EFFECT(voice) && !forced) return;
+	voices[voice].sostenuto = 127;
+}
+
+
+/* drop sustain */
+static void awe_sustain_off(int voice, int forced)
+{
+	if (voices[voice].state == AWE_ST_SUSTAINED) {
+		awe_note_off(voice);
+		awe_fx_init(voices[voice].ch);
+		awe_voice_init(voice, FALSE);
+	}
+}
+
+
+/* terminate and initialize voice */
+static void awe_terminate_and_init(int voice, int forced)
+{
+	awe_terminate(voice);
+	awe_fx_init(voices[voice].ch);
+	awe_voice_init(voice, TRUE);
+}
+
+
+/*
+ * synth operation routines
+ */
+
+#define AWE_VOICE_KEY(v)	(0x8000 | (v))
+#define AWE_CHAN_KEY(c,n)	(((c) << 8) | ((n) + 1))
+#define KEY_CHAN_MATCH(key,c)	(((key) >> 8) == (c))
+
+/* initialize the voice */
+static void
+awe_voice_init(int voice, int init_all)
+{
+	voice_info *vp = &voices[voice];
+
+	/* reset voice search key */
+	if (playing_mode == AWE_PLAY_DIRECT)
+		vp->key = AWE_VOICE_KEY(voice);
+	else
+		vp->key = 0;
+
+	/* clear voice mapping */
+	voice_alloc->map[voice] = 0;
+
+	/* touch the timing flag */
+	vp->time = current_alloc_time;
+
+	/* initialize other parameters if necessary */
+	if (init_all) {
+		vp->note = -1;
+		vp->velocity = 0;
+		vp->sostenuto = 0;
+
+		vp->sample = NULL;
+		vp->cinfo = &channels[voice];
+		vp->ch = voice;
+		vp->state = AWE_ST_OFF;
+
+		/* emu8000 parameters */
+		vp->apitch = 0;
+		vp->avol = 255;
+		vp->apan = -1;
+	}
+}
+
+/* clear effects */
+static void awe_fx_init(int ch)
+{
+	if (SINGLE_LAYER_MODE() && !ctrls[AWE_MD_KEEP_EFFECT]) {
+		memset(&channels[ch].fx, 0, sizeof(channels[ch].fx));
+		memset(&channels[ch].fx_layer, 0, sizeof(&channels[ch].fx_layer));
+	}
+}
+
+/* initialize channel info */
+static void awe_channel_init(int ch, int init_all)
+{
+	awe_chan_info *cp = &channels[ch];
+	cp->channel = ch;
+	if (init_all) {
+		cp->panning = 0; /* zero center */
+		cp->bender_range = 200; /* sense * 100 */
+		cp->main_vol = 127;
+		if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) {
+			cp->instr = ctrls[AWE_MD_DEF_DRUM];
+			cp->bank = AWE_DRUM_BANK;
+		} else {
+			cp->instr = ctrls[AWE_MD_DEF_PRESET];
+			cp->bank = ctrls[AWE_MD_DEF_BANK];
+		}
+		cp->vrec = -1;
+		cp->def_vrec = -1;
+	}
+
+	cp->bender = 0; /* zero tune skew */
+	cp->expression_vol = 127;
+	cp->chan_press = 0;
+	cp->sustained = 0;
+
+	if (! ctrls[AWE_MD_KEEP_EFFECT]) {
+		memset(&cp->fx, 0, sizeof(cp->fx));
+		memset(&cp->fx_layer, 0, sizeof(cp->fx_layer));
+	}
+}
+
+
+/* change the voice parameters; voice = channel */
+static void awe_voice_change(int voice, fx_affect_func func)
+{
+	int i; 
+	switch (playing_mode) {
+	case AWE_PLAY_DIRECT:
+		func(voice, FALSE);
+		break;
+	case AWE_PLAY_INDIRECT:
+		for (i = 0; i < awe_max_voices; i++)
+			if (voices[i].key == AWE_VOICE_KEY(voice))
+				func(i, FALSE);
+		break;
+	default:
+		for (i = 0; i < awe_max_voices; i++)
+			if (KEY_CHAN_MATCH(voices[i].key, voice))
+				func(i, FALSE);
+		break;
+	}
+}
+
+
+/*----------------------------------------------------------------
+ * device open / close
+ *----------------------------------------------------------------*/
+
+/* open device:
+ *   reset status of all voices, and clear sample position flag
+ */
+static int
+awe_open(int dev, int mode)
+{
+	if (awe_busy)
+		return -EBUSY;
+
+	awe_busy = TRUE;
+
+	/* set default mode */
+	awe_init_ctrl_parms(FALSE);
+	atten_relative = TRUE;
+	atten_offset = 0;
+	drum_flags = DEFAULT_DRUM_FLAGS;
+	playing_mode = AWE_PLAY_INDIRECT;
+
+	/* reset voices & channels */
+	awe_reset(dev);
+
+	patch_opened = 0;
+
+	return 0;
+}
+
+
+/* close device:
+ *   reset all voices again (terminate sounds)
+ */
+static void
+awe_close(int dev)
+{
+	awe_reset(dev);
+	awe_busy = FALSE;
+}
+
+
+/* set miscellaneous mode parameters
+ */
+static void
+awe_init_ctrl_parms(int init_all)
+{
+	int i;
+	for (i = 0; i < AWE_MD_END; i++) {
+		if (init_all || ctrl_parms[i].init_each_time)
+			ctrls[i] = ctrl_parms[i].value;
+	}
+}
+
+
+/* sequencer I/O control:
+ */
+static int
+awe_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+	switch (cmd) {
+	case SNDCTL_SYNTH_INFO:
+		if (playing_mode == AWE_PLAY_DIRECT)
+			awe_info.nr_voices = awe_max_voices;
+		else
+			awe_info.nr_voices = AWE_MAX_CHANNELS;
+		memcpy((char*)arg, &awe_info + 0, sizeof(awe_info));
+		return 0;
+		break;
+
+	case SNDCTL_SEQ_RESETSAMPLES:
+		awe_reset_samples();
+		awe_reset(dev);
+		return 0;
+		break;
+
+	case SNDCTL_SEQ_PERCMODE:
+		/* what's this? */
+		return 0;
+		break;
+
+	case SNDCTL_SYNTH_MEMAVL:
+		return awe_mem_size - awe_free_mem_ptr() * 2;
+
+	default:
+		printk("AWE32: unsupported ioctl %d\n", cmd);
+		return -EINVAL;
+	}
+}
+
+
+static int voice_in_range(int voice)
+{
+	if (playing_mode == AWE_PLAY_DIRECT) {
+		if (voice < 0 || voice >= awe_max_voices)
+			return FALSE;
+	} else {
+		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+			return FALSE;
+	}
+	return TRUE;
+}
+
+static void release_voice(int voice, int do_sustain)
+{
+	if (IS_NO_SOUND(voice))
+		return;
+	if (do_sustain && (voices[voice].cinfo->sustained == 127 ||
+			    voices[voice].sostenuto == 127))
+		voices[voice].state = AWE_ST_SUSTAINED;
+	else {
+		awe_note_off(voice);
+		awe_fx_init(voices[voice].ch);
+		awe_voice_init(voice, FALSE);
+	}
+}
+
+/* release all notes */
+static void awe_note_off_all(int do_sustain)
+{
+	int i;
+	for (i = 0; i < awe_max_voices; i++)
+		release_voice(i, do_sustain);
+}
+
+/* kill a voice:
+ *   not terminate, just release the voice.
+ */
+static int
+awe_kill_note(int dev, int voice, int note, int velocity)
+{
+	int i, v2, key;
+
+	DEBUG(2,printk("AWE32: [off(%d) nt=%d vl=%d]\n", voice, note, velocity));
+	if (! voice_in_range(voice))
+		return -EINVAL;
+
+	switch (playing_mode) {
+	case AWE_PLAY_DIRECT:
+	case AWE_PLAY_INDIRECT:
+		key = AWE_VOICE_KEY(voice);
+		break;
+
+	case AWE_PLAY_MULTI2:
+		v2 = voice_alloc->map[voice] >> 8;
+		voice_alloc->map[voice] = 0;
+		voice = v2;
+		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+			return -EINVAL;
+		/* continue to below */
+	default:
+		key = AWE_CHAN_KEY(voice, note);
+		break;
+	}
+
+	for (i = 0; i < awe_max_voices; i++) {
+		if (voices[i].key == key)
+			release_voice(i, TRUE);
+	}
+	return 0;
+}
+
+
+static void start_or_volume_change(int voice, int velocity)
+{
+	voices[voice].velocity = velocity;
+	awe_calc_volume(voice);
+	if (voices[voice].state == AWE_ST_STANDBY)
+		awe_note_on(voice);
+	else if (voices[voice].state == AWE_ST_ON)
+		awe_set_volume(voice, FALSE);
+}
+
+static void set_and_start_voice(int voice, int state)
+{
+	/* calculate pitch & volume parameters */
+	voices[voice].state = state;
+	awe_calc_pitch(voice);
+	awe_calc_volume(voice);
+	if (state == AWE_ST_ON)
+		awe_note_on(voice);
+}
+
+/* start a voice:
+ *   if note is 255, identical with aftertouch function.
+ *   Otherwise, start a voice with specified not and volume.
+ */
+static int
+awe_start_note(int dev, int voice, int note, int velocity)
+{
+	int i, key, state, volonly;
+
+	DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", voice, note, velocity));
+	if (! voice_in_range(voice))
+		return -EINVAL;
+	    
+	if (velocity == 0)
+		state = AWE_ST_STANDBY; /* stand by for playing */
+	else
+		state = AWE_ST_ON;	/* really play */
+	volonly = FALSE;
+
+	switch (playing_mode) {
+	case AWE_PLAY_DIRECT:
+	case AWE_PLAY_INDIRECT:
+		key = AWE_VOICE_KEY(voice);
+		if (note == 255)
+			volonly = TRUE;
+		break;
+
+	case AWE_PLAY_MULTI2:
+		voice = voice_alloc->map[voice] >> 8;
+		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+			return -EINVAL;
+		/* continue to below */
+	default:
+		if (note >= 128) { /* key volume mode */
+			note -= 128;
+			volonly = TRUE;
+		}
+		key = AWE_CHAN_KEY(voice, note);
+		break;
+	}
+
+	/* dynamic volume change */
+	if (volonly) {
+		for (i = 0; i < awe_max_voices; i++) {
+			if (voices[i].key == key)
+				start_or_volume_change(i, velocity);
+		}
+		return 0;
+	}
+
+	/* if the same note still playing, stop it */
+	if (playing_mode != AWE_PLAY_DIRECT || ctrls[AWE_MD_EXCLUSIVE_SOUND]) {
+		for (i = 0; i < awe_max_voices; i++)
+			if (voices[i].key == key) {
+				if (voices[i].state == AWE_ST_ON) {
+					awe_note_off(i);
+					awe_voice_init(i, FALSE);
+				} else if (voices[i].state == AWE_ST_STANDBY)
+					awe_voice_init(i, TRUE);
+			}
+	}
+
+	/* allocate voices */
+	if (playing_mode == AWE_PLAY_DIRECT)
+		awe_alloc_one_voice(voice, note, velocity);
+	else
+		awe_alloc_multi_voices(voice, note, velocity, key);
+
+	/* turn off other voices exlusively (for drums) */
+	for (i = 0; i < awe_max_voices; i++)
+		if (voices[i].key == key)
+			awe_exclusive_off(i);
+
+	/* set up pitch and volume parameters */
+	for (i = 0; i < awe_max_voices; i++) {
+		if (voices[i].key == key && voices[i].state == AWE_ST_OFF)
+			set_and_start_voice(i, state);
+	}
+
+	return 0;
+}
+
+
+/* search instrument from preset table with the specified bank */
+static int
+awe_search_instr(int bank, int preset)
+{
+	int i;
+
+	limitvalue(preset, 0, AWE_MAX_PRESETS-1);
+	for (i = preset_table[preset]; i >= 0; i = infos[i].next_bank) {
+		if (infos[i].bank == bank)
+			return i;
+	}
+	return -1;
+}
+
+
+/* assign the instrument to a voice */
+static int
+awe_set_instr_2(int dev, int voice, int instr_no)
+{
+	if (playing_mode == AWE_PLAY_MULTI2) {
+		voice = voice_alloc->map[voice] >> 8;
+		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+			return -EINVAL;
+	}
+	return awe_set_instr(dev, voice, instr_no);
+}
+
+/* assign the instrument to a channel; voice is the channel number */
+static int
+awe_set_instr(int dev, int voice, int instr_no)
+{
+	awe_chan_info *cinfo;
+	int def_bank;
+
+	if (! voice_in_range(voice))
+		return -EINVAL;
+
+	if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS)
+		return -EINVAL;
+
+	cinfo = &channels[voice];
+
+	if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice))
+		def_bank = AWE_DRUM_BANK; /* always search drumset */
+	else
+		def_bank = cinfo->bank;
+
+	cinfo->vrec = -1;
+	cinfo->def_vrec = -1;
+	cinfo->vrec = awe_search_instr(def_bank, instr_no);
+	if (def_bank == AWE_DRUM_BANK)	/* search default drumset */
+		cinfo->def_vrec = awe_search_instr(def_bank, ctrls[AWE_MD_DEF_DRUM]);
+	else	/* search default preset */
+		cinfo->def_vrec = awe_search_instr(ctrls[AWE_MD_DEF_BANK], instr_no);
+
+	if (cinfo->vrec < 0 && cinfo->def_vrec < 0) {
+		DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));
+	}
+
+	cinfo->instr = instr_no;
+	DEBUG(2,printk("AWE32: [program(%d) %d/%d]\n", voice, instr_no, def_bank));
+
+	return 0;
+}
+
+
+/* reset all voices; terminate sounds and initialize parameters */
+static void
+awe_reset(int dev)
+{
+	int i;
+	current_alloc_time = 0;
+	/* don't turn off voice 31 and 32.  they are used also for FM voices */
+	for (i = 0; i < awe_max_voices; i++) {
+		awe_terminate(i);
+		awe_voice_init(i, TRUE);
+	}
+	for (i = 0; i < AWE_MAX_CHANNELS; i++)
+		awe_channel_init(i, TRUE);
+	for (i = 0; i < 16; i++) {
+		awe_operations.chn_info[i].controllers[CTL_MAIN_VOLUME] = 127;
+		awe_operations.chn_info[i].controllers[CTL_EXPRESSION] = 127;
+	}
+	awe_init_fm();
+	awe_tweak();
+}
+
+
+/* hardware specific control:
+ *   GUS specific and AWE32 specific controls are available.
+ */
+static void
+awe_hw_control(int dev, unsigned char *event)
+{
+	int cmd = event[2];
+	if (cmd & _AWE_MODE_FLAG)
+		awe_hw_awe_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+	else
+		awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);
+#endif
+}
+
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+
+/* GUS compatible controls */
+static void
+awe_hw_gus_control(int dev, int cmd, unsigned char *event)
+{
+	int voice, i, key;
+	unsigned short p1;
+	short p2;
+	int plong;
+
+	if (MULTI_LAYER_MODE())
+		return;
+	if (cmd == _GUS_NUMVOICES)
+		return;
+
+	voice = event[3];
+	if (! voice_in_range(voice))
+		return;
+
+	p1 = *(unsigned short *) &event[4];
+	p2 = *(short *) &event[6];
+	plong = *(int*) &event[4];
+
+	switch (cmd) {
+	case _GUS_VOICESAMPLE:
+		awe_set_instr(dev, voice, p1);
+		return;
+
+	case _GUS_VOICEBALA:
+		/* 0 to 15 --> -128 to 127 */
+		awe_panning(dev, voice, ((int)p1 << 4) - 128);
+		return;
+
+	case _GUS_VOICEVOL:
+	case _GUS_VOICEVOL2:
+		/* not supported yet */
+		return;
+
+	case _GUS_RAMPRANGE:
+	case _GUS_RAMPRATE:
+	case _GUS_RAMPMODE:
+	case _GUS_RAMPON:
+	case _GUS_RAMPOFF:
+		/* volume ramping not supported */
+		return;
+
+	case _GUS_VOLUME_SCALE:
+		return;
+
+	case _GUS_VOICE_POS:
+		FX_SET(&channels[voice].fx, AWE_FX_SAMPLE_START,
+		       (short)(plong & 0x7fff));
+		FX_SET(&channels[voice].fx, AWE_FX_COARSE_SAMPLE_START,
+		       (plong >> 15) & 0xffff);
+		return;
+	}
+
+	key = AWE_VOICE_KEY(voice);
+	for (i = 0; i < awe_max_voices; i++) {
+		if (voices[i].key == key) {
+			switch (cmd) {
+			case _GUS_VOICEON:
+				awe_note_on(i);
+				break;
+
+			case _GUS_VOICEOFF:
+				awe_terminate(i);
+				awe_fx_init(voices[i].ch);
+				awe_voice_init(i, TRUE);
+				break;
+
+			case _GUS_VOICEFADE:
+				awe_note_off(i);
+				awe_fx_init(voices[i].ch);
+				awe_voice_init(i, FALSE);
+				break;
+
+			case _GUS_VOICEFREQ:
+				awe_calc_pitch_from_freq(i, plong);
+				break;
+			}
+		}
+	}
+}
+
+#endif /* gus_compat */
+
+
+/* AWE32 specific controls */
+static void
+awe_hw_awe_control(int dev, int cmd, unsigned char *event)
+{
+	int voice;
+	unsigned short p1;
+	short p2;
+	int i;
+
+	voice = event[3];
+	if (! voice_in_range(voice))
+		return;
+
+	if (playing_mode == AWE_PLAY_MULTI2) {
+		voice = voice_alloc->map[voice] >> 8;
+		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+			return;
+	}
+
+	p1 = *(unsigned short *) &event[4];
+	p2 = *(short *) &event[6];
+
+	switch (cmd) {
+	case _AWE_DEBUG_MODE:
+		ctrls[AWE_MD_DEBUG_MODE] = p1;
+		printk("AWE32: debug mode = %d\n", ctrls[AWE_MD_DEBUG_MODE]);
+		break;
+	case _AWE_REVERB_MODE:
+		ctrls[AWE_MD_REVERB_MODE] = p1;
+		awe_update_reverb_mode();
+		break;
+
+	case _AWE_CHORUS_MODE:
+		ctrls[AWE_MD_CHORUS_MODE] = p1;
+		awe_update_chorus_mode();
+		break;
+		      
+	case _AWE_REMOVE_LAST_SAMPLES:
+		DEBUG(0,printk("AWE32: remove last samples\n"));
+		if (locked_sf_id > 0)
+			awe_remove_samples(locked_sf_id);
+		break;
+
+	case _AWE_INITIALIZE_CHIP:
+		awe_initialize();
+		break;
+
+	case _AWE_SEND_EFFECT:
+		i = -1;
+		if (p1 >= 0x100) {
+			i = (p1 >> 8);
+			if (i < 0 || i >= MAX_LAYERS)
+				break;
+		}
+		awe_send_effect(voice, i, p1, p2);
+		break;
+
+	case _AWE_RESET_CHANNEL:
+		awe_channel_init(voice, !p1);
+		break;
+		
+	case _AWE_TERMINATE_ALL:
+		awe_reset(0);
+		break;
+
+	case _AWE_TERMINATE_CHANNEL:
+		awe_voice_change(voice, awe_terminate_and_init);
+		break;
+
+	case _AWE_RELEASE_ALL:
+		awe_note_off_all(FALSE);
+		break;
+	case _AWE_NOTEOFF_ALL:
+		awe_note_off_all(TRUE);
+		break;
+
+	case _AWE_INITIAL_VOLUME:
+		DEBUG(0,printk("AWE32: init attenuation %d\n", p1));
+		atten_relative = (char)p2;
+		atten_offset = (short)p1;
+		awe_update_volume();
+		break;
+
+	case _AWE_CHN_PRESSURE:
+		channels[voice].chan_press = p1;
+		awe_modwheel_change(voice, p1);
+		break;
+
+	case _AWE_CHANNEL_MODE:
+		DEBUG(0,printk("AWE32: channel mode = %d\n", p1));
+		playing_mode = p1;
+		awe_reset(0);
+		break;
+
+	case _AWE_DRUM_CHANNELS:
+		DEBUG(0,printk("AWE32: drum flags = %x\n", p1));
+		drum_flags = *(unsigned int*)&event[4];
+		break;
+
+	case _AWE_MISC_MODE:
+		DEBUG(0,printk("AWE32: ctrl parms = %d %d\n", p1, p2));
+		if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END) {
+			ctrls[p1] = p2;
+			if (ctrl_parms[p1].update)
+				ctrl_parms[p1].update();
+		}
+		break;
+
+	case _AWE_EQUALIZER:
+		ctrls[AWE_MD_BASS_LEVEL] = p1;
+		ctrls[AWE_MD_TREBLE_LEVEL] = p2;
+		awe_update_equalizer();
+		break;
+
+	default:
+		DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice));
+		break;
+	}
+}
+
+
+/* change effects */
+static void
+awe_send_effect(int voice, int layer, int type, int val)
+{
+	awe_chan_info *cinfo;
+	FX_Rec *fx;
+	int mode;
+
+	cinfo = &channels[voice];
+	if (layer >= 0 && layer < MAX_LAYERS)
+		fx = &cinfo->fx_layer[layer];
+	else
+		fx = &cinfo->fx;
+
+	if (type & 0x40)
+		mode = FX_FLAG_OFF;
+	else if (type & 0x80)
+		mode = FX_FLAG_ADD;
+	else
+		mode = FX_FLAG_SET;
+	type &= 0x3f;
+
+	if (type >= 0 && type < AWE_FX_END) {
+		DEBUG(2,printk("AWE32: effects (%d) %d %d\n", voice, type, val));
+		if (mode == FX_FLAG_SET)
+			FX_SET(fx, type, val);
+		else if (mode == FX_FLAG_ADD)
+			FX_ADD(fx, type, val);
+		else
+			FX_UNSET(fx, type);
+		if (mode != FX_FLAG_OFF && parm_defs[type].realtime) {
+			DEBUG(2,printk("AWE32: fx_realtime (%d)\n", voice));
+			awe_voice_change(voice, parm_defs[type].realtime);
+		}
+	}
+}
+
+
+/* change modulation wheel; voice is already mapped on multi2 mode */
+static void
+awe_modwheel_change(int voice, int value)
+{
+	int i;
+	awe_chan_info *cinfo;
+
+	cinfo = &channels[voice];
+	i = value * ctrls[AWE_MD_MOD_SENSE] / 1200;
+	FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i);
+	awe_voice_change(voice, awe_fx_fmmod);
+	FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i);
+	awe_voice_change(voice, awe_fx_fm2frq2);
+}
+
+
+/* voice pressure change */
+static void
+awe_aftertouch(int dev, int voice, int pressure)
+{
+	int note;
+
+	DEBUG(2,printk("AWE32: [after(%d) %d]\n", voice, pressure));
+	if (! voice_in_range(voice))
+		return;
+
+	switch (playing_mode) {
+	case AWE_PLAY_DIRECT:
+	case AWE_PLAY_INDIRECT:
+		awe_start_note(dev, voice, 255, pressure);
+		break;
+	case AWE_PLAY_MULTI2:
+		note = (voice_alloc->map[voice] & 0xff) - 1;
+		awe_key_pressure(dev, voice, note + 0x80, pressure);
+		break;
+	}
+}
+
+
+/* voice control change */
+static void
+awe_controller(int dev, int voice, int ctrl_num, int value)
+{
+	awe_chan_info *cinfo;
+
+	if (! voice_in_range(voice))
+		return;
+
+	if (playing_mode == AWE_PLAY_MULTI2) {
+		voice = voice_alloc->map[voice] >> 8;
+		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+			return;
+	}
+
+	cinfo = &channels[voice];
+
+	switch (ctrl_num) {
+	case CTL_BANK_SELECT: /* MIDI control #0 */
+		DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value));
+		if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice) &&
+		    !ctrls[AWE_MD_TOGGLE_DRUM_BANK])
+			break;
+		cinfo->bank = value;
+		if (cinfo->bank == AWE_DRUM_BANK)
+			DRUM_CHANNEL_ON(cinfo->channel);
+		else
+			DRUM_CHANNEL_OFF(cinfo->channel);
+		awe_set_instr(dev, voice, cinfo->instr);
+		break;
+
+	case CTL_MODWHEEL: /* MIDI control #1 */
+		DEBUG(2,printk("AWE32: [modwheel(%d) %d]\n", voice, value));
+		awe_modwheel_change(voice, value);
+		break;
+
+	case CTRL_PITCH_BENDER: /* SEQ1 V2 contorl */
+		DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, value));
+		/* zero centered */
+		cinfo->bender = value;
+		awe_voice_change(voice, awe_set_voice_pitch);
+		break;
+
+	case CTRL_PITCH_BENDER_RANGE: /* SEQ1 V2 control */
+		DEBUG(2,printk("AWE32: [range(%d) %d]\n", voice, value));
+		/* value = sense x 100 */
+		cinfo->bender_range = value;
+		/* no audible pitch change yet.. */
+		break;
+
+	case CTL_EXPRESSION: /* MIDI control #11 */
+		if (SINGLE_LAYER_MODE())
+			value /= 128;
+	case CTRL_EXPRESSION: /* SEQ1 V2 control */
+		DEBUG(2,printk("AWE32: [expr(%d) %d]\n", voice, value));
+		/* 0 - 127 */
+		cinfo->expression_vol = value;
+		awe_voice_change(voice, awe_set_voice_vol);
+		break;
+
+	case CTL_PAN:	/* MIDI control #10 */
+		DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value));
+		/* (0-127) -> signed 8bit */
+		cinfo->panning = value * 2 - 128;
+		if (ctrls[AWE_MD_REALTIME_PAN])
+			awe_voice_change(voice, awe_set_pan);
+		break;
+
+	case CTL_MAIN_VOLUME:	/* MIDI control #7 */
+		if (SINGLE_LAYER_MODE())
+			value = (value * 100) / 16383;
+	case CTRL_MAIN_VOLUME:	/* SEQ1 V2 control */
+		DEBUG(2,printk("AWE32: [mainvol(%d) %d]\n", voice, value));
+		/* 0 - 127 */
+		cinfo->main_vol = value;
+		awe_voice_change(voice, awe_set_voice_vol);
+		break;
+
+	case CTL_EXT_EFF_DEPTH: /* reverb effects: 0-127 */
+		DEBUG(2,printk("AWE32: [reverb(%d) %d]\n", voice, value));
+		FX_SET(&cinfo->fx, AWE_FX_REVERB, value * 2);
+		break;
+
+	case CTL_CHORUS_DEPTH: /* chorus effects: 0-127 */
+		DEBUG(2,printk("AWE32: [chorus(%d) %d]\n", voice, value));
+		FX_SET(&cinfo->fx, AWE_FX_CHORUS, value * 2);
+		break;
+
+	case 120:  /* all sounds off */
+		awe_note_off_all(FALSE);
+		break;
+	case 123:  /* all notes off */
+		awe_note_off_all(TRUE);
+		break;
+
+	case CTL_SUSTAIN: /* MIDI control #64 */
+		cinfo->sustained = value;
+		if (value != 127)
+			awe_voice_change(voice, awe_sustain_off);
+		break;
+
+	case CTL_SOSTENUTO: /* MIDI control #66 */
+		if (value == 127)
+			awe_voice_change(voice, awe_sostenuto_on);
+		else
+			awe_voice_change(voice, awe_sustain_off);
+		break;
+
+	default:
+		DEBUG(0,printk("AWE32: [control(%d) ctrl=%d val=%d]\n",
+			   voice, ctrl_num, value));
+		break;
+	}
+}
+
+
+/* voice pan change (value = -128 - 127) */
+static void
+awe_panning(int dev, int voice, int value)
+{
+	awe_chan_info *cinfo;
+
+	if (! voice_in_range(voice))
+		return;
+
+	if (playing_mode == AWE_PLAY_MULTI2) {
+		voice = voice_alloc->map[voice] >> 8;
+		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+			return;
+	}
+
+	cinfo = &channels[voice];
+	cinfo->panning = value;
+	DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, cinfo->panning));
+	if (ctrls[AWE_MD_REALTIME_PAN])
+		awe_voice_change(voice, awe_set_pan);
+}
+
+
+/* volume mode change */
+static void
+awe_volume_method(int dev, int mode)
+{
+	/* not impremented */
+	DEBUG(0,printk("AWE32: [volmethod mode=%d]\n", mode));
+}
+
+
+/* pitch wheel change: 0-16384 */
+static void
+awe_bender(int dev, int voice, int value)
+{
+	awe_chan_info *cinfo;
+
+	if (! voice_in_range(voice))
+		return;
+
+	if (playing_mode == AWE_PLAY_MULTI2) {
+		voice = voice_alloc->map[voice] >> 8;
+		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
+			return;
+	}
+
+	/* convert to zero centered value */
+	cinfo = &channels[voice];
+	cinfo->bender = value - 8192;
+	DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, cinfo->bender));
+	awe_voice_change(voice, awe_set_voice_pitch);
+}
+
+
+/*----------------------------------------------------------------
+ * load a sound patch:
+ *   three types of patches are accepted: AWE, GUS, and SYSEX.
+ *----------------------------------------------------------------*/
+
+static int
+awe_load_patch(int dev, int format, const char *addr,
+	       int offs, int count, int pmgr_flag)
+{
+	awe_patch_info patch;
+	int rc = 0;
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+	if (format == GUS_PATCH) {
+		return awe_load_guspatch(addr, offs, count, pmgr_flag);
+	} else
+#endif
+	if (format == SYSEX_PATCH) {
+		/* no system exclusive message supported yet */
+		return 0;
+	} else if (format != AWE_PATCH) {
+		printk("AWE32 Error: Invalid patch format (key) 0x%x\n", format);
+		return -EINVAL;
+	}
+	
+	if (count < AWE_PATCH_INFO_SIZE) {
+		printk("AWE32 Error: Patch header too short\n");
+		return -EINVAL;
+	}
+	copy_from_user(((char*)&patch) + offs, addr + offs, 
+		       AWE_PATCH_INFO_SIZE - offs);
+
+	count -= AWE_PATCH_INFO_SIZE;
+	if (count < patch.len) {
+		printk("AWE32: sample: Patch record too short (%d<%d)\n",
+		       count, patch.len);
+		return -EINVAL;
+	}
+	
+	switch (patch.type) {
+	case AWE_LOAD_INFO:
+		rc = awe_load_info(&patch, addr, count);
+		break;
+	case AWE_LOAD_DATA:
+		rc = awe_load_data(&patch, addr, count);
+		break;
+	case AWE_OPEN_PATCH:
+		rc = awe_open_patch(&patch, addr, count);
+		break;
+	case AWE_CLOSE_PATCH:
+		rc = awe_close_patch(&patch, addr, count);
+		break;
+	case AWE_UNLOAD_PATCH:
+		rc = awe_unload_patch(&patch, addr, count);
+		break;
+	case AWE_REPLACE_DATA:
+		rc = awe_replace_data(&patch, addr, count);
+		break;
+	case AWE_MAP_PRESET:
+		rc = awe_load_map(&patch, addr, count);
+		break;
+	/* case AWE_PROBE_INFO:
+		rc = awe_probe_info(&patch, addr, count);
+		break;*/
+	case AWE_PROBE_DATA:
+		rc = awe_probe_data(&patch, addr, count);
+		break;
+	case AWE_LOAD_CHORUS_FX:
+		rc = awe_load_chorus_fx(&patch, addr, count);
+		break;
+	case AWE_LOAD_REVERB_FX:
+		rc = awe_load_reverb_fx(&patch, addr, count);
+		break;
+
+	default:
+		printk("AWE32 Error: unknown patch format type %d\n",
+		       patch.type);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+
+/* create an sflist record */
+static int
+awe_create_sf(int type, char *name)
+{
+	sf_list *rec;
+
+	/* terminate sounds */
+	awe_reset(0);
+	if (current_sf_id >= max_sfs) {
+		int newsize = max_sfs + AWE_MAX_SF_LISTS;
+		sf_list *newlist = realloc_block(sflists, sizeof(sf_list)*max_sfs,
+						 sizeof(sf_list)*newsize);
+		if (newlist == NULL)
+			return 1;
+		sflists = newlist;
+		max_sfs = newsize;
+	}
+	rec = &sflists[current_sf_id];
+	rec->sf_id = current_sf_id + 1;
+	rec->type = type;
+	if (current_sf_id == 0 || (type & AWE_PAT_LOCKED) != 0)
+		locked_sf_id = current_sf_id + 1;
+	rec->num_info = awe_free_info();
+	rec->num_sample = awe_free_sample();
+	rec->mem_ptr = awe_free_mem_ptr();
+	rec->infos = -1;
+	rec->samples = -1;
+
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	rec->shared = 0;
+	if (name)
+		memcpy(rec->name, name, AWE_PATCH_NAME_LEN);
+	else
+		strcpy(rec->name, "*TEMPORARY*");
+	if (current_sf_id > 0 && name && (type & AWE_PAT_SHARED) != 0) {
+		/* is the current font really a shared font? */
+		if (is_shared_sf(rec->name)) {
+			/* check if the shared font is already installed */
+			int i;
+			for (i = current_sf_id; i > 0; i--) {
+				if (is_identical_name(rec->name, i)) {
+					rec->shared = i;
+					break;
+				}
+			}
+		}
+	}
+#endif /* allow sharing */
+
+	current_sf_id++;
+
+	return 0;
+}
+
+
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+
+/* check if the given name is a valid shared name */
+#define ASC_TO_KEY(c) ((c) - 'A' + 1)
+static int is_shared_sf(unsigned char *name)
+{
+	static unsigned char id_head[6] = {
+		ASC_TO_KEY('A'), ASC_TO_KEY('W'), ASC_TO_KEY('E'),
+		AWE_MAJOR_VERSION,
+		AWE_MINOR_VERSION,
+		AWE_TINY_VERSION,
+	};
+	if (memcmp(name, id_head, 6) == 0)
+		return TRUE;
+	return FALSE;
+}
+
+/* check if the given name matches to the existing list */
+static int is_identical_name(unsigned char *name, int sf) 
+{
+	char *id = sflists[sf-1].name;
+	if (is_shared_sf(id) && memcmp(id, name, AWE_PATCH_NAME_LEN) == 0)
+		return TRUE;
+	return FALSE;
+}
+
+/* check if the given voice info exists */
+static int info_duplicated(awe_voice_list *rec)
+{
+	int j, sf_id;
+	sf_list *sf;
+
+	/* search for all sharing lists */
+	for (sf_id = rec->v.sf_id; sf_id > 0 && sf_id <= current_sf_id; sf_id = sf->shared) {
+		sf = &sflists[sf_id - 1];
+		for (j = sf->infos; j >= 0; j = infos[j].next) {
+			awe_voice_list *p = &infos[j];
+			if (p->type == V_ST_NORMAL &&
+			    p->bank == rec->bank &&
+			    p->instr == rec->instr &&
+			    p->v.low == rec->v.low &&
+			    p->v.high == rec->v.high &&
+			    p->v.sample == rec->v.sample)
+				return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+#endif /* AWE_ALLOW_SAMPLE_SHARING */
+
+
+/* open patch; create sf list and set opened flag */
+static int
+awe_open_patch(awe_patch_info *patch, const char *addr, int count)
+{
+	awe_open_parm parm;
+	int shared;
+
+	copy_from_user(&parm, addr + AWE_PATCH_INFO_SIZE, sizeof(parm));
+	shared = FALSE;
+
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	if (current_sf_id > 0 && (parm.type & AWE_PAT_SHARED) != 0) {
+		/* is the previous font the same font? */
+		if (is_identical_name(parm.name, current_sf_id)) {
+			/* then append to the previous */
+			shared = TRUE;
+			awe_reset(0);
+			if (parm.type & AWE_PAT_LOCKED)
+				locked_sf_id = current_sf_id;
+		}
+	}
+#endif /* allow sharing */
+	if (! shared) {
+		if (awe_create_sf(parm.type, parm.name)) {
+			printk("AWE32: can't open: failed to alloc new list\n");
+			return -ENOSPC;
+		}
+	}
+	patch_opened = TRUE;
+	return current_sf_id;
+}
+
+/* check if the patch is already opened */
+static int
+check_patch_opened(int type, char *name)
+{
+	if (! patch_opened) {
+		if (awe_create_sf(type, name)) {
+			printk("AWE32: failed to alloc new list\n");
+			return -ENOSPC;
+		}
+		patch_opened = TRUE;
+		return current_sf_id;
+	}
+	return current_sf_id;
+}
+
+/* close the patch; if no voice is loaded, remove the patch */
+static int
+awe_close_patch(awe_patch_info *patch, const char *addr, int count)
+{
+	if (patch_opened && current_sf_id > 0) {
+		/* if no voice is loaded, release the current patch */
+		if (sflists[current_sf_id-1].infos == -1)
+			awe_remove_samples(current_sf_id - 1);
+	}
+	patch_opened = 0;
+	return 0;
+}
+
+
+/* remove the latest patch */
+static int
+awe_unload_patch(awe_patch_info *patch, const char *addr, int count)
+{
+	if (current_sf_id > 0 && current_sf_id > locked_sf_id)
+		awe_remove_samples(current_sf_id - 1);
+	return 0;
+}
+
+/* allocate voice info list records */
+static int alloc_new_info(int nvoices)
+{
+	int newsize, free_info;
+	awe_voice_list *newlist;
+	free_info = awe_free_info();
+	if (free_info + nvoices >= max_infos) {
+		do {
+			newsize = max_infos + AWE_MAX_INFOS;
+		} while (free_info + nvoices >= newsize);
+		newlist = realloc_block(infos, sizeof(awe_voice_list)*max_infos,
+					sizeof(awe_voice_list)*newsize);
+		if (newlist == NULL) {
+			printk("AWE32: can't alloc info table\n");
+			return -ENOSPC;
+		}
+		infos = newlist;
+		max_infos = newsize;
+	}
+	return 0;
+}
+
+/* allocate sample info list records */
+static int alloc_new_sample(void)
+{
+	int newsize, free_sample;
+	awe_sample_list *newlist;
+	free_sample = awe_free_sample();
+	if (free_sample >= max_samples) {
+		newsize = max_samples + AWE_MAX_SAMPLES;
+		newlist = realloc_block(samples,
+					sizeof(awe_sample_list)*max_samples,
+					sizeof(awe_sample_list)*newsize);
+		if (newlist == NULL) {
+			printk("AWE32: can't alloc sample table\n");
+			return -ENOSPC;
+		}
+		samples = newlist;
+		max_samples = newsize;
+	}
+	return 0;
+}
+
+/* load voice map */
+static int
+awe_load_map(awe_patch_info *patch, const char *addr, int count)
+{
+	awe_voice_map map;
+	awe_voice_list *rec;
+	int p, free_info;
+
+	/* get the link info */
+	if (count < sizeof(map)) {
+		printk("AWE32 Error: invalid patch info length\n");
+		return -EINVAL;
+	}
+	copy_from_user(&map, addr + AWE_PATCH_INFO_SIZE, sizeof(map));
+	
+	/* check if the identical mapping already exists */
+	p = awe_search_instr(map.map_bank, map.map_instr);
+	for (; p >= 0; p = infos[p].next_instr) {
+		if (p >= 0 && infos[p].type == V_ST_MAPPED &&
+		    infos[p].v.low == map.map_key &&
+		    infos[p].v.start == map.src_instr &&
+		    infos[p].v.end == map.src_bank &&
+		    infos[p].v.fixkey == map.src_key)
+			return 0; /* already present! */
+	}
+
+	if (check_patch_opened(AWE_PAT_TYPE_MAP, NULL) < 0)
+		return -ENOSPC;
+
+	if (alloc_new_info(1) < 0)
+		return -ENOSPC;
+
+	free_info = awe_free_info();
+	rec = &infos[free_info];
+	rec->bank = map.map_bank;
+	rec->instr = map.map_instr;
+	rec->type = V_ST_MAPPED;
+	rec->disabled = FALSE;
+	awe_init_voice_info(&rec->v);
+	if (map.map_key >= 0) {
+		rec->v.low = map.map_key;
+		rec->v.high = map.map_key;
+	}
+	rec->v.start = map.src_instr;
+	rec->v.end = map.src_bank;
+	rec->v.fixkey = map.src_key;
+	rec->v.sf_id = current_sf_id;
+	add_info_list(free_info);
+	add_sf_info(free_info);
+
+	return 0;
+}
+
+#if 0
+/* probe preset in the current list -- nothing to be loaded */
+static int
+awe_probe_info(awe_patch_info *patch, const char *addr, int count)
+{
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	awe_voice_map map;
+	int p;
+
+	if (! patch_opened)
+		return -EINVAL;
+
+	/* get the link info */
+	if (count < sizeof(map)) {
+		printk("AWE32 Error: invalid patch info length\n");
+		return -EINVAL;
+	}
+	copy_from_user(&map, addr + AWE_PATCH_INFO_SIZE, sizeof(map));
+	
+	/* check if the identical mapping already exists */
+	p = awe_search_instr(map.src_bank, map.src_instr);
+	for (; p >= 0; p = infos[p].next_instr) {
+		if (p >= 0 && infos[p].type == V_ST_NORMAL &&
+		    is_identical_id(infos[p].v.sf_id, current_sf_id) &&
+		    infos[p].v.low <= map.src_key &&
+		    infos[p].v.high >= map.src_key)
+			return 0; /* already present! */
+	}
+#endif /* allow sharing */
+	return -EINVAL;
+}
+#endif
+
+/* probe sample in the current list -- nothing to be loaded */
+static int
+awe_probe_data(awe_patch_info *patch, const char *addr, int count)
+{
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	if (! patch_opened)
+		return -EINVAL;
+
+	/* search the specified sample by optarg */
+	if (search_sample_index(current_sf_id, patch->optarg, 0) >= 0)
+		return 0;
+#endif /* allow sharing */
+	return -EINVAL;
+}
+
+/* load voice information data */
+static int
+awe_load_info(awe_patch_info *patch, const char *addr, int count)
+{
+	int offset;
+	awe_voice_rec_hdr hdr;
+	int i;
+	int total_size;
+
+	if (count < AWE_VOICE_REC_SIZE) {
+		printk("AWE32 Error: invalid patch info length\n");
+		return -EINVAL;
+	}
+
+	offset = AWE_PATCH_INFO_SIZE;
+	copy_from_user((char*)&hdr, addr + offset, AWE_VOICE_REC_SIZE);
+	offset += AWE_VOICE_REC_SIZE;
+
+	if (hdr.nvoices <= 0 || hdr.nvoices >= 100) {
+		printk("AWE32 Error: Illegal voice number %d\n", hdr.nvoices);
+		return -EINVAL;
+	}
+	total_size = AWE_VOICE_REC_SIZE + AWE_VOICE_INFO_SIZE * hdr.nvoices;
+	if (count < total_size) {
+		printk("AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n",
+		       count, hdr.nvoices);
+		return -EINVAL;
+	}
+
+	if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0)
+		return -ENOSPC;
+
+#if 0 /* it looks like not so useful.. */
+	/* check if the same preset already exists in the info list */
+	for (i = sflists[current_sf_id-1].infos; i >= 0; i = infos[i].next) {
+		if (infos[i].disabled) continue;
+		if (infos[i].bank == hdr.bank && infos[i].instr == hdr.instr) {
+			/* in exclusive mode, do skip loading this */
+			if (hdr.write_mode == AWE_WR_EXCLUSIVE)
+				return 0;
+			/* in replace mode, disable the old data */
+			else if (hdr.write_mode == AWE_WR_REPLACE)
+				infos[i].disabled = TRUE;
+		}
+	}
+	if (hdr.write_mode == AWE_WR_REPLACE)
+		rebuild_preset_list();
+#endif
+
+	if (alloc_new_info(hdr.nvoices) < 0)
+		return -ENOSPC;
+
+	for (i = 0; i < hdr.nvoices; i++) {
+		int rec = awe_free_info();
+
+		infos[rec].bank = hdr.bank;
+		infos[rec].instr = hdr.instr;
+		infos[rec].type = V_ST_NORMAL;
+		infos[rec].disabled = FALSE;
+
+		/* copy awe_voice_info parameters */
+		copy_from_user(&infos[rec].v, addr + offset, AWE_VOICE_INFO_SIZE);
+		offset += AWE_VOICE_INFO_SIZE;
+		infos[rec].v.sf_id = current_sf_id;
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+		if (sflists[current_sf_id-1].shared) {
+			if (info_duplicated(&infos[rec]))
+				continue;
+		}
+#endif /* allow sharing */
+		if (infos[rec].v.mode & AWE_MODE_INIT_PARM)
+			awe_init_voice_parm(&infos[rec].v.parm);
+		awe_set_sample(&infos[rec].v);
+		add_info_list(rec);
+		add_sf_info(rec);
+	}
+
+	return 0;
+}
+
+
+/* load wave sample data */
+static int
+awe_load_data(awe_patch_info *patch, const char *addr, int count)
+{
+	int offset, size;
+	int rc, free_sample;
+	awe_sample_info tmprec, *rec;
+
+	if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0)
+		return -ENOSPC;
+
+	size = (count - AWE_SAMPLE_INFO_SIZE) / 2;
+	offset = AWE_PATCH_INFO_SIZE;
+	copy_from_user(&tmprec, addr + offset, AWE_SAMPLE_INFO_SIZE);
+	offset += AWE_SAMPLE_INFO_SIZE;
+	if (size != tmprec.size) {
+		printk("AWE32: load: sample size differed (%d != %d)\n",
+		       tmprec.size, size);
+		return -EINVAL;
+	}
+
+	if (search_sample_index(current_sf_id, tmprec.sample, 0) >= 0) {
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+		/* if shared sample, skip this data */
+		if (sflists[current_sf_id-1].type & AWE_PAT_SHARED)
+			return 0;
+#endif /* allow sharing */
+		DEBUG(1,printk("AWE32: sample data %d already present\n", tmprec.sample));
+		return -EINVAL;
+	}
+
+	if (alloc_new_sample() < 0)
+		return -ENOSPC;
+
+	free_sample = awe_free_sample();
+	rec = &samples[free_sample].v;
+	*rec = tmprec;
+
+	if (rec->size > 0)
+		if ((rc = awe_write_wave_data(addr, offset, rec, -1)) != 0)
+			return rc;
+
+	rec->sf_id = current_sf_id;
+
+	add_sf_sample(free_sample);
+
+	return 0;
+}
+
+
+/* replace wave sample data */
+static int
+awe_replace_data(awe_patch_info *patch, const char *addr, int count)
+{
+	int offset;
+	int size;
+	int rc, i;
+	int channels;
+	awe_sample_info cursmp;
+	int save_mem_ptr;
+
+	if (! patch_opened) {
+		printk("AWE32: replace: patch not opened\n");
+		return -EINVAL;
+	}
+
+	size = (count - AWE_SAMPLE_INFO_SIZE) / 2;
+	offset = AWE_PATCH_INFO_SIZE;
+	copy_from_user(&cursmp, addr + offset, AWE_SAMPLE_INFO_SIZE);
+	offset += AWE_SAMPLE_INFO_SIZE;
+	if (cursmp.size == 0 || size != cursmp.size) {
+		printk("AWE32: replace: illegal sample size (%d!=%d)\n",
+		       cursmp.size, size);
+		return -EINVAL;
+	}
+	channels = patch->optarg;
+	if (channels <= 0 || channels > AWE_NORMAL_VOICES) {
+		printk("AWE32: replace: illegal channels %d\n", channels);
+		return -EINVAL;
+	}
+
+	for (i = sflists[current_sf_id-1].samples;
+	     i >= 0; i = samples[i].next) {
+		if (samples[i].v.sample == cursmp.sample)
+			break;
+	}
+	if (i < 0) {
+		printk("AWE32: replace: cannot find existing sample data %d\n",
+		       cursmp.sample);
+		return -EINVAL;
+	}
+		
+	if (samples[i].v.size != cursmp.size) {
+		printk("AWE32: replace: exiting size differed (%d!=%d)\n",
+		       samples[i].v.size, cursmp.size);
+		return -EINVAL;
+	}
+
+	save_mem_ptr = awe_free_mem_ptr();
+	sflists[current_sf_id-1].mem_ptr = samples[i].v.start - awe_mem_start;
+	memcpy(&samples[i].v, &cursmp, sizeof(cursmp));
+	if ((rc = awe_write_wave_data(addr, offset, &samples[i].v, channels)) != 0)
+		return rc;
+	sflists[current_sf_id-1].mem_ptr = save_mem_ptr;
+	samples[i].v.sf_id = current_sf_id;
+
+	return 0;
+}
+
+
+/*----------------------------------------------------------------*/
+
+static const char *readbuf_addr;
+static int readbuf_offs;
+static int readbuf_flags;
+#ifdef MALLOC_LOOP_DATA
+static unsigned short *readbuf_loop;
+static int readbuf_loopstart, readbuf_loopend;
+#endif
+
+/* initialize read buffer */
+static int
+readbuf_init(const char *addr, int offset, awe_sample_info *sp)
+{
+#ifdef MALLOC_LOOP_DATA
+	readbuf_loop = NULL;
+	readbuf_loopstart = sp->loopstart;
+	readbuf_loopend = sp->loopend;
+	if (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) {
+		int looplen = sp->loopend - sp->loopstart;
+		readbuf_loop = vmalloc(looplen * 2);
+		if (readbuf_loop == NULL) {
+			printk("AWE32: can't malloc temp buffer\n");
+			return -ENOSPC;
+		}
+	}
+#endif
+	readbuf_addr = addr;
+	readbuf_offs = offset;
+	readbuf_flags = sp->mode_flags;
+	return 0;
+}
+
+/* read directly from user buffer */
+static unsigned short
+readbuf_word(int pos)
+{
+	unsigned short c;
+	/* read from user buffer */
+	if (readbuf_flags & AWE_SAMPLE_8BITS) {
+		unsigned char cc;
+		get_user(cc, (unsigned char*)&(readbuf_addr)[readbuf_offs + pos]);
+		c = cc << 8; /* convert 8bit -> 16bit */
+	} else {
+		get_user(c, (unsigned short*)&(readbuf_addr)[readbuf_offs + pos * 2]);
+	}
+	if (readbuf_flags & AWE_SAMPLE_UNSIGNED)
+		c ^= 0x8000; /* unsigned -> signed */
+#ifdef MALLOC_LOOP_DATA
+	/* write on cache for reverse loop */
+	if (readbuf_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) {
+		if (pos >= readbuf_loopstart && pos < readbuf_loopend)
+			readbuf_loop[pos - readbuf_loopstart] = c;
+	}
+#endif
+	return c;
+}
+
+#ifdef MALLOC_LOOP_DATA
+/* read from cache */
+static unsigned short
+readbuf_word_cache(int pos)
+{
+	if (pos >= readbuf_loopstart && pos < readbuf_loopend)
+		return readbuf_loop[pos - readbuf_loopstart];
+	return 0;
+}
+
+static void
+readbuf_end(void)
+{
+	if (readbuf_loop)
+		vfree(readbuf_loop);
+	readbuf_loop = NULL;
+}
+
+#else
+
+#define readbuf_word_cache	readbuf_word
+#define readbuf_end()		/**/
+
+#endif
+
+/*----------------------------------------------------------------*/
+
+#define BLANK_LOOP_START	8
+#define BLANK_LOOP_END		40
+#define BLANK_LOOP_SIZE		48
+
+/* loading onto memory */
+static int 
+awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels)
+{
+	int i, truesize, dram_offset;
+	int rc;
+
+	/* be sure loop points start < end */
+	if (sp->loopstart > sp->loopend) {
+		int tmp = sp->loopstart;
+		sp->loopstart = sp->loopend;
+		sp->loopend = tmp;
+	}
+
+	/* compute true data size to be loaded */
+	truesize = sp->size;
+	if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)
+		truesize += sp->loopend - sp->loopstart;
+	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK)
+		truesize += BLANK_LOOP_SIZE;
+	if (awe_free_mem_ptr() + truesize >= awe_mem_size/2) {
+		DEBUG(-1,printk("AWE32 Error: Sample memory full\n"));
+		return -ENOSPC;
+	}
+
+	/* recalculate address offset */
+	sp->end -= sp->start;
+	sp->loopstart -= sp->start;
+	sp->loopend -= sp->start;
+
+	dram_offset = awe_free_mem_ptr() + awe_mem_start;
+	sp->start = dram_offset;
+	sp->end += dram_offset;
+	sp->loopstart += dram_offset;
+	sp->loopend += dram_offset;
+
+	/* set the total size (store onto obsolete checksum value) */
+	if (sp->size == 0)
+		sp->checksum = 0;
+	else
+		sp->checksum = truesize;
+
+	if ((rc = awe_open_dram_for_write(dram_offset, channels)) != 0)
+		return rc;
+
+	if (readbuf_init(addr, offset, sp) < 0)
+		return -ENOSPC;
+
+	for (i = 0; i < sp->size; i++) {
+		unsigned short c;
+		c = readbuf_word(i);
+		awe_write_dram(c);
+		if (i == sp->loopend &&
+		    (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP))) {
+			int looplen = sp->loopend - sp->loopstart;
+			/* copy reverse loop */
+			int k;
+			for (k = 1; k <= looplen; k++) {
+				c = readbuf_word_cache(i - k);
+				awe_write_dram(c);
+			}
+			if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP) {
+				sp->end += looplen;
+			} else {
+				sp->start += looplen;
+				sp->end += looplen;
+			}
+		}
+	}
+	readbuf_end();
+
+	/* if no blank loop is attached in the sample, add it */
+	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) {
+		for (i = 0; i < BLANK_LOOP_SIZE; i++)
+			awe_write_dram(0);
+		if (sp->mode_flags & AWE_SAMPLE_SINGLESHOT) {
+			sp->loopstart = sp->end + BLANK_LOOP_START;
+			sp->loopend = sp->end + BLANK_LOOP_END;
+		}
+	}
+
+	sflists[current_sf_id-1].mem_ptr += truesize;
+	awe_close_dram();
+
+	/* initialize FM */
+	awe_init_fm();
+
+	return 0;
+}
+
+
+/*----------------------------------------------------------------*/
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+
+/* calculate GUS envelope time:
+ * is this correct?  i have no idea..
+ */
+static int
+calc_gus_envelope_time(int rate, int start, int end)
+{
+	int r, p, t;
+	r = (3 - ((rate >> 6) & 3)) * 3;
+	p = rate & 0x3f;
+	t = end - start;
+	if (t < 0) t = -t;
+	if (13 > r)
+		t = t << (13 - r);
+	else
+		t = t >> (r - 13);
+	return (t * 10) / (p * 441);
+}
+
+#define calc_gus_sustain(val)  (0x7f - vol_table[(val)/2])
+#define calc_gus_attenuation(val)	vol_table[(val)/2]
+
+/* load GUS patch */
+static int
+awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag)
+{
+	struct patch_info patch;
+	awe_voice_info *rec;
+	awe_sample_info *smp;
+	int sizeof_patch;
+	int note, free_sample, free_info;
+	int rc;
+
+	sizeof_patch = (int)((long)&patch.data[0] - (long)&patch); /* header size */
+	if (size < sizeof_patch) {
+		printk("AWE32 Error: Patch header too short\n");
+		return -EINVAL;
+	}
+	copy_from_user(((char*)&patch) + offs, addr + offs, sizeof_patch - offs);
+	size -= sizeof_patch;
+	if (size < patch.len) {
+		printk("AWE32 Warning: Patch record too short (%d<%d)\n",
+		       size, patch.len);
+		return -EINVAL;
+	}
+	if (check_patch_opened(AWE_PAT_TYPE_GUS, NULL) < 0)
+		return -ENOSPC;
+	if (alloc_new_sample() < 0)
+		return -ENOSPC;
+	if (alloc_new_info(1))
+		return -ENOSPC;
+
+	free_sample = awe_free_sample();
+	smp = &samples[free_sample].v;
+
+	smp->sample = free_sample;
+	smp->start = 0;
+	smp->end = patch.len;
+	smp->loopstart = patch.loop_start;
+	smp->loopend = patch.loop_end;
+	smp->size = patch.len;
+
+	/* set up mode flags */
+	smp->mode_flags = 0;
+	if (!(patch.mode & WAVE_16_BITS))
+		smp->mode_flags |= AWE_SAMPLE_8BITS;
+	if (patch.mode & WAVE_UNSIGNED)
+		smp->mode_flags |= AWE_SAMPLE_UNSIGNED;
+	smp->mode_flags |= AWE_SAMPLE_NO_BLANK;
+	if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
+		smp->mode_flags |= AWE_SAMPLE_SINGLESHOT;
+	if (patch.mode & WAVE_BIDIR_LOOP)
+		smp->mode_flags |= AWE_SAMPLE_BIDIR_LOOP;
+	if (patch.mode & WAVE_LOOP_BACK)
+		smp->mode_flags |= AWE_SAMPLE_REVERSE_LOOP;
+
+	DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no, smp->mode_flags));
+	if (patch.mode & WAVE_16_BITS) {
+		/* convert to word offsets */
+		smp->size /= 2;
+		smp->end /= 2;
+		smp->loopstart /= 2;
+		smp->loopend /= 2;
+	}
+	smp->checksum_flag = 0;
+	smp->checksum = 0;
+
+	if ((rc = awe_write_wave_data(addr, sizeof_patch, smp, -1)) != 0)
+		return rc;
+
+	smp->sf_id = current_sf_id;
+	add_sf_sample(free_sample);
+
+	/* set up voice info */
+	free_info = awe_free_info();
+	rec = &infos[free_info].v;
+	awe_init_voice_info(rec);
+	rec->sample = free_sample; /* the last sample */
+	rec->rate_offset = calc_rate_offset(patch.base_freq);
+	note = freq_to_note(patch.base_note);
+	rec->root = note / 100;
+	rec->tune = -(note % 100);
+	rec->low = freq_to_note(patch.low_note) / 100;
+	rec->high = freq_to_note(patch.high_note) / 100;
+	DEBUG(1,printk("AWE32: [gus base offset=%d, note=%d, range=%d-%d(%d-%d)]\n",
+		       rec->rate_offset, note,
+		       rec->low, rec->high,
+	      patch.low_note, patch.high_note));
+	/* panning position; -128 - 127 => 0-127 */
+	rec->pan = (patch.panning + 128) / 2;
+
+	/* detuning is ignored */
+	/* 6points volume envelope */
+	if (patch.mode & WAVE_ENVELOPES) {
+		int attack, hold, decay, release;
+		attack = calc_gus_envelope_time
+			(patch.env_rate[0], 0, patch.env_offset[0]);
+		hold = calc_gus_envelope_time
+			(patch.env_rate[1], patch.env_offset[0],
+			 patch.env_offset[1]);
+		decay = calc_gus_envelope_time
+			(patch.env_rate[2], patch.env_offset[1],
+			 patch.env_offset[2]);
+		release = calc_gus_envelope_time
+			(patch.env_rate[3], patch.env_offset[1],
+			 patch.env_offset[4]);
+		release += calc_gus_envelope_time
+			(patch.env_rate[4], patch.env_offset[3],
+			 patch.env_offset[4]);
+		release += calc_gus_envelope_time
+			(patch.env_rate[5], patch.env_offset[4],
+			 patch.env_offset[5]);
+		rec->parm.volatkhld = (calc_parm_attack(attack) << 8) |
+			calc_parm_hold(hold);
+		rec->parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
+			calc_parm_decay(decay);
+		rec->parm.volrelease = 0x8000 | calc_parm_decay(release);
+		DEBUG(2,printk("AWE32: [gusenv atk=%d, hld=%d, dcy=%d, rel=%d]\n", attack, hold, decay, release));
+		rec->attenuation = calc_gus_attenuation(patch.env_offset[0]);
+	}
+
+	/* tremolo effect */
+	if (patch.mode & WAVE_TREMOLO) {
+		int rate = (patch.tremolo_rate * 1000 / 38) / 42;
+		rec->parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
+		DEBUG(2,printk("AWE32: [gusenv tremolo rate=%d, dep=%d, tremfrq=%x]\n",
+			       patch.tremolo_rate, patch.tremolo_depth,
+			       rec->parm.tremfrq));
+	}
+	/* vibrato effect */
+	if (patch.mode & WAVE_VIBRATO) {
+		int rate = (patch.vibrato_rate * 1000 / 38) / 42;
+		rec->parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
+		DEBUG(2,printk("AWE32: [gusenv vibrato rate=%d, dep=%d, tremfrq=%x]\n",
+			       patch.tremolo_rate, patch.tremolo_depth,
+			       rec->parm.tremfrq));
+	}
+	
+	/* scale_freq, scale_factor, volume, and fractions not implemented */
+
+	/* append to the tail of the list */
+	infos[free_info].bank = ctrls[AWE_MD_GUS_BANK];
+	infos[free_info].instr = patch.instr_no;
+	infos[free_info].disabled = FALSE;
+	infos[free_info].type = V_ST_NORMAL;
+	infos[free_info].v.sf_id = current_sf_id;
+
+	add_info_list(free_info);
+	add_sf_info(free_info);
+
+	/* set the voice index */
+	awe_set_sample(rec);
+
+	return 0;
+}
+
+#endif  /* AWE_HAS_GUS_COMPATIBILITY */
+
+/*
+ * sample and voice list handlers
+ */
+
+/* append this to the sf list */
+static void add_sf_info(int rec)
+{
+	int sf_id = infos[rec].v.sf_id;
+	if (sf_id <= 0) return;
+	sf_id--;
+	if (sflists[sf_id].infos < 0)
+		sflists[sf_id].infos = rec;
+	else {
+		int i, prev;
+		prev = sflists[sf_id].infos;
+		while ((i = infos[prev].next) >= 0)
+			prev = i;
+		infos[prev].next = rec;
+	}
+	infos[rec].next = -1;
+	sflists[sf_id].num_info++;
+}
+
+/* prepend this sample to sf list */
+static void add_sf_sample(int rec)
+{
+	int sf_id = samples[rec].v.sf_id;
+	if (sf_id <= 0) return;
+	sf_id--;
+	samples[rec].next = sflists[sf_id].samples;
+	sflists[sf_id].samples = rec;
+	sflists[sf_id].num_sample++;
+}
+
+/* purge the old records which don't belong with the same file id */
+static void purge_old_list(int rec, int next)
+{
+	infos[rec].next_instr = next;
+	if (infos[rec].bank == AWE_DRUM_BANK) {
+		/* remove samples with the same note range */
+		int cur, *prevp = &infos[rec].next_instr;
+		int low = infos[rec].v.low;
+		int high = infos[rec].v.high;
+		for (cur = next; cur >= 0; cur = infos[cur].next_instr) {
+			if (infos[cur].v.low == low &&
+			    infos[cur].v.high == high &&
+			    ! is_identical_id(infos[cur].v.sf_id, infos[rec].v.sf_id))
+				*prevp = infos[cur].next_instr;
+			prevp = &infos[cur].next_instr;
+		}
+	} else {
+		if (! is_identical_id(infos[next].v.sf_id, infos[rec].v.sf_id))
+			infos[rec].next_instr = -1;
+	}
+}
+
+/* prepend to top of the preset table */
+static void add_info_list(int rec)
+{
+	int *prevp, cur;
+	int instr;
+	int bank;
+
+	if (infos[rec].disabled)
+		return;
+
+	instr = infos[rec].instr;
+	bank = infos[rec].bank;
+	limitvalue(instr, 0, AWE_MAX_PRESETS-1);
+	prevp = &preset_table[instr];
+	cur = *prevp;
+	while (cur >= 0) {
+		/* search the first record with the same bank number */
+		if (infos[cur].bank == bank) {
+			/* replace the list with the new record */
+			infos[rec].next_bank = infos[cur].next_bank;
+			*prevp = rec;
+			purge_old_list(rec, cur);
+			return;
+		}
+		prevp = &infos[cur].next_bank;
+		cur = infos[cur].next_bank;
+	}
+
+	/* this is the first bank record.. just add this */
+	infos[rec].next_instr = -1;
+	infos[rec].next_bank = preset_table[instr];
+	preset_table[instr] = rec;
+}
+
+/* remove samples later than the specified sf_id */
+static void
+awe_remove_samples(int sf_id)
+{
+	if (sf_id <= 0) {
+		awe_reset_samples();
+		return;
+	}
+	/* already removed? */
+	if (current_sf_id <= sf_id)
+		return;
+
+	current_sf_id = sf_id;
+	if (locked_sf_id > sf_id)
+		locked_sf_id = sf_id;
+
+	rebuild_preset_list();
+}
+
+/* rebuild preset search list */
+static void rebuild_preset_list(void)
+{
+	int i, j;
+
+	for (i = 0; i < AWE_MAX_PRESETS; i++)
+		preset_table[i] = -1;
+
+	for (i = 0; i < current_sf_id; i++) {
+		for (j = sflists[i].infos; j >= 0; j = infos[j].next)
+			add_info_list(j);
+	}
+}
+
+/* compare the given sf_id pair */
+static int is_identical_id(int id1, int id2)
+{
+	if (id1 == id2)
+		return TRUE;
+	if (id1 <= 0 || id2 <= 0) /* this must not happen.. */
+		return FALSE;
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	{
+		/* compare with the sharing id */
+		int i;
+		if (id1 < id2) { /* make sure id1 > id2 */
+			int tmp; tmp = id1; id1 = id2; id2 = tmp;
+		}
+		for (i = sflists[id1-1].shared; i > 0 && i <= current_sf_id; i = sflists[i-1].shared) {
+			if (i == id2)
+				return TRUE;
+		}
+	}
+#endif /* allow sharing */
+	return FALSE;
+}
+
+/* search the sample index matching with the given sample id */
+static int search_sample_index(int sf, int sample, int level)
+{
+	int i;
+
+	if (sf <= 0 || sf > current_sf_id)
+		return -1; /* this must not happen */
+
+	for (i = sflists[sf-1].samples; i >= 0; i = samples[i].next) {
+		if (samples[i].v.sample == sample)
+			return i;
+	}
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	if ((i = sflists[sf-1].shared) > 0 && i <= current_sf_id) { /* search recursively */
+		if (level > current_sf_id)
+			return -1; /* strange sharing loop.. quit */
+		return search_sample_index(i, sample, level + 1);
+	}
+#endif
+	return -1;
+}
+
+/* search the specified sample */
+static short
+awe_set_sample(awe_voice_info *vp)
+{
+	int i;
+
+	vp->index = -1;
+	if ((i = search_sample_index(vp->sf_id, vp->sample, 0)) < 0)
+		return -1;
+
+	/* set the actual sample offsets */
+	vp->start += samples[i].v.start;
+	vp->end += samples[i].v.end;
+	vp->loopstart += samples[i].v.loopstart;
+	vp->loopend += samples[i].v.loopend;
+	/* copy mode flags */
+	vp->mode = samples[i].v.mode_flags;
+	/* set index */
+	vp->index = i;
+
+	return i;
+}
+
+
+/*----------------------------------------------------------------
+ * voice allocation
+ *----------------------------------------------------------------*/
+
+/* look for all voices associated with the specified note & velocity */
+static int
+awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist)
+{
+	int nvoices;
+
+	nvoices = 0;
+	for (; rec >= 0; rec = infos[rec].next_instr) {
+		if (note >= infos[rec].v.low &&
+		    note <= infos[rec].v.high &&
+		    velocity >= infos[rec].v.vellow &&
+		    velocity <= infos[rec].v.velhigh) {
+			if (infos[rec].type == V_ST_MAPPED) {
+				/* mapper */
+				vlist[0] = &infos[rec].v;
+				return -1;
+			}
+			vlist[nvoices++] = &infos[rec].v;
+			if (nvoices >= AWE_MAX_VOICES)
+				break;
+		}
+	}
+	return nvoices;	
+}
+
+/* store the voice list from the specified note and velocity.
+   if the preset is mapped, seek for the destination preset, and rewrite
+   the note number if necessary.
+   */
+static int
+really_alloc_voices(int vrec, int def_vrec, int *note, int velocity, awe_voice_info **vlist, int level)
+{
+	int nvoices;
+
+	nvoices = awe_search_multi_voices(vrec, *note, velocity, vlist);
+	if (nvoices == 0)
+		nvoices = awe_search_multi_voices(def_vrec, *note, velocity, vlist);
+	if (nvoices < 0) { /* mapping */
+		int preset = vlist[0]->start;
+		int bank = vlist[0]->end;
+		int key = vlist[0]->fixkey;
+		if (level > 5) {
+			printk("AWE32: too deep mapping level\n");
+			return 0;
+		}
+		vrec = awe_search_instr(bank, preset);
+		if (bank == AWE_DRUM_BANK)
+			def_vrec = awe_search_instr(bank, 0);
+		else
+			def_vrec = awe_search_instr(0, preset);
+		if (key >= 0)
+			*note = key;
+		return really_alloc_voices(vrec, def_vrec, note, velocity, vlist, level+1);
+	}
+
+	return nvoices;
+}
+
+/* allocate voices corresponding note and velocity; supports multiple insts. */
+static void
+awe_alloc_multi_voices(int ch, int note, int velocity, int key)
+{
+	int i, v, nvoices;
+	awe_voice_info *vlist[AWE_MAX_VOICES];
+
+	if (channels[ch].vrec < 0 && channels[ch].def_vrec < 0)
+		awe_set_instr(0, ch, channels[ch].instr);
+
+	/* check the possible voices; note may be changeable if mapped */
+	nvoices = really_alloc_voices(channels[ch].vrec, channels[ch].def_vrec,
+				      &note, velocity, vlist, 0);
+
+	/* set the voices */
+	current_alloc_time++;
+	for (i = 0; i < nvoices; i++) {
+		v = awe_clear_voice();
+		voices[v].key = key;
+		voices[v].ch = ch;
+		voices[v].note = note;
+		voices[v].velocity = velocity;
+		voices[v].time = current_alloc_time;
+		voices[v].cinfo = &channels[ch];
+		voices[v].sample = vlist[i];
+		voices[v].state = AWE_ST_MARK;
+		voices[v].layer = nvoices - i - 1;  /* in reverse order */
+	}
+
+	/* clear the mark in allocated voices */
+	for (i = 0; i < awe_max_voices; i++) {
+		if (voices[i].state == AWE_ST_MARK)
+			voices[i].state = AWE_ST_OFF;
+			
+	}
+}
+
+
+/* search the best voice from the specified status condition */
+static int
+search_best_voice(int condition)
+{
+	int i, time, best;
+	int vtarget = 0xffff, min_vtarget = 0xffff;
+
+	best = -1;
+	time = current_alloc_time + 1;
+	for (i = 0; i < awe_max_voices; i++) {
+		if (! (voices[i].state & condition))
+			continue;
+#ifdef AWE_CHECK_VTARGET
+		/* get current volume */
+		vtarget = (awe_peek_dw(AWE_VTFT(i)) >> 16) & 0xffff;
+#endif
+		if (best < 0 || vtarget < min_vtarget ||
+		    (vtarget == min_vtarget && voices[i].time < time)) {
+			best = i;
+			time = voices[i].time;
+			min_vtarget = vtarget;
+		}
+	}
+	/* clear voice */
+	if (best >= 0) {
+		if (voices[best].state != AWE_ST_OFF)
+			awe_terminate(best);
+		awe_voice_init(best, TRUE);
+	}
+
+	return best;
+}
+
+/* search an empty voice.
+   if no empty voice is found, at least terminate a voice
+   */
+static int
+awe_clear_voice(void)
+{
+	int best;
+
+	/* looking for the oldest empty voice */
+	if ((best = search_best_voice(AWE_ST_OFF)) >= 0)
+		return best;
+	if ((best = search_best_voice(AWE_ST_RELEASED)) >= 0)
+		return best;
+	/* looking for the oldest sustained voice */
+	if ((best = search_best_voice(AWE_ST_SUSTAINED)) >= 0)
+		return best;
+
+	if (MULTI_LAYER_MODE() && ctrls[AWE_MD_CHN_PRIOR]) {
+		int ch = -1;
+		int time = current_alloc_time + 1;
+		int i;
+		/* looking for the voices from high channel (except drum ch) */
+		for (i = 0; i < awe_max_voices; i++) {
+			if (IS_DRUM_CHANNEL(voices[i].ch)) continue;
+			if (voices[i].ch < ch) continue;
+			if (voices[i].state != AWE_ST_MARK &&
+			    (voices[i].ch > ch || voices[i].time < time)) {
+				best = i;
+				time = voices[i].time;
+				ch = voices[i].ch;
+			}
+		}
+	}
+	if (best < 0)
+		best = search_best_voice(~AWE_ST_MARK);
+
+	if (best >= 0)
+		return best;
+
+	return 0;
+}
+
+
+/* search sample for the specified note & velocity and set it on the voice;
+ * note that voice is the voice index (not channel index)
+ */
+static void
+awe_alloc_one_voice(int voice, int note, int velocity)
+{
+	int ch, nvoices;
+	awe_voice_info *vlist[AWE_MAX_VOICES];
+
+	ch = voices[voice].ch;
+	if (channels[ch].vrec < 0 && channels[ch].def_vrec < 0)
+		awe_set_instr(0, ch, channels[ch].instr);
+
+	nvoices = really_alloc_voices(voices[voice].cinfo->vrec,
+				      voices[voice].cinfo->def_vrec,
+				      &note, velocity, vlist, 0);
+	if (nvoices > 0) {
+		voices[voice].time = ++current_alloc_time;
+		voices[voice].sample = vlist[0]; /* use the first one */
+		voices[voice].layer = 0;
+		voices[voice].note = note;
+		voices[voice].velocity = velocity;
+	}
+}
+
+
+/*----------------------------------------------------------------
+ * sequencer2 functions
+ *----------------------------------------------------------------*/
+
+/* search an empty voice; used by sequencer2 */
+static int
+awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
+{
+	playing_mode = AWE_PLAY_MULTI2;
+	awe_info.nr_voices = AWE_MAX_CHANNELS;
+	return awe_clear_voice();
+}
+
+
+/* set up voice; used by sequencer2 */
+static void
+awe_setup_voice(int dev, int voice, int chn)
+{
+	struct channel_info *info;
+	if (synth_devs[dev] == NULL ||
+	    (info = &synth_devs[dev]->chn_info[chn]) == NULL)
+		return;
+
+	if (voice < 0 || voice >= awe_max_voices)
+		return;
+
+	DEBUG(2,printk("AWE32: [setup(%d) ch=%d]\n", voice, chn));
+	channels[chn].expression_vol = info->controllers[CTL_EXPRESSION];
+	channels[chn].main_vol = info->controllers[CTL_MAIN_VOLUME];
+	channels[chn].panning =
+		info->controllers[CTL_PAN] * 2 - 128; /* signed 8bit */
+	channels[chn].bender = info->bender_value; /* zero center */
+	channels[chn].bank = info->controllers[CTL_BANK_SELECT];
+	channels[chn].sustained = info->controllers[CTL_SUSTAIN];
+	if (info->controllers[CTL_EXT_EFF_DEPTH]) {
+		FX_SET(&channels[chn].fx, AWE_FX_REVERB,
+		       info->controllers[CTL_EXT_EFF_DEPTH] * 2);
+	}
+	if (info->controllers[CTL_CHORUS_DEPTH]) {
+		FX_SET(&channels[chn].fx, AWE_FX_CHORUS,
+		       info->controllers[CTL_CHORUS_DEPTH] * 2);
+	}
+	awe_set_instr(dev, chn, info->pgm_num);
+}
+
+
+#ifdef CONFIG_AWE32_MIXER
+/*
+ * AWE32 mixer device control
+ */
+
+static int awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg);
+
+static int my_mixerdev = -1;
+
+static struct mixer_operations awe_mixer_operations = {
+	"AWE32 Equalizer",
+	awe_mixer_ioctl,
+};
+
+static void attach_mixer(void)
+{
+	if ((my_mixerdev = sound_alloc_mixerdev()) >= 0) {
+		mixer_devs[my_mixerdev] = &awe_mixer_operations;
+	}
+}
+
+static void unload_mixer(void)
+{
+	if (my_mixerdev >= 0)
+		sound_unload_mixerdev(my_mixerdev);
+}
+
+static int
+awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+	int i, level, value;
+
+	if (((cmd >> 8) & 0xff) != 'M')
+		return -EINVAL;
+
+	level = (int) *(int *)arg;
+	level = ((level & 0xff) + (level >> 8)) / 2;
+	DEBUG(0,printk("AWEMix: cmd=%x val=%d\n", cmd & 0xff, level));
+
+	if (_SIOC_DIR(cmd) & _IOC_WRITE) {
+		switch (cmd & 0xff) {
+		case SOUND_MIXER_BASS:
+			value = level * 12 / 100;
+			if (value >= 12)
+				value = 11;
+			ctrls[AWE_MD_BASS_LEVEL] = value;
+			awe_update_equalizer();
+			break;
+		case SOUND_MIXER_TREBLE:
+			value = level * 12 / 100;
+			if (value >= 12)
+				value = 11;
+			ctrls[AWE_MD_TREBLE_LEVEL] = value;
+			awe_update_equalizer();
+			break;
+		case SOUND_MIXER_VOLUME:
+			level = level * 127 / 100;
+			if (level >= 128) level = 127;
+			atten_relative = FALSE;
+			atten_offset = vol_table[level];
+			awe_update_volume();
+			break;
+		}
+	}
+	switch (cmd & 0xff) {
+	case SOUND_MIXER_BASS:
+		level = ctrls[AWE_MD_BASS_LEVEL] * 100 / 24;
+		level = (level << 8) | level;
+		break;
+	case SOUND_MIXER_TREBLE:
+		level = ctrls[AWE_MD_TREBLE_LEVEL] * 100 / 24;
+		level = (level << 8) | level;
+		break;
+	case SOUND_MIXER_VOLUME:
+		value = atten_offset;
+		if (atten_relative)
+			value += ctrls[AWE_MD_ZERO_ATTEN];
+		for (i = 127; i > 0; i--) {
+			if (value <= vol_table[i])
+				break;
+		}
+		level = i * 100 / 127;
+		level = (level << 8) | level;
+		break;
+	case SOUND_MIXER_DEVMASK:
+		level = SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_VOLUME;
+		break;
+	default:
+		level = 0;
+		break;
+	}
+	return *(int *)arg = level;
+}
+#endif /* CONFIG_AWE32_MIXER */
+
+
+/*
+ * initialization of AWE32
+ */
+
+/* intiailize audio channels */
+static void
+awe_init_audio(void)
+{
+	int ch;
+
+	/* turn off envelope engines */
+	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+		awe_poke(AWE_DCYSUSV(ch), 0x80);
+	}
+  
+	/* reset all other parameters to zero */
+	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+		awe_poke(AWE_ENVVOL(ch), 0);
+		awe_poke(AWE_ENVVAL(ch), 0);
+		awe_poke(AWE_DCYSUS(ch), 0);
+		awe_poke(AWE_ATKHLDV(ch), 0);
+		awe_poke(AWE_LFO1VAL(ch), 0);
+		awe_poke(AWE_ATKHLD(ch), 0);
+		awe_poke(AWE_LFO2VAL(ch), 0);
+		awe_poke(AWE_IP(ch), 0);
+		awe_poke(AWE_IFATN(ch), 0);
+		awe_poke(AWE_PEFE(ch), 0);
+		awe_poke(AWE_FMMOD(ch), 0);
+		awe_poke(AWE_TREMFRQ(ch), 0);
+		awe_poke(AWE_FM2FRQ2(ch), 0);
+		awe_poke_dw(AWE_PTRX(ch), 0);
+		awe_poke_dw(AWE_VTFT(ch), 0);
+		awe_poke_dw(AWE_PSST(ch), 0);
+		awe_poke_dw(AWE_CSL(ch), 0);
+		awe_poke_dw(AWE_CCCA(ch), 0);
+	}
+
+	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
+		awe_poke_dw(AWE_CPF(ch), 0);
+		awe_poke_dw(AWE_CVCF(ch), 0);
+	}
+}
+
+
+/* initialize DMA address */
+static void
+awe_init_dma(void)
+{
+	awe_poke_dw(AWE_SMALR, 0);
+	awe_poke_dw(AWE_SMARR, 0);
+	awe_poke_dw(AWE_SMALW, 0);
+	awe_poke_dw(AWE_SMARW, 0);
+}
+
+
+/* initialization arrays; from ADIP */
+
+static unsigned short init1[128] = {
+	0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
+	0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
+	0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
+	0x33ff, 0x0c30,  0x37ff, 0x0d30, 0x3bff, 0x0e30,  0x3fff, 0x0f30,
+
+	0x43ff, 0x0030,  0x47ff, 0x0130, 0x4bff, 0x0230,  0x4fff, 0x0330,
+	0x53ff, 0x0430,  0x57ff, 0x0530, 0x5bff, 0x0630,  0x5fff, 0x0730,
+	0x63ff, 0x0830,  0x67ff, 0x0930, 0x6bff, 0x0a30,  0x6fff, 0x0b30,
+	0x73ff, 0x0c30,  0x77ff, 0x0d30, 0x7bff, 0x0e30,  0x7fff, 0x0f30,
+
+	0x83ff, 0x0030,  0x87ff, 0x0130, 0x8bff, 0x0230,  0x8fff, 0x0330,
+	0x93ff, 0x0430,  0x97ff, 0x0530, 0x9bff, 0x0630,  0x9fff, 0x0730,
+	0xa3ff, 0x0830,  0xa7ff, 0x0930, 0xabff, 0x0a30,  0xafff, 0x0b30,
+	0xb3ff, 0x0c30,  0xb7ff, 0x0d30, 0xbbff, 0x0e30,  0xbfff, 0x0f30,
+
+	0xc3ff, 0x0030,  0xc7ff, 0x0130, 0xcbff, 0x0230,  0xcfff, 0x0330,
+	0xd3ff, 0x0430,  0xd7ff, 0x0530, 0xdbff, 0x0630,  0xdfff, 0x0730,
+	0xe3ff, 0x0830,  0xe7ff, 0x0930, 0xebff, 0x0a30,  0xefff, 0x0b30,
+	0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
+};
+
+static unsigned short init2[128] = {
+	0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
+	0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
+	0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
+	0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
+
+	0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
+	0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
+	0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
+	0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
+
+	0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
+	0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
+	0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
+	0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
+
+	0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
+	0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
+	0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
+	0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
+};
+
+static unsigned short init3[128] = {
+	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
+	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
+	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
+	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
+
+	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
+	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
+	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
+	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
+
+	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
+	0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
+	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
+	0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
+
+	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
+	0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
+	0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
+	0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
+};
+
+static unsigned short init4[128] = {
+	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
+	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
+	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
+	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
+
+	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
+	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
+	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
+	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
+
+	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
+	0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
+	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
+	0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
+
+	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
+	0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
+	0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
+	0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
+};
+
+
+/* send initialization arrays to start up */
+static void
+awe_init_array(void)
+{
+	awe_send_array(init1);
+	awe_wait(1024);
+	awe_send_array(init2);
+	awe_send_array(init3);
+	awe_poke_dw(AWE_HWCF4, 0);
+	awe_poke_dw(AWE_HWCF5, 0x83);
+	awe_poke_dw(AWE_HWCF6, 0x8000);
+	awe_send_array(init4);
+}
+
+/* send an initialization array */
+static void
+awe_send_array(unsigned short *data)
+{
+	int i;
+	unsigned short *p;
+
+	p = data;
+	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+		awe_poke(AWE_INIT1(i), *p);
+	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+		awe_poke(AWE_INIT2(i), *p);
+	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+		awe_poke(AWE_INIT3(i), *p);
+	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
+		awe_poke(AWE_INIT4(i), *p);
+}
+
+
+/*
+ * set up awe32 channels to some known state.
+ */
+
+/* set the envelope & LFO parameters to the default values; see ADIP */
+static void
+awe_tweak_voice(int i)
+{
+	/* set all mod/vol envelope shape to minimum */
+	awe_poke(AWE_ENVVOL(i), 0x8000);
+	awe_poke(AWE_ENVVAL(i), 0x8000);
+	awe_poke(AWE_DCYSUS(i), 0x7F7F);
+	awe_poke(AWE_ATKHLDV(i), 0x7F7F);
+	awe_poke(AWE_ATKHLD(i), 0x7F7F);
+	awe_poke(AWE_PEFE(i), 0);  /* mod envelope height to zero */
+	awe_poke(AWE_LFO1VAL(i), 0x8000); /* no delay for LFO1 */
+	awe_poke(AWE_LFO2VAL(i), 0x8000);
+	awe_poke(AWE_IP(i), 0xE000);	/* no pitch shift */
+	awe_poke(AWE_IFATN(i), 0xFF00);	/* volume to minimum */
+	awe_poke(AWE_FMMOD(i), 0);
+	awe_poke(AWE_TREMFRQ(i), 0);
+	awe_poke(AWE_FM2FRQ2(i), 0);
+}
+
+static void
+awe_tweak(void)
+{
+	int i;
+	/* reset all channels */
+	for (i = 0; i < awe_max_voices; i++)
+		awe_tweak_voice(i);
+}
+
+
+/*
+ *  initializes the FM section of AWE32;
+ *   see Vince Vu's unofficial AWE32 programming guide
+ */
+
+static void
+awe_init_fm(void)
+{
+#ifndef AWE_ALWAYS_INIT_FM
+	/* if no extended memory is on board.. */
+	if (awe_mem_size <= 0)
+		return;
+#endif
+	DEBUG(3,printk("AWE32: initializing FM\n"));
+
+	/* Initialize the last two channels for DRAM refresh and producing
+	   the reverb and chorus effects for Yamaha OPL-3 synthesizer */
+
+	/* 31: FM left channel, 0xffffe0-0xffffe8 */
+	awe_poke(AWE_DCYSUSV(30), 0x80);
+	awe_poke_dw(AWE_PSST(30), 0xFFFFFFE0); /* full left */
+	awe_poke_dw(AWE_CSL(30), 0x00FFFFE8 |
+		    (DEF_FM_CHORUS_DEPTH << 24));
+	awe_poke_dw(AWE_PTRX(30), (DEF_FM_REVERB_DEPTH << 8));
+	awe_poke_dw(AWE_CPF(30), 0);
+	awe_poke_dw(AWE_CCCA(30), 0x00FFFFE3);
+
+	/* 32: FM right channel, 0xfffff0-0xfffff8 */
+	awe_poke(AWE_DCYSUSV(31), 0x80);
+	awe_poke_dw(AWE_PSST(31), 0x00FFFFF0); /* full right */
+	awe_poke_dw(AWE_CSL(31), 0x00FFFFF8 |
+		    (DEF_FM_CHORUS_DEPTH << 24));
+	awe_poke_dw(AWE_PTRX(31), (DEF_FM_REVERB_DEPTH << 8));
+	awe_poke_dw(AWE_CPF(31), 0x8000);
+	awe_poke_dw(AWE_CCCA(31), 0x00FFFFF3);
+
+	/* skew volume & cutoff */
+	awe_poke_dw(AWE_VTFT(30), 0x8000FFFF);
+	awe_poke_dw(AWE_VTFT(31), 0x8000FFFF);
+
+	voices[30].state = AWE_ST_FM;
+	voices[31].state = AWE_ST_FM;
+
+	/* change maximum channels to 30 */
+	awe_max_voices = AWE_NORMAL_VOICES;
+	if (playing_mode == AWE_PLAY_DIRECT)
+		awe_info.nr_voices = awe_max_voices;
+	else
+		awe_info.nr_voices = AWE_MAX_CHANNELS;
+	voice_alloc->max_voice = awe_max_voices;
+}
+
+/*
+ *  AWE32 DRAM access routines
+ */
+
+/* open DRAM write accessing mode */
+static int
+awe_open_dram_for_write(int offset, int channels)
+{
+	int vidx[AWE_NORMAL_VOICES];
+	int i;
+
+	if (channels < 0 || channels >= AWE_NORMAL_VOICES) {
+		channels = AWE_NORMAL_VOICES;
+		for (i = 0; i < AWE_NORMAL_VOICES; i++)
+			vidx[i] = i;
+	} else {
+		for (i = 0; i < channels; i++) {
+			vidx[i] = awe_clear_voice();
+			voices[vidx[i]].state = AWE_ST_MARK;
+		}
+	}
+
+	/* use all channels for DMA transfer */
+	for (i = 0; i < channels; i++) {
+		if (vidx[i] < 0) continue;
+		awe_poke(AWE_DCYSUSV(vidx[i]), 0x80);
+		awe_poke_dw(AWE_VTFT(vidx[i]), 0);
+		awe_poke_dw(AWE_CVCF(vidx[i]), 0);
+		awe_poke_dw(AWE_PTRX(vidx[i]), 0x40000000);
+		awe_poke_dw(AWE_CPF(vidx[i]), 0x40000000);
+		awe_poke_dw(AWE_PSST(vidx[i]), 0);
+		awe_poke_dw(AWE_CSL(vidx[i]), 0);
+		awe_poke_dw(AWE_CCCA(vidx[i]), 0x06000000);
+		voices[vidx[i]].state = AWE_ST_DRAM;
+	}
+	/* point channels 31 & 32 to ROM samples for DRAM refresh */
+	awe_poke_dw(AWE_VTFT(30), 0);
+	awe_poke_dw(AWE_PSST(30), 0x1d8);
+	awe_poke_dw(AWE_CSL(30), 0x1e0);
+	awe_poke_dw(AWE_CCCA(30), 0x1d8);
+	awe_poke_dw(AWE_VTFT(31), 0);
+	awe_poke_dw(AWE_PSST(31), 0x1d8);
+	awe_poke_dw(AWE_CSL(31), 0x1e0);
+	awe_poke_dw(AWE_CCCA(31), 0x1d8);
+	voices[30].state = AWE_ST_FM;
+	voices[31].state = AWE_ST_FM;
+
+	/* if full bit is on, not ready to write on */
+	if (awe_peek_dw(AWE_SMALW) & 0x80000000) {
+		for (i = 0; i < channels; i++) {
+			awe_poke_dw(AWE_CCCA(vidx[i]), 0);
+			voices[vidx[i]].state = AWE_ST_OFF;
+		}
+		return -ENOSPC;
+	}
+
+	/* set address to write */
+	awe_poke_dw(AWE_SMALW, offset);
+
+	return 0;
+}
+
+/* open DRAM for RAM size detection */
+static void
+awe_open_dram_for_check(void)
+{
+	int i;
+	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+		awe_poke(AWE_DCYSUSV(i), 0x80);
+		awe_poke_dw(AWE_VTFT(i), 0);
+		awe_poke_dw(AWE_CVCF(i), 0);
+		awe_poke_dw(AWE_PTRX(i), 0x40000000);
+		awe_poke_dw(AWE_CPF(i), 0x40000000);
+		awe_poke_dw(AWE_PSST(i), 0);
+		awe_poke_dw(AWE_CSL(i), 0);
+		if (i & 1) /* DMA write */
+			awe_poke_dw(AWE_CCCA(i), 0x06000000);
+		else	   /* DMA read */
+			awe_poke_dw(AWE_CCCA(i), 0x04000000);
+		voices[i].state = AWE_ST_DRAM;
+	}
+}
+
+
+/* close dram access */
+static void
+awe_close_dram(void)
+{
+	int i;
+	/* wait until FULL bit in SMAxW register be false */
+	for (i = 0; i < 10000; i++) {
+		if (!(awe_peek_dw(AWE_SMALW) & 0x80000000))
+			break;
+		awe_wait(10);
+	}
+
+	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
+		if (voices[i].state == AWE_ST_DRAM) {
+			awe_poke_dw(AWE_CCCA(i), 0);
+			awe_poke(AWE_DCYSUSV(i), 0x807F);
+			voices[i].state = AWE_ST_OFF;
+		}
+	}
+}
+
+
+/*================================================================
+ * detect presence of AWE32 and check memory size
+ *================================================================*/
+
+/* detect emu8000 chip on the specified address; from VV's guide */
+
+static int
+awe_detect_base(int addr)
+{
+	setup_ports(addr, 0, 0);
+	if ((awe_peek(AWE_U1) & 0x000F) != 0x000C)
+		return 0;
+	if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058)
+		return 0;
+	if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003)
+		return 0;
+        DEBUG(0,printk("AWE32 found at %x\n", addr));
+	return 1;
+}
+	
+static int
+awe_detect(void)
+{
+	int base;
+
+	if (port_setuped) /* already initialized by PnP */
+		return 1;
+
+	if (awe_port) /* use default i/o port value */
+		setup_ports(awe_port, 0, 0);
+	else { /* probe it */
+		for (base = 0x620; base <= 0x680; base += 0x20)
+			if (awe_detect_base(base))
+				return 1;
+		DEBUG(0,printk("AWE32 not found\n"));
+		return 0;
+	}
+
+	return 1;
+}
+
+
+/*================================================================
+ * check dram size on AWE board
+ *================================================================*/
+
+/* any three numbers you like */
+#define UNIQUE_ID1	0x1234
+#define UNIQUE_ID2	0x4321
+#define UNIQUE_ID3	0xFFFF
+
+static void
+awe_check_dram(void)
+{
+	if (awe_present) /* already initialized */
+		return;
+
+	if (awe_mem_size >= 0) { /* given by config file or module option */
+		awe_mem_size *= 1024; /* convert to Kbytes */
+		return;
+	}
+
+	awe_open_dram_for_check();
+
+	awe_mem_size = 0;
+
+	/* set up unique two id numbers */
+	awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET);
+	awe_poke(AWE_SMLD, UNIQUE_ID1);
+	awe_poke(AWE_SMLD, UNIQUE_ID2);
+
+	while (awe_mem_size < AWE_MAX_DRAM_SIZE) {
+		awe_wait(5);
+		/* read a data on the DRAM start address */
+		awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET);
+		awe_peek(AWE_SMLD); /* discard stale data  */
+		if (awe_peek(AWE_SMLD) != UNIQUE_ID1)
+			break;
+		if (awe_peek(AWE_SMLD) != UNIQUE_ID2)
+			break;
+		awe_mem_size += 512;  /* increment 512kbytes */
+		/* Write a unique data on the test address;
+		 * if the address is out of range, the data is written on
+		 * 0x200000(=AWE_DRAM_OFFSET).  Then the two id words are
+		 * broken by this data.
+		 */
+		awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET + awe_mem_size*512L);
+		awe_poke(AWE_SMLD, UNIQUE_ID3);
+		awe_wait(5);
+		/* read a data on the just written DRAM address */
+		awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET + awe_mem_size*512L);
+		awe_peek(AWE_SMLD); /* discard stale data  */
+		if (awe_peek(AWE_SMLD) != UNIQUE_ID3)
+			break;
+	}
+	awe_close_dram();
+
+	DEBUG(0,printk("AWE32: %d Kbytes memory detected\n", awe_mem_size));
+
+	/* convert to Kbytes */
+	awe_mem_size *= 1024;
+}
+
+
+/*================================================================
+ * chorus and reverb controls; from VV's guide
+ *================================================================*/
+
+/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
+static char chorus_defined[AWE_CHORUS_NUMBERS];
+static awe_chorus_fx_rec chorus_parm[AWE_CHORUS_NUMBERS] = {
+	{0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
+	{0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
+	{0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
+	{0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
+	{0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
+	{0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
+	{0xE600, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay */
+	{0xE6C0, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay + feedback */
+};
+
+static int
+awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count)
+{
+	if (patch->optarg < AWE_CHORUS_PREDEFINED || patch->optarg >= AWE_CHORUS_NUMBERS) {
+		printk("AWE32 Error: illegal chorus mode %d for uploading\n", patch->optarg);
+		return -EINVAL;
+	}
+	if (count < sizeof(awe_chorus_fx_rec)) {
+		printk("AWE32 Error: too short chorus fx parameters\n");
+		return -EINVAL;
+	}
+	copy_from_user(&chorus_parm[patch->optarg], addr + AWE_PATCH_INFO_SIZE,
+		       sizeof(awe_chorus_fx_rec));
+	chorus_defined[patch->optarg] = TRUE;
+	return 0;
+}
+
+static void
+awe_set_chorus_mode(int effect)
+{
+	if (effect < 0 || effect >= AWE_CHORUS_NUMBERS ||
+	    (effect >= AWE_CHORUS_PREDEFINED && !chorus_defined[effect]))
+		return;
+	awe_poke(AWE_INIT3(9), chorus_parm[effect].feedback);
+	awe_poke(AWE_INIT3(12), chorus_parm[effect].delay_offset);
+	awe_poke(AWE_INIT4(3), chorus_parm[effect].lfo_depth);
+	awe_poke_dw(AWE_HWCF4, chorus_parm[effect].delay);
+	awe_poke_dw(AWE_HWCF5, chorus_parm[effect].lfo_freq);
+	awe_poke_dw(AWE_HWCF6, 0x8000);
+	awe_poke_dw(AWE_HWCF7, 0x0000);
+}
+
+static void
+awe_update_chorus_mode(void)
+{
+	awe_set_chorus_mode(ctrls[AWE_MD_CHORUS_MODE]);
+}
+
+/*----------------------------------------------------------------*/
+
+/* reverb mode settings; write the following 28 data of 16 bit length
+ *   on the corresponding ports in the reverb_cmds array
+ */
+static char reverb_defined[AWE_CHORUS_NUMBERS];
+static awe_reverb_fx_rec reverb_parm[AWE_REVERB_NUMBERS] = {
+{{  /* room 1 */
+	0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
+	0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
+	0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
+	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
+}},
+{{  /* room 2 */
+	0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
+	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
+	0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
+	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
+}},
+{{  /* room 3 */
+	0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
+	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
+	0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
+	0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
+}},
+{{  /* hall 1 */
+	0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
+	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
+	0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
+	0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
+}},
+{{  /* hall 2 */
+	0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
+	0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
+	0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
+	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
+}},
+{{  /* plate */
+	0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
+	0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
+	0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
+	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
+}},
+{{  /* delay */
+	0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
+	0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
+	0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
+	0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
+}},
+{{  /* panning delay */
+	0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
+	0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
+	0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
+	0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
+}},
+};
+
+static struct ReverbCmdPair {
+	unsigned short cmd, port;
+} reverb_cmds[28] = {
+  {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
+  {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
+  {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
+  {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
+  {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
+  {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
+  {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
+};
+
+static int
+awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count)
+{
+	if (patch->optarg < AWE_REVERB_PREDEFINED || patch->optarg >= AWE_REVERB_NUMBERS) {
+		printk("AWE32 Error: illegal reverb mode %d for uploading\n", patch->optarg);
+		return -EINVAL;
+	}
+	if (count < sizeof(awe_reverb_fx_rec)) {
+		printk("AWE32 Error: too short reverb fx parameters\n");
+		return -EINVAL;
+	}
+	copy_from_user(&reverb_parm[patch->optarg], addr + AWE_PATCH_INFO_SIZE,
+		       sizeof(awe_reverb_fx_rec));
+	reverb_defined[patch->optarg] = TRUE;
+	return 0;
+}
+
+static void
+awe_set_reverb_mode(int effect)
+{
+	int i;
+	if (effect < 0 || effect >= AWE_REVERB_NUMBERS ||
+	    (effect >= AWE_REVERB_PREDEFINED && !reverb_defined[effect]))
+		return;
+	for (i = 0; i < 28; i++)
+		awe_poke(reverb_cmds[i].cmd, reverb_cmds[i].port,
+			 reverb_parm[effect].parms[i]);
+}
+
+static void
+awe_update_reverb_mode(void)
+{
+	awe_set_reverb_mode(ctrls[AWE_MD_REVERB_MODE]);
+}
+
+/*================================================================
+ * treble/bass equalizer control
+ *================================================================*/
+
+static unsigned short bass_parm[12][3] = {
+	{0xD26A, 0xD36A, 0x0000}, /* -12 dB */
+	{0xD25B, 0xD35B, 0x0000}, /*  -8 */
+	{0xD24C, 0xD34C, 0x0000}, /*  -6 */
+	{0xD23D, 0xD33D, 0x0000}, /*  -4 */
+	{0xD21F, 0xD31F, 0x0000}, /*  -2 */
+	{0xC208, 0xC308, 0x0001}, /*   0 (HW default) */
+	{0xC219, 0xC319, 0x0001}, /*  +2 */
+	{0xC22A, 0xC32A, 0x0001}, /*  +4 */
+	{0xC24C, 0xC34C, 0x0001}, /*  +6 */
+	{0xC26E, 0xC36E, 0x0001}, /*  +8 */
+	{0xC248, 0xC348, 0x0002}, /* +10 */
+	{0xC26A, 0xC36A, 0x0002}, /* +12 dB */
+};
+
+static unsigned short treble_parm[12][9] = {
+	{0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
+	{0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
+	{0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
+	{0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
+	{0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
+	{0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
+	{0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
+	{0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
+	{0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
+	{0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
+	{0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
+	{0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +12 dB */
+};
+
+
+/*
+ * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
+ */
+static void
+awe_equalizer(int bass, int treble)
+{
+	unsigned short w;
+
+	if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
+		return;
+	awe_poke(AWE_INIT4(0x01), bass_parm[bass][0]);
+	awe_poke(AWE_INIT4(0x11), bass_parm[bass][1]);
+	awe_poke(AWE_INIT3(0x11), treble_parm[treble][0]);
+	awe_poke(AWE_INIT3(0x13), treble_parm[treble][1]);
+	awe_poke(AWE_INIT3(0x1B), treble_parm[treble][2]);
+	awe_poke(AWE_INIT4(0x07), treble_parm[treble][3]);
+	awe_poke(AWE_INIT4(0x0B), treble_parm[treble][4]);
+	awe_poke(AWE_INIT4(0x0D), treble_parm[treble][5]);
+	awe_poke(AWE_INIT4(0x17), treble_parm[treble][6]);
+	awe_poke(AWE_INIT4(0x19), treble_parm[treble][7]);
+	w = bass_parm[bass][2] + treble_parm[treble][8];
+	awe_poke(AWE_INIT4(0x15), (unsigned short)(w + 0x0262));
+	awe_poke(AWE_INIT4(0x1D), (unsigned short)(w + 0x8362));
+}
+
+static void awe_update_equalizer(void)
+{
+	awe_equalizer(ctrls[AWE_MD_BASS_LEVEL], ctrls[AWE_MD_TREBLE_LEVEL]);
+}
+
+
+#ifdef CONFIG_AWE32_MIDIEMU
+
+/*================================================================
+ * Emu8000 MIDI Emulation
+ *================================================================*/
+
+/*================================================================
+ * midi queue record
+ *================================================================*/
+
+/* queue type */
+enum { Q_NONE, Q_VARLEN, Q_READ, Q_SYSEX, };
+
+#define MAX_MIDIBUF	64
+
+/* midi status */
+typedef struct MidiStatus {
+	int queue;	/* queue type */
+	int qlen;	/* queue length */
+	int read;	/* chars read */
+	int status;	/* current status */
+	int chan;	/* current channel */
+	unsigned char buf[MAX_MIDIBUF];
+} MidiStatus;
+
+/* MIDI mode type */
+enum { MODE_GM, MODE_GS, MODE_XG, };
+
+/* NRPN / CC -> Emu8000 parameter converter */
+typedef struct {
+	int control;
+	int awe_effect;
+	unsigned short (*convert)(int val);
+} ConvTable;
+
+
+/*================================================================
+ * prototypes
+ *================================================================*/
+
+static int awe_midi_open(int dev, int mode, void (*input)(int,unsigned char), void (*output)(int));
+static void awe_midi_close(int dev);
+static int awe_midi_ioctl(int dev, unsigned cmd, caddr_t arg);
+static int awe_midi_outputc(int dev, unsigned char midi_byte);
+
+static void init_midi_status(MidiStatus *st);
+static void clear_rpn(void);
+static void get_midi_char(MidiStatus *st, int c);
+/*static void queue_varlen(MidiStatus *st, int c);*/
+static void special_event(MidiStatus *st, int c);
+static void queue_read(MidiStatus *st, int c);
+static void midi_note_on(MidiStatus *st);
+static void midi_note_off(MidiStatus *st);
+static void midi_key_pressure(MidiStatus *st);
+static void midi_channel_pressure(MidiStatus *st);
+static void midi_pitch_wheel(MidiStatus *st);
+static void midi_program_change(MidiStatus *st);
+static void midi_control_change(MidiStatus *st);
+static void midi_select_bank(MidiStatus *st, int val);
+static void midi_nrpn_event(MidiStatus *st);
+static void midi_rpn_event(MidiStatus *st);
+static void midi_detune(int chan, int coarse, int fine);
+static void midi_system_exclusive(MidiStatus *st);
+static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val);
+static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val);
+static int xg_control_change(MidiStatus *st, int cmd, int val);
+
+#define numberof(ary)	(sizeof(ary)/sizeof(ary[0]))
+
+
+/*================================================================
+ * OSS Midi device record
+ *================================================================*/
+
+static struct midi_operations awe_midi_operations =
+{
+	{"AWE Midi Emu", 0, 0, SNDCARD_SB},
+	NULL /*&std_midi_synth*/,
+	{0}, /* input_info */
+	awe_midi_open, /*open*/
+	awe_midi_close, /*close*/
+	awe_midi_ioctl, /*ioctl*/
+	awe_midi_outputc, /*outputc*/
+	NULL /*start_read*/,
+	NULL /*end_read*/,
+	NULL, /* kick */
+	NULL, /* command */
+};
+
+static int my_mididev = -1;
+
+static void attach_midiemu(void)
+{
+	if ((my_mididev = sound_alloc_mididev()) < 0)
+		printk ("Sound: Too many midi devices detected\n");
+	else
+		midi_devs[my_mididev] = &awe_midi_operations;
+}
+
+static void unload_midiemu(void)
+{
+	if (my_mididev >= 0)
+		sound_unload_mididev(my_mididev);
+}
+
+
+/*
+ * open/close midi device
+ */
+
+static int midi_opened = FALSE;
+
+static int midi_mode;
+static int coarsetune = 0, finetune = 0;
+
+static int xg_mapping = TRUE;
+static int xg_bankmode = 0;
+
+/* effect sensitivity */
+
+#define FX_CUTOFF	0
+#define FX_RESONANCE	1
+#define FX_ATTACK	2
+#define FX_RELEASE	3
+#define FX_VIBRATE	4
+#define FX_VIBDEPTH	5
+#define FX_VIBDELAY	6
+#define FX_NUMS		7
+
+#define DEF_FX_CUTOFF		170
+#define DEF_FX_RESONANCE	6
+#define DEF_FX_ATTACK		50
+#define DEF_FX_RELEASE		50
+#define DEF_FX_VIBRATE		30
+#define DEF_FX_VIBDEPTH		4
+#define DEF_FX_VIBDELAY		1500
+
+/* effect sense: */
+static int gs_sense[] = 
+{
+	DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
+	DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
+};
+static int xg_sense[] = 
+{
+	DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
+	DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
+};
+
+
+/* current status */
+static MidiStatus curst;
+
+
+static int
+awe_midi_open (int dev, int mode,
+	       void (*input)(int,unsigned char),
+	       void (*output)(int))
+{
+	if (midi_opened)
+		return -EBUSY;
+
+	midi_opened = TRUE;
+
+	midi_mode = MODE_GM;
+
+	curst.queue = Q_NONE;
+	curst.qlen = 0;
+	curst.read = 0;
+	curst.status = 0;
+	curst.chan = 0;
+	memset(curst.buf, 0, sizeof(curst.buf));
+
+	init_midi_status(&curst);
+
+	return 0;
+}
+
+static void
+awe_midi_close (int dev)
+{
+	midi_opened = FALSE;
+}
+
+
+static int
+awe_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
+{
+	return -EPERM;
+}
+
+static int
+awe_midi_outputc (int dev, unsigned char midi_byte)
+{
+	if (! midi_opened)
+		return 1;
+
+	/* force to change playing mode */
+	playing_mode = AWE_PLAY_MULTI;
+
+	get_midi_char(&curst, midi_byte);
+	return 1;
+}
+
+
+/*
+ * initialize
+ */
+
+static void init_midi_status(MidiStatus *st)
+{
+	clear_rpn();
+	coarsetune = 0;
+	finetune = 0;
+}
+
+
+/*
+ * RPN & NRPN
+ */
+
+#define MAX_MIDI_CHANNELS	16
+
+/* RPN & NRPN */
+static unsigned char nrpn[MAX_MIDI_CHANNELS];  /* current event is NRPN? */
+static int msb_bit;  /* current event is msb for RPN/NRPN */
+/* RPN & NRPN indeces */
+static unsigned char rpn_msb[MAX_MIDI_CHANNELS], rpn_lsb[MAX_MIDI_CHANNELS];
+/* RPN & NRPN values */
+static int rpn_val[MAX_MIDI_CHANNELS];
+
+static void clear_rpn(void)
+{
+	int i;
+	for (i = 0; i < MAX_MIDI_CHANNELS; i++) {
+		nrpn[i] = 0;
+		rpn_msb[i] = 127;
+		rpn_lsb[i] = 127;
+		rpn_val[i] = 0;
+	}
+	msb_bit = 0;
+}
+
+
+/*
+ * process midi queue
+ */
+
+/* status event types */
+typedef void (*StatusEvent)(MidiStatus *st);
+static struct StatusEventList {
+	StatusEvent process;
+	int qlen;
+} status_event[8] = {
+	{midi_note_off, 2},
+	{midi_note_on, 2},
+	{midi_key_pressure, 2},
+	{midi_control_change, 2},
+	{midi_program_change, 1},
+	{midi_channel_pressure, 1},
+	{midi_pitch_wheel, 2},
+	{NULL, 0},
+};
+
+
+/* read a char from fifo and process it */
+static void get_midi_char(MidiStatus *st, int c)
+{
+	if (c == 0xfe) {
+		/* ignore active sense */
+		st->queue = Q_NONE;
+		return;
+	}
+
+	switch (st->queue) {
+	/* case Q_VARLEN: queue_varlen(st, c); break;*/
+	case Q_READ:
+	case Q_SYSEX:
+		queue_read(st, c);
+		break;
+	case Q_NONE:
+		st->read = 0;
+		if ((c & 0xf0) == 0xf0) {
+			special_event(st, c);
+		} else if (c & 0x80) { /* status change */
+			st->status = (c >> 4) & 0x07;
+			st->chan = c & 0x0f;
+			st->queue = Q_READ;
+			st->qlen = status_event[st->status].qlen;
+			if (st->qlen == 0)
+				st->queue = Q_NONE;
+		}
+		break;
+	}
+}
+
+/* 0xfx events */
+static void special_event(MidiStatus *st, int c)
+{
+	switch (c) {
+	case 0xf0: /* system exclusive */
+		st->queue = Q_SYSEX;
+		st->qlen = 0;
+		break;
+	case 0xf1: /* MTC quarter frame */
+	case 0xf3: /* song select */
+		st->queue = Q_READ;
+		st->qlen = 1;
+		break;
+	case 0xf2: /* song position */
+		st->queue = Q_READ;
+		st->qlen = 2;
+		break;
+	}
+}
+
+#if 0
+/* read variable length value */
+static void queue_varlen(MidiStatus *st, int c)
+{
+	st->qlen += (c & 0x7f);
+	if (c & 0x80) {
+		st->qlen <<= 7;
+		return;
+	}
+	if (st->qlen <= 0) {
+		st->qlen = 0;
+		st->queue = Q_NONE;
+	}
+	st->queue = Q_READ;
+	st->read = 0;
+}
+#endif
+
+
+/* read a char */
+static void queue_read(MidiStatus *st, int c)
+{
+	if (st->read < MAX_MIDIBUF) {
+		if (st->queue != Q_SYSEX)
+			c &= 0x7f;
+		st->buf[st->read] = (unsigned char)c;
+	}
+	st->read++;
+	if (st->queue == Q_SYSEX && c == 0xf7) {
+		midi_system_exclusive(st);
+		st->queue = Q_NONE;
+	} else if (st->queue == Q_READ && st->read >= st->qlen) {
+		if (status_event[st->status].process)
+			status_event[st->status].process(st);
+		st->queue = Q_NONE;
+	}
+}
+
+
+/*
+ * status events
+ */
+
+/* note on */
+static void midi_note_on(MidiStatus *st)
+{
+	DEBUG(2,printk("midi: note_on (%d) %d %d\n", st->chan, st->buf[0], st->buf[1]));
+	if (st->buf[1] == 0)
+		midi_note_off(st);
+	else
+		awe_start_note(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* note off */
+static void midi_note_off(MidiStatus *st)
+{
+	DEBUG(2,printk("midi: note_off (%d) %d %d\n", st->chan, st->buf[0], st->buf[1]));
+	awe_kill_note(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* key pressure change */
+static void midi_key_pressure(MidiStatus *st)
+{
+	awe_key_pressure(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* channel pressure change */
+static void midi_channel_pressure(MidiStatus *st)
+{
+	channels[st->chan].chan_press = st->buf[0];
+	awe_modwheel_change(st->chan, st->buf[0]);
+}
+
+/* pitch wheel change */
+static void midi_pitch_wheel(MidiStatus *st)
+{
+	int val = (int)st->buf[1] * 128 + st->buf[0];
+	awe_bender(0, st->chan, val);
+}
+
+/* program change */
+static void midi_program_change(MidiStatus *st)
+{
+	int preset;
+	preset = st->buf[0];
+	if (midi_mode == MODE_GS && IS_DRUM_CHANNEL(st->chan) && preset == 127)
+		preset = 0;
+	else if (midi_mode == MODE_XG && xg_mapping && IS_DRUM_CHANNEL(st->chan))
+		preset += 64;
+
+	awe_set_instr(0, st->chan, preset);
+}
+
+#define send_effect(chan,type,val) awe_send_effect(chan,-1,type,val)
+#define add_effect(chan,type,val) awe_send_effect(chan,-1,(type)|0x80,val)
+#define unset_effect(chan,type) awe_send_effect(chan,-1,(type)|0x40,0)
+
+/* midi control change */
+static void midi_control_change(MidiStatus *st)
+{
+	int cmd = st->buf[0];
+	int val = st->buf[1];
+
+	DEBUG(2,printk("midi: control (%d) %d %d\n", st->chan, cmd, val));
+	if (midi_mode == MODE_XG) {
+		if (xg_control_change(st, cmd, val))
+			return;
+	}
+
+	/* controls #31 - #64 are LSB of #0 - #31 */
+	msb_bit = 1;
+	if (cmd >= 0x20 && cmd < 0x40) {
+		msb_bit = 0;
+		cmd -= 0x20;
+	}
+
+	switch (cmd) {
+	case CTL_SOFT_PEDAL:
+		if (val == 127)
+			add_effect(st->chan, AWE_FX_CUTOFF, -160);
+		else
+			unset_effect(st->chan, AWE_FX_CUTOFF);
+		break;
+
+	case CTL_BANK_SELECT:
+		midi_select_bank(st, val);
+		break;
+		
+	/* set RPN/NRPN parameter */
+	case CTL_REGIST_PARM_NUM_MSB:
+		nrpn[st->chan]=0; rpn_msb[st->chan]=val;
+		break;
+	case CTL_REGIST_PARM_NUM_LSB:
+		nrpn[st->chan]=0; rpn_lsb[st->chan]=val;
+		break;
+	case CTL_NONREG_PARM_NUM_MSB:
+		nrpn[st->chan]=1; rpn_msb[st->chan]=val;
+		break;
+	case CTL_NONREG_PARM_NUM_LSB:
+		nrpn[st->chan]=1; rpn_lsb[st->chan]=val;
+		break;
+
+	/* send RPN/NRPN entry */
+	case CTL_DATA_ENTRY:
+		if (msb_bit)
+			rpn_val[st->chan] = val * 128;
+		else
+			rpn_val[st->chan] |= val;
+		if (nrpn[st->chan])
+			midi_nrpn_event(st);
+		else
+			midi_rpn_event(st);
+		break;
+
+	/* increase/decrease data entry */
+	case CTL_DATA_INCREMENT:
+		rpn_val[st->chan]++;
+		midi_rpn_event(st);
+		break;
+	case CTL_DATA_DECREMENT:
+		rpn_val[st->chan]--;
+		midi_rpn_event(st);
+		break;
+
+	/* default */
+	default:
+		awe_controller(0, st->chan, cmd, val);
+		break;
+	}
+}
+
+/* tone bank change */
+static void midi_select_bank(MidiStatus *st, int val)
+{
+	if (midi_mode == MODE_XG && msb_bit) {
+		xg_bankmode = val;
+		/* XG MSB value; not normal bank selection */
+		switch (val) {
+		case 127: /* remap to drum channel */
+			awe_controller(0, st->chan, CTL_BANK_SELECT, 128);
+			break;
+		default: /* remap to normal channel */
+			awe_controller(0, st->chan, CTL_BANK_SELECT, val);
+			break;
+		}
+		return;
+	} else if (midi_mode == MODE_GS && !msb_bit)
+		/* ignore LSB bank in GS mode (used for mapping) */
+		return;
+
+	/* normal bank controls; accept both MSB and LSB */
+	if (! IS_DRUM_CHANNEL(st->chan)) {
+		if (midi_mode == MODE_XG) {
+			if (xg_bankmode) return;
+			if (val == 64 || val == 126)
+				val = 0;
+		} else if (midi_mode == MODE_GS && val == 127)
+			val = 0;
+		awe_controller(0, st->chan, CTL_BANK_SELECT, val);
+	}
+}
+
+
+/*================================================================
+ * RPN events
+ *================================================================*/
+
+static void midi_rpn_event(MidiStatus *st)
+{
+	int type;
+	type = (rpn_msb[st->chan]<<8) | rpn_lsb[st->chan];
+	switch (type) {
+	case 0x0000: /* Pitch bend sensitivity */
+		/* MSB only / 1 semitone per 128 */
+		if (msb_bit) {
+			channels[st->chan].bender_range = 
+				rpn_val[st->chan] * 100 / 128;
+		}
+		break;
+					
+	case 0x0001: /* fine tuning: */
+		/* MSB/LSB, 8192=center, 100/8192 cent step */
+		finetune = rpn_val[st->chan] - 8192;
+		midi_detune(st->chan, coarsetune, finetune);
+		break;
+
+	case 0x0002: /* coarse tuning */
+		/* MSB only / 8192=center, 1 semitone per 128 */
+		if (msb_bit) {
+			coarsetune = rpn_val[st->chan] - 8192;
+			midi_detune(st->chan, coarsetune, finetune);
+		}
+		break;
+
+	case 0x7F7F: /* "lock-in" RPN */
+		break;
+	}
+}
+
+
+/* tuning:
+ *   coarse = -8192 to 8192 (100 cent per 128)
+ *   fine = -8192 to 8192 (max=100cent)
+ */
+static void midi_detune(int chan, int coarse, int fine)
+{
+	/* 4096 = 1200 cents in AWE parameter */
+	int val;
+	val = coarse * 4096 / (12 * 128);
+	val += fine / 24;
+	if (val)
+		send_effect(chan, AWE_FX_INIT_PITCH, val);
+	else
+		unset_effect(chan, AWE_FX_INIT_PITCH);
+}
+
+
+/*================================================================
+ * system exclusive message
+ * GM/GS/XG macros are accepted
+ *================================================================*/
+
+static void midi_system_exclusive(MidiStatus *st)
+{
+	/* GM on */
+	static unsigned char gm_on_macro[] = {
+		0x7e,0x7f,0x09,0x01,
+	};
+	/* XG on */
+	static unsigned char xg_on_macro[] = {
+		0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
+	};
+	/* GS prefix
+	 * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off
+	 * reverb mode: XX=0x01, YY=0x30, ZZ=0-7
+	 * chorus mode: XX=0x01, YY=0x38, ZZ=0-7
+	 */
+	static unsigned char gs_pfx_macro[] = {
+		0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/
+	};
+
+#if 0
+	/* SC88 system mode set
+	 * single module mode: XX=1
+	 * double module mode: XX=0
+	 */
+	static unsigned char gs_mode_macro[] = {
+		0x41,0x10,0x42,0x12,0x00,0x00,0x7F,/*ZZ*/
+	};
+	/* SC88 display macro: XX=01:bitmap, 00:text
+	 */
+	static unsigned char gs_disp_macro[] = {
+		0x41,0x10,0x45,0x12,0x10,/*XX,00*/
+	};
+#endif
+
+	/* GM on */
+	if (memcmp(st->buf, gm_on_macro, sizeof(gm_on_macro)) == 0) {
+		if (midi_mode != MODE_GS && midi_mode != MODE_XG)
+			midi_mode = MODE_GM;
+		init_midi_status(st);
+	}
+
+	/* GS macros */
+	else if (memcmp(st->buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) {
+		if (midi_mode != MODE_GS && midi_mode != MODE_XG)
+			midi_mode = MODE_GS;
+
+		if (st->buf[5] == 0x00 && st->buf[6] == 0x7f && st->buf[7] == 0x00) {
+			/* GS reset */
+			init_midi_status(st);
+		}
+
+		else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x15) {
+			/* drum pattern */
+			int p = st->buf[5] & 0x0f;
+			if (p == 0) p = 9;
+			else if (p < 10) p--;
+			if (st->buf[7] == 0)
+				DRUM_CHANNEL_OFF(p);
+			else
+				DRUM_CHANNEL_ON(p);
+
+		} else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x21) {
+			/* program */
+			int p = st->buf[5] & 0x0f;
+			if (p == 0) p = 9;
+			else if (p < 10) p--;
+			if (! IS_DRUM_CHANNEL(p))
+				awe_set_instr(0, p, st->buf[7]);
+
+		} else if (st->buf[5] == 0x01 && st->buf[6] == 0x30) {
+			/* reverb mode */
+			awe_set_reverb_mode(st->buf[7]);
+
+		} else if (st->buf[5] == 0x01 && st->buf[6] == 0x38) {
+			/* chorus mode */
+			awe_set_chorus_mode(st->buf[7]);
+
+		} else if (st->buf[5] == 0x00 && st->buf[6] == 0x04) {
+			/* master volume */
+			awe_change_master_volume(st->buf[7]);
+
+		}
+	}
+
+	/* XG on */
+	else if (memcmp(st->buf, xg_on_macro, sizeof(xg_on_macro)) == 0) {
+		midi_mode = MODE_XG;
+		xg_mapping = TRUE;
+		xg_bankmode = 0;
+	}
+}
+
+
+/*
+ * convert NRPN/control values
+ */
+
+static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val)
+{
+	int i, cval;
+	for (i = 0; i < num_tables; i++) {
+		if (table[i].control == type) {
+			cval = table[i].convert(val);
+			send_effect(st->chan, table[i].awe_effect, cval);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val)
+{
+	int i, cval;
+	for (i = 0; i < num_tables; i++) {
+		if (table[i].control == type) {
+			cval = table[i].convert(val);
+			add_effect(st->chan, table[i].awe_effect|0x80, cval);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+
+/*
+ * AWE32 NRPN effects
+ */
+
+static unsigned short fx_delay(int val);
+static unsigned short fx_attack(int val);
+static unsigned short fx_hold(int val);
+static unsigned short fx_decay(int val);
+static unsigned short fx_the_value(int val);
+static unsigned short fx_twice_value(int val);
+static unsigned short fx_conv_pitch(int val);
+static unsigned short fx_conv_Q(int val);
+
+/* function for each NRPN */		/* [range]  units */
+#define fx_env1_delay	fx_delay	/* [0,5900] 4msec */
+#define fx_env1_attack	fx_attack	/* [0,5940] 1msec */
+#define fx_env1_hold	fx_hold		/* [0,8191] 1msec */
+#define fx_env1_decay	fx_decay	/* [0,5940] 4msec */
+#define fx_env1_release	fx_decay	/* [0,5940] 4msec */
+#define fx_env1_sustain	fx_the_value	/* [0,127] 0.75dB */
+#define fx_env1_pitch	fx_the_value	/* [-127,127] 9.375cents */
+#define fx_env1_cutoff	fx_the_value	/* [-127,127] 56.25cents */
+
+#define fx_env2_delay	fx_delay	/* [0,5900] 4msec */
+#define fx_env2_attack	fx_attack	/* [0,5940] 1msec */
+#define fx_env2_hold	fx_hold		/* [0,8191] 1msec */
+#define fx_env2_decay	fx_decay	/* [0,5940] 4msec */
+#define fx_env2_release	fx_decay	/* [0,5940] 4msec */
+#define fx_env2_sustain	fx_the_value	/* [0,127] 0.75dB */
+
+#define fx_lfo1_delay	fx_delay	/* [0,5900] 4msec */
+#define fx_lfo1_freq	fx_twice_value	/* [0,127] 84mHz */
+#define fx_lfo1_volume	fx_twice_value	/* [0,127] 0.1875dB */
+#define fx_lfo1_pitch	fx_the_value	/* [-127,127] 9.375cents */
+#define fx_lfo1_cutoff	fx_twice_value	/* [-64,63] 56.25cents */
+
+#define fx_lfo2_delay	fx_delay	/* [0,5900] 4msec */
+#define fx_lfo2_freq	fx_twice_value	/* [0,127] 84mHz */
+#define fx_lfo2_pitch	fx_the_value	/* [-127,127] 9.375cents */
+
+#define fx_init_pitch	fx_conv_pitch	/* [-8192,8192] cents */
+#define fx_chorus	fx_the_value	/* [0,255] -- */
+#define fx_reverb	fx_the_value	/* [0,255] -- */
+#define fx_cutoff	fx_twice_value	/* [0,127] 62Hz */
+#define fx_filterQ	fx_conv_Q	/* [0,127] -- */
+
+static unsigned short fx_delay(int val)
+{
+	return (unsigned short)calc_parm_delay(val);
+}
+
+static unsigned short fx_attack(int val)
+{
+	return (unsigned short)calc_parm_attack(val);
+}
+
+static unsigned short fx_hold(int val)
+{
+	return (unsigned short)calc_parm_hold(val);
+}
+
+static unsigned short fx_decay(int val)
+{
+	return (unsigned short)calc_parm_decay(val);
+}
+
+static unsigned short fx_the_value(int val)
+{
+	return (unsigned short)(val & 0xff);
+}
+
+static unsigned short fx_twice_value(int val)
+{
+	return (unsigned short)((val * 2) & 0xff);
+}
+
+static unsigned short fx_conv_pitch(int val)
+{
+	return (short)(val * 4096 / 1200);
+}
+
+static unsigned short fx_conv_Q(int val)
+{
+	return (unsigned short)((val / 8) & 0xff);
+}
+
+
+static ConvTable awe_effects[] =
+{
+	{ 0, AWE_FX_LFO1_DELAY,	fx_lfo1_delay},
+	{ 1, AWE_FX_LFO1_FREQ,	fx_lfo1_freq},
+	{ 2, AWE_FX_LFO2_DELAY,	fx_lfo2_delay},
+	{ 3, AWE_FX_LFO2_FREQ,	fx_lfo2_freq},
+
+	{ 4, AWE_FX_ENV1_DELAY,	fx_env1_delay},
+	{ 5, AWE_FX_ENV1_ATTACK,fx_env1_attack},
+	{ 6, AWE_FX_ENV1_HOLD,	fx_env1_hold},
+	{ 7, AWE_FX_ENV1_DECAY,	fx_env1_decay},
+	{ 8, AWE_FX_ENV1_SUSTAIN,	fx_env1_sustain},
+	{ 9, AWE_FX_ENV1_RELEASE,	fx_env1_release},
+
+	{10, AWE_FX_ENV2_DELAY,	fx_env2_delay},
+	{11, AWE_FX_ENV2_ATTACK,	fx_env2_attack},
+	{12, AWE_FX_ENV2_HOLD,	fx_env2_hold},
+	{13, AWE_FX_ENV2_DECAY,	fx_env2_decay},
+	{14, AWE_FX_ENV2_SUSTAIN,	fx_env2_sustain},
+	{15, AWE_FX_ENV2_RELEASE,	fx_env2_release},
+
+	{16, AWE_FX_INIT_PITCH,	fx_init_pitch},
+	{17, AWE_FX_LFO1_PITCH,	fx_lfo1_pitch},
+	{18, AWE_FX_LFO2_PITCH,	fx_lfo2_pitch},
+	{19, AWE_FX_ENV1_PITCH,	fx_env1_pitch},
+	{20, AWE_FX_LFO1_VOLUME,	fx_lfo1_volume},
+	{21, AWE_FX_CUTOFF,		fx_cutoff},
+	{22, AWE_FX_FILTERQ,	fx_filterQ},
+	{23, AWE_FX_LFO1_CUTOFF,	fx_lfo1_cutoff},
+	{24, AWE_FX_ENV1_CUTOFF,	fx_env1_cutoff},
+	{25, AWE_FX_CHORUS,		fx_chorus},
+	{26, AWE_FX_REVERB,		fx_reverb},
+};
+
+static int num_awe_effects = numberof(awe_effects);
+
+
+/*
+ * GS(SC88) NRPN effects; still experimental
+ */
+
+/* cutoff: quarter semitone step, max=255 */
+static unsigned short gs_cutoff(int val)
+{
+	return (val - 64) * gs_sense[FX_CUTOFF] / 50;
+}
+
+/* resonance: 0 to 15(max) */
+static unsigned short gs_filterQ(int val)
+{
+	return (val - 64) * gs_sense[FX_RESONANCE] / 50;
+}
+
+/* attack: */
+static unsigned short gs_attack(int val)
+{
+	return -(val - 64) * gs_sense[FX_ATTACK] / 50;
+}
+
+/* decay: */
+static unsigned short gs_decay(int val)
+{
+	return -(val - 64) * gs_sense[FX_RELEASE] / 50;
+}
+
+/* release: */
+static unsigned short gs_release(int val)
+{
+	return -(val - 64) * gs_sense[FX_RELEASE] / 50;
+}
+
+/* vibrato freq: 0.042Hz step, max=255 */
+static unsigned short gs_vib_rate(int val)
+{
+	return (val - 64) * gs_sense[FX_VIBRATE] / 50;
+}
+
+/* vibrato depth: max=127, 1 octave */
+static unsigned short gs_vib_depth(int val)
+{
+	return (val - 64) * gs_sense[FX_VIBDEPTH] / 50;
+}
+
+/* vibrato delay: -0.725msec step */
+static unsigned short gs_vib_delay(int val)
+{
+	return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;
+}
+
+static ConvTable gs_effects[] =
+{
+	{32, AWE_FX_CUTOFF,	gs_cutoff},
+	{33, AWE_FX_FILTERQ,	gs_filterQ},
+	{99, AWE_FX_ENV2_ATTACK, gs_attack},
+	{100, AWE_FX_ENV2_DECAY, gs_decay},
+	{102, AWE_FX_ENV2_RELEASE, gs_release},
+	{8, AWE_FX_LFO1_FREQ, gs_vib_rate},
+	{9, AWE_FX_LFO1_VOLUME, gs_vib_depth},
+	{10, AWE_FX_LFO1_DELAY, gs_vib_delay},
+};
+
+static int num_gs_effects = numberof(gs_effects);
+
+
+/*================================================================
+ * NRPN events: accept as AWE32/SC88 specific controls
+ *================================================================*/
+
+static void midi_nrpn_event(MidiStatus *st)
+{
+	if (rpn_msb[st->chan] == 127 && rpn_lsb[st->chan] <= 26) {
+		if (! msb_bit) /* both MSB/LSB necessary */
+			send_converted_effect(awe_effects, num_awe_effects,
+					      st, rpn_lsb[st->chan],
+					      rpn_val[st->chan] - 8192);
+	} else if (rpn_msb[st->chan] == 1) {
+		if (msb_bit) /* only MSB is valid */
+			add_converted_effect(gs_effects, num_gs_effects,
+					     st, rpn_lsb[st->chan],
+					     rpn_val[st->chan] / 128);
+	}
+}
+
+
+/*----------------------------------------------------------------
+ * XG control effects; still experimental
+ *----------------------------------------------------------------*/
+
+/* cutoff: quarter semitone step, max=255 */
+static unsigned short xg_cutoff(int val)
+{
+	return (val - 64) * xg_sense[FX_CUTOFF] / 64;
+}
+
+/* resonance: 0(open) to 15(most nasal) */
+static unsigned short xg_filterQ(int val)
+{
+	return (val - 64) * xg_sense[FX_RESONANCE] / 64;
+}
+
+/* attack: */
+static unsigned short xg_attack(int val)
+{
+	return -(val - 64) * xg_sense[FX_ATTACK] / 64;
+}
+
+/* release: */
+static unsigned short xg_release(int val)
+{
+	return -(val - 64) * xg_sense[FX_RELEASE] / 64;
+}
+
+static ConvTable xg_effects[] =
+{
+	{71, AWE_FX_CUTOFF,	xg_cutoff},
+	{74, AWE_FX_FILTERQ,	xg_filterQ},
+	{72, AWE_FX_ENV2_RELEASE, xg_release},
+	{73, AWE_FX_ENV2_ATTACK, xg_attack},
+};
+
+static int num_xg_effects = numberof(xg_effects);
+
+static int xg_control_change(MidiStatus *st, int cmd, int val)
+{
+	return add_converted_effect(xg_effects, num_xg_effects, st, cmd, val);
+}
+
+#endif /* CONFIG_AWE32_MIDIEMU */
+
+/* new type interface */
+static int __init attach_awe(void)
+{
+#ifdef CONFIG_PNP_DRV
+	if (pnp) {
+		awe_initpnp();
+		if (awe_pnp_ok)
+			return 0;
+	}
+#endif /* pnp */
+	
+	_attach_awe();
+	
+	return 0;
+}									
+
+static void __exit unload_awe(void)								
+{
+#ifdef CONFIG_PNP_DRV
+	if (pnp)
+		awe_unload_pnp();
+#endif
+	
+	_unload_awe();
+}
+
+module_init(attach_awe);
+module_exit(unload_awe);
+
+#ifndef MODULE
+static int __init setup_awe(char *str)
+{
+	/* io, memsize */
+	int ints[3];
+
+	str = get_options(str, ARRAY_SIZE(ints), ints);
+
+	io = ints[1];
+	memsize = ints[2];
+
+	return 1;
+}
+
+__setup("awe=", setup_awe);
+#endif
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/awe_wave.h linux/drivers/sound/awe_wave.h
--- v2.3.50/linux/drivers/sound/awe_wave.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/awe_wave.h	Wed Mar  8 11:37:03 2000
@@ -0,0 +1,87 @@
+/*
+ * sound/awe_config.h
+ *
+ * Configuration of AWE32/SB32/AWE64 wave table synth driver.
+ *   version 0.4.3; Mar. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * 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.
+ */
+
+/*
+ * chorus & reverb effects send for FM chip: from 0 to 0xff
+ * larger numbers often cause weird sounds.
+ */
+
+#define DEF_FM_CHORUS_DEPTH	0x10
+#define DEF_FM_REVERB_DEPTH	0x10
+
+
+/*
+ * other compile conditions
+ */
+
+/* initialize FM passthrough even without extended RAM */
+#undef AWE_ALWAYS_INIT_FM
+
+/* debug on */
+#define AWE_DEBUG_ON
+
+/* GUS compatible mode */
+#define AWE_HAS_GUS_COMPATIBILITY
+
+/* add MIDI emulation by wavetable */
+#define CONFIG_AWE32_MIDIEMU
+
+/* add mixer control of emu8000 equalizer */
+#undef CONFIG_AWE32_MIXER
+
+/* use new volume calculation method as default */
+#define AWE_USE_NEW_VOLUME_CALC
+
+/* check current volume target for searching empty voices */
+#define AWE_CHECK_VTARGET
+
+/* allow sample sharing */
+#define AWE_ALLOW_SAMPLE_SHARING
+
+/*
+ * AWE32 card configuration:
+ * uncomment the following lines *ONLY* when auto detection doesn't
+ * work properly on your machine.
+ */
+
+/*#define AWE_DEFAULT_BASE_ADDR	0x620*/	/* base port address */
+/*#define AWE_DEFAULT_MEM_SIZE	512*/	/* kbytes */
+
+/*
+ * maximum size of soundfont list table
+ */
+
+#define AWE_MAX_SF_LISTS 16
+
+/*
+ * chunk size of sample and voice tables
+ */
+
+#define AWE_MAX_SAMPLES 400
+#define AWE_MAX_INFOS 800
+
+#define AWE_MAJOR_VERSION	0
+#define AWE_MINOR_VERSION	4
+#define AWE_TINY_VERSION	3
+#define AWE_VERSION_NUMBER	((AWE_MAJOR_VERSION<<16)|(AWE_MINOR_VERSION<<8)|AWE_TINY_VERSION)
+#define AWEDRV_VERSION		"0.4.3"
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/dev_table.c linux/drivers/sound/dev_table.c
--- v2.3.50/linux/drivers/sound/dev_table.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/dev_table.c	Thu Mar  9 23:31:43 2000
@@ -11,7 +11,6 @@
  * for more info.
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 
 #define _DEV_TABLE_C_
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.3.50/linux/drivers/sound/dev_table.h	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/dev_table.h	Thu Mar  9 23:31:43 2000
@@ -15,8 +15,6 @@
 #ifndef _DEV_TABLE_H_
 #define _DEV_TABLE_H_
 
-#include <linux/config.h>
-
 /*
  * Sound card numbers 27 to 999. (1 to 26 are defined in soundcard.h)
  * Numbers 1000 to N are reserved for driver's internal use.
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/Config.in linux/drivers/sound/lowlevel/Config.in
--- v2.3.50/linux/drivers/sound/lowlevel/Config.in	Sat Feb 26 22:31:49 2000
+++ linux/drivers/sound/lowlevel/Config.in	Wed Dec 31 16:00:00 1969
@@ -1,66 +0,0 @@
-dep_tristate '  ACI mixer (miroPCM12)' CONFIG_ACI_MIXER $CONFIG_SOUND_OSS
-
-dep_tristate '  AWE32 synth' CONFIG_AWE32_SYNTH $CONFIG_SOUND_OSS
-
-if [ "$CONFIG_AWE32_SYNTH" = "y" -o "$CONFIG_AWE32_SYNTH" = "m" ]; then
-   comment 'AWE32 PnP-ISA Cards are not always setup correctly'
-   bool 'Configure AWE32 synth Base Address and Default Memory Size' CONFIG_AWE32_SYNTH_DEFAULTS
-   if [ "$CONFIG_AWE32_SYNTH_DEFAULTS" = "y" ]; then
-      hex 'AWE32 synth Base Address 620' AWE_DEFAULT_BASE_ADDR 620
-      int 'AWE32 synth Default Memory Size 512 1024 or 4096' AWE_DEFAULT_MEM_SIZE 512
-   fi
-fi
-
-if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND" = "m" ]; then
-   dep_tristate '  Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_AEDSP16 $CONFIG_SOUND_OSS
-   if [ "$CONFIG_AEDSP16" = "y" -o "$CONFIG_AEDSP16" = "m" ]; then
-      hex 'I/O base for Audio Excel DSP 16 220 or 240' CONFIG_AEDSP16_BASE 220
-      hex 'I/O base for MPU401 Check from manual of the card' CONFIG_MPU_BASE 330
-   fi
-
-   if [ "$CONFIG_AEDSP16" = "y" -o "$CONFIG_AEDSP16" = "m" ]; then
-      comment 'SC-6600 Audio Cards have no jumper switches at all'
-      bool '    SC-6600 based audio cards (new Audio Excel DSP 16)' CONFIG_SC6600
-      if [ "$CONFIG_SC6600" = "y" ]; then
-	 comment 'SC-6600 specific configuration'
-	 bool '      Activate SC-6600 Joystick Interface' CONFIG_SC6600_JOY
-	 int 'SC-6600 CDROM Interface (4=None, 3=IDE, 1=Panasonic, 0=?Sony?)' CONFIG_SC6600_CDROM 4
-	 hex 'SC-6600 CDROM Interface I/O Address' CONFIG_SC6600_CDROMBASE 0
-      fi
-
-      if [ "$CONFIG_SOUND_SB" = "y" -o "$CONFIG_SOUND_SB" = "m" ]; then
-	 if [ "$CONFIG_AEDSP16_MSS" != "y" ]; then
-	    bool 'Audio Excel DSP 16 (SBPro emulation)' CONFIG_AEDSP16_SBPRO
-	    if [ "$CONFIG_AEDSP16_SBPRO" = "y" ]; then
-	       comment 'Audio Excel DSP 16 [Sound Blaster Pro]'
-	       hex 'I/O base for Audio Excel DSP 16 220, 240' CONFIG_AEDSP16_BASE $CONFIG_SB_BASE 220
-	       int 'Audio Excel DSP 16 IRQ 5, 7, 9, 10, 11' CONFIG_AEDSP16_SB_IRQ $CONFIG_SB_IRQ 5
-	       int 'Audio Excel DSP 16 DMA 0, 1 or 3' CONFIG_AEDSP16_SB_DMA $CONFIG_SB_DMA 0
-	    fi
-	 fi
-      fi
-
-      if [ "$CONFIG_SOUND_MSS" = "y" -o "$CONFIG_SOUND_MSS" = "m" ]; then
-	 if [ "$CONFIG_AEDSP16_SBPRO" != "y" ]; then
-	    bool '    Audio Excel DSP 16 (MSS emulation)' CONFIG_AEDSP16_MSS
-	    if [ "$CONFIG_AEDSP16_MSS" = "y" ]; then
-	       comment 'Audio Excel DSP 16 [Microsoft Sound System]'
-	       hex 'I/O base for Audio Excel DSP 16 220 or 240' CONFIG_AEDSP16_BASE 220
-	       int 'Audio Excel DSP 16 IRQ 5, 7, 9, 10, 11' CONFIG_AEDSP16_MSS_IRQ $CONFIG_MSS_IRQ 5
-	       int 'Audio Excel DSP 16 DMA 0, 1 or 3' CONFIG_AEDSP16_MSS_DMA $CONFIG_MSS_DMA 1
-	    fi
-	 fi
-      fi
-
-      if [ "$CONFIG_SOUND_MPU401" = "y" -o "$CONFIG_SOUND_MPU401" = "m" ]; then
-	 bool 'Audio Excel DSP 16 (MPU401 emulation)' CONFIG_AEDSP16_MPU401
-	 if [ "$CONFIG_AEDSP16_MPU401" = "y" ]; then
-	    comment 'Audio Excel DSP 16 [MPU-401]'
-	    if [ "$CONFIG_AEDSP16_SBPRO" != "y" -a "$CONFIG_AEDSP16_MSS" != "y" ]; then
-	       hex 'I/O base for Audio Excel DSP 16 220 or 240' CONFIG_AEDSP16_BASE 220
-	    fi
-	    int 'MPU401 IRQ for Audio Excel DSP 16 5, 7, 9, 10 or 0 (disable)' CONFIG_AEDSP16_MPU_IRQ $CONFIG_MPU_IRQ
-	 fi
-      fi
-   fi
-fi
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/Makefile linux/drivers/sound/lowlevel/Makefile
--- v2.3.50/linux/drivers/sound/lowlevel/Makefile	Sun Jun  7 10:37:41 1998
+++ linux/drivers/sound/lowlevel/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,24 +0,0 @@
-# Makefile for the Linux low-level sound card drivers.
-#
-# 11 Feb 1998, Michael Elizabeth Chastain, <mailto:mec@shout.net>
-# Rewritten to use lists instead of if statements.
-
-export-objs			:= soundlow.o
-
-list-y				:=
-list-m				:=
-list-n				:=
-list-				:=
-
-obj-$(CONFIG_SOUND_OSS)		+= soundlow.o
-obj-$(CONFIG_ACI_MIXER)		+= aci.o
-obj-$(CONFIG_AEDSP16)		+= aedsp16.o
-obj-$(CONFIG_AWE32_SYNTH)	+= awe_wave.o
-
-O_TARGET	:= lowlevel.o
-O_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-y)))
-OX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-y)))
-M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-m)))
-
-include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/README linux/drivers/sound/lowlevel/README
--- v2.3.50/linux/drivers/sound/lowlevel/README	Sun Jan 17 18:25:47 1999
+++ linux/drivers/sound/lowlevel/README	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-Additional low level sound drivers for Linux
-============================================
-
-This directory contains some low level sound drivers.
-These drivers are used to be (when Linux sound drivers was OSS/Lite) external
-drivers, not maintained by Hannu Savolainen and not touched by him.
-Now things are changed: the new Linux sound driver code maintained by Alan Cox
-include these lowlevel drivers and they are no more neglected (thanks Alan).
-
-The following low level drivers are included:
-
-- ACI MIXER for miroPCM12 by Markus Kuhn
-  (mskuhn@cip.informatik.uni-erlangen.de).
-- Audio Excel DSP 16 initialization driver by Riccardo Facchetti
-  (fizban@tin.it)
-- SB32/AWE synthesizer driver (Emu8000) by Takashi Iwai
-  (iwai@dragon.mm.t.u-tokyo.ac.jp).
-
-You can find documentation for these drivers in the Documentation/sound
-directory.
-
-[ File edited 17.01.1999 - Riccardo Facchetti ]
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/aci.c linux/drivers/sound/lowlevel/aci.c
--- v2.3.50/linux/drivers/sound/lowlevel/aci.c	Sun Aug 23 13:32:25 1998
+++ linux/drivers/sound/lowlevel/aci.c	Wed Dec 31 16:00:00 1969
@@ -1,679 +0,0 @@
-/*
- * Audio Command Interface (ACI) driver (sound/aci.c)
- *
- * ACI is a protocol used to communicate with the microcontroller on
- * some sound cards produced by miro, e.g. the miroSOUND PCM12 and
- * PCM20. The ACI has been developed for miro by Norberto Pellicci
- * <pellicci@home.com>. Special thanks to both him and miro for
- * providing the ACI specification.
- *
- * The main function of the ACI is to control the mixer and to get a
- * product identification. On the PCM20, ACI also controls the radio
- * tuner on this card, this is supported in the Video for Linux 
- * radio-miropcm20 driver.
- * 
- * This Voxware ACI driver currently only supports the ACI functions
- * on the miroSOUND PCM12 and PCM20 card. Support for miro sound cards 
- * with additional ACI functions can easily be added later.
- *
- * / NOTE / When compiling as a module, make sure to load the module 
- * after loading the mad16 module. The initialisation code expects the
- * MAD16 default mixer to be already available.
- *
- * / NOTE / When compiling as a module, make sure to load the module 
- * after loading the mad16 module. The initialisation code expects the
- * MAD16 default mixer to be already available.
- *
- * Revision history:
- *
- *   1995-11-10  Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
- *        First version written.
- *   1995-12-31  Markus Kuhn
- *        Second revision, general code cleanup.
- *   1996-05-16	 Hannu Savolainen
- *	  Integrated with other parts of the driver.
- *   1996-05-28  Markus Kuhn
- *        Initialize CS4231A mixer, make ACI first mixer,
- *        use new private mixer API for solo mode.
- *   1998-08-18  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
- *	  Small modification to export ACI functions and 
- *	  complete modularisation.
- */
-
-/*
- * Some driver specific information and features:
- *
- * This mixer driver identifies itself to applications as "ACI" in
- * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
- *
- * Proprietary mixer features that go beyond the standard OSS mixer
- * interface are:
- * 
- * Full duplex solo configuration:
- *
- *   int solo_mode;
- *   ioctl(fd, SOUND_MIXER_PRIVATE1, &solo_mode);
- *
- *   solo_mode = 0: deactivate solo mode (default)
- *   solo_mode > 0: activate solo mode
- *                  With activated solo mode, the PCM input can not any
- *                  longer hear the signals produced by the PCM output.
- *                  Activating solo mode is important in duplex mode in order
- *                  to avoid feedback distortions.
- *   solo_mode < 0: do not change solo mode (just retrieve the status)
- *
- *   When the ioctl() returns 0, solo_mode contains the previous
- *   status (0 = deactivated, 1 = activated). If solo mode is not
- *   implemented on this card, ioctl() returns -1 and sets errno to
- *   EINVAL.
- *
- */
-
-#include <linux/config.h> /* for CONFIG_ACI_MIXER */
-#include <linux/module.h> 
-#include "lowlevel.h"
-#include "../sound_config.h"
-
-#if defined(CONFIG_ACI_MIXER) || defined(CONFIG_ACI_MIXER_MODULE)
-
-#undef  DEBUG             /* if defined, produce a verbose report via syslog */
-
-int aci_port = 0x354; /* as determined by bit 4 in the OPTi 929 MC4 register */
-unsigned char aci_idcode[2] = {0, 0};         /* manufacturer and product ID */
-unsigned char aci_version = 0;                       /* ACI firmware version */
-int aci_solo;                     /* status bit of the card that can't be    *
-                                   * checked with ACI versions prior to 0xb0 */
-
-static int aci_present = 0;
-
-#ifdef MODULE                  /* Whether the aci mixer is to be reset.    */
-int aci_reset = 0;             /* Default: don't reset if the driver is a  */
-MODULE_PARM(aci_reset,"i");
-#else                          /* module; use "insmod aci.o aci_reset=1" */
-int aci_reset = 1;             /* to override.                             */
-#endif
-
-
-#define COMMAND_REGISTER    (aci_port)
-#define STATUS_REGISTER     (aci_port + 1)
-#define BUSY_REGISTER       (aci_port + 2)
-
-/*
- * Wait until the ACI microcontroller has set the READYFLAG in the
- * Busy/IRQ Source Register to 0. This is required to avoid
- * overrunning the sound card microcontroller. We do a busy wait here,
- * because the microcontroller is not supposed to signal a busy
- * condition for more than a few clock cycles. In case of a time-out,
- * this function returns -1.
- *
- * This busy wait code normally requires less than 15 loops and
- * practically always less than 100 loops on my i486/DX2 66 MHz.
- *
- * Warning: Waiting on the general status flag after reseting the MUTE
- * function can take a VERY long time, because the PCM12 does some kind
- * of fade-in effect. For this reason, access to the MUTE function has
- * not been implemented at all.
- */
-
-static int busy_wait(void)
-{
-  long timeout;
-
-  for (timeout = 0; timeout < 10000000L; timeout++)
-    if ((inb_p(BUSY_REGISTER) & 1) == 0)
-      return 0;
-
-#ifdef DEBUG
-  printk("ACI: READYFLAG timed out.\n");
-#endif
-
-  return -1;
-}
-
-
-/*
- * Read the GENERAL STATUS register.
- */
-
-static int read_general_status(void)
-{
-  unsigned long flags;
-  int status;
-
-  save_flags(flags);
-  cli();
-  if (busy_wait()) { restore_flags(flags); return -1; }
-  status = (unsigned) inb_p(STATUS_REGISTER);
-  restore_flags(flags);
-  return status;
-}
-
-
-/*
- * The four ACI command types (implied, write, read and indexed) can
- * be sent to the microcontroller using the following four functions.
- * If a problem occurred, they return -1.
- */
-
-int aci_implied_cmd(unsigned char opcode)
-{
-  unsigned long flags;
-
-#ifdef DEBUG
-  printk("ACI: aci_implied_cmd(0x%02x)\n", opcode);
-#endif
-
-  save_flags(flags);
-  cli();
-  
-  if (read_general_status() < 0 || busy_wait()) {
-    restore_flags(flags);
-    return -1;
-  }
-  outb_p(opcode, COMMAND_REGISTER);
-
-  restore_flags(flags);
-  return 0;
-}
-
-
-int aci_write_cmd(unsigned char opcode, unsigned char parameter)
-{
-  unsigned long flags;
-  int status;
-
-#ifdef DEBUG
-  printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
-#endif
-
-  save_flags(flags);
-  cli();
-  
-  if (read_general_status() < 0 || busy_wait()) {
-    restore_flags(flags);
-    return -1;
-  }
-  outb_p(opcode, COMMAND_REGISTER);
-  if (busy_wait()) { restore_flags(flags); return -1; }
-  outb_p(parameter, COMMAND_REGISTER);
-
-  if ((status = read_general_status()) < 0) {
-    restore_flags(flags);
-    return -1;
-  }
-  /* polarity of the INVALID flag depends on ACI version */
-  if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
-      (aci_version >= 0xb0 && (status & 0x40) == 0)) {
-    restore_flags(flags);
-    printk("ACI: invalid write command 0x%02x, 0x%02x.\n",
-	   opcode, parameter);
-    return -1;
-  }
-
-  restore_flags(flags);
-  return 0;
-}
-
-/*
- * This write command send 2 parameters instead of one.
- * Only used in PCM20 radio frequency tuning control
- */
-
-int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2)
-{
-  unsigned long flags;
-  int status;
-
-#ifdef DEBUG
-  printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode, parameter, parameter2);
-#endif
-
-  save_flags(flags);
-  cli();
-  
-  if (read_general_status() < 0 || busy_wait()) {
-    restore_flags(flags);
-    return -1;
-  }
-  outb_p(opcode, COMMAND_REGISTER);
-  if (busy_wait()) { restore_flags(flags); return -1; }
-  outb_p(parameter, COMMAND_REGISTER);
-  if (busy_wait()) { restore_flags(flags); return -1; }
-  outb_p(parameter2, COMMAND_REGISTER);
-
-  if ((status = read_general_status()) < 0) {
-    restore_flags(flags);
-    return -1;
-  }
-  /* polarity of the INVALID flag depends on ACI version */
-  if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
-      (aci_version >= 0xb0 && (status & 0x40) == 0)) {
-    restore_flags(flags);
-#if 0	/* Frequency tuning works, but the INVALID flag is set ??? */
-    printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n",
-	   opcode, parameter, parameter2);
-#endif
-    return -1;
-  }
-
-  restore_flags(flags);
-  return 0;
-}
-
-int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter)
-{
-  unsigned long flags;
-  int i = 0;
-
-  save_flags(flags);
-  cli();
-  
-  if (read_general_status() < 0) { restore_flags(flags); return -1; }
-  while (i < length) {
-    if (busy_wait()) { restore_flags(flags); return -1; }
-    outb_p(opcode, COMMAND_REGISTER);
-    if (busy_wait()) { restore_flags(flags); return -1; }
-    parameter[i++] = inb_p(STATUS_REGISTER);
-#ifdef DEBUG
-    if (i == 1)
-      printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n", opcode, length,
-	     parameter[i-1]);
-    else
-      printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter[i-1]);
-#endif
-  }
-
-  restore_flags(flags);
-  return 0;
-}
-
-
-int aci_indexed_cmd(unsigned char opcode, unsigned char index,
-		       unsigned char *parameter)
-{
-  unsigned long flags;
-
-  save_flags(flags);
-  cli();
-  
-  if (read_general_status() < 0 || busy_wait()) {
-    restore_flags(flags);
-    return -1;
-  }
-  outb_p(opcode, COMMAND_REGISTER);
-  if (busy_wait()) { restore_flags(flags); return -1; }
-  outb_p(index, COMMAND_REGISTER);
-  if (busy_wait()) { restore_flags(flags); return -1; }
-  *parameter = inb_p(STATUS_REGISTER);
-#ifdef DEBUG
-  printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
-	 *parameter);
-#endif
-
-  restore_flags(flags);
-  return 0;
-}
-
-
-/*
- * The following macro SCALE can be used to scale one integer volume
- * value into another one using only integer arithmetic. If the input
- * value x is in the range 0 <= x <= xmax, then the result will be in
- * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
- *
- * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
- * following nice properties:
- *
- * - SCALE(xmax,ymax,xmax) = ymax
- * - SCALE(xmax,ymax,0) = 0
- * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
- *
- * In addition, the rounding error is minimal and nicely distributed.
- * The proofs are left as an exercise to the reader.
- */
-
-#define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
-
-
-static int getvolume(caddr_t arg,
-		     unsigned char left_index, unsigned char right_index)
-{
-  int vol;
-  unsigned char buf;
-
-  /* left channel */
-  if (aci_indexed_cmd(0xf0, left_index, &buf)) return -EIO;
-  vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
-  /* right channel */
-  if (aci_indexed_cmd(0xf0, right_index, &buf)) return -EIO;
-  vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
-
-  return (*(int *) arg = vol);
-}
-
-
-static int setvolume(caddr_t arg, 
-		     unsigned char left_index, unsigned char right_index)
-{
-  int vol, ret;
-
-  /* left channel */
-  vol = *(int *)arg & 0xff;
-  if (vol > 100) vol = 100;
-  vol = SCALE(100, 0x20, vol);
-  if (aci_write_cmd(left_index, 0x20 - vol)) return -EIO;
-  ret = SCALE(0x20, 100, vol);
-  /* right channel */
-  vol = (*(int *)arg >> 8) & 0xff;
-  if (vol > 100) vol = 100;
-  vol = SCALE(100, 0x20, vol);
-  if (aci_write_cmd(right_index, 0x20 - vol)) return -EIO;
-  ret |= SCALE(0x20, 100, vol) << 8;
- 
-  return (*(int *) arg = ret);
-}
-
-
-static int
-aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
-{
-  int status, vol;
-  unsigned char buf;
-
-  /* handle solo mode control */
-  if (cmd == SOUND_MIXER_PRIVATE1) {
-    if (*(int *) arg >= 0) {
-      aci_solo = !!*(int *) arg;
-      if (aci_write_cmd(0xd2, aci_solo)) return -EIO;
-    } else if (aci_version >= 0xb0) {
-      if ((status = read_general_status()) < 0) return -EIO;
-      return (*(int *) arg = (status & 0x20) == 0);
-    }
-    return (*(int *) arg = aci_solo);
-  }
-
-  if (((cmd >> 8) & 0xff) == 'M') {
-    if (cmd & IOC_IN)
-      /* read and write */
-      switch (cmd & 0xff) {
-      case SOUND_MIXER_VOLUME:
-	return setvolume(arg, 0x01, 0x00);
-      case SOUND_MIXER_CD:
-	return setvolume(arg, 0x3c, 0x34);
-      case SOUND_MIXER_MIC:
-	return setvolume(arg, 0x38, 0x30);
-      case SOUND_MIXER_LINE:
-	return setvolume(arg, 0x39, 0x31);
-      case SOUND_MIXER_SYNTH:
-	return setvolume(arg, 0x3b, 0x33);
-      case SOUND_MIXER_PCM:
-	return setvolume(arg, 0x3a, 0x32);
-      case SOUND_MIXER_LINE1:  /* AUX1 */
-	return setvolume(arg, 0x3d, 0x35);
-      case SOUND_MIXER_LINE2:  /* AUX2 */
-	return setvolume(arg, 0x3e, 0x36);
-      case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
-	vol = *(int *) arg & 0xff;
-	if (vol > 100) vol = 100;
-	vol = SCALE(100, 3, vol);
-	if (aci_write_cmd(0x03, vol)) return -EIO;
-	vol = SCALE(3, 100, vol);
-	return (*(int *) arg = vol | (vol << 8));
-      case SOUND_MIXER_RECSRC:
-	return (*(int *) arg = 0);
-	break;
-      default:
-	return -EINVAL;
-      }
-    else
-      /* only read */
-      switch (cmd & 0xff) {
-      case SOUND_MIXER_DEVMASK:
-	return (*(int *) arg =
-				 SOUND_MASK_VOLUME | SOUND_MASK_CD    |
-				 SOUND_MASK_MIC    | SOUND_MASK_LINE  |
-				 SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
-#if 0
-				 SOUND_MASK_IGAIN  |
-#endif
-				 SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
-	break;
-      case SOUND_MIXER_STEREODEVS:
-	return (*(int *) arg =
-				 SOUND_MASK_VOLUME | SOUND_MASK_CD   |
-				 SOUND_MASK_MIC    | SOUND_MASK_LINE |
-				 SOUND_MASK_SYNTH  | SOUND_MASK_PCM  |
-				 SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
-	break;
-      case SOUND_MIXER_RECMASK:
-	return (*(int *) arg = 0);
-	break;
-      case SOUND_MIXER_RECSRC:
-	return (*(int *) arg = 0);
-	break;
-      case SOUND_MIXER_CAPS:
-	return (*(int *) arg = 0);
-	break;
-      case SOUND_MIXER_VOLUME:
-	return getvolume(arg, 0x04, 0x03);
-      case SOUND_MIXER_CD:
-	return getvolume(arg, 0x0a, 0x09);
-      case SOUND_MIXER_MIC:
-	return getvolume(arg, 0x06, 0x05);
-      case SOUND_MIXER_LINE:
-	return getvolume(arg, 0x08, 0x07);
-      case SOUND_MIXER_SYNTH:
-	return getvolume(arg, 0x0c, 0x0b);
-      case SOUND_MIXER_PCM:
-	return getvolume(arg, 0x0e, 0x0d);
-      case SOUND_MIXER_LINE1:  /* AUX1 */
-	return getvolume(arg, 0x11, 0x10);
-      case SOUND_MIXER_LINE2:  /* AUX2 */
-	return getvolume(arg, 0x13, 0x12);
-      case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
-	if (aci_indexed_cmd(0xf0, 0x21, &buf)) return -EIO;
-	vol = SCALE(3, 100, buf <= 3 ? buf : 3);
-	vol |= vol << 8;
-	return (*(int *) arg = vol);
-      default:
-	return -EINVAL;
-      }
-  }
-
-  return -EINVAL;
-}
-
-
-static struct mixer_operations aci_mixer_operations =
-{
-  "ACI",
-  "ACI mixer",
-  aci_mixer_ioctl,
-  NULL
-};
-
-static unsigned char
-mad_read (int port)
-{
-  outb (0xE3, 0xf8f); /* Write MAD16 password */
-  return inb (port);  /* Read from port */
-}
-
-
-/*
- * Check, whether there actually is any ACI port operational and if
- * one was found, then initialize the ACI interface, reserve the I/O
- * addresses and attach the new mixer to the relevant VoxWare data
- * structures.
- *
- * Returns:  1   ACI mixer detected
- *           0   nothing there
- *
- * There is also an internal mixer in the codec (CS4231A or AD1845),
- * that deserves no purpose in an ACI based system which uses an
- * external ACI controlled stereo mixer. Make sure that this codec
- * mixer has the AUX1 input selected as the recording source, that the
- * input gain is set near maximum and that the other channels going
- * from the inputs to the codec output are muted.
- */
-
-int attach_aci(void)
-{
-  char *boardname = "unknown";
-  int volume;
-
-#define MC4_PORT	0xf90
-
-  aci_port =
-      (mad_read(MC4_PORT) & 0x10) ? 0x344 : 0x354;
-
-  if (check_region(aci_port, 3)) {
-#ifdef DEBUG
-    printk("ACI: I/O area 0x%03x-0x%03x already used.\n",
-           aci_port, aci_port+2);
-#endif
-    return 0;
-  }
-
-  if (aci_read_cmd(0xf2, 2, aci_idcode)) {
-#ifdef DEBUG
-    printk("ACI: Failed to read idcode.\n");
-#endif
-    return 0;
-  }
-  if (aci_read_cmd(0xf1, 1, &aci_version)) {
-#ifdef DEBUG
-    printk("ACI: Failed to read version.\n");
-#endif
-    return 0;
-  }
-
-  if (aci_idcode[0] == 0x6d) {
-    /* It looks like a miro sound card. */
-    switch (aci_idcode[1]) {
-    case 0x41:
-      boardname = "PCM1 pro / early PCM12";
-      break;
-    case 0x42:
-      boardname = "PCM12";
-      break;
-    case 0x43:
-      boardname = "PCM20";
-      break;
-    default:
-      boardname = "unknown miro";
-    }
-  } else
-#ifndef DEBUG
-    return 0;
-#endif
-  
-  printk("<ACI %02x, id %02x %02x (%s)> at 0x%03x\n",
-	 aci_version, aci_idcode[0], aci_idcode[1], boardname, aci_port);
-
-  if (aci_reset) {
-    /* initialize ACI mixer */
-    aci_implied_cmd(0xff);
-    aci_solo = 0;
-  }
-
-  /* attach the mixer */
-  request_region(aci_port, 3, "sound mixer (ACI)");
-  if (num_mixers < MAX_MIXER_DEV) {
-    if (num_mixers > 0 &&
-        !strncmp("MAD16 WSS", mixer_devs[num_mixers-1]->name, 9)) {
-      /*
-       * The previously registered mixer device is the CS4231A which
-       * has no function on an ACI card. Make the ACI mixer the first
-       * of the two mixer devices.
-       */
-      mixer_devs[num_mixers] = mixer_devs[num_mixers-1];
-      mixer_devs[num_mixers-1] = &aci_mixer_operations;
-      /*
-       * Initialize the CS4231A mixer with reasonable values. It is
-       * unlikely that the user ever will want to change these as all
-       * channels can be mixed via ACI.
-       */
-      volume = 0x6464;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_PCM,     (caddr_t) &volume);
-      volume = 0x6464;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_IGAIN,   (caddr_t) &volume);
-      volume = 0;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_SPEAKER, (caddr_t) &volume);
-      volume = 0;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_MIC,     (caddr_t) &volume);
-      volume = 0;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_IMIX,    (caddr_t) &volume);
-      volume = 0;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_LINE1,   (caddr_t) &volume);
-      volume = 0;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_LINE2,   (caddr_t) &volume);
-      volume = 0;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_LINE3,   (caddr_t) &volume);
-      volume = SOUND_MASK_LINE1;
-      mixer_devs[num_mixers]->
-        ioctl(num_mixers, SOUND_MIXER_WRITE_RECSRC,  (caddr_t) &volume);
-      num_mixers++;
-    } else
-      mixer_devs[num_mixers++] = &aci_mixer_operations;
-  }
-
-  /* Just do something; otherwise the first write command fails, at
-   * least with my PCM20.
-   */
-  aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_READ_VOLUME, (caddr_t) &volume);
-
-  if (aci_reset) {
-    /* Initialize ACI mixer with reasonable power-up values */
-    volume = 0x3232;
-    aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_VOLUME, (caddr_t) &volume);
-    volume = 0x3232;
-    aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_SYNTH,  (caddr_t) &volume);
-    volume = 0x3232;
-    aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_PCM,    (caddr_t) &volume);
-    volume = 0x3232;
-    aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE,   (caddr_t) &volume);
-    volume = 0x3232;
-    aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_MIC,    (caddr_t) &volume);
-    volume = 0x3232;
-    aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_CD,     (caddr_t) &volume);
-    volume = 0x3232;
-    aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE1,  (caddr_t) &volume);
-    volume = 0x3232;
-    aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE2,  (caddr_t) &volume);
-  }
-  
-  aci_present = 1;
-
-  return 1;
-}
-
-void unload_aci(void)
-{
-  if (aci_present)
-    release_region(aci_port, 3);
-}
-
-#endif
-
-#if defined(MODULE)
-
-int init_module(void) {
-	attach_aci();
-	return(0);
-}
-
-void cleanup_module(void) {
-	unload_aci();
-}
-
-#endif /* MODULE */
- 
\ No newline at end of file
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/aedsp16.c linux/drivers/sound/lowlevel/aedsp16.c
--- v2.3.50/linux/drivers/sound/lowlevel/aedsp16.c	Sun Aug 23 13:32:25 1998
+++ linux/drivers/sound/lowlevel/aedsp16.c	Wed Dec 31 16:00:00 1969
@@ -1,1400 +0,0 @@
-/*
-   drivers/sound/lowlevel/aedsp16.c
-
-   Audio Excel DSP 16 software configuration routines
-   Copyright (C) 1995,1996,1997,1998  Riccardo Facchetti (fizban@tin.it)
-
-   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.
-
- */
-/*
- * Include the main OSS Lite header file. It include all the os, OSS Lite, etc
- * headers needed by this source.
- */
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include "../sound_config.h"
-#include "../soundmodule.h"
-
-/*
- * Sanity checks
- */
-
-#if !defined(CONFIG_AEDSP16_BASE)
-# undef CONFIG_AEDSP16
-#else
-# if defined(MODULE) && defined(CONFIG_AEDSP16_MODULE)
-#  define CONFIG_AEDSP16 1
-# endif
-#endif
-
-
-#if defined(CONFIG_AEDSP16)
-
-#if defined(CONFIG_AEDSP16_SBPRO) && defined(CONFIG_AEDSP16_MSS)
-#error You have to enable only one of the MSS and SBPRO emulations.
-#endif
-
-/*
-
-   READ THIS
-
-   This module started to configure the Audio Excel DSP 16 Sound Card.
-   Now works with the SC-6000 (old aedsp16) and new SC-6600 based cards.
-
-   NOTE: I have NO idea about Audio Excel DSP 16 III. If someone owns this
-   audio card and want to see the kernel support for it, please contact me.
-
-   Audio Excel DSP 16 is an SB pro II, Microsoft Sound System and MPU-401
-   compatible card.
-   It is software-only configurable (no jumpers to hard-set irq/dma/mpu-irq),
-   so before this module, the only way to configure the DSP under linux was
-   boot the MS-DOS loading the sound.sys device driver (this driver soft-
-   configure the sound board hardware by massaging someone of its registers),
-   and then ctrl-alt-del to boot linux with the DSP configured by the DOS
-   driver.
-
-   This module works configuring your Audio Excel DSP 16's irq, dma and
-   mpu-401-irq. The OSS Lite routines rely on the fact that if the
-   hardware is there, they can detect it. The problem with AEDSP16 is
-   that no hardware can be found by the probe routines if the sound card
-   is not configured properly. Sometimes the kernel probe routines can find
-   an SBPRO even when the card is not configured (this is the standard setup
-   of the card), but the SBPRO emulation don't work well if the card is not
-   properly initialized. For this reason
-
-   aedsp16_init_board()
-
-   routine is called before the OSS Lite probe routines try to detect the
-   hardware.
-
-   NOTE (READ THE NOTE TOO, IT CONTAIN USEFUL INFORMATIONS)
-
-   NOTE: Now it works with SC-6000 and SC-6600 based audio cards. The new cards
-   have no jumper switch at all. No more WSS or MPU-401 I/O port switches. They
-   have to be configured by software.
-
-   NOTE: The driver is merged with the new OSS Lite sound driver. It works
-   as a lowlevel driver.
-
-   The Audio Excel DSP 16 Sound Card emulates both SBPRO and MSS;
-   the OSS Lite sound driver can be configured for SBPRO and MSS cards
-   at the same time, but the aedsp16 can't be two cards!!
-   When we configure it, we have to choose the SBPRO or the MSS emulation
-   for AEDSP16. We also can install a *REAL* card of the other type (see [1]).
-
-   NOTE: If someone can test the combination AEDSP16+MSS or AEDSP16+SBPRO
-   please let me know if it works.
-
-   The MPU-401 support can be compiled in together with one of the other
-   two operating modes.
-
-   NOTE: This is something like plug-and-play: we have only to plug
-   the AEDSP16 board in the socket, and then configure and compile
-   a kernel that uses the AEDSP16 software configuration capability.
-   No jumper setting is needed!
-
-   For example, if you want AEDSP16 to be an SBPro, on irq 10, dma 3
-   you have just to make config the OSS Lite package, configuring
-   the AEDSP16 sound card, then activating the SBPro emulation mode
-   and at last configuring IRQ and DMA.
-   Compile the kernel and run it.
-
-   NOTE: This means for SC-6000 cards that you can choose irq and dma,
-   but not the I/O addresses. To change I/O addresses you have to set
-   them with jumpers. For SC-6600 cards you have no jumpers so you have
-   to set up your full card configuration in the make config.
-
-   You can change the irq/dma/mirq settings WITHOUT THE NEED to open
-   your computer and massage the jumpers (there are no irq/dma/mirq
-   jumpers to be configured anyway, only I/O BASE values have to be
-   configured with jumpers)
-
-   For some ununderstandable reason, the card default of irq 7, dma 1,
-   don't work for me. Seems to be an IRQ or DMA conflict. Under heavy
-   HDD work, the kernel start to erupt out a lot of messages like:
-
-   'Sound: DMA timed out - IRQ/DRQ config error?'
-
-   For what I can say, I have NOT any conflict at irq 7 (under linux I'm
-   using the lp polling driver), and dma line 1 is unused as stated by
-   /proc/dma. I can suppose this is a bug of AEDSP16. I know my hardware so
-   I'm pretty sure I have not any conflict, but may be I'm wrong. Who knows!
-   Anyway a setting of irq 10, dma 3 works really fine.
-
-   NOTE: if someone can use AEDSP16 with irq 7, dma 1, please let me know
-   the emulation mode, all the installed hardware and the hardware
-   configuration (irq and dma settings of all the hardware).
-
-   This init module should work with SBPRO+MSS, when one of the two is
-   the AEDSP16 emulation and the other the real card. (see [1])
-   For example:
-
-   AEDSP16 (0x220) in SBPRO emu (0x220) + real MSS + other
-   AEDSP16 (0x220) in MSS emu + real SBPRO (0x240) + other
-
-   MPU401 should work. (see [2])
-
-   [1]
-       ---
-       Date: Mon, 29 Jul 1997 08:35:40 +0100
-       From: Mr S J Greenaway <sjg95@unixfe.rl.ac.uk>
-
-       [...]
-       Just to let you know got my Audio Excel (emulating a MSS) working
-       with my original SB16, thanks for the driver!
-       [...]
-       ---
-
-   [2] Not tested by me for lack of hardware.
-
-   TODO, WISHES AND TECH
-
-   - About I/O ports allocation -
-
-   Request the 2x0h region (port base) in any case if we are using this card.
-
-   NOTE: the "aedsp16 (base)" string with which we are requesting the aedsp16
-   port base region (see code) does not mean necessarily that we are emulating
-   sbpro.  Even if this region is the sbpro I/O ports region, we use this
-   region to access the control registers of the card, and if emulating
-   sbpro, I/O sbpro registers too. If we are emulating MSS, the sbpro
-   registers are not used, in no way, to emulate an sbpro: they are
-   used only for configuration purposes.
-
-   Started Fri Mar 17 16:13:18 MET 1995
-
-   v0.1 (ALPHA, was an user-level program called AudioExcelDSP16.c)
-   - Initial code.
-   v0.2 (ALPHA)
-   - Cleanups.
-   - Integrated with Linux voxware v 2.90-2 kernel sound driver.
-   - SoundBlaster Pro mode configuration.
-   - Microsoft Sound System mode configuration.
-   - MPU-401 mode configuration.
-   v0.3 (ALPHA)
-   - Cleanups.
-   - Rearranged the code to let aedsp16_init_board be more general.
-   - Erased the REALLY_SLOW_IO. We don't need it. Erased the linux/io.h
-   inclusion too. We rely on os.h
-   - Used the  to get a variable
-   len string (we are not sure about the len of Copyright string).
-   This works with any SB and compatible.
-   - Added the code to request_region at device init (should go in
-   the main body of voxware).
-   v0.4 (BETA)
-   - Better configure.c patch for aedsp16 configuration (better
-   logic of inclusion of AEDSP16 support)
-   - Modified the conditional compilation to better support more than
-   one sound card of the emulated type (read the NOTES above)
-   - Moved the sb init routine from the attach to the very first
-   probe in sb_card.c
-   - Rearrangements and cleanups
-   - Wiped out some unnecessary code and variables: this is kernel
-   code so it is better save some TEXT and DATA
-   - Fixed the request_region code. We must allocate the aedsp16 (sbpro)
-   I/O ports in any case because they are used to access the DSP
-   configuration registers and we can not allow anyone to get them.
-   v0.5
-   - cleanups on comments
-   - prep for diffs against v3.0-proto-950402
-   v0.6
-   - removed the request_region()s when compiling the MODULE sound.o
-   because we are not allowed (by the actual voxware structure) to
-   release_region()
-   v0.7 (pre ALPHA, not distributed)
-   - started porting this module to kernel 1.3.84. Dummy probe/attach
-   routines.
-   v0.8 (ALPHA)
-   - attached all the init routines.
-   v0.9 (BETA)
-   - Integrated with linux-pre2.0.7
-   - Integrated with configuration scripts.
-   - Cleaned up and beautyfied the code.
-   v0.9.9 (BETA)
-   - Thanks to Piercarlo Grandi: corrected the conditonal compilation code.
-     Now only the code configured is compiled in, with some memory saving.
-   v0.9.10
-   - Integration into the sound/lowlevel/ section of the sound driver.
-   - Re-organized the code.
-   v0.9.11 (not distributed)
-   - Rewritten the init interface-routines to initialize the AEDSP16 in
-     one shot.
-   - More cosmetics.
-   - SC-6600 support.
-   - More soft/hard configuration.
-   v0.9.12
-   - Refined the v0.9.11 code with conditional compilation to distinguish
-     between SC-6000 and SC-6600 code.
-   v1.0.0
-   - Prep for merging with OSS Lite and Linux kernel 2.1.13
-   - Corrected a bug in request/check/release region calls (thanks to the
-     new kernel exception handling).
-   v1.1
-   - Revamped for integration with new modularized sound drivers: to enhance
-     the flexibility of modular version, I have removed all the conditional
-     compilation for SBPRO, MPU and MSS code. Now it is all managed with
-     the ae_config structure.
-   v1.2
-   - Module informations added.
-   - Removed aedsp16_delay_10msec(), now using mdelay(10)
-   - All data and funcs moved to .*.init section.
-
-   Known Problems:
-   - Audio Excel DSP 16 III don't work with this driver.
-
-   Credits:
-   Many thanks to Gerald Britton <gbritton@CapAccess.org>. He helped me a
-   lot in testing the 0.9.11 and 0.9.12 versions of this driver.
-
- */
-
-
-#define VERSION "1.2"		/* Version of Audio Excel DSP 16 driver */
-
-#undef	AEDSP16_DEBUG 1		/* Define this to enable debug code     */
-#undef	AEDSP16_DEBUG_MORE 1	/* Define this to enable more debug     */
-#undef	AEDSP16_INFO  1		/* Define this to enable info code      */
-
-#if defined(AEDSP16_DEBUG)
-# define DBG(x)  printk x
-# if defined(AEDSP16_DEBUG_MORE)
-#  define DBG1(x) printk x
-# else
-#  define DBG1(x)
-# endif
-#else
-# define DBG(x)
-# define DBG1(x)
-#endif
-
-/*
- * Misc definitions
- */
-#define TRUE	1
-#define FALSE	0
-
-/*
- * Region Size for request/check/release region.
- */
-#define IOBASE_REGION_SIZE	0x10
-
-/*
- * Hardware related defaults
- */
-#define DEF_AEDSP16_IOB 0x220   /* 0x220(default) 0x240                 */
-#define DEF_AEDSP16_IRQ 7	/* 5 7(default) 9 10 11                 */
-#define DEF_AEDSP16_MRQ 0	/* 5 7 9 10 0(default), 0 means disable */
-#define DEF_AEDSP16_DMA 1	/* 0 1(default) 3                       */
-
-/*
- * Commands of AEDSP16's DSP (SBPRO+special).
- * Some of them are COMMAND_xx, in the future they may change.
- */
-#define WRITE_MDIRQ_CFG   0x50	/* Set M&I&DRQ mask (the real config)   */
-#define COMMAND_52        0x52	/*                                      */
-#define READ_HARD_CFG     0x58	/* Read Hardware Config (I/O base etc)  */
-#define COMMAND_5C        0x5c	/*                                      */
-#define COMMAND_60        0x60	/*                                      */
-#define COMMAND_66        0x66	/*                                      */
-#define COMMAND_6C        0x6c	/*                                      */
-#define COMMAND_6E        0x6e	/*                                      */
-#define COMMAND_88        0x88	/*                                      */
-#define DSP_INIT_MSS      0x8c	/* Enable Microsoft Sound System mode   */
-#define COMMAND_C5        0xc5	/*                                      */
-#define GET_DSP_VERSION   0xe1	/* Get DSP Version                      */
-#define GET_DSP_COPYRIGHT 0xe3	/* Get DSP Copyright                    */
-
-/*
- * Offsets of AEDSP16 DSP I/O ports. The offset is added to base I/O port
- * to have the actual I/O port.
- * Register permissions are:
- * (wo) == Write Only
- * (ro) == Read  Only
- * (w-) == Write
- * (r-) == Read
- */
-#define DSP_RESET    0x06	/* offset of DSP RESET             (wo) */
-#define DSP_READ     0x0a	/* offset of DSP READ              (ro) */
-#define DSP_WRITE    0x0c	/* offset of DSP WRITE             (w-) */
-#define DSP_COMMAND  0x0c	/* offset of DSP COMMAND           (w-) */
-#define DSP_STATUS   0x0c	/* offset of DSP STATUS            (r-) */
-#define DSP_DATAVAIL 0x0e	/* offset of DSP DATA AVAILABLE    (ro) */
-
-
-#define RETRY           10	/* Various retry values on I/O opera-   */
-#define STATUSRETRY   1000	/* tions. Sometimes we have to          */
-#define HARDRETRY   500000	/* wait for previous cmd to complete    */
-
-/*
- * Size of character arrays that store name and version of sound card
- */
-#define CARDNAMELEN 15		/* Size of the card's name in chars     */
-#define CARDVERLEN  2		/* Size of the card's version in chars  */
-
-#if defined(CONFIG_SC6600)
-/*
- * Bitmapped flags of hard configuration
- */
-/*
- * Decode macros (xl == low byte, xh = high byte)
- */
-#define IOBASE(xl)		((xl & 0x01)?0x240:0x220)
-#define JOY(xl)  		(xl & 0x02)
-#define MPUADDR(xl)		( 			\
-				(xl & 0x0C)?0x330:	\
-				(xl & 0x08)?0x320:	\
-				(xl & 0x04)?0x310:	\
-						0x300)
-#define WSSADDR(xl)		((xl & 0x10)?0xE80:0x530)
-#define CDROM(xh)		(xh & 0x20)
-#define CDROMADDR(xh)		(((xh & 0x1F) << 4) + 0x200)
-/*
- * Encode macros
- */
-#define BLDIOBASE(xl, val) {		\
-	xl &= ~0x01; 			\
-	if (val == 0x240)		\
-		xl |= 0x01;		\
-	}
-#define BLDJOY(xl, val) {		\
-	xl &= ~0x02; 			\
-	if (val == 1)			\
-		xl |= 0x02;		\
-	}
-#define BLDMPUADDR(xl, val) {		\
-	xl &= ~0x0C;			\
-	switch (val) {			\
-		case 0x330:		\
-			xl |= 0x0C;	\
-			break;		\
-		case 0x320:		\
-			xl |= 0x08;	\
-			break;		\
-		case 0x310:		\
-			xl |= 0x04;	\
-			break;		\
-		case 0x300:		\
-			xl |= 0x00;	\
-			break;		\
-		default:		\
-			xl |= 0x00;	\
-			break;		\
-		}			\
-	}
-#define BLDWSSADDR(xl, val) {		\
-	xl &= ~0x10; 			\
-	if (val == 0xE80)		\
-		xl |= 0x10;		\
-	}
-#define BLDCDROM(xh, val) {		\
-	xh &= ~0x20; 			\
-	if (val == 1)			\
-		xh |= 0x20;		\
-	}
-#define BLDCDROMADDR(xh, val) {		\
-	int tmp = val;			\
-	tmp -= 0x200;			\
-	tmp >>= 4;			\
-	tmp &= 0x1F;			\
-	xh |= tmp;			\
-	xh &= 0x7F;			\
-	xh |= 0x40;			\
-	}
-#endif /* CONFIG_SC6600 */
-
-/*
- * Bit mapped flags for calling aedsp16_init_board(), and saving the current
- * emulation mode.
- */
-#define INIT_NONE   (0   )
-#define INIT_SBPRO  (1<<0)
-#define INIT_MSS    (1<<1)
-#define INIT_MPU401 (1<<2)
-
-static int      soft_cfg __initdata = 0;	/* bitmapped config */
-static int      soft_cfg_mss __initdata = 0;	/* bitmapped mss config */
-static int      ver[CARDVERLEN] __initdata = {0, 0};	/* DSP Ver:
-						   hi->ver[0] lo->ver[1] */
-
-#if defined(CONFIG_SC6600)
-static int	hard_cfg[2]     /* lo<-hard_cfg[0] hi<-hard_cfg[1]      */
-                     __initdata = { 0, 0};
-#endif /* CONFIG_SC6600 */
-
-#if defined(CONFIG_SC6600)
-/* Decoded hard configuration */
-struct	d_hcfg {
-	int iobase;
-	int joystick;
-	int mpubase;
-	int wssbase;
-	int cdrom;
-	int cdrombase;
-};
-
-struct d_hcfg decoded_hcfg __initdata = {0, };
-
-#endif /* CONFIG_SC6600 */
-
-/* orVals contain the values to be or'ed       				*/
-struct orVals {
-	int	val;		/* irq|mirq|dma                         */
-	int	or;		/* soft_cfg |= TheStruct.or             */
-};
-
-/* aedsp16_info contain the audio card configuration                  */
-struct aedsp16_info {
-	int base_io;            /* base I/O address for accessing card  */
-	int irq;                /* irq value for DSP I/O                */
-	int mpu_irq;            /* irq for mpu401 interface I/O         */
-	int dma;                /* dma value for DSP I/O                */
-	int mss_base;           /* base I/O for Microsoft Sound System  */
-	int mpu_base;           /* base I/O for MPU-401 emulation       */
-	int init;               /* Initialization status of the card    */
-};
-
-/*
- * Magic values that the DSP will eat when configuring irq/mirq/dma
- */
-/* DSP IRQ conversion array             */
-static struct orVals orIRQ[] __initdata = {
-	{0x05, 0x28},
-	{0x07, 0x08},
-	{0x09, 0x10},
-	{0x0a, 0x18},
-	{0x0b, 0x20},
-	{0x00, 0x00}
-};
-
-/* MPU-401 IRQ conversion array         */
-static struct orVals orMIRQ[] __initdata = {
-	{0x05, 0x04},
-	{0x07, 0x44},
-	{0x09, 0x84},
-	{0x0a, 0xc4},
-	{0x00, 0x00}
-};
-
-/* DMA Channels conversion array        */
-static struct orVals orDMA[] __initdata = {
-	{0x00, 0x01},
-	{0x01, 0x02},
-	{0x03, 0x03},
-	{0x00, 0x00}
-};
-
-static struct aedsp16_info ae_config __initdata = {
-	DEF_AEDSP16_IOB,
-	DEF_AEDSP16_IRQ,
-	DEF_AEDSP16_MRQ,
-	DEF_AEDSP16_DMA,
-	-1,
-	-1,
-	INIT_NONE
-};
-
-/*
- * Buffers to store audio card informations
- */
-static char     DSPCopyright[CARDNAMELEN + 1] __initdata = {0, };
-static char     DSPVersion[CARDVERLEN + 1] __initdata = {0, };
-
-static int __init aedsp16_wait_data(int port)
-{
-	int             loop = STATUSRETRY;
-	unsigned char   ret = 0;
-
-	DBG1(("aedsp16_wait_data (0x%x): ", port));
-
-	do {
-		  ret = inb(port + DSP_DATAVAIL);
-	/*
-	 * Wait for data available (bit 7 of ret == 1)
-	 */
-	  } while (!(ret & 0x80) && loop--);
-
-	if (ret & 0x80) {
-		DBG1(("success.\n"));
-		return TRUE;
-	}
-
-	DBG1(("failure.\n"));
-	return FALSE;
-}
-
-static int __init aedsp16_read(int port)
-{
-	int inbyte;
-
-	DBG(("    Read DSP Byte (0x%x): ", port));
-
-	if (aedsp16_wait_data(port) == FALSE) {
-		DBG(("failure.\n"));
-		return -1;
-	}
-
-	inbyte = inb(port + DSP_READ);
-
-	DBG(("read [0x%x]/{%c}.\n", inbyte, inbyte));
-
-	return inbyte;
-}
-
-static int __init aedsp16_test_dsp(int port)
-{
-	return ((aedsp16_read(port) == 0xaa) ? TRUE : FALSE);
-}
-
-static int __init aedsp16_dsp_reset(int port)
-{
-	/*
-	 * Reset DSP
-	 */
-
-	DBG(("Reset DSP:\n"));
-
-	outb(1, (port + DSP_RESET));
-	udelay(10);
-	outb(0, (port + DSP_RESET));
-	udelay(10);
-	udelay(10);
-	if (aedsp16_test_dsp(port) == TRUE) {
-		DBG(("success.\n"));
-		return TRUE;
-	} else
-		DBG(("failure.\n"));
-	return FALSE;
-}
-
-static int __init aedsp16_write(int port, int cmd)
-{
-	unsigned char   ret;
-	int             loop = HARDRETRY;
-
-	DBG(("    Write DSP Byte (0x%x) [0x%x]: ", port, cmd));
-
-	do {
-		ret = inb(port + DSP_STATUS);
-		/*
-		 * DSP ready to receive data if bit 7 of ret == 0
-		 */
-		if (!(ret & 0x80)) {
-			outb(cmd, port + DSP_COMMAND);
-			DBG(("success.\n"));
-			return 0;
-		}
-	} while (loop--);
-
-	DBG(("timeout.\n"));
-	printk("[AEDSP16] DSP Command (0x%x) timeout.\n", cmd);
-
-	return -1;
-}
-
-#if defined(CONFIG_SC6600)
-
-#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
-void __init aedsp16_pinfo(void) {
-	DBG(("\n Base address:  %x\n", decoded_hcfg.iobase));
-	DBG((" Joystick    : %s present\n", decoded_hcfg.joystick?"":" not"));
-	DBG((" WSS addr    :  %x\n", decoded_hcfg.wssbase));
-	DBG((" MPU-401 addr:  %x\n", decoded_hcfg.mpubase));
-	DBG((" CDROM       : %s present\n", (decoded_hcfg.cdrom!=4)?"":" not"));
-	DBG((" CDROMADDR   :  %x\n\n", decoded_hcfg.cdrombase));
-}
-#endif
-
-void __init aedsp16_hard_decode(void) {
-
-	DBG((" aedsp16_hard_decode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
-
-/*
- * Decode Cfg Bytes.
- */
-	decoded_hcfg.iobase	= IOBASE(hard_cfg[0]);
-	decoded_hcfg.joystick	= JOY(hard_cfg[0]);
-	decoded_hcfg.wssbase	= WSSADDR(hard_cfg[0]);
-	decoded_hcfg.mpubase	= MPUADDR(hard_cfg[0]);
-	decoded_hcfg.cdrom	= CDROM(hard_cfg[1]);
-	decoded_hcfg.cdrombase	= CDROMADDR(hard_cfg[1]);
-
-#if defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
-	printk(" Original sound card configuration:\n");
-	aedsp16_pinfo();
-#endif
-
-/*
- * Now set up the real kernel configuration.
- */
-	decoded_hcfg.iobase	= ae_config.base_io;
-	decoded_hcfg.wssbase	= ae_config.mss_base;
-	decoded_hcfg.mpubase	= ae_config.mpu_base;
-
-#if defined(CONFIG_SC6600_JOY)
- 	decoded_hcfg.joystick	= CONFIG_SC6600_JOY; /* Enable */
-#endif
-#if defined(CONFIG_SC6600_CDROM)
-	decoded_hcfg.cdrom	= CONFIG_SC6600_CDROM; /* 4:N-3:I-2:G-1:P-0:S */
-#endif
-#if defined(CONFIG_SC6600_CDROMBASE)
-	decoded_hcfg.cdrombase	= CONFIG_SC6600_CDROMBASE; /* 0 Disable */
-#endif
-
-#if defined(AEDSP16_DEBUG)
-	DBG((" New Values:\n"));
-	aedsp16_pinfo();
-#endif
-
-	DBG(("success.\n"));
-}
-
-void __init aedsp16_hard_encode(void) {
-
-	DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
-
-	hard_cfg[0] = 0;
-	hard_cfg[1] = 0;
-
-	hard_cfg[0] |= 0x20;
-
-	BLDIOBASE (hard_cfg[0], decoded_hcfg.iobase);
-	BLDWSSADDR(hard_cfg[0], decoded_hcfg.wssbase);
-	BLDMPUADDR(hard_cfg[0], decoded_hcfg.mpubase);
-	BLDJOY(hard_cfg[0], decoded_hcfg.joystick);
-	BLDCDROM(hard_cfg[1], decoded_hcfg.cdrom);
-	BLDCDROMADDR(hard_cfg[1], decoded_hcfg.cdrombase);
-
-#if defined(AEDSP16_DEBUG)
-	aedsp16_pinfo();
-#endif
-
-	DBG((" aedsp16_hard_encode: 0x%x, 0x%x\n", hard_cfg[0], hard_cfg[1]));
-	DBG(("success.\n"));
-
-}
-
-static int __init aedsp16_hard_write(int port) {
-
-	DBG(("aedsp16_hard_write:\n"));
-
-	if (aedsp16_write(port, COMMAND_6C)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6C);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-	if (aedsp16_write(port, COMMAND_5C)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-	if (aedsp16_write(port, hard_cfg[0])) {
-		printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[0]);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-	if (aedsp16_write(port, hard_cfg[1])) {
-		printk("[AEDSP16] DATA 0x%x: failed!\n", hard_cfg[1]);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-	if (aedsp16_write(port, COMMAND_C5)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_C5);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-
-	DBG(("success.\n"));
-
-	return TRUE;
-}
-
-static int __init aedsp16_hard_read(int port) {
-
-	DBG(("aedsp16_hard_read:\n"));
-
-	if (aedsp16_write(port, READ_HARD_CFG)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", READ_HARD_CFG);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-
-	if ((hard_cfg[0] = aedsp16_read(port)) == -1) {
-		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
-			READ_HARD_CFG);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-	if ((hard_cfg[1] = aedsp16_read(port)) == -1) {
-		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
-			READ_HARD_CFG);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-	if (aedsp16_read(port) == -1) {
-		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
-			READ_HARD_CFG);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-
-	DBG(("success.\n"));
-
-	return TRUE;
-}
-
-static int __init aedsp16_ext_cfg_write(int port) {
-
-	int extcfg, val;
-
-	if (aedsp16_write(port, COMMAND_66)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_66);
-		return FALSE;
-	}
-
-	extcfg = 7;
-	if (decoded_hcfg.cdrom != 2)
-		extcfg = 0x0F;
-	if ((decoded_hcfg.cdrom == 4) ||
-	    (decoded_hcfg.cdrom == 3))
-		extcfg &= ~2;
-	if (decoded_hcfg.cdrombase == 0)
-		extcfg &= ~2;
-	if (decoded_hcfg.mpubase == 0)
-		extcfg &= ~1;
-
-	if (aedsp16_write(port, extcfg)) {
-		printk("[AEDSP16] Write extcfg: failed!\n");
-		return FALSE;
-	}
-	if (aedsp16_write(port, 0)) {
-		printk("[AEDSP16] Write extcfg: failed!\n");
-		return FALSE;
-	}
-	if (decoded_hcfg.cdrom == 3) {
-		if (aedsp16_write(port, COMMAND_52)) {
-			printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52);
-			return FALSE;
-		}
-		if ((val = aedsp16_read(port)) == -1) {
-			printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n"
-					, COMMAND_52);
-			return FALSE;
-		}
-		val &= 0x7F;
-		if (aedsp16_write(port, COMMAND_60)) {
-			printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60);
-			return FALSE;
-		}
-		if (aedsp16_write(port, val)) {
-			printk("[AEDSP16] Write val: failed!\n");
-			return FALSE;
-		}
-	}
-
-	return TRUE;
-}
-
-#endif /* CONFIG_SC6600 */
-
-static int __init aedsp16_cfg_write(int port) {
-	if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
-		return FALSE;
-	}
-	if (aedsp16_write(port, soft_cfg)) {
-		printk("[AEDSP16] Initialization of (M)IRQ and DMA: failed!\n");
-		return FALSE;
-	}
-	return TRUE;
-}
-
-static int __init aedsp16_init_mss(int port)
-{
-	DBG(("aedsp16_init_mss:\n"));
-
-	mdelay(10);
-
-	if (aedsp16_write(port, DSP_INIT_MSS)) {
-		printk("[AEDSP16] aedsp16_init_mss [0x%x]: failed!\n",
-				DSP_INIT_MSS);
-		DBG(("failure.\n"));
-		return FALSE;
-	}
-	
-	mdelay(10);
-
-	if (aedsp16_cfg_write(port) == FALSE)
-		return FALSE;
-
-	outb(soft_cfg_mss, ae_config.mss_base);
-
-	DBG(("success.\n"));
-
-	return TRUE;
-}
-
-static int __init aedsp16_setup_board(int port) {
-	int	loop = RETRY;
-
-#if defined(CONFIG_SC6600)
-	int	val = 0;
-
-	if (aedsp16_hard_read(port) == FALSE) {
-		printk("[AEDSP16] aedsp16_hard_read: failed!\n");
-		return FALSE;
-	}
-
-	if (aedsp16_write(port, COMMAND_52)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_52);
-		return FALSE;
-	}
-
-	if ((val = aedsp16_read(port)) == -1) {
-		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
-				COMMAND_52);
-		return FALSE;
-	}
-#endif
-
-	do {
-		if (aedsp16_write(port, COMMAND_88)) {
-			printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_88);
-			return FALSE;
-		}
-		mdelay(10);
-	} while ((aedsp16_wait_data(port) == FALSE) && loop--);
-
-	if (aedsp16_read(port) == -1) {
-		printk("[AEDSP16] aedsp16_read after CMD 0x%x: failed\n",
-				COMMAND_88);
-		return FALSE;
-	}
-
-#if !defined(CONFIG_SC6600)
-	if (aedsp16_write(port, COMMAND_5C)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
-		return FALSE;
-	}
-#endif
-
-	if (aedsp16_cfg_write(port) == FALSE)
-		return FALSE;
-
-#if defined(CONFIG_SC6600)
-	if (aedsp16_write(port, COMMAND_60)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_60);
-		return FALSE;
-	}
-	if (aedsp16_write(port, val)) {
-		printk("[AEDSP16] DATA 0x%x: failed!\n", val);
-		return FALSE;
-	}
-	if (aedsp16_write(port, COMMAND_6E)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_6E);
-		return FALSE;
-	}
-	if (aedsp16_write(port, ver[0])) {
-		printk("[AEDSP16] DATA 0x%x: failed!\n", ver[0]);
-		return FALSE;
-	}
-	if (aedsp16_write(port, ver[1])) {
-		printk("[AEDSP16] DATA 0x%x: failed!\n", ver[1]);
-		return FALSE;
-	}
-
-	if (aedsp16_hard_write(port) == FALSE) {
-		printk("[AEDSP16] aedsp16_hard_write: failed!\n");
-		return FALSE;
-	}
-
-	if (aedsp16_write(port, COMMAND_5C)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", COMMAND_5C);
-		return FALSE;
-	}
-
-#if defined(THIS_IS_A_THING_I_HAVE_NOT_TESTED_YET)
-	if (aedsp16_cfg_write(port) == FALSE)
-		return FALSE;
-#endif
-
-#endif
-
-	return TRUE;
-}
-
-static int __init aedsp16_stdcfg(int port) {
-	if (aedsp16_write(port, WRITE_MDIRQ_CFG)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", WRITE_MDIRQ_CFG);
-		return FALSE;
-	}
-	/*
-	 * 0x0A == (IRQ 7, DMA 1, MIRQ 0)
-	 */
-	if (aedsp16_write(port, 0x0A)) {
-		printk("[AEDSP16] aedsp16_stdcfg: failed!\n");
-		return FALSE;
-	}
-	return TRUE;
-}
-
-static int __init aedsp16_dsp_version(int port)
-{
-	int             len = 0;
-	int             ret;
-
-	DBG(("Get DSP Version:\n"));
-
-	if (aedsp16_write(ae_config.base_io, GET_DSP_VERSION)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_VERSION);
-		DBG(("failed.\n"));
-		return FALSE;
-	}
-
-	do {
-		if ((ret = aedsp16_read(port)) == -1) {
-			DBG(("failed.\n"));
-			return FALSE;
-		}
-	/*
-	 * We already know how many int are stored (2), so we know when the
-	 * string is finished.
-	 */
-		ver[len++] = ret;
-	  } while (len < CARDVERLEN);
-	sprintf(DSPVersion, "%d.%d", ver[0], ver[1]);
-
-	DBG(("success.\n"));
-
-	return TRUE;
-}
-
-static int __init aedsp16_dsp_copyright(int port)
-{
-	int             len = 0;
-	int             ret;
-
-	DBG(("Get DSP Copyright:\n"));
-
-	if (aedsp16_write(ae_config.base_io, GET_DSP_COPYRIGHT)) {
-		printk("[AEDSP16] CMD 0x%x: failed!\n", GET_DSP_COPYRIGHT);
-		DBG(("failed.\n"));
-		return FALSE;
-	}
-
-	do {
-		if ((ret = aedsp16_read(port)) == -1) {
-	/*
-	 * If no more data available, return to the caller, no error if len>0.
-	 * We have no other way to know when the string is finished.
-	 */
-			if (len)
-				break;
-			else {
-				DBG(("failed.\n"));
-				return FALSE;
-			}
-		}
-
-		DSPCopyright[len++] = ret;
-
-	  } while (len < CARDNAMELEN);
-
-	DBG(("success.\n"));
-
-	return TRUE;
-}
-
-static void __init aedsp16_init_tables(void)
-{
-	int i = 0;
-
-	memset(DSPCopyright, 0, CARDNAMELEN + 1);
-	memset(DSPVersion, 0, CARDVERLEN + 1);
-
-	for (i = 0; orIRQ[i].or; i++)
-		if (orIRQ[i].val == ae_config.irq) {
-			soft_cfg |= orIRQ[i].or;
-			soft_cfg_mss |= orIRQ[i].or;
-		}
-
-	for (i = 0; orMIRQ[i].or; i++)
-		if (orMIRQ[i].or == ae_config.mpu_irq)
-			soft_cfg |= orMIRQ[i].or;
-
-	for (i = 0; orDMA[i].or; i++)
-		if (orDMA[i].val == ae_config.dma) {
-			soft_cfg |= orDMA[i].or;
-			soft_cfg_mss |= orDMA[i].or;
-		}
-}
-
-static int __init aedsp16_init_board(void)
-{
-	aedsp16_init_tables();
-
-	if (aedsp16_dsp_reset(ae_config.base_io) == FALSE) {
-		printk("[AEDSP16] aedsp16_dsp_reset: failed!\n");
-		return FALSE;
-	}
-	if (aedsp16_dsp_copyright(ae_config.base_io) == FALSE) {
-		printk("[AEDSP16] aedsp16_dsp_copyright: failed!\n");
-		return FALSE;
-	}
-
-	/*
-	 * My AEDSP16 card return SC-6000 in DSPCopyright, so
-	 * if we have something different, we have to be warned.
-	 */
-	if (strcmp("SC-6000", DSPCopyright))
-		printk("[AEDSP16] Warning: non SC-6000 audio card!\n");
-
-	if (aedsp16_dsp_version(ae_config.base_io) == FALSE) {
-		printk("[AEDSP16] aedsp16_dsp_version: failed!\n");
-		return FALSE;
-	}
-
-	if (aedsp16_stdcfg(ae_config.base_io) == FALSE) {
-		printk("[AEDSP16] aedsp16_stdcfg: failed!\n");
-		return FALSE;
-	}
-
-#if defined(CONFIG_SC6600)
-	if (aedsp16_hard_read(ae_config.base_io) == FALSE) {
-		printk("[AEDSP16] aedsp16_hard_read: failed!\n");
-		return FALSE;
-	}
-
-	aedsp16_hard_decode();
-
-	aedsp16_hard_encode();
-
-	if (aedsp16_hard_write(ae_config.base_io) == FALSE) {
-		printk("[AEDSP16] aedsp16_hard_write: failed!\n");
-		return FALSE;
-	}
-
-	if (aedsp16_ext_cfg_write(ae_config.base_io) == FALSE) {
-		printk("[AEDSP16] aedsp16_ext_cfg_write: failed!\n");
-		return FALSE;
-	}
-#endif /* CONFIG_SC6600 */
-
-	if (aedsp16_setup_board(ae_config.base_io) == FALSE) {
-		printk("[AEDSP16] aedsp16_setup_board: failed!\n");
-		return FALSE;
-	}
-
-	if (ae_config.mss_base != -1) {
-		if (ae_config.init & INIT_MSS) {
-			if (aedsp16_init_mss(ae_config.base_io) == FALSE) {
-				printk("[AEDSP16] Can not initialize"
-				       "Microsoft Sound System mode.\n");
-				return FALSE;
-			}
-		}
-	}
-
-#if !defined(MODULE) || defined(AEDSP16_INFO) || defined(AEDSP16_DEBUG)
-
-	printk("Audio Excel DSP 16 init v%s (%s %s) [",
-		VERSION, DSPCopyright,
-		DSPVersion);
-
-	if (ae_config.mpu_base != -1) {
-		if (ae_config.init & INIT_MPU401) {
-			printk("MPU401");
-			if ((ae_config.init & INIT_MSS) ||
-			    (ae_config.init & INIT_SBPRO))
-				printk(" ");
-		}
-	}
-
-	if (ae_config.mss_base == -1) {
-		if (ae_config.init & INIT_SBPRO) {
-			printk("SBPro");
-			if (ae_config.init & INIT_MSS)
-				printk(" ");
-		}
-	}
-
-	if (ae_config.mss_base != -1)
-		if (ae_config.init & INIT_MSS)
-			printk("MSS");
-
-	printk("]\n");
-#endif /* MODULE || AEDSP16_INFO || AEDSP16_DEBUG */
-
-	mdelay(10);
-
-	return TRUE;
-}
-
-static int __init init_aedsp16_sb(void)
-{
-	DBG(("init_aedsp16_sb: "));
-
-/*
- * If the card is already init'ed MSS, we can not init it to SBPRO too
- * because the board can not emulate simultaneously MSS and SBPRO.
- */
-	if (ae_config.init & INIT_MSS)
-		return FALSE;
-	if (ae_config.init & INIT_SBPRO)
-		return FALSE;
-
-	ae_config.init |= INIT_SBPRO;
-
-	DBG(("done.\n"));
-
-	return TRUE;
-}
-
-static void __init uninit_aedsp16_sb(void)
-{
-	DBG(("uninit_aedsp16_sb: "));
-
-	ae_config.init &= ~INIT_SBPRO;
-
-	DBG(("done.\n"));
-}
-
-static int __init init_aedsp16_mss(void)
-{
-	DBG(("init_aedsp16_mss: "));
-
-/*
- * If the card is already init'ed SBPRO, we can not init it to MSS too
- * because the board can not emulate simultaneously MSS and SBPRO.
- */
-	if (ae_config.init & INIT_SBPRO)
-		return FALSE;
-	if (ae_config.init & INIT_MSS)
-		return FALSE;
-/*
- * We must check the CONFIG_AEDSP16_BASE region too because these are the I/O 
- * ports to access card's control registers.
- */
-	if (!(ae_config.init & INIT_MPU401)) {
-		if (check_region(ae_config.base_io, IOBASE_REGION_SIZE)) {
-			printk(
-			"AEDSP16 BASE I/O port region is already in use.\n");
-			return FALSE;
-		}
-	}
-
-/*
- * We must allocate the CONFIG_AEDSP16_BASE region too because these are the 
- * I/O ports to access card's control registers.
- */
-	if (!(ae_config.init & INIT_MPU401))
-		request_region(ae_config.base_io, IOBASE_REGION_SIZE,
-				"aedsp16 (base)");
-
-	ae_config.init |= INIT_MSS;
-
-	DBG(("done.\n"));
-
-	return TRUE;
-}
-
-static void __init uninit_aedsp16_mss(void)
-{
-	DBG(("uninit_aedsp16_mss: "));
-
-	if ((!(ae_config.init & INIT_MPU401)) &&
-	   (ae_config.init & INIT_MSS)) {
-		release_region(ae_config.base_io, IOBASE_REGION_SIZE);
-		DBG(("AEDSP16 base region released.\n"));
-	}
-
-	ae_config.init &= ~INIT_MSS;
-	DBG(("done.\n"));
-}
-
-static int __init init_aedsp16_mpu(void)
-{
-	DBG(("init_aedsp16_mpu: "));
-
-	if (ae_config.init & INIT_MPU401)
-		return FALSE;
-
-/*
- * We must check the CONFIG_AEDSP16_BASE region too because these are the I/O 
- * ports to access card's control registers.
- */
-	if (!(ae_config.init & (INIT_MSS | INIT_SBPRO))) {
-		if (check_region(ae_config.base_io, IOBASE_REGION_SIZE)) {
-			printk(
-			"AEDSP16 BASE I/O port region is already in use.\n");
-			return FALSE;
-		}
-	}
-
-	if (!(ae_config.init & (INIT_MSS | INIT_SBPRO)))
-		request_region(ae_config.base_io, IOBASE_REGION_SIZE,
-				"aedsp16 (base)");
-
-	ae_config.init |= INIT_MPU401;
-
-	DBG(("done.\n"));
-
-	return TRUE;
-}
-
-static void __init uninit_aedsp16_mpu(void)
-{
-	DBG(("uninit_aedsp16_mpu: "));
-
-	if ((!(ae_config.init & (INIT_MSS | INIT_SBPRO))) &&
-	   (ae_config.init & INIT_MPU401)) {
-		release_region(ae_config.base_io, IOBASE_REGION_SIZE);
-		DBG(("AEDSP16 base region released.\n"));
-	}
-
-	ae_config.init &= ~INIT_MPU401;
-
-	DBG(("done.\n"));
-}
-
-int __init init_aedsp16(void)
-{
-	int initialized = FALSE;
-
-#if !defined(MODULE)
-	ae_config.base_io = CONFIG_AEDSP16_BASE;
-#if defined(CONFIG_AEDSP16_SBPRO)
-	ae_config.irq = CONFIG_AEDSP16_SB_IRQ;
-	ae_config.dma = CONFIG_AEDSP16_SB_DMA;
-#endif
-#if defined(CONFIG_AEDSP16_MSS)
-	ae_config.mss_base = CONFIG_MSS_BASE;
-	ae_config.irq = CONFIG_AEDSP16_MSS_IRQ;
-	ae_config.dma = CONFIG_AEDSP16_MSS_DMA;
-#endif
-#if defined(CONFIG_AEDSP16_MPU401)
-	ae_config.mpu_base = CONFIG_MPU_BASE;
-	ae_config.mpu_irq = CONFIG_AEDSP16_MPU_IRQ;
-#endif
-#endif /* !MODULE */
-	DBG(("Initializing BASE[0x%x] IRQ[%d] DMA[%d] MIRQ[%d]\n",
-	     ae_config.base_io,ae_config.irq,ae_config.dma,ae_config.mpu_irq));
-
-	if (ae_config.mss_base == -1) {
-		if (init_aedsp16_sb() == FALSE) {
-			uninit_aedsp16_sb();
-		} else {
-			initialized = TRUE;
-		}
-	}
-
-	if (ae_config.mpu_base != -1) {
-		if (init_aedsp16_mpu() == FALSE) {
-			uninit_aedsp16_mpu();
-		} else {
-			initialized = TRUE;
-		}
-	}
-
-/*
- * In the sequence of init routines, the MSS init MUST be the last!
- * This because of the special register programming the MSS mode needs.
- * A board reset would disable the MSS mode restoring the default SBPRO
- * mode.
- */
-	if (ae_config.mss_base != -1) {
-		if (init_aedsp16_mss() == FALSE) {
-			uninit_aedsp16_mss();
-		} else {
-			initialized = TRUE;
-		}
-	}
-
-	if (initialized)
-		initialized = aedsp16_init_board();
-	return initialized;
-}
-
-void __init uninit_aedsp16(void)
-{
-	if (ae_config.mss_base != -1)
-		uninit_aedsp16_mss();
-	else
-		uninit_aedsp16_sb();
-	if (ae_config.mpu_base != -1)
-		uninit_aedsp16_mpu();
-}
-
-#if defined(MODULE)
-
-int io = -1;
-int irq = -1;
-int dma = -1;
-int mpu_irq = -1;
-int mss_base = -1;
-int mpu_base = -1;
-
-
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)");
-MODULE_PARM(irq, "i");
-MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)");
-MODULE_PARM(dma, "i");
-MODULE_PARM_DESC(dma, "dma line (0 1 3)");
-MODULE_PARM(mpu_irq, "i");
-MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)");
-MODULE_PARM(mss_base, "i");
-MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)");
-MODULE_PARM(mpu_base, "i");
-MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)");
-MODULE_AUTHOR("Riccardo Facchetti <fizban@tin.it>");
-MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION);
-
-int init_module(void) {
-	printk("Audio Excel DSP 16 init driver Copyright (C) Riccardo Facchetti 1995-98\n");
-	if (io == -1 || dma == -1 || irq == -1) {
-		printk(KERN_INFO "aedsp16: I/O, IRQ and DMA are mandatory\n");
-		return -EINVAL;
-	}
-
-	ae_config.base_io = io;
-	ae_config.irq = irq;
-	ae_config.dma = dma;
-
-	ae_config.mss_base = mss_base;
-	ae_config.mpu_base = mpu_base;
-	ae_config.mpu_irq = mpu_irq;
-
-	if (init_aedsp16() == FALSE) {
-		printk(KERN_ERR "aedsp16: initialization failed\n");
-		/*
-		 * XXX
-		 * What error should we return here ?
-		 */
-		return -EINVAL;
-	}
-	SOUND_LOCK;
-	return 0;
-}
-
-void cleanup_module(void) {
-	uninit_aedsp16();
-	SOUND_LOCK_END;
-}
-#endif /* MODULE */
-
-#endif /* CONFIG_AEDSP16 */
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/awe_compat.h linux/drivers/sound/lowlevel/awe_compat.h
--- v2.3.50/linux/drivers/sound/lowlevel/awe_compat.h	Sat May 15 15:05:36 1999
+++ linux/drivers/sound/lowlevel/awe_compat.h	Wed Dec 31 16:00:00 1969
@@ -1,257 +0,0 @@
-/*
- * sound/awe_compat.h
- *
- * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
- *   version 0.4.3; Oct. 1, 1998
- *
- * Copyright (C) 1996-1998 Takashi Iwai
- *
- * 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 AWE_COMPAT_H_DEF
-#define AWE_COMPAT_H_DEF
-
-/*================================================================
- * version check
- *================================================================*/
-
-#include "awe_config.h"
-
-#define ASC_LINUX_VERSION(V,P,S)    (((V) * 65536) + ((P) * 256) + (S))
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-/* linux version check */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
-#define AWE_OBSOLETE_VOXWARE
-#endif
-
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0)
-#define AWE_NEW_KERNEL_INTERFACE
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,80)
-#define AWE_MODULE_SUPPORT
-#endif
-#endif
-
-#ifdef AWE_OBSOLETE_VOXWARE
-#include "soundvers.h"
-#else
-#include "../soundvers.h"
-#endif
-
-#if defined(SOUND_INTERNAL_VERSION) && SOUND_INTERNAL_VERSION >= 0x30803
-/* OSS/Free-3.8 */
-#define AWE_NO_PATCHMGR
-#define AWE_OSS38
-#define HAS_LOWLEVEL_H
-#endif
-
-/*================================================================
- * INCLUDE OTHER HEADER FILES
- *================================================================*/
-
-/* set up module */
-
-#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
-#include <linux/config.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#include "../soundmodule.h"
-#endif
-
-
-/* reading configuration of sound driver */
-
-#ifdef AWE_OBSOLETE_VOXWARE
-
-#include "sound_config.h"
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
-#define CONFIG_AWE32_SYNTH
-#endif
-
-#else /* AWE_OBSOLETE_VOXWARE */
-
-#ifdef HAS_LOWLEVEL_H
-#include "lowlevel.h"
-#endif
-
-#include "../sound_config.h"
-
-#endif /* AWE_OBSOLETE_VOXWARE */
-
-
-/*================================================================
- * include AWE header files
- *================================================================*/
-
-#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
-
-#include "awe_hw.h"
-#include "awe_version.h"
-#include <linux/awe_voice.h>
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-/* include finetune table */
-#ifdef AWE_OBSOLETE_VOXWARE
-#  include "tuning.h"
-#else
-#  include "../tuning.h"
-#endif
-#include <linux/ultrasound.h>
-#endif /* AWE_HAS_GUS_COMPATIBILITY */
-
-
-/*----------------------------------------------------------------
- * compatibility macros for AWE32 driver
- *----------------------------------------------------------------*/
-
-/* redefine following macros */
-#undef IOCTL_IN
-#undef IOCTL_OUT
-#undef OUTW
-#undef COPY_FROM_USER
-#undef COPY_TO_USER
-#undef GET_BYTE_FROM_USER
-#undef GET_SHORT_FROM_USER
-#undef IOCTL_TO_USER
-  
-/* use inline prefix */
-#define INLINE	/*inline*/
-
-/*----------------------------------------------------------------
- * memory management for linux
- *----------------------------------------------------------------*/
-
-#ifdef AWE_OBSOLETE_VOXWARE
-/* old type linux system */
-
-/* i/o requests; nothing */
-#define awe_check_port()	0	/* always false */
-#define awe_request_region()	/* nothing */
-#define awe_release_region()	/* nothing */
-
-static int _mem_start;  /* memory pointer for permanent buffers */
-
-#define my_malloc_init(memptr)	_mem_start = (memptr)
-#define my_malloc_memptr()	_mem_start
-#define my_free(ptr)	/* do nothing */
-
-/* allocate buffer only once */
-#define INIT_TABLE(buffer,index,nums,type) {\
-PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
-}
-
-#else
-
-#define AWE_DYNAMIC_BUFFER
-
-#define my_malloc_init(ptr)	/* nothing */
-#define my_malloc_memptr()	0
-#define my_malloc(size)		vmalloc(size)
-#define my_free(ptr)		if (ptr) {vfree(ptr);}
-
-/* do not allocate buffer at beginning */
-#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
-
-/* old type macro */
-#define RET_ERROR(err)		-err
-
-#endif
-
-/*----------------------------------------------------------------
- * i/o interfaces for linux
- *----------------------------------------------------------------*/
-
-#define OUTW(data,addr)		outw(data, addr)
-
-#ifdef AWE_NEW_KERNEL_INTERFACE
-#define COPY_FROM_USER(target,source,offs,count) \
-	copy_from_user(target, (source)+(offs), count)
-#define GET_BYTE_FROM_USER(target,addr,offs) \
-	get_user(target, (unsigned char*)&((addr)[offs]))
-#define GET_SHORT_FROM_USER(target,addr,offs) \
-	get_user(target, (unsigned short*)&((addr)[offs]))
-#ifdef AWE_OSS38
-#define IOCTL_TO_USER(target,offs,source,count) \
-	memcpy(target, (source)+(offs), count)
-#define IO_WRITE_CHECK(cmd)	(_SIOC_DIR(cmd) & _IOC_WRITE)
-#else
-#define IOCTL_TO_USER(target,offs,source,count) \
-	copy_to_user(target, (source)+(offs), count)
-#define IO_WRITE_CHECK(cmd)	(_IOC_DIR(cmd) & _IOC_WRITE)
-#endif /* AWE_OSS38 */
-#define COPY_TO_USER	IOCTL_TO_USER
-#define IOCTL_IN(arg)	(*(int*)(arg))
-#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
-
-#else /* old type i/o */
-#define COPY_FROM_USER(target,source,offs,count) \
-	memcpy_fromfs(target, (source)+(offs), (count))
-#define GET_BYTE_FROM_USER(target,addr,offs) \
-	*((char  *)&(target)) = get_fs_byte((addr)+(offs))
-#define GET_SHORT_FROM_USER(target,addr,offs) \
-	*((short *)&(target)) = get_fs_word((addr)+(offs))
-#ifdef AWE_OSS38
-#define IOCTL_TO_USER(target,offs,source,count) \
-	memcpy(target, (source)+(offs), count)
-#define COPY_TO_USER(target,offs,source,count)  \
-	memcpy_tofs(target, (source)+(offs), (count))
-#define IOCTL_IN(arg)	(*(int*)(arg))
-#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
-#define IO_WRITE_CHECK(cmd)	(_SIOC_DIR(cmd) & _IOC_WRITE)
-#else /* AWE_OSS38 */
-#define IOCTL_TO_USER(target,offs,source,count) \
-	memcpy_tofs(target, (source)+(offs), (count))
-#define COPY_TO_USER	IOCTL_TO_USER
-#define IOCTL_IN(arg)		get_fs_long((long *)(arg))
-#define IOCTL_OUT(arg,ret)	snd_ioctl_return((int *)arg, ret)
-#define IO_WRITE_CHECK(cmd)	(cmd & IOC_IN)
-#endif /* AWE_OSS38 */
-
-#endif /* AWE_NEW_KERNEL_INTERFACE */
-
-#define BZERO(target,len)	memset(target, 0, len)
-#define MEMCPY(dst,src,len)	memcpy(dst, src, len)
-#define MEMCMP(p1,p2,len)	memcmp(p1, p2, len)
-
-/* old style device tables (not modulized) */
-#ifndef AWE_MODULE_SUPPORT
-
-#define sound_alloc_synthdev() \
-	(num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
-#define sound_alloc_mixerdev() \
-	(num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
-#define sound_alloc_mididev() \
-	(num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
-#define sound_unload_synthdev(dev)	/**/
-#define sound_unload_mixerdev(dev)	/**/
-#define sound_unload_mididev(dev)	/**/
-
-#endif /* AWE_MODULE_SUPPORT */
-
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,1,0)
-inline static void interruptible_sleep_on_timeout(wait_queue_head_t *q, unsigned long timeout)
-{
-	current->timeout = jiffies + timeout;
-	interruptible_sleep_on(q);
-}
-#endif
-
-#endif /* CONFIG_AWE32_SYNTH */
-
-#endif /* AWE_COMPAT_H_DEF */
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/awe_config.h linux/drivers/sound/lowlevel/awe_config.h
--- v2.3.50/linux/drivers/sound/lowlevel/awe_config.h	Wed Dec 16 12:52:01 1998
+++ linux/drivers/sound/lowlevel/awe_config.h	Wed Dec 31 16:00:00 1969
@@ -1,102 +0,0 @@
-/*
- * sound/awe_config.h
- *
- * Configuration of AWE32/SB32/AWE64 wave table synth driver.
- *   version 0.4.3; Mar. 1, 1998
- *
- * Copyright (C) 1996-1998 Takashi Iwai
- *
- * 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 AWE_CONFIG_H_DEF
-#define AWE_CONFIG_H_DEF
-
-/*----------------------------------------------------------------
- * system configuration
- *----------------------------------------------------------------*/
-
-/* if your kernel support module for each soundcard, define this.
- * NOTE: it will be automatically set on linux-2.1.x kernels.
- *       only define here if you have moduler sound system on
- *       2.0.x kernel (like RedHat).
- */
-#undef AWE_MODULE_SUPPORT
-
-
-/*----------------------------------------------------------------
- * chorus & reverb effects send for FM chip: from 0 to 0xff
- * larger numbers often cause weird sounds.
- *----------------------------------------------------------------*/
-
-#define DEF_FM_CHORUS_DEPTH	0x10
-#define DEF_FM_REVERB_DEPTH	0x10
-
-
-/*----------------------------------------------------------------*
- * other compile conditions
- *----------------------------------------------------------------*/
-
-/* initialize FM passthrough even without extended RAM */
-#undef AWE_ALWAYS_INIT_FM
-
-/* debug on */
-#define AWE_DEBUG_ON
-
-/* GUS compatible mode */
-#define AWE_HAS_GUS_COMPATIBILITY
-
-/* add MIDI emulation by wavetable */
-#define CONFIG_AWE32_MIDIEMU
-
-/* add mixer control of emu8000 equalizer */
-#undef CONFIG_AWE32_MIXER
-
-/* use new volume calculation method as default */
-#define AWE_USE_NEW_VOLUME_CALC
-
-/* check current volume target for searching empty voices */
-#define AWE_CHECK_VTARGET
-
-/* allow sample sharing */
-#define AWE_ALLOW_SAMPLE_SHARING
-
-/*================================================================
- * Usually, you don't have to touch the following options.
- *================================================================*/
-
-/*----------------------------------------------------------------
- * AWE32 card configuration:
- * uncomment the following lines *ONLY* when auto detection doesn't
- * work properly on your machine.
- *----------------------------------------------------------------*/
-
-/*#define AWE_DEFAULT_BASE_ADDR	0x620*/	/* base port address */
-/*#define AWE_DEFAULT_MEM_SIZE	512*/	/* kbytes */
-
-/*----------------------------------------------------------------
- * maximum size of soundfont list table
- *----------------------------------------------------------------*/
-
-#define AWE_MAX_SF_LISTS 16
-
-/*----------------------------------------------------------------
- * chunk size of sample and voice tables
- *----------------------------------------------------------------*/
-
-#define AWE_MAX_SAMPLES 400
-#define AWE_MAX_INFOS 800
-
-#endif  /* AWE_CONFIG_H_DEF */
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/awe_hw.h linux/drivers/sound/lowlevel/awe_hw.h
--- v2.3.50/linux/drivers/sound/lowlevel/awe_hw.h	Wed Dec 16 12:52:01 1998
+++ linux/drivers/sound/lowlevel/awe_hw.h	Wed Dec 31 16:00:00 1969
@@ -1,99 +0,0 @@
-/*
- * sound/awe_hw.h
- *
- * Access routines and definitions for the low level driver for the 
- * Creative AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.3; Mar. 1, 1998
- *
- * Copyright (C) 1996-1998 Takashi Iwai
- *
- * 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 AWE_HW_H_DEF
-#define AWE_HW_H_DEF
-
-/*
- * Emu-8000 control registers
- * name(channel)	reg, port
- */
-
-#define awe_cmd_idx(reg,ch)	(((reg)<< 5) | (ch))
-
-#define Data0    0		/* 0x620: doubleword r/w */
-#define Data1    1		/* 0xA20: doubleword r/w */
-#define Data2    2		/* 0xA22: word r/w */
-#define Data3    3		/* 0xE20: word r/w */
-#define Pointer  4		/* 0xE22 register pointer r/w */
-
-#define AWE_CPF(ch)	awe_cmd_idx(0,ch), Data0	/* DW: current pitch and fractional address */
-#define AWE_PTRX(ch)	awe_cmd_idx(1,ch), Data0	/* DW: pitch target and reverb send */
-#define AWE_CVCF(ch)	awe_cmd_idx(2,ch), Data0	/* DW: current volume and filter cutoff */
-#define AWE_VTFT(ch)	awe_cmd_idx(3,ch), Data0	/* DW: volume and filter cutoff targets */
-#define AWE_0080(ch)	awe_cmd_idx(4,ch), Data0	/* DW: ?? */
-#define AWE_00A0(ch)	awe_cmd_idx(5,ch), Data0	/* DW: ?? */
-#define AWE_PSST(ch)	awe_cmd_idx(6,ch), Data0	/* DW: pan send and loop start address */
-#define AWE_CSL(ch)	awe_cmd_idx(7,ch), Data0	/* DW: chorus send and loop end address */
-#define AWE_CCCA(ch)	awe_cmd_idx(0,ch), Data1	/* DW: Q, control bits, and current address */
-#define AWE_HWCF4	awe_cmd_idx(1,9),  Data1	/* DW: config dw 4 */
-#define AWE_HWCF5	awe_cmd_idx(1,10), Data1	/* DW: config dw 5 */
-#define AWE_HWCF6	awe_cmd_idx(1,13), Data1	/* DW: config dw 6 */
-#define AWE_HWCF7	awe_cmd_idx(1,14), Data1	/* DW: config dw 7? (not documented) */
-#define AWE_SMALR	awe_cmd_idx(1,20), Data1	/* DW: sound memory address for left read */
-#define AWE_SMARR	awe_cmd_idx(1,21), Data1	/* DW:    for right read */
-#define AWE_SMALW	awe_cmd_idx(1,22), Data1	/* DW: sound memory address for left write */
-#define AWE_SMARW	awe_cmd_idx(1,23), Data1	/* DW:    for right write */
-#define AWE_SMLD	awe_cmd_idx(1,26), Data1	/* W: sound memory left data */
-#define AWE_SMRD	awe_cmd_idx(1,26), Data2	/* W:    right data */
-#define AWE_WC		awe_cmd_idx(1,27), Data2	/* W: sample counter */
-#define AWE_WC_Cmd	awe_cmd_idx(1,27)
-#define AWE_WC_Port	Data2
-#define AWE_HWCF1	awe_cmd_idx(1,29), Data1	/* W: config w 1 */
-#define AWE_HWCF2	awe_cmd_idx(1,30), Data1	/* W: config w 2 */
-#define AWE_HWCF3	awe_cmd_idx(1,31), Data1	/* W: config w 3 */
-#define AWE_INIT1(ch)	awe_cmd_idx(2,ch), Data1	/* W: init array 1 */
-#define AWE_INIT2(ch)	awe_cmd_idx(2,ch), Data2	/* W: init array 2 */
-#define AWE_INIT3(ch)	awe_cmd_idx(3,ch), Data1	/* W: init array 3 */
-#define AWE_INIT4(ch)	awe_cmd_idx(3,ch), Data2	/* W: init array 4 */
-#define AWE_ENVVOL(ch)	awe_cmd_idx(4,ch), Data1	/* W: volume envelope delay */
-#define AWE_DCYSUSV(ch)	awe_cmd_idx(5,ch), Data1	/* W: volume envelope sustain and decay */
-#define AWE_ENVVAL(ch)	awe_cmd_idx(6,ch), Data1	/* W: modulation envelope delay */
-#define AWE_DCYSUS(ch)	awe_cmd_idx(7,ch), Data1	/* W: modulation envelope sustain and decay */
-#define AWE_ATKHLDV(ch)	awe_cmd_idx(4,ch), Data2	/* W: volume envelope attack and hold */
-#define AWE_LFO1VAL(ch)	awe_cmd_idx(5,ch), Data2	/* W: LFO#1 Delay */
-#define AWE_ATKHLD(ch)	awe_cmd_idx(6,ch), Data2	/* W: modulation envelope attack and hold */
-#define AWE_LFO2VAL(ch)	awe_cmd_idx(7,ch), Data2	/* W: LFO#2 Delay */
-#define AWE_IP(ch)	awe_cmd_idx(0,ch), Data3	/* W: initial pitch */
-#define AWE_IFATN(ch)	awe_cmd_idx(1,ch), Data3	/* W: initial filter cutoff and attenuation */
-#define AWE_PEFE(ch)	awe_cmd_idx(2,ch), Data3	/* W: pitch and filter envelope heights */
-#define AWE_FMMOD(ch)	awe_cmd_idx(3,ch), Data3	/* W: vibrato and filter modulation freq */
-#define AWE_TREMFRQ(ch)	awe_cmd_idx(4,ch), Data3	/* W: LFO#1 tremolo amount and freq */
-#define AWE_FM2FRQ2(ch)	awe_cmd_idx(5,ch), Data3	/* W: LFO#2 vibrato amount and freq */
-
-/* used during detection (returns ROM version?; not documented in ADIP) */
-#define AWE_U1		0xE0, Data3	  /* (R)(W) used in initialization */
-#define AWE_U2(ch)	0xC0+(ch), Data3  /* (W)(W) used in init envelope  */
-
-
-#define AWE_MAX_VOICES		32
-#define AWE_NORMAL_VOICES	30	/*30&31 are reserved for DRAM refresh*/
-
-#define AWE_MAX_CHANNELS	32	/* max midi channels (must >= voices) */
-#define AWE_MAX_LAYERS	AWE_MAX_VOICES	/* maximum number of multiple layers */
-
-#define AWE_DRAM_OFFSET		0x200000
-#define AWE_MAX_DRAM_SIZE	(28 * 1024)	/* 28 MB is max onboard memory */
-
-#endif
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/awe_version.h linux/drivers/sound/lowlevel/awe_version.h
--- v2.3.50/linux/drivers/sound/lowlevel/awe_version.h	Wed Dec 16 12:52:01 1998
+++ linux/drivers/sound/lowlevel/awe_version.h	Wed Dec 31 16:00:00 1969
@@ -1,35 +0,0 @@
-/*
- * sound/awe_version.h
- *
- * Version defines for the AWE32/SB32/AWE64 wave table synth driver.
- *   version 0.4.3; Mar. 1, 1998
- *
- * Copyright (C) 1996-1998 Takashi Iwai
- *
- * 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.
- */
-
-/* AWE32 driver version number */
-
-#ifndef AWE_VERSION_H_DEF
-#define AWE_VERSION_H_DEF
-
-#define AWE_MAJOR_VERSION	0
-#define AWE_MINOR_VERSION	4
-#define AWE_TINY_VERSION	3
-#define AWE_VERSION_NUMBER	((AWE_MAJOR_VERSION<<16)|(AWE_MINOR_VERSION<<8)|AWE_TINY_VERSION)
-#define AWEDRV_VERSION		"0.4.3"
-
-#endif
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/awe_wave.c linux/drivers/sound/lowlevel/awe_wave.c
--- v2.3.50/linux/drivers/sound/lowlevel/awe_wave.c	Wed May 26 09:35:00 1999
+++ linux/drivers/sound/lowlevel/awe_wave.c	Wed Dec 31 16:00:00 1969
@@ -1,6255 +0,0 @@
-/*
- * sound/awe_wave.c
- *
- * The low level driver for the AWE32/SB32/AWE64 wave table synth.
- *   version 0.4.3; Feb. 1, 1999
- *
- * Copyright (C) 1996-1999 Takashi Iwai
- *
- * 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.
- */
-
-/* include initial header files and compatibility macros */
-#ifdef __FreeBSD__
-#  include <i386/isa/sound/awe_compat.h>
-#else
-#  include "awe_compat.h"
-#endif /* FreeBSD */
-#ifdef __linux__
-#  include <linux/config.h>
-#endif
-
-/*----------------------------------------------------------------*/
-
-#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
-
-/*----------------------------------------------------------------
- * debug message
- *----------------------------------------------------------------*/
-
-#ifdef AWE_DEBUG_ON
-#define DEBUG(LVL,XXX)	{if (ctrls[AWE_MD_DEBUG_MODE] > LVL) { XXX; }}
-#define ERRMSG(XXX)	{if (ctrls[AWE_MD_DEBUG_MODE]) { XXX; }}
-#define FATALERR(XXX)	XXX
-#else
-#define DEBUG(LVL,XXX) /**/
-#define ERRMSG(XXX)	XXX
-#define FATALERR(XXX)	XXX
-#endif
-
-/*----------------------------------------------------------------
- * bank and voice record
- *----------------------------------------------------------------*/
-
-/* soundfont record */
-typedef struct _sf_list {
-	unsigned short sf_id;
-	unsigned short type;
-	int num_info;		/* current info table index */
-	int num_sample;		/* current sample table index */
-	int mem_ptr;		/* current word byte pointer */
-	int infos;
-	int samples;
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-	int shared;		/* shared index */
-	unsigned char name[AWE_PATCH_NAME_LEN];
-#endif
-} sf_list;
-
-/* bank record */
-typedef struct _awe_voice_list {
-	int next;	/* linked list with same sf_id */
-	unsigned char bank, instr;	/* preset number information */
-	char type, disabled;	/* type=normal/mapped, disabled=boolean */
-	awe_voice_info v;	/* voice information */
-	int next_instr;	/* preset table list */
-	int next_bank;	/* preset table list */
-} awe_voice_list;
-
-/* voice list type */
-#define V_ST_NORMAL	0
-#define V_ST_MAPPED	1
-
-typedef struct _awe_sample_list {
-	int next;	/* linked list with same sf_id */
-	awe_sample_info v;	/* sample information */
-} awe_sample_list;
-
-/* sample and information table */
-static int current_sf_id = 0;
-static int locked_sf_id = 0;
-static int max_sfs;
-static sf_list *sflists = NULL;
-
-#define awe_free_mem_ptr() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].mem_ptr)
-#define awe_free_info() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].num_info)
-#define awe_free_sample() (current_sf_id <= 0 ? 0 : sflists[current_sf_id-1].num_sample)
-
-static int max_samples;
-static awe_sample_list *samples = NULL;
-
-static int max_infos;
-static awe_voice_list *infos = NULL;
-
-
-#define AWE_MAX_PRESETS		256
-#define AWE_DEFAULT_PRESET	0
-#define AWE_DEFAULT_BANK	0
-#define AWE_DEFAULT_DRUM	0
-#define AWE_DRUM_BANK		128
-
-#define MAX_LAYERS	AWE_MAX_VOICES
-
-/* preset table index */
-static int preset_table[AWE_MAX_PRESETS];
-
-/*----------------------------------------------------------------
- * voice table
- *----------------------------------------------------------------*/
-
-/* effects table */
-typedef	struct FX_Rec { /* channel effects */
-	unsigned char flags[AWE_FX_END];
-	short val[AWE_FX_END];
-} FX_Rec;
-
-
-/* channel parameters */
-typedef struct _awe_chan_info {
-	int channel;		/* channel number */
-	int bank;		/* current tone bank */
-	int instr;		/* current program */
-	int bender;		/* midi pitchbend (-8192 - 8192) */
-	int bender_range;	/* midi bender range (x100) */
-	int panning;		/* panning (0-127) */
-	int main_vol;		/* channel volume (0-127) */
-	int expression_vol;	/* midi expression (0-127) */
-	int chan_press;		/* channel pressure */
-	int vrec;		/* instrument list */
-	int def_vrec;		/* default instrument list */
-	int sustained;		/* sustain status in MIDI */
-	FX_Rec fx;		/* effects */
-	FX_Rec fx_layer[MAX_LAYERS]; /* layer effects */
-} awe_chan_info;
-
-/* voice parameters */
-typedef struct _voice_info {
-	int state;
-#define AWE_ST_OFF		(1<<0)	/* no sound */
-#define AWE_ST_ON		(1<<1)	/* playing */
-#define AWE_ST_STANDBY		(1<<2)	/* stand by for playing */
-#define AWE_ST_SUSTAINED	(1<<3)	/* sustained */
-#define AWE_ST_MARK		(1<<4)	/* marked for allocation */
-#define AWE_ST_DRAM		(1<<5)	/* DRAM read/write */
-#define AWE_ST_FM		(1<<6)	/* reserved for FM */
-#define AWE_ST_RELEASED		(1<<7)	/* released */
-
-	int ch;			/* midi channel */
-	int key;		/* internal key for search */
-	int layer;		/* layer number (for channel mode only) */
-	int time;		/* allocated time */
-	awe_chan_info	*cinfo;	/* channel info */
-
-	int note;		/* midi key (0-127) */
-	int velocity;		/* midi velocity (0-127) */
-	int sostenuto;		/* sostenuto on/off */
-	awe_voice_info *sample;	/* assigned voice */
-
-	/* EMU8000 parameters */
-	int apitch;		/* pitch parameter */
-	int avol;		/* volume parameter */
-	int apan;		/* panning parameter */
-	int acutoff;		/* cutoff parameter */
-	short aaux;		/* aux word */
-} voice_info;
-
-/* voice information */
-static voice_info voices[AWE_MAX_VOICES];
-
-#define IS_NO_SOUND(v)	(voices[v].state & (AWE_ST_OFF|AWE_ST_RELEASED|AWE_ST_STANDBY|AWE_ST_SUSTAINED))
-#define IS_NO_EFFECT(v)	(voices[v].state != AWE_ST_ON)
-#define IS_PLAYING(v)	(voices[v].state & (AWE_ST_ON|AWE_ST_SUSTAINED|AWE_ST_RELEASED))
-#define IS_EMPTY(v)	(voices[v].state & (AWE_ST_OFF|AWE_ST_MARK|AWE_ST_DRAM|AWE_ST_FM))
-
-
-/* MIDI channel effects information (for hw control) */
-static awe_chan_info channels[AWE_MAX_CHANNELS];
-
-
-/*----------------------------------------------------------------
- * global variables
- *----------------------------------------------------------------*/
-
-#ifndef AWE_DEFAULT_BASE_ADDR
-#define AWE_DEFAULT_BASE_ADDR	0	/* autodetect */
-#endif
-
-#ifndef AWE_DEFAULT_MEM_SIZE
-#define AWE_DEFAULT_MEM_SIZE	-1	/* autodetect */
-#endif
-
-/* set variables */
-#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
-/* replace awe_port variable with exported variable */
-#define awe_port	io
-#define awe_mem_size	memsize
-int io = AWE_DEFAULT_BASE_ADDR; /* Emu8000 base address */
-int memsize = AWE_DEFAULT_MEM_SIZE; /* memory size in Kbytes */
-#ifdef MODULE_PARM
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "base i/o port of Emu8000");
-MODULE_PARM(memsize, "i");
-MODULE_PARM_DESC(memsize, "onboard DRAM size in Kbytes");
-#endif
-#else
-static int awe_port = AWE_DEFAULT_BASE_ADDR;
-static int awe_mem_size = AWE_DEFAULT_MEM_SIZE;
-#endif /* module */
-
-/* DRAM start offset */
-static int awe_mem_start = AWE_DRAM_OFFSET;
-
-/* maximum channels for playing */
-static int awe_max_voices = AWE_MAX_VOICES;
-
-static int patch_opened = 0;		/* sample already loaded? */
-
-static char atten_relative = FALSE;
-static short atten_offset = 0;
-
-static int awe_present = FALSE;		/* awe device present? */
-static int awe_busy = FALSE;		/* awe device opened? */
-
-static int my_dev = -1;			
-
-#define DEFAULT_DRUM_FLAGS	((1 << 9) | (1 << 25))
-#define IS_DRUM_CHANNEL(c)	(drum_flags & (1 << (c)))
-#define DRUM_CHANNEL_ON(c)	(drum_flags |= (1 << (c)))
-#define DRUM_CHANNEL_OFF(c)	(drum_flags &= ~(1 << (c)))
-static unsigned int drum_flags = DEFAULT_DRUM_FLAGS; /* channel flags */
-
-static int playing_mode = AWE_PLAY_INDIRECT;
-#define SINGLE_LAYER_MODE()	(playing_mode == AWE_PLAY_INDIRECT || playing_mode == AWE_PLAY_DIRECT)
-#define MULTI_LAYER_MODE()	(playing_mode == AWE_PLAY_MULTI || playing_mode == AWE_PLAY_MULTI2)
-
-static int current_alloc_time = 0;	/* voice allocation index for channel mode */
-
-static struct synth_info awe_info = {
-	"AWE32 Synth",		/* name */
-	0,			/* device */
-	SYNTH_TYPE_SAMPLE,	/* synth_type */
-	SAMPLE_TYPE_AWE32,	/* synth_subtype */
-	0,			/* perc_mode (obsolete) */
-	AWE_MAX_VOICES,		/* nr_voices */
-	0,			/* nr_drums (obsolete) */
-	AWE_MAX_INFOS		/* instr_bank_size */
-};
-
-
-static struct voice_alloc_info *voice_alloc;	/* set at initialization */
-
-
-/*----------------------------------------------------------------
- * function prototypes
- *----------------------------------------------------------------*/
-
-#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
-static int awe_check_port(void);
-static void awe_request_region(void);
-static void awe_release_region(void);
-#endif /* linux & obsolete */
-
-static void awe_reset_samples(void);
-/* emu8000 chip i/o access */
-static void setup_ports(int p1, int p2, int p3);
-static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data);
-static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data);
-static unsigned short awe_peek(unsigned short cmd, unsigned short port);
-static unsigned int awe_peek_dw(unsigned short cmd, unsigned short port);
-static void awe_wait(unsigned short delay);
-
-/* initialize emu8000 chip */
-static int _attach_awe(void);
-static void _unload_awe(void);
-static void awe_initialize(void);
-
-/* set voice parameters */
-static void awe_init_ctrl_parms(int init_all);
-static void awe_init_voice_info(awe_voice_info *vp);
-static void awe_init_voice_parm(awe_voice_parm *pp);
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-static int freq_to_note(int freq);
-static int calc_rate_offset(int Hz);
-/*static int calc_parm_delay(int msec);*/
-static int calc_parm_hold(int msec);
-static int calc_parm_attack(int msec);
-static int calc_parm_decay(int msec);
-static int calc_parm_search(int msec, short *table);
-#endif /* gus compat */
-
-/* turn on/off note */
-static void awe_note_on(int voice);
-static void awe_note_off(int voice);
-static void awe_terminate(int voice);
-static void awe_exclusive_off(int voice);
-static void awe_note_off_all(int do_sustain);
-
-/* calculate voice parameters */
-typedef void (*fx_affect_func)(int voice, int forced);
-static void awe_set_pitch(int voice, int forced);
-static void awe_set_voice_pitch(int voice, int forced);
-static void awe_set_volume(int voice, int forced);
-static void awe_set_voice_vol(int voice, int forced);
-static void awe_set_pan(int voice, int forced);
-static void awe_fx_fmmod(int voice, int forced);
-static void awe_fx_tremfrq(int voice, int forced);
-static void awe_fx_fm2frq2(int voice, int forced);
-static void awe_fx_filterQ(int voice, int forced);
-static void awe_calc_pitch(int voice);
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-static void awe_calc_pitch_from_freq(int voice, int freq);
-#endif
-static void awe_calc_volume(int voice);
-static void awe_update_volume(void);
-static void awe_change_master_volume(short val);
-static void awe_voice_init(int voice, int init_all);
-static void awe_channel_init(int ch, int init_all);
-static void awe_fx_init(int ch);
-static void awe_send_effect(int voice, int layer, int type, int val);
-static void awe_modwheel_change(int voice, int value);
-
-/* sequencer interface */
-static int awe_open(int dev, int mode);
-static void awe_close(int dev);
-static int awe_ioctl(int dev, unsigned int cmd, caddr_t arg);
-static int awe_kill_note(int dev, int voice, int note, int velocity);
-static int awe_start_note(int dev, int v, int note_num, int volume);
-static int awe_set_instr(int dev, int voice, int instr_no);
-static int awe_set_instr_2(int dev, int voice, int instr_no);
-static void awe_reset(int dev);
-static void awe_hw_control(int dev, unsigned char *event);
-static int awe_load_patch(int dev, int format, const char *addr,
-			  int offs, int count, int pmgr_flag);
-static void awe_aftertouch(int dev, int voice, int pressure);
-static void awe_controller(int dev, int voice, int ctrl_num, int value);
-static void awe_panning(int dev, int voice, int value);
-static void awe_volume_method(int dev, int mode);
-#ifndef AWE_NO_PATCHMGR
-static int awe_patchmgr(int dev, struct patmgr_info *rec);
-#endif
-static void awe_bender(int dev, int voice, int value);
-static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc);
-static void awe_setup_voice(int dev, int voice, int chn);
-
-#define awe_key_pressure(dev,voice,key,press) awe_start_note(dev,voice,(key)+128,press)
-
-/* hardware controls */
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-static void awe_hw_gus_control(int dev, int cmd, unsigned char *event);
-#endif
-static void awe_hw_awe_control(int dev, int cmd, unsigned char *event);
-static void awe_voice_change(int voice, fx_affect_func func);
-static void awe_sostenuto_on(int voice, int forced);
-static void awe_sustain_off(int voice, int forced);
-static void awe_terminate_and_init(int voice, int forced);
-
-/* voice search */
-static int awe_search_instr(int bank, int preset);
-static int awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist);
-static void awe_alloc_multi_voices(int ch, int note, int velocity, int key);
-static void awe_alloc_one_voice(int voice, int note, int velocity);
-static int awe_clear_voice(void);
-
-/* load / remove patches */
-static int awe_open_patch(awe_patch_info *patch, const char *addr, int count);
-static int awe_close_patch(awe_patch_info *patch, const char *addr, int count);
-static int awe_unload_patch(awe_patch_info *patch, const char *addr, int count);
-static int awe_load_info(awe_patch_info *patch, const char *addr, int count);
-static int awe_load_data(awe_patch_info *patch, const char *addr, int count);
-static int awe_replace_data(awe_patch_info *patch, const char *addr, int count);
-static int awe_load_map(awe_patch_info *patch, const char *addr, int count);
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag);
-#endif
-/*static int awe_probe_info(awe_patch_info *patch, const char *addr, int count);*/
-static int awe_probe_data(awe_patch_info *patch, const char *addr, int count);
-static int check_patch_opened(int type, char *name);
-static int awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels);
-static void add_sf_info(int rec);
-static void add_sf_sample(int rec);
-static void purge_old_list(int rec, int next);
-static void add_info_list(int rec);
-static void awe_remove_samples(int sf_id);
-static void rebuild_preset_list(void);
-static short awe_set_sample(awe_voice_info *vp);
-static int search_sample_index(int sf, int sample, int level);
-
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-static int is_identical_id(int id1, int id2);
-static int is_identical_name(unsigned char *name, int id);
-static int is_shared_sf(unsigned char *name);
-static int info_duplicated(awe_voice_list *rec);
-#endif /* allow sharing */
-
-/* lowlevel functions */
-static void awe_init_audio(void);
-static void awe_init_dma(void);
-static void awe_init_array(void);
-static void awe_send_array(unsigned short *data);
-static void awe_tweak_voice(int voice);
-static void awe_tweak(void);
-static void awe_init_fm(void);
-static int awe_open_dram_for_write(int offset, int channels);
-static void awe_open_dram_for_check(void);
-static void awe_close_dram(void);
-static void awe_write_dram(unsigned short c);
-static int awe_detect_base(int addr);
-static int awe_detect(void);
-static void awe_check_dram(void);
-static int awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count);
-static void awe_set_chorus_mode(int mode);
-static void awe_update_chorus_mode(void);
-static int awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count);
-static void awe_set_reverb_mode(int mode);
-static void awe_update_reverb_mode(void);
-static void awe_equalizer(int bass, int treble);
-static void awe_update_equalizer(void);
-
-#ifdef CONFIG_AWE32_MIXER
-static void attach_mixer(void);
-static void unload_mixer(void);
-#endif
-
-#ifdef CONFIG_AWE32_MIDIEMU
-static void attach_midiemu(void);
-static void unload_midiemu(void);
-#endif
-
-#define limitvalue(x, a, b) if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b)
-
-#ifdef __FreeBSD__
-/* FIXME */
-#define MALLOC_LOOP_DATA
-#define WAIT_BY_LOOP
-#endif
-
-/*----------------------------------------------------------------
- * control parameters
- *----------------------------------------------------------------*/
-
-
-#ifdef AWE_USE_NEW_VOLUME_CALC
-#define DEF_VOLUME_CALC	TRUE
-#else
-#define DEF_VOLUME_CALC	FALSE
-#endif /* new volume */
-
-#define DEF_ZERO_ATTEN		32	/* 12dB below */
-#define DEF_MOD_SENSE		18
-#define DEF_CHORUS_MODE		2
-#define DEF_REVERB_MODE		4
-#define DEF_BASS_LEVEL		5
-#define DEF_TREBLE_LEVEL	9
-
-static struct CtrlParmsDef {
-	int value;
-	int init_each_time;
-	void (*update)(void);
-} ctrl_parms[AWE_MD_END] = {
-	{0,0, NULL}, {0,0, NULL}, /* <-- not used */
-	{AWE_VERSION_NUMBER, FALSE, NULL},
-	{TRUE, FALSE, NULL}, /* exclusive */
-	{TRUE, FALSE, NULL}, /* realpan */
-	{AWE_DEFAULT_BANK, FALSE, NULL}, /* gusbank */
-	{FALSE, TRUE, NULL}, /* keep effect */
-	{DEF_ZERO_ATTEN, FALSE, awe_update_volume}, /* zero_atten */
-	{FALSE, FALSE, NULL}, /* chn_prior */
-	{DEF_MOD_SENSE, FALSE, NULL}, /* modwheel sense */
-	{AWE_DEFAULT_PRESET, FALSE, NULL}, /* def_preset */
-	{AWE_DEFAULT_BANK, FALSE, NULL}, /* def_bank */
-	{AWE_DEFAULT_DRUM, FALSE, NULL}, /* def_drum */
-	{FALSE, FALSE, NULL}, /* toggle_drum_bank */
-	{DEF_VOLUME_CALC, FALSE, awe_update_volume}, /* new_volume_calc */
-	{DEF_CHORUS_MODE, FALSE, awe_update_chorus_mode}, /* chorus mode */
-	{DEF_REVERB_MODE, FALSE, awe_update_reverb_mode}, /* reverb mode */
-	{DEF_BASS_LEVEL, FALSE, awe_update_equalizer}, /* bass level */
-	{DEF_TREBLE_LEVEL, FALSE, awe_update_equalizer}, /* treble level */
-	{0, FALSE, NULL},	/* debug mode */
-	{FALSE, FALSE, NULL}, /* pan exchange */
-};
-
-static int ctrls[AWE_MD_END];
-
-
-/*----------------------------------------------------------------
- * synth operation table
- *----------------------------------------------------------------*/
-
-static struct synth_operations awe_operations =
-{
-#ifdef AWE_OSS38
-	"EMU8K",
-#endif
-	&awe_info,
-	0,
-	SYNTH_TYPE_SAMPLE,
-	SAMPLE_TYPE_AWE32,
-	awe_open,
-	awe_close,
-	awe_ioctl,
-	awe_kill_note,
-	awe_start_note,
-	awe_set_instr_2,
-	awe_reset,
-	awe_hw_control,
-	awe_load_patch,
-	awe_aftertouch,
-	awe_controller,
-	awe_panning,
-	awe_volume_method,
-#ifndef AWE_NO_PATCHMGR
-	awe_patchmgr,
-#endif
-	awe_bender,
-	awe_alloc,
-	awe_setup_voice
-};
-
-
-/*================================================================
- * General attach / unload interface
- *================================================================*/
-
-static int _attach_awe(void)
-{
-	if (awe_present) return 0; /* for OSS38.. called twice? */
-
-	/* check presence of AWE32 card */
-	if (! awe_detect()) {
-		printk(KERN_WARNING "AWE32: not detected\n");
-		return 0;
-	}
-
-	/* check AWE32 ports are available */
-#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
-	if (awe_check_port()) {
-		printk(KERN_WARNING "AWE32: I/O area already used.\n");
-		return 0;
-	}
-#endif
-
-	/* set buffers to NULL */
-	sflists = NULL;
-	samples = NULL;
-	infos = NULL;
-
-	/* allocate sample tables */
-	INIT_TABLE(sflists, max_sfs, AWE_MAX_SF_LISTS, sf_list);
-	INIT_TABLE(samples, max_samples, AWE_MAX_SAMPLES, awe_sample_list);
-	INIT_TABLE(infos, max_infos, AWE_MAX_INFOS, awe_voice_list);
-
-	my_dev = sound_alloc_synthdev();
-	if (my_dev == -1) {
-		printk(KERN_WARNING "AWE32 Error: too many synthesizers\n");
-		return 0;
-	}
-
-	voice_alloc = &awe_operations.alloc;
-	voice_alloc->max_voice = awe_max_voices;
-	synth_devs[my_dev] = &awe_operations;
-
-#ifdef CONFIG_AWE32_MIXER
-	attach_mixer();
-#endif
-#ifdef CONFIG_AWE32_MIDIEMU
-	attach_midiemu();
-#endif
-
-#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
-	/* reserve I/O ports for awedrv */
-	awe_request_region();
-#endif
-
-	/* clear all samples */
-	awe_reset_samples();
-
-	/* intialize AWE32 hardware */
-	awe_initialize();
-
-	sprintf(awe_info.name, "AWE32-%s (RAM%dk)",
-		AWEDRV_VERSION, awe_mem_size/1024);
-	printk("<SoundBlaster EMU8000 (RAM%dk)>\n", awe_mem_size/1024);
-
-	awe_present = TRUE;
-
-#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
-	SOUND_LOCK;
-#endif
-
-	return 1;
-}
-
-
-#ifdef AWE_DYNAMIC_BUFFER
-static void free_tables(void)
-{
-	if (sflists)
-		my_free(sflists);
-	sflists = NULL; max_sfs = 0;
-	if (samples)
-		my_free(samples);
-	samples = NULL; max_samples = 0;
-	if (infos)
-		my_free(infos);
-	infos = NULL; max_infos = 0;
-}
-
-static void *realloc_block(void *buf, int oldsize, int size)
-{
-	void *ptr;
-	if (oldsize == size)
-		return buf;
-	if ((ptr = my_malloc(size)) == NULL)
-		return NULL;
-	if (oldsize && size)
-		MEMCPY(ptr, buf, ((oldsize < size) ? oldsize : size) );
-	if (buf)
-		my_free(buf);
-	return ptr;
-}
-
-
-#else /* dynamic buffer */
-
-#define free_buffers() /**/
-
-#endif /* dynamic_buffer */
-
-
-static void _unload_awe(void)
-{
-	if (awe_present) {
-		awe_reset_samples();
-		awe_release_region();
-		free_tables();
-#ifdef CONFIG_AWE32_MIXER
-		unload_mixer();
-#endif
-#ifdef CONFIG_AWE32_MIDIEMU
-		unload_midiemu();
-#endif
-		sound_unload_synthdev(my_dev);
-		awe_present = FALSE;
-#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
-		SOUND_LOCK_END;
-#endif
-	}
-}
-
-
-/*================================================================
- * Linux interface
- *================================================================*/
-
-#ifdef linux
-
-/*----------------------------------------------------------------
- * Linux PnP driver support
- *----------------------------------------------------------------*/
-
-#ifdef CONFIG_PNP_DRV
-
-#include <linux/pnp.h>
-
-static int pnp = 1;	/* use PnP as default */
-
-#define AWE_NUM_CHIPS	3
-static unsigned int pnp_ids[AWE_NUM_CHIPS] = {
-	PNP_EISAID('C','T','L',0x0021),
-	PNP_EISAID('C','T','L',0x0022),
-	PNP_EISAID('C','T','L',0x0023),
-};
-static struct pnp_driver pnp_awe[AWE_NUM_CHIPS];
-static int awe_pnp_ok = 0;
-
-static void awe_pnp_config(struct pnp_device *d)
-{
-	struct pnp_resource *r;
-	int port[3];
-	int nio = 0;
-
-	port[0] = port[1] = port[2] = 0;
-	for (r = d->res; r != NULL; r = r->next) {
-		if (r->type == PNP_RES_IO) {
-			if (nio >= 0 && nio < 3)
-				port[nio] = r->start;
-			nio++;
-		}
-	}
-	setup_ports(port[0], port[1], port[2]);
-	DEBUG(0,printk("AWE32: PnP setup ports: %x:%x:%x\n", port[0], port[1], port[2]));
-}
-
-static int awe_pnp_event (struct pnp_device *d, struct pnp_drv_event *e)
-{
-	struct pnp_driver *drv = d->l.k.driver;
-
-	switch (e->type) {
-	case PNP_DRV_ALLOC:
-		drv->flags |= PNP_DRV_INUSE;
-		awe_pnp_ok = 1;
-		awe_pnp_config(d);
-		_attach_awe();
-		break;
-
-	case PNP_DRV_DISABLE:
-	case PNP_DRV_EMERGSTOP:
-		drv->flags &= ~PNP_DRV_INUSE;
-		awe_pnp_ok = 0;
-		_unload_awe();
-		break;
-
-	case PNP_DRV_CONFIG:
-		if (awe_busy) return 1; /* used now */
-		awe_release_region();
-		awe_pnp_config(d);
-		awe_request_region();
-		break;
-		
-	case PNP_DRV_RECONFIG:
-		break;
-	}
-	return 0;
-}
-
-static int awe_initpnp (void)
-{
-	int i;
-	for (i = 0; i < AWE_NUM_CHIPS; i++) {
-		pnp_awe[i].id.type = PNP_HDL_ISA;
-		pnp_awe[i].id.t.isa.id = pnp_ids[i];
-		pnp_awe[i].id.next = NULL;
-		pnp_awe[i].name = "Soundblaster AWE32/AWE64 PnP";
-		pnp_awe[i].event = awe_pnp_event;
-		pnp_register_driver(&pnp_awe[i], 1);
-	}
-	return 0;
-}
-
-static void awe_unload_pnp (void)
-{
-	int i;
-	for (i = 0; i < AWE_NUM_CHIPS; i++)
-		pnp_unregister_driver(&pnp_awe[i]);
-}
-#endif /* PnP support */
-
-/*----------------------------------------------------------------
- * device / lowlevel (module) interface
- *----------------------------------------------------------------*/
-
-#ifdef AWE_OBSOLETEL_VOXWARE
-
-/* old type interface */
-int attach_awe_obsolete(int mem_start, struct address_info *hw_config)
-{
-	my_malloc_init(mem_start);
-	if (! _attach_awe())
-		return 0;
-	return my_malloc_memptr();
-}
-
-int probe_awe_obsolete(struct address_info *hw_config)
-{
-	return 1;
-	/*return awe_detect();*/
-}
-
-#else /* !obsolete */
-
-/* new type interface */
-int attach_awe(void)
-{
-#ifdef CONFIG_PNP_DRV
-	if (pnp) {
-		awe_initpnp();
-		if (awe_pnp_ok)
-			return 0;
-	}
-#endif /* pnp */
-	_attach_awe();
-	return 0;
-}
-
-void unload_awe(void)
-{
-#ifdef CONFIG_PNP_DRV
-	if (pnp)
-		awe_unload_pnp();
-#endif /* pnp */
-	_unload_awe();
-}
-
-/* module interface */
-
-#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
-int init_module(void)
-{
-	return attach_awe();
-}
-
-void cleanup_module(void)
-{
-	unload_awe();
-}
-
-#ifdef MODULE_PARM
-EXPORT_NO_SYMBOLS;
-MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>");
-MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver");
-MODULE_SUPPORTED_DEVICE("sound");
-#endif
-
-#endif /* module */
-
-#endif /* AWE_OBSOLETE_VOXWARE */
-
-#endif /* linux */
-
-
-/*================================================================
- * FreeBSD interface
- *================================================================*/
-
-#ifdef __FreeBSD__
-
-#ifdef AWE_OBSOLETE_VOXWARE
-long attach_awe_obsolete(long mem_start, struct address_info *hw_config)
-{
-	_attach_awe();
-	return 0;
-}
-
-int probe_awe_obsolete(struct address_info *hw_config)
-{
-	return 1;
-}
-
-#else /* !obsolete */
-
-/* new type interface */
-void attach_awe(struct address_info *hw_config)
-{
-	_attach_awe();
-}
-
-int probe_awe(struct address_info *hw_config)
-{
-	return 1;
-}
-
-#endif /* obsolete */
-
-#endif /* FreeBSD */
-
-
-/*================================================================
- * clear sample tables 
- *================================================================*/
-
-static void
-awe_reset_samples(void)
-{
-	int i;
-
-	/* free all bank tables */
-	for (i = 0; i < AWE_MAX_PRESETS; i++)
-		preset_table[i] = -1;
-
-	free_tables();
-
-	current_sf_id = 0;
-	locked_sf_id = 0;
-	patch_opened = 0;
-}
-
-
-/*================================================================
- * EMU register access
- *================================================================*/
-
-/* select a given AWE32 pointer */
-static int awe_ports[5];
-static int port_setuped = FALSE;
-static int awe_cur_cmd = -1;
-#define awe_set_cmd(cmd) \
-if (awe_cur_cmd != cmd) { OUTW(cmd, awe_ports[Pointer]); awe_cur_cmd = cmd; }
-
-/* store values to i/o port array */
-static void setup_ports(int port1, int port2, int port3)
-{
-	awe_ports[0] = port1;
-	if (port2 == 0)
-		port2 = port1 + 0x400;
-	awe_ports[1] = port2;
-	awe_ports[2] = port2 + 2;
-	if (port3 == 0)
-		port3 = port1 + 0x800;
-	awe_ports[3] = port3;
-	awe_ports[4] = port3 + 2;
-
-	port_setuped = TRUE;
-}
-
-/* write 16bit data */
-INLINE static void
-awe_poke(unsigned short cmd, unsigned short port, unsigned short data)
-{
-	awe_set_cmd(cmd);
-	OUTW(data, awe_ports[port]);
-}
-
-/* write 32bit data */
-INLINE static void
-awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data)
-{
-	unsigned short addr = awe_ports[port];
-	awe_set_cmd(cmd);
-	OUTW(data, addr);		/* write lower 16 bits */
-	OUTW(data >> 16, addr + 2);	/* write higher 16 bits */
-}
-
-/* read 16bit data */
-INLINE static unsigned short
-awe_peek(unsigned short cmd, unsigned short port)
-{
-	unsigned short k;
-	awe_set_cmd(cmd);
-	k = inw(awe_ports[port]);
-	return k;
-}
-
-/* read 32bit data */
-INLINE static unsigned int
-awe_peek_dw(unsigned short cmd, unsigned short port)
-{
-	unsigned int k1, k2;
-	unsigned short addr = awe_ports[port];
-	awe_set_cmd(cmd);
-	k1 = inw(addr);
-	k2 = inw(addr + 2);
-	k1 |= k2 << 16;
-	return k1;
-}
-
-/* wait delay number of AWE32 44100Hz clocks */
-#ifdef WAIT_BY_LOOP /* wait by loop -- that's not good.. */
-static void
-awe_wait(unsigned short delay)
-{
-	unsigned short clock, target;
-	unsigned short port = awe_ports[AWE_WC_Port];
-	int counter;
-  
-	/* sample counter */
-	awe_set_cmd(AWE_WC_Cmd);
-	clock = (unsigned short)inw(port);
-	target = clock + delay;
-	counter = 0;
-	if (target < clock) {
-		for (; (unsigned short)inw(port) > target; counter++)
-			if (counter > 65536)
-				break;
-	}
-	for (; (unsigned short)inw(port) < target; counter++)
-		if (counter > 65536)
-			break;
-}
-#else
-
-static void awe_wait(unsigned short delay)
-{
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout((HZ*(unsigned long)delay + 44099)/44100);
-}
-#endif /* wait by loop */
-
-/* write a word data */
-INLINE static void
-awe_write_dram(unsigned short c)
-{
-	awe_poke(AWE_SMLD, c);
-}
-
-
-#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
-
-/*================================================================
- * port check / request
- *  0x620-623, 0xA20-A23, 0xE20-E23
- *================================================================*/
-
-static int
-awe_check_port(void)
-{
-	if (! port_setuped) return 0;
-	return (check_region(awe_ports[0], 4) ||
-		check_region(awe_ports[1], 4) ||
-		check_region(awe_ports[3], 4));
-}
-
-static void
-awe_request_region(void)
-{
-	if (! port_setuped) return;
-	request_region(awe_ports[0], 4, "sound driver (AWE32)");
-	request_region(awe_ports[1], 4, "sound driver (AWE32)");
-	request_region(awe_ports[3], 4, "sound driver (AWE32)");
-}
-
-static void
-awe_release_region(void)
-{
-	if (! port_setuped) return;
-	release_region(awe_ports[0], 4);
-	release_region(awe_ports[1], 4);
-	release_region(awe_ports[3], 4);
-}
-
-#endif /* linux && !AWE_OBSOLETE_VOXWARE */
-
-
-/*================================================================
- * AWE32 initialization
- *================================================================*/
-static void
-awe_initialize(void)
-{
-	DEBUG(0,printk("AWE32: initializing..\n"));
-
-	/* initialize hardware configuration */
-	awe_poke(AWE_HWCF1, 0x0059);
-	awe_poke(AWE_HWCF2, 0x0020);
-
-	/* disable audio; this seems to reduce a clicking noise a bit.. */
-	awe_poke(AWE_HWCF3, 0);
-
-	/* initialize audio channels */
-	awe_init_audio();
-
-	/* initialize DMA */
-	awe_init_dma();
-
-	/* initialize init array */
-	awe_init_array();
-
-	/* check DRAM memory size */
-	awe_check_dram();
-
-	/* initialize the FM section of the AWE32 */
-	awe_init_fm();
-
-	/* set up voice envelopes */
-	awe_tweak();
-
-	/* enable audio */
-	awe_poke(AWE_HWCF3, 0x0004);
-
-	/* set default values */
-	awe_init_ctrl_parms(TRUE);
-
-	/* set equalizer */
-	awe_update_equalizer();
-
-	/* set reverb & chorus modes */
-	awe_update_reverb_mode();
-	awe_update_chorus_mode();
-}
-
-
-/*================================================================
- * AWE32 voice parameters
- *================================================================*/
-
-/* initialize voice_info record */
-static void
-awe_init_voice_info(awe_voice_info *vp)
-{
-	vp->sf_id = 0; /* normal mode */
-	vp->sample = 0;
-	vp->rate_offset = 0;
-
-	vp->start = 0;
-	vp->end = 0;
-	vp->loopstart = 0;
-	vp->loopend = 0;
-	vp->mode = 0;
-	vp->root = 60;
-	vp->tune = 0;
-	vp->low = 0;
-	vp->high = 127;
-	vp->vellow = 0;
-	vp->velhigh = 127;
-
-	vp->fixkey = -1;
-	vp->fixvel = -1;
-	vp->fixpan = -1;
-	vp->pan = -1;
-
-	vp->exclusiveClass = 0;
-	vp->amplitude = 127;
-	vp->attenuation = 0;
-	vp->scaleTuning = 100;
-
-	awe_init_voice_parm(&vp->parm);
-}
-
-/* initialize voice_parm record:
- * Env1/2: delay=0, attack=0, hold=0, sustain=0, decay=0, release=0.
- * Vibrato and Tremolo effects are zero.
- * Cutoff is maximum.
- * Chorus and Reverb effects are zero.
- */
-static void
-awe_init_voice_parm(awe_voice_parm *pp)
-{
-	pp->moddelay = 0x8000;
-	pp->modatkhld = 0x7f7f;
-	pp->moddcysus = 0x7f7f;
-	pp->modrelease = 0x807f;
-	pp->modkeyhold = 0;
-	pp->modkeydecay = 0;
-
-	pp->voldelay = 0x8000;
-	pp->volatkhld = 0x7f7f;
-	pp->voldcysus = 0x7f7f;
-	pp->volrelease = 0x807f;
-	pp->volkeyhold = 0;
-	pp->volkeydecay = 0;
-
-	pp->lfo1delay = 0x8000;
-	pp->lfo2delay = 0x8000;
-	pp->pefe = 0;
-
-	pp->fmmod = 0;
-	pp->tremfrq = 0;
-	pp->fm2frq2 = 0;
-
-	pp->cutoff = 0xff;
-	pp->filterQ = 0;
-
-	pp->chorus = 0;
-	pp->reverb = 0;
-}	
-
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-
-/* convert frequency mHz to abstract cents (= midi key * 100) */
-static int
-freq_to_note(int mHz)
-{
-	/* abscents = log(mHz/8176) / log(2) * 1200 */
-	unsigned int max_val = (unsigned int)0xffffffff / 10000;
-	int i, times;
-	unsigned int base;
-	unsigned int freq;
-	int note, tune;
-
-	if (mHz == 0)
-		return 0;
-	if (mHz < 0)
-		return 12799; /* maximum */
-
-	freq = mHz;
-	note = 0;
-	for (base = 8176 * 2; freq >= base; base *= 2) {
-		note += 12;
-		if (note >= 128) /* over maximum */
-			return 12799;
-	}
-	base /= 2;
-
-	/* to avoid overflow... */
-	times = 10000;
-	while (freq > max_val) {
-		max_val *= 10;
-		times /= 10;
-		base /= 10;
-	}
-
-	freq = freq * times / base;
-	for (i = 0; i < 12; i++) {
-		if (freq < semitone_tuning[i+1])
-			break;
-		note++;
-	}
-
-	tune = 0;
-	freq = freq * 10000 / semitone_tuning[i];
-	for (i = 0; i < 100; i++) {
-		if (freq < cent_tuning[i+1])
-			break;
-		tune++;
-	}
-
-	return note * 100 + tune;
-}
-
-
-/* convert Hz to AWE32 rate offset:
- * sample pitch offset for the specified sample rate
- * rate=44100 is no offset, each 4096 is 1 octave (twice).
- * eg, when rate is 22050, this offset becomes -4096.
- */
-static int
-calc_rate_offset(int Hz)
-{
-	/* offset = log(Hz / 44100) / log(2) * 4096 */
-	int freq, base, i;
-
-	/* maybe smaller than max (44100Hz) */
-	if (Hz <= 0 || Hz >= 44100) return 0;
-
-	base = 0;
-	for (freq = Hz * 2; freq < 44100; freq *= 2)
-		base++;
-	base *= 1200;
-
-	freq = 44100 * 10000 / (freq/2);
-	for (i = 0; i < 12; i++) {
-		if (freq < semitone_tuning[i+1])
-			break;
-		base += 100;
-	}
-	freq = freq * 10000 / semitone_tuning[i];
-	for (i = 0; i < 100; i++) {
-		if (freq < cent_tuning[i+1])
-			break;
-		base++;
-	}
-	return -base * 4096 / 1200;
-}
-
-
-/*----------------------------------------------------------------
- * convert envelope time parameter to AWE32 raw parameter
- *----------------------------------------------------------------*/
-
-/* attack & decay/release time table (msec) */
-static short attack_time_tbl[128] = {
-32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
-707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
-361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
-180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
-90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
-45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
-22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
-11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
-};
-
-static short decay_time_tbl[128] = {
-32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
-2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
-1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
-691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
-345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
-172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
-86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
-43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
-};
-
-#define calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725);
-
-/* delay time = 0x8000 - msec/92 */
-static int
-calc_parm_hold(int msec)
-{
-	int val = (0x7f * 92 - msec) / 92;
-	if (val < 1) val = 1;
-	if (val > 127) val = 127;
-	return val;
-}
-
-/* attack time: search from time table */
-static int
-calc_parm_attack(int msec)
-{
-	return calc_parm_search(msec, attack_time_tbl);
-}
-
-/* decay/release time: search from time table */
-static int
-calc_parm_decay(int msec)
-{
-	return calc_parm_search(msec, decay_time_tbl);
-}
-
-/* search an index for specified time from given time table */
-static int
-calc_parm_search(int msec, short *table)
-{
-	int left = 1, right = 127, mid;
-	while (left < right) {
-		mid = (left + right) / 2;
-		if (msec < (int)table[mid])
-			left = mid + 1;
-		else
-			right = mid;
-	}
-	return left;
-}
-#endif /* AWE_HAS_GUS_COMPATIBILITY */
-
-
-/*================================================================
- * effects table
- *================================================================*/
-
-/* set an effect value */
-#define FX_FLAG_OFF	0
-#define FX_FLAG_SET	1
-#define FX_FLAG_ADD	2
-
-#define FX_SET(rec,type,value) \
-	((rec)->flags[type] = FX_FLAG_SET, (rec)->val[type] = (value))
-#define FX_ADD(rec,type,value) \
-	((rec)->flags[type] = FX_FLAG_ADD, (rec)->val[type] = (value))
-#define FX_UNSET(rec,type) \
-	((rec)->flags[type] = FX_FLAG_OFF, (rec)->val[type] = 0)
-
-/* check the effect value is set */
-#define FX_ON(rec,type)	((rec)->flags[type])
-
-#define PARM_BYTE	0
-#define PARM_WORD	1
-#define PARM_SIGN	2
-
-static struct PARM_DEFS {
-	int type;	/* byte or word */
-	int low, high;	/* value range */
-	fx_affect_func realtime;	/* realtime paramater change */
-} parm_defs[] = {
-	{PARM_WORD, 0, 0x8000, NULL},	/* env1 delay */
-	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 attack */
-	{PARM_BYTE, 0, 0x7e, NULL},	/* env1 hold */
-	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 decay */
-	{PARM_BYTE, 1, 0x7f, NULL},	/* env1 release */
-	{PARM_BYTE, 0, 0x7f, NULL},	/* env1 sustain */
-	{PARM_BYTE, 0, 0xff, NULL},	/* env1 pitch */
-	{PARM_BYTE, 0, 0xff, NULL},	/* env1 cutoff */
-
-	{PARM_WORD, 0, 0x8000, NULL},	/* env2 delay */
-	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 attack */
-	{PARM_BYTE, 0, 0x7e, NULL},	/* env2 hold */
-	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 decay */
-	{PARM_BYTE, 1, 0x7f, NULL},	/* env2 release */
-	{PARM_BYTE, 0, 0x7f, NULL},	/* env2 sustain */
-
-	{PARM_WORD, 0, 0x8000, NULL},	/* lfo1 delay */
-	{PARM_BYTE, 0, 0xff, awe_fx_tremfrq},	/* lfo1 freq */
-	{PARM_SIGN, -128, 127, awe_fx_tremfrq},	/* lfo1 volume */
-	{PARM_SIGN, -128, 127, awe_fx_fmmod},	/* lfo1 pitch */
-	{PARM_BYTE, 0, 0xff, awe_fx_fmmod},	/* lfo1 cutoff */
-
-	{PARM_WORD, 0, 0x8000, NULL},	/* lfo2 delay */
-	{PARM_BYTE, 0, 0xff, awe_fx_fm2frq2},	/* lfo2 freq */
-	{PARM_SIGN, -128, 127, awe_fx_fm2frq2},	/* lfo2 pitch */
-
-	{PARM_WORD, 0, 0xffff, awe_set_voice_pitch},	/* initial pitch */
-	{PARM_BYTE, 0, 0xff, NULL},	/* chorus */
-	{PARM_BYTE, 0, 0xff, NULL},	/* reverb */
-	{PARM_BYTE, 0, 0xff, awe_set_volume},	/* initial cutoff */
-	{PARM_BYTE, 0, 15, awe_fx_filterQ},	/* initial resonance */
-
-	{PARM_WORD, 0, 0xffff, NULL},	/* sample start */
-	{PARM_WORD, 0, 0xffff, NULL},	/* loop start */
-	{PARM_WORD, 0, 0xffff, NULL},	/* loop end */
-	{PARM_WORD, 0, 0xffff, NULL},	/* coarse sample start */
-	{PARM_WORD, 0, 0xffff, NULL},	/* coarse loop start */
-	{PARM_WORD, 0, 0xffff, NULL},	/* coarse loop end */
-	{PARM_BYTE, 0, 0xff, awe_set_volume},	/* initial attenuation */
-};
-
-
-static unsigned char
-FX_BYTE(FX_Rec *rec, FX_Rec *lay, int type, unsigned char value)
-{
-	int effect = 0;
-	int on = 0;
-	if (lay && (on = FX_ON(lay, type)) != 0)
-		effect = lay->val[type];
-	if (!on && (on = FX_ON(rec, type)) != 0)
-		effect = rec->val[type];
-	if (on == FX_FLAG_ADD) {
-		if (parm_defs[type].type == PARM_SIGN) {
-			if (value > 0x7f)
-				effect += (int)value - 0x100;
-			else
-				effect += (int)value;
-		} else {
-			effect += (int)value;
-		}
-	}
-	if (on) {
-		if (effect < parm_defs[type].low)
-			effect = parm_defs[type].low;
-		else if (effect > parm_defs[type].high)
-			effect = parm_defs[type].high;
-		return (unsigned char)effect;
-	}
-	return value;
-}
-
-/* get word effect value */
-static unsigned short
-FX_WORD(FX_Rec *rec, FX_Rec *lay, int type, unsigned short value)
-{
-	int effect = 0;
-	int on = 0;
-	if (lay && (on = FX_ON(lay, type)) != 0)
-		effect = lay->val[type];
-	if (!on && (on = FX_ON(rec, type)) != 0)
-		effect = rec->val[type];
-	if (on == FX_FLAG_ADD)
-		effect += (int)value;
-	if (on) {
-		if (effect < parm_defs[type].low)
-			effect = parm_defs[type].low;
-		else if (effect > parm_defs[type].high)
-			effect = parm_defs[type].high;
-		return (unsigned short)effect;
-	}
-	return value;
-}
-
-/* get word (upper=type1/lower=type2) effect value */
-static unsigned short
-FX_COMB(FX_Rec *rec, FX_Rec *lay, int type1, int type2, unsigned short value)
-{
-	unsigned short tmp;
-	tmp = FX_BYTE(rec, lay, type1, (unsigned char)(value >> 8));
-	tmp <<= 8;
-	tmp |= FX_BYTE(rec, lay, type2, (unsigned char)(value & 0xff));
-	return tmp;
-}
-
-/* address offset */
-static int
-FX_OFFSET(FX_Rec *rec, FX_Rec *lay, int lo, int hi, int mode)
-{
-	int addr = 0;
-	if (lay && FX_ON(lay, hi))
-		addr = (short)lay->val[hi];
-	else if (FX_ON(rec, hi))
-		addr = (short)rec->val[hi];
-	addr = addr << 15;
-	if (lay && FX_ON(lay, lo))
-		addr += (short)lay->val[lo];
-	else if (FX_ON(rec, lo))
-		addr += (short)rec->val[lo];
-	if (!(mode & AWE_SAMPLE_8BITS))
-		addr /= 2;
-	return addr;
-}
-
-
-/*================================================================
- * turn on/off sample
- *================================================================*/
-
-/* table for volume target calculation */
-static unsigned short voltarget[16] = { 
-   0xEAC0, 0XE0C8, 0XD740, 0XCE20, 0XC560, 0XBD08, 0XB500, 0XAD58,
-   0XA5F8, 0X9EF0, 0X9830, 0X91C0, 0X8B90, 0X85A8, 0X8000, 0X7A90
-};
-
-static void
-awe_note_on(int voice)
-{
-	unsigned int temp;
-	int addr;
-	int vtarget, ftarget, ptarget, pitch;
-	awe_voice_info *vp;
-	awe_voice_parm_block *parm;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	/* A voice sample must assigned before calling */
-	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
-		return;
-
-	parm = (awe_voice_parm_block*)&vp->parm;
-
-	/* channel to be silent and idle */
-	awe_poke(AWE_DCYSUSV(voice), 0x0080);
-	awe_poke(AWE_VTFT(voice), 0x0000FFFF);
-	awe_poke(AWE_CVCF(voice), 0x0000FFFF);
-	awe_poke(AWE_PTRX(voice), 0);
-	awe_poke(AWE_CPF(voice), 0);
-
-	/* set pitch offset */
-	awe_set_pitch(voice, TRUE);
-
-	/* modulation & volume envelope */
-	if (parm->modatk >= 0x80 && parm->moddelay >= 0x8000) {
-		awe_poke(AWE_ENVVAL(voice), 0xBFFF);
-		pitch = (parm->env1pit<<4) + voices[voice].apitch;
-		if (pitch > 0xffff) pitch = 0xffff;
-		/* calculate filter target */
-		ftarget = parm->cutoff + parm->env1fc;
-		limitvalue(ftarget, 0, 255);
-		ftarget <<= 8;
-	} else {
-		awe_poke(AWE_ENVVAL(voice),
-			 FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, parm->moddelay));
-		ftarget = parm->cutoff;
-		ftarget <<= 8;
-		pitch = voices[voice].apitch;
-	}
-
-	/* calcualte pitch target */
-	if (pitch != 0xffff) {
-		ptarget = 1 << (pitch >> 12);
-		if (pitch & 0x800) ptarget += (ptarget*0x102e)/0x2710;
-		if (pitch & 0x400) ptarget += (ptarget*0x764)/0x2710;
-		if (pitch & 0x200) ptarget += (ptarget*0x389)/0x2710;
-		ptarget += (ptarget>>1);
-		if (ptarget > 0xffff) ptarget = 0xffff;
-
-	} else ptarget = 0xffff;
-	if (parm->modatk >= 0x80)
-		awe_poke(AWE_ATKHLD(voice),
-			 FX_BYTE(fx, fx_lay, AWE_FX_ENV1_HOLD, parm->modhld) << 8 | 0x7f);
-	else
-		awe_poke(AWE_ATKHLD(voice),
-			 FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK,
-				 vp->parm.modatkhld));
-	awe_poke(AWE_DCYSUS(voice),
-		 FX_COMB(fx, fx_lay, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,
-			  vp->parm.moddcysus));
-
-	if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {
-		awe_poke(AWE_ENVVOL(voice), 0xBFFF);
-		vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);
-	} else {
-		awe_poke(AWE_ENVVOL(voice),
-			 FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
-		vtarget = 0;
-	}
-	if (parm->volatk >= 0x80)
-		awe_poke(AWE_ATKHLDV(voice),
-			 FX_BYTE(fx, fx_lay, AWE_FX_ENV2_HOLD, parm->volhld) << 8 | 0x7f);
-	else
-		awe_poke(AWE_ATKHLDV(voice),
-			 FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK,
-			 vp->parm.volatkhld));
-	/* decay/sustain parameter for volume envelope must be set at last */
-
-	/* cutoff and volume */
-	awe_set_volume(voice, TRUE);
-
-	/* modulation envelope heights */
-	awe_poke(AWE_PEFE(voice),
-		 FX_COMB(fx, fx_lay, AWE_FX_ENV1_PITCH, AWE_FX_ENV1_CUTOFF,
-			 vp->parm.pefe));
-
-	/* lfo1/2 delay */
-	awe_poke(AWE_LFO1VAL(voice),
-		 FX_WORD(fx, fx_lay, AWE_FX_LFO1_DELAY, vp->parm.lfo1delay));
-	awe_poke(AWE_LFO2VAL(voice),
-		 FX_WORD(fx, fx_lay, AWE_FX_LFO2_DELAY, vp->parm.lfo2delay));
-
-	/* lfo1 pitch & cutoff shift */
-	awe_fx_fmmod(voice, TRUE);
-	/* lfo1 volume & freq */
-	awe_fx_tremfrq(voice, TRUE);
-	/* lfo2 pitch & freq */
-	awe_fx_fm2frq2(voice, TRUE);
-	/* pan & loop start */
-	awe_set_pan(voice, TRUE);
-
-	/* chorus & loop end (chorus 8bit, MSB) */
-	addr = vp->loopend - 1;
-	addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_END,
-			  AWE_FX_COARSE_LOOP_END, vp->mode);
-	temp = FX_BYTE(fx, fx_lay, AWE_FX_CHORUS, vp->parm.chorus);
-	temp = (temp <<24) | (unsigned int)addr;
-	awe_poke_dw(AWE_CSL(voice), temp);
-	DEBUG(4,printk("AWE32: [-- loopend=%x/%x]\n", vp->loopend, addr));
-
-	/* Q & current address (Q 4bit value, MSB) */
-	addr = vp->start - 1;
-	addr += FX_OFFSET(fx, fx_lay, AWE_FX_SAMPLE_START,
-			  AWE_FX_COARSE_SAMPLE_START, vp->mode);
-	temp = FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ);
-	temp = (temp<<28) | (unsigned int)addr;
-	awe_poke_dw(AWE_CCCA(voice), temp);
-	DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n", vp->start, addr));
-
-	/* clear unknown registers */
-	awe_poke_dw(AWE_00A0(voice), 0);
-	awe_poke_dw(AWE_0080(voice), 0);
-
-	/* reset volume */
-	awe_poke_dw(AWE_VTFT(voice), (vtarget<<16)|ftarget);
-	awe_poke_dw(AWE_CVCF(voice), (vtarget<<16)|ftarget);
-
-	/* turn on envelope */
-	awe_poke(AWE_DCYSUSV(voice),
-		 FX_COMB(fx, fx_lay, AWE_FX_ENV2_SUSTAIN, AWE_FX_ENV2_DECAY,
-			  vp->parm.voldcysus));
-	/* set reverb */
-	temp = FX_BYTE(fx, fx_lay, AWE_FX_REVERB, vp->parm.reverb);
-	temp = (temp << 8) | (ptarget << 16) | voices[voice].aaux;
-	awe_poke_dw(AWE_PTRX(voice), temp);
-	awe_poke_dw(AWE_CPF(voice), ptarget << 16);
-
-	voices[voice].state = AWE_ST_ON;
-
-	/* clear voice position for the next note on this channel */
-	if (SINGLE_LAYER_MODE()) {
-		FX_UNSET(fx, AWE_FX_SAMPLE_START);
-		FX_UNSET(fx, AWE_FX_COARSE_SAMPLE_START);
-	}
-}
-
-
-/* turn off the voice */
-static void
-awe_note_off(int voice)
-{
-	awe_voice_info *vp;
-	unsigned short tmp;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	if ((vp = voices[voice].sample) == NULL) {
-		voices[voice].state = AWE_ST_OFF;
-		return;
-	}
-
-	tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV1_RELEASE,
-			       (unsigned char)vp->parm.modrelease);
-	awe_poke(AWE_DCYSUS(voice), tmp);
-	tmp = 0x8000 | FX_BYTE(fx, fx_lay, AWE_FX_ENV2_RELEASE,
-			       (unsigned char)vp->parm.volrelease);
-	awe_poke(AWE_DCYSUSV(voice), tmp);
-	voices[voice].state = AWE_ST_RELEASED;
-}
-
-/* force to terminate the voice (no releasing echo) */
-static void
-awe_terminate(int voice)
-{
-	awe_poke(AWE_DCYSUSV(voice), 0x807F);
-	awe_tweak_voice(voice);
-	voices[voice].state = AWE_ST_OFF;
-}
-
-/* turn off other voices with the same exclusive class (for drums) */
-static void
-awe_exclusive_off(int voice)
-{
-	int i, exclass;
-
-	if (voices[voice].sample == NULL)
-		return;
-	if ((exclass = voices[voice].sample->exclusiveClass) == 0)
-		return;	/* not exclusive */
-
-	/* turn off voices with the same class */
-	for (i = 0; i < awe_max_voices; i++) {
-		if (i != voice && IS_PLAYING(i) &&
-		    voices[i].sample && voices[i].ch == voices[voice].ch &&
-		    voices[i].sample->exclusiveClass == exclass) {
-			DEBUG(4,printk("AWE32: [exoff(%d)]\n", i));
-			awe_terminate(i);
-			awe_voice_init(i, TRUE);
-		}
-	}
-}
-
-
-/*================================================================
- * change the parameters of an audible voice
- *================================================================*/
-
-/* change pitch */
-static void
-awe_set_pitch(int voice, int forced)
-{
-	if (IS_NO_EFFECT(voice) && !forced) return;
-	awe_poke(AWE_IP(voice), voices[voice].apitch);
-	DEBUG(3,printk("AWE32: [-- pitch=%x]\n", voices[voice].apitch));
-}
-
-/* calculate & change pitch */
-static void
-awe_set_voice_pitch(int voice, int forced)
-{
-	awe_calc_pitch(voice);
-	awe_set_pitch(voice, forced);
-}
-
-/* change volume & cutoff */
-static void
-awe_set_volume(int voice, int forced)
-{
-	awe_voice_info *vp;
-	unsigned short tmp2;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	if (!IS_PLAYING(voice) && !forced) return;
-	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
-		return;
-
-	tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF,
-		       (unsigned char)voices[voice].acutoff);
-	tmp2 = (tmp2 << 8);
-	tmp2 |= FX_BYTE(fx, fx_lay, AWE_FX_ATTEN,
-			(unsigned char)voices[voice].avol);
-	awe_poke(AWE_IFATN(voice), tmp2);
-}
-
-/* calculate & change volume */
-static void
-awe_set_voice_vol(int voice, int forced)
-{
-	if (IS_EMPTY(voice))
-		return;
-	awe_calc_volume(voice);
-	awe_set_volume(voice, forced);
-}
-
-
-/* change pan; this could make a click noise.. */
-static void
-awe_set_pan(int voice, int forced)
-{
-	unsigned int temp;
-	int addr;
-	awe_voice_info *vp;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	if (IS_NO_EFFECT(voice) && !forced) return;
-	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
-		return;
-
-	/* pan & loop start (pan 8bit, MSB, 0:right, 0xff:left) */
-	if (vp->fixpan > 0)	/* 0-127 */
-		temp = 255 - (int)vp->fixpan * 2;
-	else {
-		int pos = 0;
-		if (vp->pan >= 0) /* 0-127 */
-			pos = (int)vp->pan * 2 - 128;
-		pos += voices[voice].cinfo->panning; /* -128 - 127 */
-		temp = 127 - pos;
-	}
-	limitvalue(temp, 0, 255);
-	if (ctrls[AWE_MD_PAN_EXCHANGE]) {
-		temp = 255 - temp;
-	}
-	if (forced || temp != voices[voice].apan) {
-		voices[voice].apan = temp;
-		addr = vp->loopstart - 1;
-		addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_START,
-				  AWE_FX_COARSE_LOOP_START, vp->mode);
-		temp = (temp<<24) | (unsigned int)addr;
-		awe_poke_dw(AWE_PSST(voice), temp);
-		DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n", vp->loopstart, addr));
-		if (temp == 0) voices[voice].aaux = 0xff;
-		else voices[voice].aaux = (-temp)&0xff;
-	}
-}
-
-/* effects change during playing */
-static void
-awe_fx_fmmod(int voice, int forced)
-{
-	awe_voice_info *vp;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	if (IS_NO_EFFECT(voice) && !forced) return;
-	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
-		return;
-	awe_poke(AWE_FMMOD(voice),
-		 FX_COMB(fx, fx_lay, AWE_FX_LFO1_PITCH, AWE_FX_LFO1_CUTOFF,
-			 vp->parm.fmmod));
-}
-
-/* set tremolo (lfo1) volume & frequency */
-static void
-awe_fx_tremfrq(int voice, int forced)
-{
-	awe_voice_info *vp;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	if (IS_NO_EFFECT(voice) && !forced) return;
-	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
-		return;
-	awe_poke(AWE_TREMFRQ(voice),
-		 FX_COMB(fx, fx_lay, AWE_FX_LFO1_VOLUME, AWE_FX_LFO1_FREQ,
-			 vp->parm.tremfrq));
-}
-
-/* set lfo2 pitch & frequency */
-static void
-awe_fx_fm2frq2(int voice, int forced)
-{
-	awe_voice_info *vp;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	if (IS_NO_EFFECT(voice) && !forced) return;
-	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
-		return;
-	awe_poke(AWE_FM2FRQ2(voice),
-		 FX_COMB(fx, fx_lay, AWE_FX_LFO2_PITCH, AWE_FX_LFO2_FREQ,
-			 vp->parm.fm2frq2));
-}
-
-
-/* Q & current address (Q 4bit value, MSB) */
-static void
-awe_fx_filterQ(int voice, int forced)
-{
-	unsigned int addr;
-	awe_voice_info *vp;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	if (IS_NO_EFFECT(voice) && !forced) return;
-	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
-		return;
-
-	addr = awe_peek_dw(AWE_CCCA(voice)) & 0xffffff;
-	addr |= (FX_BYTE(fx, fx_lay, AWE_FX_FILTERQ, vp->parm.filterQ) << 28);
-	awe_poke_dw(AWE_CCCA(voice), addr);
-}
-
-/*================================================================
- * calculate pitch offset
- *----------------------------------------------------------------
- * 0xE000 is no pitch offset at 44100Hz sample.
- * Every 4096 is one octave.
- *================================================================*/
-
-static void
-awe_calc_pitch(int voice)
-{
-	voice_info *vp = &voices[voice];
-	awe_voice_info *ap;
-	awe_chan_info *cp = voices[voice].cinfo;
-	int offset;
-
-	/* search voice information */
-	if ((ap = vp->sample) == NULL)
-			return;
-	if (ap->index < 0) {
-		DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample));
-		if (awe_set_sample(ap) < 0)
-			return;
-	}
-
-	/* calculate offset */
-	if (ap->fixkey >= 0) {
-		DEBUG(3,printk("AWE32: p-> fixkey(%d) tune(%d)\n", ap->fixkey, ap->tune));
-		offset = (ap->fixkey - ap->root) * 4096 / 12;
-	} else {
-		DEBUG(3,printk("AWE32: p(%d)-> root(%d) tune(%d)\n", vp->note, ap->root, ap->tune));
-		offset = (vp->note - ap->root) * 4096 / 12;
-		DEBUG(4,printk("AWE32: p-> ofs=%d\n", offset));
-	}
-	offset = (offset * ap->scaleTuning) / 100;
-	DEBUG(4,printk("AWE32: p-> scale* ofs=%d\n", offset));
-	offset += ap->tune * 4096 / 1200;
-	DEBUG(4,printk("AWE32: p-> tune+ ofs=%d\n", offset));
-	if (cp->bender != 0) {
-		DEBUG(3,printk("AWE32: p-> bend(%d) %d\n", voice, cp->bender));
-		/* (819200: 1 semitone) ==> (4096: 12 semitones) */
-		offset += cp->bender * cp->bender_range / 2400;
-	}
-
-	/* add initial pitch correction */
-	if (FX_ON(&cp->fx_layer[vp->layer], AWE_FX_INIT_PITCH))
-		offset += cp->fx_layer[vp->layer].val[AWE_FX_INIT_PITCH];
-	else if (FX_ON(&cp->fx, AWE_FX_INIT_PITCH))
-		offset += cp->fx.val[AWE_FX_INIT_PITCH];
-
-	/* 0xe000: root pitch */
-	vp->apitch = 0xe000 + ap->rate_offset + offset;
-	DEBUG(4,printk("AWE32: p-> sum aofs=%x, rate_ofs=%d\n", vp->apitch, ap->rate_offset));
-	if (vp->apitch > 0xffff)
-		vp->apitch = 0xffff;
-	if (vp->apitch < 0)
-		vp->apitch = 0;
-}
-
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-/* calculate MIDI key and semitone from the specified frequency */
-static void
-awe_calc_pitch_from_freq(int voice, int freq)
-{
-	voice_info *vp = &voices[voice];
-	awe_voice_info *ap;
-	FX_Rec *fx = &voices[voice].cinfo->fx;
-	FX_Rec *fx_lay = NULL;
-	int offset;
-	int note;
-
-	if (voices[voice].layer < MAX_LAYERS)
-		fx_lay = &voices[voice].cinfo->fx_layer[voices[voice].layer];
-
-	/* search voice information */
-	if ((ap = vp->sample) == NULL)
-		return;
-	if (ap->index < 0) {
-		DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample));
-		if (awe_set_sample(ap) < 0)
-			return;
-	}
-	note = freq_to_note(freq);
-	offset = (note - ap->root * 100 + ap->tune) * 4096 / 1200;
-	offset = (offset * ap->scaleTuning) / 100;
-	if (fx_lay && FX_ON(fx_lay, AWE_FX_INIT_PITCH))
-		offset += fx_lay->val[AWE_FX_INIT_PITCH];
-	else if (FX_ON(fx, AWE_FX_INIT_PITCH))
-		offset += fx->val[AWE_FX_INIT_PITCH];
-	vp->apitch = 0xe000 + ap->rate_offset + offset;
-	if (vp->apitch > 0xffff)
-		vp->apitch = 0xffff;
-	if (vp->apitch < 0)
-		vp->apitch = 0;
-}
-#endif /* AWE_HAS_GUS_COMPATIBILITY */
-
-
-/*================================================================
- * calculate volume attenuation
- *----------------------------------------------------------------
- * Voice volume is controlled by volume attenuation parameter.
- * So volume becomes maximum when avol is 0 (no attenuation), and
- * minimum when 255 (-96dB or silence).
- *================================================================*/
-
-static int vol_table[128] = {
-	255,111,95,86,79,74,70,66,63,61,58,56,54,52,50,49,
-	47,46,45,43,42,41,40,39,38,37,36,35,34,34,33,32,
-	31,31,30,29,29,28,27,27,26,26,25,24,24,23,23,22,
-	22,21,21,21,20,20,19,19,18,18,18,17,17,16,16,16,
-	15,15,15,14,14,14,13,13,13,12,12,12,11,11,11,10,
-	10,10,10,9,9,9,8,8,8,8,7,7,7,7,6,6,
-	6,6,5,5,5,5,5,4,4,4,4,3,3,3,3,3,
-	2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
-};
-
-/* tables for volume->attenuation calculation */
-static unsigned char voltab1[128] = {
-   0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
-   0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
-   0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
-   0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
-   0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
-   0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
-   0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
-   0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
-   0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
-   0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
-   0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
-   0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
-   0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static unsigned char voltab2[128] = {
-   0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
-   0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
-   0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
-   0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
-   0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
-   0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
-   0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
-   0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
-   0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
-   0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
-   0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
-   0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
-   0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static unsigned char expressiontab[128] = {
-   0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
-   0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
-   0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
-   0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
-   0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
-   0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
-   0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
-   0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
-   0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
-   0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
-   0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
-   0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
-   0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static void
-awe_calc_volume(int voice)
-{
-	voice_info *vp = &voices[voice];
-	awe_voice_info *ap;
-	awe_chan_info *cp = voices[voice].cinfo;
-	int vol;
-
-	/* search voice information */
-	if ((ap = vp->sample) == NULL)
-		return;
-
-	ap = vp->sample;
-	if (ap->index < 0) {
-		DEBUG(3,printk("AWE32: set sample (%d)\n", ap->sample));
-		if (awe_set_sample(ap) < 0)
-			return;
-	}
-	
-	if (ctrls[AWE_MD_NEW_VOLUME_CALC]) {
-		int main_vol = cp->main_vol * ap->amplitude / 127;
-		limitvalue(vp->velocity, 0, 127);
-		limitvalue(main_vol, 0, 127);
-		limitvalue(cp->expression_vol, 0, 127);
-
-		vol = voltab1[main_vol] + voltab2[vp->velocity];
-		vol = (vol * 8) / 3;
-		vol += ap->attenuation;
-		if (cp->expression_vol < 127)
-			vol += ((0x100 - vol) * expressiontab[cp->expression_vol])/128;
-		vol += atten_offset;
-		if (atten_relative)
-			vol += ctrls[AWE_MD_ZERO_ATTEN];
-		limitvalue(vol, 0, 255);
-		vp->avol = vol;
-		
-	} else {
-		/* 0 - 127 */
-		vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127);
-		vol = vol * ap->amplitude / 127;
-
-		if (vol < 0) vol = 0;
-		if (vol > 127) vol = 127;
-
-		/* calc to attenuation */
-		vol = vol_table[vol];
-		vol += (int)ap->attenuation;
-		vol += atten_offset;
-		if (atten_relative)
-			vol += ctrls[AWE_MD_ZERO_ATTEN];
-		if (vol > 255) vol = 255;
-
-		vp->avol = vol;
-	}
-	if (cp->bank !=  AWE_DRUM_BANK && ((awe_voice_parm_block*)(&ap->parm))->volatk < 0x7d) {
-		int atten;
-		if (vp->velocity < 70) atten = 70;
-		else atten = vp->velocity;
-		vp->acutoff = (atten * ap->parm.cutoff + 0xa0) >> 7;
-	} else {
-		vp->acutoff = ap->parm.cutoff;
-	}
-	DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol));
-}
-
-/* change master volume */
-static void
-awe_change_master_volume(short val)
-{
-	limitvalue(val, 0, 127);
-	atten_offset = vol_table[val];
-	atten_relative = TRUE;
-	awe_update_volume();
-}
-
-/* update volumes of all available channels */
-static void awe_update_volume(void)
-{
-	int i;
-	for (i = 0; i < awe_max_voices; i++)
-		awe_set_voice_vol(i, TRUE);
-}
-
-/* set sostenuto on */
-static void awe_sostenuto_on(int voice, int forced)
-{
-	if (IS_NO_EFFECT(voice) && !forced) return;
-	voices[voice].sostenuto = 127;
-}
-
-
-/* drop sustain */
-static void awe_sustain_off(int voice, int forced)
-{
-	if (voices[voice].state == AWE_ST_SUSTAINED) {
-		awe_note_off(voice);
-		awe_fx_init(voices[voice].ch);
-		awe_voice_init(voice, FALSE);
-	}
-}
-
-
-/* terminate and initialize voice */
-static void awe_terminate_and_init(int voice, int forced)
-{
-	awe_terminate(voice);
-	awe_fx_init(voices[voice].ch);
-	awe_voice_init(voice, TRUE);
-}
-
-
-/*================================================================
- * synth operation routines
- *================================================================*/
-
-#define AWE_VOICE_KEY(v)	(0x8000 | (v))
-#define AWE_CHAN_KEY(c,n)	(((c) << 8) | ((n) + 1))
-#define KEY_CHAN_MATCH(key,c)	(((key) >> 8) == (c))
-
-/* initialize the voice */
-static void
-awe_voice_init(int voice, int init_all)
-{
-	voice_info *vp = &voices[voice];
-
-	/* reset voice search key */
-	if (playing_mode == AWE_PLAY_DIRECT)
-		vp->key = AWE_VOICE_KEY(voice);
-	else
-		vp->key = 0;
-
-	/* clear voice mapping */
-	voice_alloc->map[voice] = 0;
-
-	/* touch the timing flag */
-	vp->time = current_alloc_time;
-
-	/* initialize other parameters if necessary */
-	if (init_all) {
-		vp->note = -1;
-		vp->velocity = 0;
-		vp->sostenuto = 0;
-
-		vp->sample = NULL;
-		vp->cinfo = &channels[voice];
-		vp->ch = voice;
-		vp->state = AWE_ST_OFF;
-
-		/* emu8000 parameters */
-		vp->apitch = 0;
-		vp->avol = 255;
-		vp->apan = -1;
-	}
-}
-
-/* clear effects */
-static void awe_fx_init(int ch)
-{
-	if (SINGLE_LAYER_MODE() && !ctrls[AWE_MD_KEEP_EFFECT]) {
-		BZERO(&channels[ch].fx, sizeof(channels[ch].fx));
-		BZERO(&channels[ch].fx_layer, sizeof(&channels[ch].fx_layer));
-	}
-}
-
-/* initialize channel info */
-static void awe_channel_init(int ch, int init_all)
-{
-	awe_chan_info *cp = &channels[ch];
-	cp->channel = ch;
-	if (init_all) {
-		cp->panning = 0; /* zero center */
-		cp->bender_range = 200; /* sense * 100 */
-		cp->main_vol = 127;
-		if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) {
-			cp->instr = ctrls[AWE_MD_DEF_DRUM];
-			cp->bank = AWE_DRUM_BANK;
-		} else {
-			cp->instr = ctrls[AWE_MD_DEF_PRESET];
-			cp->bank = ctrls[AWE_MD_DEF_BANK];
-		}
-		cp->vrec = -1;
-		cp->def_vrec = -1;
-	}
-
-	cp->bender = 0; /* zero tune skew */
-	cp->expression_vol = 127;
-	cp->chan_press = 0;
-	cp->sustained = 0;
-
-	if (! ctrls[AWE_MD_KEEP_EFFECT]) {
-		BZERO(&cp->fx, sizeof(cp->fx));
-		BZERO(&cp->fx_layer, sizeof(cp->fx_layer));
-	}
-}
-
-
-/* change the voice parameters; voice = channel */
-static void awe_voice_change(int voice, fx_affect_func func)
-{
-	int i; 
-	switch (playing_mode) {
-	case AWE_PLAY_DIRECT:
-		func(voice, FALSE);
-		break;
-	case AWE_PLAY_INDIRECT:
-		for (i = 0; i < awe_max_voices; i++)
-			if (voices[i].key == AWE_VOICE_KEY(voice))
-				func(i, FALSE);
-		break;
-	default:
-		for (i = 0; i < awe_max_voices; i++)
-			if (KEY_CHAN_MATCH(voices[i].key, voice))
-				func(i, FALSE);
-		break;
-	}
-}
-
-
-/*----------------------------------------------------------------
- * device open / close
- *----------------------------------------------------------------*/
-
-/* open device:
- *   reset status of all voices, and clear sample position flag
- */
-static int
-awe_open(int dev, int mode)
-{
-	if (awe_busy)
-		return RET_ERROR(EBUSY);
-
-	awe_busy = TRUE;
-
-	/* set default mode */
-	awe_init_ctrl_parms(FALSE);
-	atten_relative = TRUE;
-	atten_offset = 0;
-	drum_flags = DEFAULT_DRUM_FLAGS;
-	playing_mode = AWE_PLAY_INDIRECT;
-
-	/* reset voices & channels */
-	awe_reset(dev);
-
-	patch_opened = 0;
-
-	return 0;
-}
-
-
-/* close device:
- *   reset all voices again (terminate sounds)
- */
-static void
-awe_close(int dev)
-{
-	awe_reset(dev);
-	awe_busy = FALSE;
-}
-
-
-/* set miscellaneous mode parameters
- */
-static void
-awe_init_ctrl_parms(int init_all)
-{
-	int i;
-	for (i = 0; i < AWE_MD_END; i++) {
-		if (init_all || ctrl_parms[i].init_each_time)
-			ctrls[i] = ctrl_parms[i].value;
-	}
-}
-
-
-/* sequencer I/O control:
- */
-static int
-awe_ioctl(int dev, unsigned int cmd, caddr_t arg)
-{
-	switch (cmd) {
-	case SNDCTL_SYNTH_INFO:
-		if (playing_mode == AWE_PLAY_DIRECT)
-			awe_info.nr_voices = awe_max_voices;
-		else
-			awe_info.nr_voices = AWE_MAX_CHANNELS;
-		IOCTL_TO_USER((char*)arg, 0, &awe_info, sizeof(awe_info));
-		return 0;
-		break;
-
-	case SNDCTL_SEQ_RESETSAMPLES:
-		awe_reset_samples();
-		awe_reset(dev);
-		return 0;
-		break;
-
-	case SNDCTL_SEQ_PERCMODE:
-		/* what's this? */
-		return 0;
-		break;
-
-	case SNDCTL_SYNTH_MEMAVL:
-		return awe_mem_size - awe_free_mem_ptr() * 2;
-
-	default:
-		printk("AWE32: unsupported ioctl %d\n", cmd);
-		return RET_ERROR(EINVAL);
-	}
-}
-
-
-static int voice_in_range(int voice)
-{
-	if (playing_mode == AWE_PLAY_DIRECT) {
-		if (voice < 0 || voice >= awe_max_voices)
-			return FALSE;
-	} else {
-		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
-			return FALSE;
-	}
-	return TRUE;
-}
-
-static void release_voice(int voice, int do_sustain)
-{
-	if (IS_NO_SOUND(voice))
-		return;
-	if (do_sustain && (voices[voice].cinfo->sustained == 127 ||
-			    voices[voice].sostenuto == 127))
-		voices[voice].state = AWE_ST_SUSTAINED;
-	else {
-		awe_note_off(voice);
-		awe_fx_init(voices[voice].ch);
-		awe_voice_init(voice, FALSE);
-	}
-}
-
-/* release all notes */
-static void awe_note_off_all(int do_sustain)
-{
-	int i;
-	for (i = 0; i < awe_max_voices; i++)
-		release_voice(i, do_sustain);
-}
-
-/* kill a voice:
- *   not terminate, just release the voice.
- */
-static int
-awe_kill_note(int dev, int voice, int note, int velocity)
-{
-	int i, v2, key;
-
-	DEBUG(2,printk("AWE32: [off(%d) nt=%d vl=%d]\n", voice, note, velocity));
-	if (! voice_in_range(voice))
-		return RET_ERROR(EINVAL);
-
-	switch (playing_mode) {
-	case AWE_PLAY_DIRECT:
-	case AWE_PLAY_INDIRECT:
-		key = AWE_VOICE_KEY(voice);
-		break;
-
-	case AWE_PLAY_MULTI2:
-		v2 = voice_alloc->map[voice] >> 8;
-		voice_alloc->map[voice] = 0;
-		voice = v2;
-		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
-			return RET_ERROR(EINVAL);
-		/* continue to below */
-	default:
-		key = AWE_CHAN_KEY(voice, note);
-		break;
-	}
-
-	for (i = 0; i < awe_max_voices; i++) {
-		if (voices[i].key == key)
-			release_voice(i, TRUE);
-	}
-	return 0;
-}
-
-
-static void start_or_volume_change(int voice, int velocity)
-{
-	voices[voice].velocity = velocity;
-	awe_calc_volume(voice);
-	if (voices[voice].state == AWE_ST_STANDBY)
-		awe_note_on(voice);
-	else if (voices[voice].state == AWE_ST_ON)
-		awe_set_volume(voice, FALSE);
-}
-
-static void set_and_start_voice(int voice, int state)
-{
-	/* calculate pitch & volume parameters */
-	voices[voice].state = state;
-	awe_calc_pitch(voice);
-	awe_calc_volume(voice);
-	if (state == AWE_ST_ON)
-		awe_note_on(voice);
-}
-
-/* start a voice:
- *   if note is 255, identical with aftertouch function.
- *   Otherwise, start a voice with specified not and volume.
- */
-static int
-awe_start_note(int dev, int voice, int note, int velocity)
-{
-	int i, key, state, volonly;
-
-	DEBUG(2,printk("AWE32: [on(%d) nt=%d vl=%d]\n", voice, note, velocity));
-	if (! voice_in_range(voice))
-		return RET_ERROR(EINVAL);
-	    
-	if (velocity == 0)
-		state = AWE_ST_STANDBY; /* stand by for playing */
-	else
-		state = AWE_ST_ON;	/* really play */
-	volonly = FALSE;
-
-	switch (playing_mode) {
-	case AWE_PLAY_DIRECT:
-	case AWE_PLAY_INDIRECT:
-		key = AWE_VOICE_KEY(voice);
-		if (note == 255)
-			volonly = TRUE;
-		break;
-
-	case AWE_PLAY_MULTI2:
-		voice = voice_alloc->map[voice] >> 8;
-		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
-			return RET_ERROR(EINVAL);
-		/* continue to below */
-	default:
-		if (note >= 128) { /* key volume mode */
-			note -= 128;
-			volonly = TRUE;
-		}
-		key = AWE_CHAN_KEY(voice, note);
-		break;
-	}
-
-	/* dynamic volume change */
-	if (volonly) {
-		for (i = 0; i < awe_max_voices; i++) {
-			if (voices[i].key == key)
-				start_or_volume_change(i, velocity);
-		}
-		return 0;
-	}
-
-	/* if the same note still playing, stop it */
-	if (playing_mode != AWE_PLAY_DIRECT || ctrls[AWE_MD_EXCLUSIVE_SOUND]) {
-		for (i = 0; i < awe_max_voices; i++)
-			if (voices[i].key == key) {
-				if (voices[i].state == AWE_ST_ON) {
-					awe_note_off(i);
-					awe_voice_init(i, FALSE);
-				} else if (voices[i].state == AWE_ST_STANDBY)
-					awe_voice_init(i, TRUE);
-			}
-	}
-
-	/* allocate voices */
-	if (playing_mode == AWE_PLAY_DIRECT)
-		awe_alloc_one_voice(voice, note, velocity);
-	else
-		awe_alloc_multi_voices(voice, note, velocity, key);
-
-	/* turn off other voices exlusively (for drums) */
-	for (i = 0; i < awe_max_voices; i++)
-		if (voices[i].key == key)
-			awe_exclusive_off(i);
-
-	/* set up pitch and volume parameters */
-	for (i = 0; i < awe_max_voices; i++) {
-		if (voices[i].key == key && voices[i].state == AWE_ST_OFF)
-			set_and_start_voice(i, state);
-	}
-
-	return 0;
-}
-
-
-/* search instrument from preset table with the specified bank */
-static int
-awe_search_instr(int bank, int preset)
-{
-	int i;
-
-	limitvalue(preset, 0, AWE_MAX_PRESETS-1);
-	for (i = preset_table[preset]; i >= 0; i = infos[i].next_bank) {
-		if (infos[i].bank == bank)
-			return i;
-	}
-	return -1;
-}
-
-
-/* assign the instrument to a voice */
-static int
-awe_set_instr_2(int dev, int voice, int instr_no)
-{
-	if (playing_mode == AWE_PLAY_MULTI2) {
-		voice = voice_alloc->map[voice] >> 8;
-		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
-			return RET_ERROR(EINVAL);
-	}
-	return awe_set_instr(dev, voice, instr_no);
-}
-
-/* assign the instrument to a channel; voice is the channel number */
-static int
-awe_set_instr(int dev, int voice, int instr_no)
-{
-	awe_chan_info *cinfo;
-	int def_bank;
-
-	if (! voice_in_range(voice))
-		return RET_ERROR(EINVAL);
-
-	if (instr_no < 0 || instr_no >= AWE_MAX_PRESETS)
-		return RET_ERROR(EINVAL);
-
-	cinfo = &channels[voice];
-
-	if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice))
-		def_bank = AWE_DRUM_BANK; /* always search drumset */
-	else
-		def_bank = cinfo->bank;
-
-	cinfo->vrec = -1;
-	cinfo->def_vrec = -1;
-	cinfo->vrec = awe_search_instr(def_bank, instr_no);
-	if (def_bank == AWE_DRUM_BANK)	/* search default drumset */
-		cinfo->def_vrec = awe_search_instr(def_bank, ctrls[AWE_MD_DEF_DRUM]);
-	else	/* search default preset */
-		cinfo->def_vrec = awe_search_instr(ctrls[AWE_MD_DEF_BANK], instr_no);
-
-	if (cinfo->vrec < 0 && cinfo->def_vrec < 0) {
-		DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));
-	}
-
-	cinfo->instr = instr_no;
-	DEBUG(2,printk("AWE32: [program(%d) %d/%d]\n", voice, instr_no, def_bank));
-
-	return 0;
-}
-
-
-/* reset all voices; terminate sounds and initialize parameters */
-static void
-awe_reset(int dev)
-{
-	int i;
-	current_alloc_time = 0;
-	/* don't turn off voice 31 and 32.  they are used also for FM voices */
-	for (i = 0; i < awe_max_voices; i++) {
-		awe_terminate(i);
-		awe_voice_init(i, TRUE);
-	}
-	for (i = 0; i < AWE_MAX_CHANNELS; i++)
-		awe_channel_init(i, TRUE);
-	for (i = 0; i < 16; i++) {
-		awe_operations.chn_info[i].controllers[CTL_MAIN_VOLUME] = 127;
-		awe_operations.chn_info[i].controllers[CTL_EXPRESSION] = 127;
-	}
-	awe_init_fm();
-	awe_tweak();
-}
-
-
-/* hardware specific control:
- *   GUS specific and AWE32 specific controls are available.
- */
-static void
-awe_hw_control(int dev, unsigned char *event)
-{
-	int cmd = event[2];
-	if (cmd & _AWE_MODE_FLAG)
-		awe_hw_awe_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-	else
-		awe_hw_gus_control(dev, cmd & _AWE_MODE_VALUE_MASK, event);
-#endif
-}
-
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-
-/* GUS compatible controls */
-static void
-awe_hw_gus_control(int dev, int cmd, unsigned char *event)
-{
-	int voice, i, key;
-	unsigned short p1;
-	short p2;
-	int plong;
-
-	if (MULTI_LAYER_MODE())
-		return;
-	if (cmd == _GUS_NUMVOICES)
-		return;
-
-	voice = event[3];
-	if (! voice_in_range(voice))
-		return;
-
-	p1 = *(unsigned short *) &event[4];
-	p2 = *(short *) &event[6];
-	plong = *(int*) &event[4];
-
-	switch (cmd) {
-	case _GUS_VOICESAMPLE:
-		awe_set_instr(dev, voice, p1);
-		return;
-
-	case _GUS_VOICEBALA:
-		/* 0 to 15 --> -128 to 127 */
-		awe_panning(dev, voice, ((int)p1 << 4) - 128);
-		return;
-
-	case _GUS_VOICEVOL:
-	case _GUS_VOICEVOL2:
-		/* not supported yet */
-		return;
-
-	case _GUS_RAMPRANGE:
-	case _GUS_RAMPRATE:
-	case _GUS_RAMPMODE:
-	case _GUS_RAMPON:
-	case _GUS_RAMPOFF:
-		/* volume ramping not supported */
-		return;
-
-	case _GUS_VOLUME_SCALE:
-		return;
-
-	case _GUS_VOICE_POS:
-		FX_SET(&channels[voice].fx, AWE_FX_SAMPLE_START,
-		       (short)(plong & 0x7fff));
-		FX_SET(&channels[voice].fx, AWE_FX_COARSE_SAMPLE_START,
-		       (plong >> 15) & 0xffff);
-		return;
-	}
-
-	key = AWE_VOICE_KEY(voice);
-	for (i = 0; i < awe_max_voices; i++) {
-		if (voices[i].key == key) {
-			switch (cmd) {
-			case _GUS_VOICEON:
-				awe_note_on(i);
-				break;
-
-			case _GUS_VOICEOFF:
-				awe_terminate(i);
-				awe_fx_init(voices[i].ch);
-				awe_voice_init(i, TRUE);
-				break;
-
-			case _GUS_VOICEFADE:
-				awe_note_off(i);
-				awe_fx_init(voices[i].ch);
-				awe_voice_init(i, FALSE);
-				break;
-
-			case _GUS_VOICEFREQ:
-				awe_calc_pitch_from_freq(i, plong);
-				break;
-			}
-		}
-	}
-}
-
-#endif /* gus_compat */
-
-
-/* AWE32 specific controls */
-static void
-awe_hw_awe_control(int dev, int cmd, unsigned char *event)
-{
-	int voice;
-	unsigned short p1;
-	short p2;
-	int i;
-
-	voice = event[3];
-	if (! voice_in_range(voice))
-		return;
-
-	if (playing_mode == AWE_PLAY_MULTI2) {
-		voice = voice_alloc->map[voice] >> 8;
-		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
-			return;
-	}
-
-	p1 = *(unsigned short *) &event[4];
-	p2 = *(short *) &event[6];
-
-	switch (cmd) {
-	case _AWE_DEBUG_MODE:
-		ctrls[AWE_MD_DEBUG_MODE] = p1;
-		printk("AWE32: debug mode = %d\n", ctrls[AWE_MD_DEBUG_MODE]);
-		break;
-	case _AWE_REVERB_MODE:
-		ctrls[AWE_MD_REVERB_MODE] = p1;
-		awe_update_reverb_mode();
-		break;
-
-	case _AWE_CHORUS_MODE:
-		ctrls[AWE_MD_CHORUS_MODE] = p1;
-		awe_update_chorus_mode();
-		break;
-		      
-	case _AWE_REMOVE_LAST_SAMPLES:
-		DEBUG(0,printk("AWE32: remove last samples\n"));
-		if (locked_sf_id > 0)
-			awe_remove_samples(locked_sf_id);
-		break;
-
-	case _AWE_INITIALIZE_CHIP:
-		awe_initialize();
-		break;
-
-	case _AWE_SEND_EFFECT:
-		i = -1;
-		if (p1 >= 0x100) {
-			i = (p1 >> 8);
-			if (i < 0 || i >= MAX_LAYERS)
-				break;
-		}
-		awe_send_effect(voice, i, p1, p2);
-		break;
-
-	case _AWE_RESET_CHANNEL:
-		awe_channel_init(voice, !p1);
-		break;
-		
-	case _AWE_TERMINATE_ALL:
-		awe_reset(0);
-		break;
-
-	case _AWE_TERMINATE_CHANNEL:
-		awe_voice_change(voice, awe_terminate_and_init);
-		break;
-
-	case _AWE_RELEASE_ALL:
-		awe_note_off_all(FALSE);
-		break;
-	case _AWE_NOTEOFF_ALL:
-		awe_note_off_all(TRUE);
-		break;
-
-	case _AWE_INITIAL_VOLUME:
-		DEBUG(0,printk("AWE32: init attenuation %d\n", p1));
-		atten_relative = (char)p2;
-		atten_offset = (short)p1;
-		awe_update_volume();
-		break;
-
-	case _AWE_CHN_PRESSURE:
-		channels[voice].chan_press = p1;
-		awe_modwheel_change(voice, p1);
-		break;
-
-	case _AWE_CHANNEL_MODE:
-		DEBUG(0,printk("AWE32: channel mode = %d\n", p1));
-		playing_mode = p1;
-		awe_reset(0);
-		break;
-
-	case _AWE_DRUM_CHANNELS:
-		DEBUG(0,printk("AWE32: drum flags = %x\n", p1));
-		drum_flags = *(unsigned int*)&event[4];
-		break;
-
-	case _AWE_MISC_MODE:
-		DEBUG(0,printk("AWE32: ctrl parms = %d %d\n", p1, p2));
-		if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END) {
-			ctrls[p1] = p2;
-			if (ctrl_parms[p1].update)
-				ctrl_parms[p1].update();
-		}
-		break;
-
-	case _AWE_EQUALIZER:
-		ctrls[AWE_MD_BASS_LEVEL] = p1;
-		ctrls[AWE_MD_TREBLE_LEVEL] = p2;
-		awe_update_equalizer();
-		break;
-
-	default:
-		DEBUG(0,printk("AWE32: hw control cmd=%d voice=%d\n", cmd, voice));
-		break;
-	}
-}
-
-
-/* change effects */
-static void
-awe_send_effect(int voice, int layer, int type, int val)
-{
-	awe_chan_info *cinfo;
-	FX_Rec *fx;
-	int mode;
-
-	cinfo = &channels[voice];
-	if (layer >= 0 && layer < MAX_LAYERS)
-		fx = &cinfo->fx_layer[layer];
-	else
-		fx = &cinfo->fx;
-
-	if (type & 0x40)
-		mode = FX_FLAG_OFF;
-	else if (type & 0x80)
-		mode = FX_FLAG_ADD;
-	else
-		mode = FX_FLAG_SET;
-	type &= 0x3f;
-
-	if (type >= 0 && type < AWE_FX_END) {
-		DEBUG(2,printk("AWE32: effects (%d) %d %d\n", voice, type, val));
-		if (mode == FX_FLAG_SET)
-			FX_SET(fx, type, val);
-		else if (mode == FX_FLAG_ADD)
-			FX_ADD(fx, type, val);
-		else
-			FX_UNSET(fx, type);
-		if (mode != FX_FLAG_OFF && parm_defs[type].realtime) {
-			DEBUG(2,printk("AWE32: fx_realtime (%d)\n", voice));
-			awe_voice_change(voice, parm_defs[type].realtime);
-		}
-	}
-}
-
-
-/* change modulation wheel; voice is already mapped on multi2 mode */
-static void
-awe_modwheel_change(int voice, int value)
-{
-	int i;
-	awe_chan_info *cinfo;
-
-	cinfo = &channels[voice];
-	i = value * ctrls[AWE_MD_MOD_SENSE] / 1200;
-	FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i);
-	awe_voice_change(voice, awe_fx_fmmod);
-	FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i);
-	awe_voice_change(voice, awe_fx_fm2frq2);
-}
-
-
-/* voice pressure change */
-static void
-awe_aftertouch(int dev, int voice, int pressure)
-{
-	int note;
-
-	DEBUG(2,printk("AWE32: [after(%d) %d]\n", voice, pressure));
-	if (! voice_in_range(voice))
-		return;
-
-	switch (playing_mode) {
-	case AWE_PLAY_DIRECT:
-	case AWE_PLAY_INDIRECT:
-		awe_start_note(dev, voice, 255, pressure);
-		break;
-	case AWE_PLAY_MULTI2:
-		note = (voice_alloc->map[voice] & 0xff) - 1;
-		awe_key_pressure(dev, voice, note + 0x80, pressure);
-		break;
-	}
-}
-
-
-/* voice control change */
-static void
-awe_controller(int dev, int voice, int ctrl_num, int value)
-{
-	awe_chan_info *cinfo;
-
-	if (! voice_in_range(voice))
-		return;
-
-	if (playing_mode == AWE_PLAY_MULTI2) {
-		voice = voice_alloc->map[voice] >> 8;
-		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
-			return;
-	}
-
-	cinfo = &channels[voice];
-
-	switch (ctrl_num) {
-	case CTL_BANK_SELECT: /* MIDI control #0 */
-		DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value));
-		if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice) &&
-		    !ctrls[AWE_MD_TOGGLE_DRUM_BANK])
-			break;
-		cinfo->bank = value;
-		if (cinfo->bank == AWE_DRUM_BANK)
-			DRUM_CHANNEL_ON(cinfo->channel);
-		else
-			DRUM_CHANNEL_OFF(cinfo->channel);
-		awe_set_instr(dev, voice, cinfo->instr);
-		break;
-
-	case CTL_MODWHEEL: /* MIDI control #1 */
-		DEBUG(2,printk("AWE32: [modwheel(%d) %d]\n", voice, value));
-		awe_modwheel_change(voice, value);
-		break;
-
-	case CTRL_PITCH_BENDER: /* SEQ1 V2 contorl */
-		DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, value));
-		/* zero centered */
-		cinfo->bender = value;
-		awe_voice_change(voice, awe_set_voice_pitch);
-		break;
-
-	case CTRL_PITCH_BENDER_RANGE: /* SEQ1 V2 control */
-		DEBUG(2,printk("AWE32: [range(%d) %d]\n", voice, value));
-		/* value = sense x 100 */
-		cinfo->bender_range = value;
-		/* no audible pitch change yet.. */
-		break;
-
-	case CTL_EXPRESSION: /* MIDI control #11 */
-		if (SINGLE_LAYER_MODE())
-			value /= 128;
-	case CTRL_EXPRESSION: /* SEQ1 V2 control */
-		DEBUG(2,printk("AWE32: [expr(%d) %d]\n", voice, value));
-		/* 0 - 127 */
-		cinfo->expression_vol = value;
-		awe_voice_change(voice, awe_set_voice_vol);
-		break;
-
-	case CTL_PAN:	/* MIDI control #10 */
-		DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value));
-		/* (0-127) -> signed 8bit */
-		cinfo->panning = value * 2 - 128;
-		if (ctrls[AWE_MD_REALTIME_PAN])
-			awe_voice_change(voice, awe_set_pan);
-		break;
-
-	case CTL_MAIN_VOLUME:	/* MIDI control #7 */
-		if (SINGLE_LAYER_MODE())
-			value = (value * 100) / 16383;
-	case CTRL_MAIN_VOLUME:	/* SEQ1 V2 control */
-		DEBUG(2,printk("AWE32: [mainvol(%d) %d]\n", voice, value));
-		/* 0 - 127 */
-		cinfo->main_vol = value;
-		awe_voice_change(voice, awe_set_voice_vol);
-		break;
-
-	case CTL_EXT_EFF_DEPTH: /* reverb effects: 0-127 */
-		DEBUG(2,printk("AWE32: [reverb(%d) %d]\n", voice, value));
-		FX_SET(&cinfo->fx, AWE_FX_REVERB, value * 2);
-		break;
-
-	case CTL_CHORUS_DEPTH: /* chorus effects: 0-127 */
-		DEBUG(2,printk("AWE32: [chorus(%d) %d]\n", voice, value));
-		FX_SET(&cinfo->fx, AWE_FX_CHORUS, value * 2);
-		break;
-
-	case 120:  /* all sounds off */
-		awe_note_off_all(FALSE);
-		break;
-	case 123:  /* all notes off */
-		awe_note_off_all(TRUE);
-		break;
-
-	case CTL_SUSTAIN: /* MIDI control #64 */
-		cinfo->sustained = value;
-		if (value != 127)
-			awe_voice_change(voice, awe_sustain_off);
-		break;
-
-	case CTL_SOSTENUTO: /* MIDI control #66 */
-		if (value == 127)
-			awe_voice_change(voice, awe_sostenuto_on);
-		else
-			awe_voice_change(voice, awe_sustain_off);
-		break;
-
-	default:
-		DEBUG(0,printk("AWE32: [control(%d) ctrl=%d val=%d]\n",
-			   voice, ctrl_num, value));
-		break;
-	}
-}
-
-
-/* voice pan change (value = -128 - 127) */
-static void
-awe_panning(int dev, int voice, int value)
-{
-	awe_chan_info *cinfo;
-
-	if (! voice_in_range(voice))
-		return;
-
-	if (playing_mode == AWE_PLAY_MULTI2) {
-		voice = voice_alloc->map[voice] >> 8;
-		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
-			return;
-	}
-
-	cinfo = &channels[voice];
-	cinfo->panning = value;
-	DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, cinfo->panning));
-	if (ctrls[AWE_MD_REALTIME_PAN])
-		awe_voice_change(voice, awe_set_pan);
-}
-
-
-/* volume mode change */
-static void
-awe_volume_method(int dev, int mode)
-{
-	/* not impremented */
-	DEBUG(0,printk("AWE32: [volmethod mode=%d]\n", mode));
-}
-
-
-#ifndef AWE_NO_PATCHMGR
-/* patch manager */
-static int
-awe_patchmgr(int dev, struct patmgr_info *rec)
-{
-	printk("AWE32 Warning: patch manager control not supported\n");
-	return 0;
-}
-#endif
-
-
-/* pitch wheel change: 0-16384 */
-static void
-awe_bender(int dev, int voice, int value)
-{
-	awe_chan_info *cinfo;
-
-	if (! voice_in_range(voice))
-		return;
-
-	if (playing_mode == AWE_PLAY_MULTI2) {
-		voice = voice_alloc->map[voice] >> 8;
-		if (voice < 0 || voice >= AWE_MAX_CHANNELS)
-			return;
-	}
-
-	/* convert to zero centered value */
-	cinfo = &channels[voice];
-	cinfo->bender = value - 8192;
-	DEBUG(2,printk("AWE32: [bend(%d) %d]\n", voice, cinfo->bender));
-	awe_voice_change(voice, awe_set_voice_pitch);
-}
-
-
-/*----------------------------------------------------------------
- * load a sound patch:
- *   three types of patches are accepted: AWE, GUS, and SYSEX.
- *----------------------------------------------------------------*/
-
-static int
-awe_load_patch(int dev, int format, const char *addr,
-	       int offs, int count, int pmgr_flag)
-{
-	awe_patch_info patch;
-	int rc = 0;
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-	if (format == GUS_PATCH) {
-		return awe_load_guspatch(addr, offs, count, pmgr_flag);
-	} else
-#endif
-	if (format == SYSEX_PATCH) {
-		/* no system exclusive message supported yet */
-		return 0;
-	} else if (format != AWE_PATCH) {
-		printk("AWE32 Error: Invalid patch format (key) 0x%x\n", format);
-		return RET_ERROR(EINVAL);
-	}
-	
-	if (count < AWE_PATCH_INFO_SIZE) {
-		printk("AWE32 Error: Patch header too short\n");
-		return RET_ERROR(EINVAL);
-	}
-	COPY_FROM_USER(((char*)&patch) + offs, addr, offs, 
-		       AWE_PATCH_INFO_SIZE - offs);
-
-	count -= AWE_PATCH_INFO_SIZE;
-	if (count < patch.len) {
-		printk("AWE32: sample: Patch record too short (%d<%d)\n",
-		       count, patch.len);
-		return RET_ERROR(EINVAL);
-	}
-	
-	switch (patch.type) {
-	case AWE_LOAD_INFO:
-		rc = awe_load_info(&patch, addr, count);
-		break;
-	case AWE_LOAD_DATA:
-		rc = awe_load_data(&patch, addr, count);
-		break;
-	case AWE_OPEN_PATCH:
-		rc = awe_open_patch(&patch, addr, count);
-		break;
-	case AWE_CLOSE_PATCH:
-		rc = awe_close_patch(&patch, addr, count);
-		break;
-	case AWE_UNLOAD_PATCH:
-		rc = awe_unload_patch(&patch, addr, count);
-		break;
-	case AWE_REPLACE_DATA:
-		rc = awe_replace_data(&patch, addr, count);
-		break;
-	case AWE_MAP_PRESET:
-		rc = awe_load_map(&patch, addr, count);
-		break;
-	/* case AWE_PROBE_INFO:
-		rc = awe_probe_info(&patch, addr, count);
-		break;*/
-	case AWE_PROBE_DATA:
-		rc = awe_probe_data(&patch, addr, count);
-		break;
-	case AWE_LOAD_CHORUS_FX:
-		rc = awe_load_chorus_fx(&patch, addr, count);
-		break;
-	case AWE_LOAD_REVERB_FX:
-		rc = awe_load_reverb_fx(&patch, addr, count);
-		break;
-
-	default:
-		printk("AWE32 Error: unknown patch format type %d\n",
-		       patch.type);
-		rc = RET_ERROR(EINVAL);
-	}
-
-	return rc;
-}
-
-
-/* create an sflist record */
-static int
-awe_create_sf(int type, char *name)
-{
-	sf_list *rec;
-
-	/* terminate sounds */
-	awe_reset(0);
-	if (current_sf_id >= max_sfs) {
-#ifndef AWE_DYNAMIC_BUFFER
-		return 1;
-#else
-		int newsize = max_sfs + AWE_MAX_SF_LISTS;
-		sf_list *newlist = realloc_block(sflists, sizeof(sf_list)*max_sfs,
-						 sizeof(sf_list)*newsize);
-		if (newlist == NULL)
-			return 1;
-		sflists = newlist;
-		max_sfs = newsize;
-#endif /* dynamic buffer */
-	}
-	rec = &sflists[current_sf_id];
-	rec->sf_id = current_sf_id + 1;
-	rec->type = type;
-	if (current_sf_id == 0 || (type & AWE_PAT_LOCKED) != 0)
-		locked_sf_id = current_sf_id + 1;
-	rec->num_info = awe_free_info();
-	rec->num_sample = awe_free_sample();
-	rec->mem_ptr = awe_free_mem_ptr();
-	rec->infos = -1;
-	rec->samples = -1;
-
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-	rec->shared = 0;
-	if (name)
-		memcpy(rec->name, name, AWE_PATCH_NAME_LEN);
-	else
-		strcpy(rec->name, "*TEMPORARY*");
-	if (current_sf_id > 0 && name && (type & AWE_PAT_SHARED) != 0) {
-		/* is the current font really a shared font? */
-		if (is_shared_sf(rec->name)) {
-			/* check if the shared font is already installed */
-			int i;
-			for (i = current_sf_id; i > 0; i--) {
-				if (is_identical_name(rec->name, i)) {
-					rec->shared = i;
-					break;
-				}
-			}
-		}
-	}
-#endif /* allow sharing */
-
-	current_sf_id++;
-
-	return 0;
-}
-
-
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-
-/* check if the given name is a valid shared name */
-#define ASC_TO_KEY(c) ((c) - 'A' + 1)
-static int is_shared_sf(unsigned char *name)
-{
-	static unsigned char id_head[6] = {
-		ASC_TO_KEY('A'), ASC_TO_KEY('W'), ASC_TO_KEY('E'),
-		AWE_MAJOR_VERSION,
-		AWE_MINOR_VERSION,
-		AWE_TINY_VERSION,
-	};
-	if (MEMCMP(name, id_head, 6) == 0)
-		return TRUE;
-	return FALSE;
-}
-
-/* check if the given name matches to the existing list */
-static int is_identical_name(unsigned char *name, int sf) 
-{
-	char *id = sflists[sf-1].name;
-	if (is_shared_sf(id) && MEMCMP(id, name, AWE_PATCH_NAME_LEN) == 0)
-		return TRUE;
-	return FALSE;
-}
-
-/* check if the given voice info exists */
-static int info_duplicated(awe_voice_list *rec)
-{
-	int j, sf_id;
-	sf_list *sf;
-
-	/* search for all sharing lists */
-	for (sf_id = rec->v.sf_id; sf_id > 0 && sf_id <= current_sf_id; sf_id = sf->shared) {
-		sf = &sflists[sf_id - 1];
-		for (j = sf->infos; j >= 0; j = infos[j].next) {
-			awe_voice_list *p = &infos[j];
-			if (p->type == V_ST_NORMAL &&
-			    p->bank == rec->bank &&
-			    p->instr == rec->instr &&
-			    p->v.low == rec->v.low &&
-			    p->v.high == rec->v.high &&
-			    p->v.sample == rec->v.sample)
-				return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-#endif /* AWE_ALLOW_SAMPLE_SHARING */
-
-
-/* open patch; create sf list and set opened flag */
-static int
-awe_open_patch(awe_patch_info *patch, const char *addr, int count)
-{
-	awe_open_parm parm;
-	int shared;
-
-	COPY_FROM_USER(&parm, addr, AWE_PATCH_INFO_SIZE, sizeof(parm));
-	shared = FALSE;
-
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-	if (current_sf_id > 0 && (parm.type & AWE_PAT_SHARED) != 0) {
-		/* is the previous font the same font? */
-		if (is_identical_name(parm.name, current_sf_id)) {
-			/* then append to the previous */
-			shared = TRUE;
-			awe_reset(0);
-			if (parm.type & AWE_PAT_LOCKED)
-				locked_sf_id = current_sf_id;
-		}
-	}
-#endif /* allow sharing */
-	if (! shared) {
-		if (awe_create_sf(parm.type, parm.name)) {
-			printk("AWE32: can't open: failed to alloc new list\n");
-			return RET_ERROR(ENOSPC);
-		}
-	}
-	patch_opened = TRUE;
-	return current_sf_id;
-}
-
-/* check if the patch is already opened */
-static int
-check_patch_opened(int type, char *name)
-{
-	if (! patch_opened) {
-		if (awe_create_sf(type, name)) {
-			printk("AWE32: failed to alloc new list\n");
-			return RET_ERROR(ENOSPC);
-		}
-		patch_opened = TRUE;
-		return current_sf_id;
-	}
-	return current_sf_id;
-}
-
-/* close the patch; if no voice is loaded, remove the patch */
-static int
-awe_close_patch(awe_patch_info *patch, const char *addr, int count)
-{
-	if (patch_opened && current_sf_id > 0) {
-		/* if no voice is loaded, release the current patch */
-		if (sflists[current_sf_id-1].infos == -1)
-			awe_remove_samples(current_sf_id - 1);
-	}
-	patch_opened = 0;
-	return 0;
-}
-
-
-/* remove the latest patch */
-static int
-awe_unload_patch(awe_patch_info *patch, const char *addr, int count)
-{
-	if (current_sf_id > 0 && current_sf_id > locked_sf_id)
-		awe_remove_samples(current_sf_id - 1);
-	return 0;
-}
-
-/* allocate voice info list records */
-static int alloc_new_info(int nvoices)
-{
-	int newsize, free_info;
-	awe_voice_list *newlist;
-	free_info = awe_free_info();
-	if (free_info + nvoices >= max_infos) {
-#ifndef AWE_DYNAMIC_BUFFER
-		printk("AWE32: can't alloc info table\n");
-		return RET_ERROR(ENOSPC);
-#else
-		do {
-			newsize = max_infos + AWE_MAX_INFOS;
-		} while (free_info + nvoices >= newsize);
-		newlist = realloc_block(infos, sizeof(awe_voice_list)*max_infos,
-					sizeof(awe_voice_list)*newsize);
-		if (newlist == NULL) {
-			printk("AWE32: can't alloc info table\n");
-			return RET_ERROR(ENOSPC);
-		}
-		infos = newlist;
-		max_infos = newsize;
-#endif
-	}
-	return 0;
-}
-
-/* allocate sample info list records */
-static int alloc_new_sample(void)
-{
-	int newsize, free_sample;
-	awe_sample_list *newlist;
-	free_sample = awe_free_sample();
-	if (free_sample >= max_samples) {
-#ifndef AWE_DYNAMIC_BUFFER
-		printk("AWE32: can't alloc sample table\n");
-		return RET_ERROR(ENOSPC);
-#else
-		newsize = max_samples + AWE_MAX_SAMPLES;
-		newlist = realloc_block(samples,
-					sizeof(awe_sample_list)*max_samples,
-					sizeof(awe_sample_list)*newsize);
-		if (newlist == NULL) {
-			printk("AWE32: can't alloc sample table\n");
-			return RET_ERROR(ENOSPC);
-		}
-		samples = newlist;
-		max_samples = newsize;
-#endif
-	}
-	return 0;
-}
-
-/* load voice map */
-static int
-awe_load_map(awe_patch_info *patch, const char *addr, int count)
-{
-	awe_voice_map map;
-	awe_voice_list *rec;
-	int p, free_info;
-
-	/* get the link info */
-	if (count < sizeof(map)) {
-		printk("AWE32 Error: invalid patch info length\n");
-		return RET_ERROR(EINVAL);
-	}
-	COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map));
-	
-	/* check if the identical mapping already exists */
-	p = awe_search_instr(map.map_bank, map.map_instr);
-	for (; p >= 0; p = infos[p].next_instr) {
-		if (p >= 0 && infos[p].type == V_ST_MAPPED &&
-		    infos[p].v.low == map.map_key &&
-		    infos[p].v.start == map.src_instr &&
-		    infos[p].v.end == map.src_bank &&
-		    infos[p].v.fixkey == map.src_key)
-			return 0; /* already present! */
-	}
-
-	if (check_patch_opened(AWE_PAT_TYPE_MAP, NULL) < 0)
-		return RET_ERROR(ENOSPC);
-
-	if (alloc_new_info(1) < 0)
-		return RET_ERROR(ENOSPC);
-
-	free_info = awe_free_info();
-	rec = &infos[free_info];
-	rec->bank = map.map_bank;
-	rec->instr = map.map_instr;
-	rec->type = V_ST_MAPPED;
-	rec->disabled = FALSE;
-	awe_init_voice_info(&rec->v);
-	if (map.map_key >= 0) {
-		rec->v.low = map.map_key;
-		rec->v.high = map.map_key;
-	}
-	rec->v.start = map.src_instr;
-	rec->v.end = map.src_bank;
-	rec->v.fixkey = map.src_key;
-	rec->v.sf_id = current_sf_id;
-	add_info_list(free_info);
-	add_sf_info(free_info);
-
-	return 0;
-}
-
-#if 0
-/* probe preset in the current list -- nothing to be loaded */
-static int
-awe_probe_info(awe_patch_info *patch, const char *addr, int count)
-{
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-	awe_voice_map map;
-	int p;
-
-	if (! patch_opened)
-		return RET_ERROR(EINVAL);
-
-	/* get the link info */
-	if (count < sizeof(map)) {
-		printk("AWE32 Error: invalid patch info length\n");
-		return RET_ERROR(EINVAL);
-	}
-	COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map));
-	
-	/* check if the identical mapping already exists */
-	p = awe_search_instr(map.src_bank, map.src_instr);
-	for (; p >= 0; p = infos[p].next_instr) {
-		if (p >= 0 && infos[p].type == V_ST_NORMAL &&
-		    is_identical_id(infos[p].v.sf_id, current_sf_id) &&
-		    infos[p].v.low <= map.src_key &&
-		    infos[p].v.high >= map.src_key)
-			return 0; /* already present! */
-	}
-#endif /* allow sharing */
-	return RET_ERROR(EINVAL);
-}
-#endif
-
-/* probe sample in the current list -- nothing to be loaded */
-static int
-awe_probe_data(awe_patch_info *patch, const char *addr, int count)
-{
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-	if (! patch_opened)
-		return RET_ERROR(EINVAL);
-
-	/* search the specified sample by optarg */
-	if (search_sample_index(current_sf_id, patch->optarg, 0) >= 0)
-		return 0;
-#endif /* allow sharing */
-	return RET_ERROR(EINVAL);
-}
-
-/* load voice information data */
-static int
-awe_load_info(awe_patch_info *patch, const char *addr, int count)
-{
-	int offset;
-	awe_voice_rec_hdr hdr;
-	int i;
-	int total_size;
-
-	if (count < AWE_VOICE_REC_SIZE) {
-		printk("AWE32 Error: invalid patch info length\n");
-		return RET_ERROR(EINVAL);
-	}
-
-	offset = AWE_PATCH_INFO_SIZE;
-	COPY_FROM_USER((char*)&hdr, addr, offset, AWE_VOICE_REC_SIZE);
-	offset += AWE_VOICE_REC_SIZE;
-
-	if (hdr.nvoices <= 0 || hdr.nvoices >= 100) {
-		printk("AWE32 Error: Illegal voice number %d\n", hdr.nvoices);
-		return RET_ERROR(EINVAL);
-	}
-	total_size = AWE_VOICE_REC_SIZE + AWE_VOICE_INFO_SIZE * hdr.nvoices;
-	if (count < total_size) {
-		printk("AWE32 Error: patch length(%d) is smaller than nvoices(%d)\n",
-		       count, hdr.nvoices);
-		return RET_ERROR(EINVAL);
-	}
-
-	if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0)
-		return RET_ERROR(ENOSPC);
-
-#if 0 /* it looks like not so useful.. */
-	/* check if the same preset already exists in the info list */
-	for (i = sflists[current_sf_id-1].infos; i >= 0; i = infos[i].next) {
-		if (infos[i].disabled) continue;
-		if (infos[i].bank == hdr.bank && infos[i].instr == hdr.instr) {
-			/* in exclusive mode, do skip loading this */
-			if (hdr.write_mode == AWE_WR_EXCLUSIVE)
-				return 0;
-			/* in replace mode, disable the old data */
-			else if (hdr.write_mode == AWE_WR_REPLACE)
-				infos[i].disabled = TRUE;
-		}
-	}
-	if (hdr.write_mode == AWE_WR_REPLACE)
-		rebuild_preset_list();
-#endif
-
-	if (alloc_new_info(hdr.nvoices) < 0)
-		return RET_ERROR(ENOSPC);
-
-	for (i = 0; i < hdr.nvoices; i++) {
-		int rec = awe_free_info();
-
-		infos[rec].bank = hdr.bank;
-		infos[rec].instr = hdr.instr;
-		infos[rec].type = V_ST_NORMAL;
-		infos[rec].disabled = FALSE;
-
-		/* copy awe_voice_info parameters */
-		COPY_FROM_USER(&infos[rec].v, addr, offset, AWE_VOICE_INFO_SIZE);
-		offset += AWE_VOICE_INFO_SIZE;
-		infos[rec].v.sf_id = current_sf_id;
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-		if (sflists[current_sf_id-1].shared) {
-			if (info_duplicated(&infos[rec]))
-				continue;
-		}
-#endif /* allow sharing */
-		if (infos[rec].v.mode & AWE_MODE_INIT_PARM)
-			awe_init_voice_parm(&infos[rec].v.parm);
-		awe_set_sample(&infos[rec].v);
-		add_info_list(rec);
-		add_sf_info(rec);
-	}
-
-	return 0;
-}
-
-
-/* load wave sample data */
-static int
-awe_load_data(awe_patch_info *patch, const char *addr, int count)
-{
-	int offset, size;
-	int rc, free_sample;
-	awe_sample_info tmprec, *rec;
-
-	if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0)
-		return RET_ERROR(ENOSPC);
-
-	size = (count - AWE_SAMPLE_INFO_SIZE) / 2;
-	offset = AWE_PATCH_INFO_SIZE;
-	COPY_FROM_USER(&tmprec, addr, offset, AWE_SAMPLE_INFO_SIZE);
-	offset += AWE_SAMPLE_INFO_SIZE;
-	if (size != tmprec.size) {
-		printk("AWE32: load: sample size differed (%d != %d)\n",
-		       tmprec.size, size);
-		return RET_ERROR(EINVAL);
-	}
-
-	if (search_sample_index(current_sf_id, tmprec.sample, 0) >= 0) {
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-		/* if shared sample, skip this data */
-		if (sflists[current_sf_id-1].type & AWE_PAT_SHARED)
-			return 0;
-#endif /* allow sharing */
-		DEBUG(1,printk("AWE32: sample data %d already present\n", tmprec.sample));
-		return RET_ERROR(EINVAL);
-	}
-
-	if (alloc_new_sample() < 0)
-		return RET_ERROR(ENOSPC);
-
-	free_sample = awe_free_sample();
-	rec = &samples[free_sample].v;
-	*rec = tmprec;
-
-	if (rec->size > 0)
-		if ((rc = awe_write_wave_data(addr, offset, rec, -1)) != 0)
-			return rc;
-
-	rec->sf_id = current_sf_id;
-
-	add_sf_sample(free_sample);
-
-	return 0;
-}
-
-
-/* replace wave sample data */
-static int
-awe_replace_data(awe_patch_info *patch, const char *addr, int count)
-{
-	int offset;
-	int size;
-	int rc, i;
-	int channels;
-	awe_sample_info cursmp;
-	int save_mem_ptr;
-
-	if (! patch_opened) {
-		printk("AWE32: replace: patch not opened\n");
-		return RET_ERROR(EINVAL);
-	}
-
-	size = (count - AWE_SAMPLE_INFO_SIZE) / 2;
-	offset = AWE_PATCH_INFO_SIZE;
-	COPY_FROM_USER(&cursmp, addr, offset, AWE_SAMPLE_INFO_SIZE);
-	offset += AWE_SAMPLE_INFO_SIZE;
-	if (cursmp.size == 0 || size != cursmp.size) {
-		printk("AWE32: replace: illegal sample size (%d!=%d)\n",
-		       cursmp.size, size);
-		return RET_ERROR(EINVAL);
-	}
-	channels = patch->optarg;
-	if (channels <= 0 || channels > AWE_NORMAL_VOICES) {
-		printk("AWE32: replace: illegal channels %d\n", channels);
-		return RET_ERROR(EINVAL);
-	}
-
-	for (i = sflists[current_sf_id-1].samples;
-	     i >= 0; i = samples[i].next) {
-		if (samples[i].v.sample == cursmp.sample)
-			break;
-	}
-	if (i < 0) {
-		printk("AWE32: replace: cannot find existing sample data %d\n",
-		       cursmp.sample);
-		return RET_ERROR(EINVAL);
-	}
-		
-	if (samples[i].v.size != cursmp.size) {
-		printk("AWE32: replace: exiting size differed (%d!=%d)\n",
-		       samples[i].v.size, cursmp.size);
-		return RET_ERROR(EINVAL);
-	}
-
-	save_mem_ptr = awe_free_mem_ptr();
-	sflists[current_sf_id-1].mem_ptr = samples[i].v.start - awe_mem_start;
-	MEMCPY(&samples[i].v, &cursmp, sizeof(cursmp));
-	if ((rc = awe_write_wave_data(addr, offset, &samples[i].v, channels)) != 0)
-		return rc;
-	sflists[current_sf_id-1].mem_ptr = save_mem_ptr;
-	samples[i].v.sf_id = current_sf_id;
-
-	return 0;
-}
-
-
-/*----------------------------------------------------------------*/
-
-static const char *readbuf_addr;
-static int readbuf_offs;
-static int readbuf_flags;
-#ifdef MALLOC_LOOP_DATA
-static unsigned short *readbuf_loop;
-static int readbuf_loopstart, readbuf_loopend;
-#endif
-
-/* initialize read buffer */
-static int
-readbuf_init(const char *addr, int offset, awe_sample_info *sp)
-{
-#ifdef MALLOC_LOOP_DATA
-	readbuf_loop = NULL;
-	readbuf_loopstart = sp->loopstart;
-	readbuf_loopend = sp->loopend;
-	if (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) {
-		int looplen = sp->loopend - sp->loopstart;
-		readbuf_loop = my_malloc(looplen * 2);
-		if (readbuf_loop == NULL) {
-			printk("AWE32: can't malloc temp buffer\n");
-			return RET_ERROR(ENOSPC);
-		}
-	}
-#endif
-	readbuf_addr = addr;
-	readbuf_offs = offset;
-	readbuf_flags = sp->mode_flags;
-	return 0;
-}
-
-/* read directly from user buffer */
-static unsigned short
-readbuf_word(int pos)
-{
-	unsigned short c;
-	/* read from user buffer */
-	if (readbuf_flags & AWE_SAMPLE_8BITS) {
-		unsigned char cc;
-		GET_BYTE_FROM_USER(cc, readbuf_addr, readbuf_offs + pos);
-		c = cc << 8; /* convert 8bit -> 16bit */
-	} else {
-		GET_SHORT_FROM_USER(c, readbuf_addr, readbuf_offs + pos * 2);
-	}
-	if (readbuf_flags & AWE_SAMPLE_UNSIGNED)
-		c ^= 0x8000; /* unsigned -> signed */
-#ifdef MALLOC_LOOP_DATA
-	/* write on cache for reverse loop */
-	if (readbuf_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) {
-		if (pos >= readbuf_loopstart && pos < readbuf_loopend)
-			readbuf_loop[pos - readbuf_loopstart] = c;
-	}
-#endif
-	return c;
-}
-
-#ifdef MALLOC_LOOP_DATA
-/* read from cache */
-static unsigned short
-readbuf_word_cache(int pos)
-{
-	if (pos >= readbuf_loopstart && pos < readbuf_loopend)
-		return readbuf_loop[pos - readbuf_loopstart];
-	return 0;
-}
-
-static void
-readbuf_end(void)
-{
-	if (readbuf_loop) {
-		my_free(readbuf_loop);
-	}
-	readbuf_loop = NULL;
-}
-
-#else
-
-#define readbuf_word_cache	readbuf_word
-#define readbuf_end()		/**/
-
-#endif
-
-/*----------------------------------------------------------------*/
-
-#define BLANK_LOOP_START	8
-#define BLANK_LOOP_END		40
-#define BLANK_LOOP_SIZE		48
-
-/* loading onto memory */
-static int 
-awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels)
-{
-	int i, truesize, dram_offset;
-	int rc;
-
-	/* be sure loop points start < end */
-	if (sp->loopstart > sp->loopend) {
-		int tmp = sp->loopstart;
-		sp->loopstart = sp->loopend;
-		sp->loopend = tmp;
-	}
-
-	/* compute true data size to be loaded */
-	truesize = sp->size;
-	if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP)
-		truesize += sp->loopend - sp->loopstart;
-	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK)
-		truesize += BLANK_LOOP_SIZE;
-	if (awe_free_mem_ptr() + truesize >= awe_mem_size/2) {
-		DEBUG(-1,printk("AWE32 Error: Sample memory full\n"));
-		return RET_ERROR(ENOSPC);
-	}
-
-	/* recalculate address offset */
-	sp->end -= sp->start;
-	sp->loopstart -= sp->start;
-	sp->loopend -= sp->start;
-
-	dram_offset = awe_free_mem_ptr() + awe_mem_start;
-	sp->start = dram_offset;
-	sp->end += dram_offset;
-	sp->loopstart += dram_offset;
-	sp->loopend += dram_offset;
-
-	/* set the total size (store onto obsolete checksum value) */
-	if (sp->size == 0)
-		sp->checksum = 0;
-	else
-		sp->checksum = truesize;
-
-	if ((rc = awe_open_dram_for_write(dram_offset, channels)) != 0)
-		return rc;
-
-	if (readbuf_init(addr, offset, sp) < 0)
-		return RET_ERROR(ENOSPC);
-
-	for (i = 0; i < sp->size; i++) {
-		unsigned short c;
-		c = readbuf_word(i);
-		awe_write_dram(c);
-		if (i == sp->loopend &&
-		    (sp->mode_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP))) {
-			int looplen = sp->loopend - sp->loopstart;
-			/* copy reverse loop */
-			int k;
-			for (k = 1; k <= looplen; k++) {
-				c = readbuf_word_cache(i - k);
-				awe_write_dram(c);
-			}
-			if (sp->mode_flags & AWE_SAMPLE_BIDIR_LOOP) {
-				sp->end += looplen;
-			} else {
-				sp->start += looplen;
-				sp->end += looplen;
-			}
-		}
-	}
-	readbuf_end();
-
-	/* if no blank loop is attached in the sample, add it */
-	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK) {
-		for (i = 0; i < BLANK_LOOP_SIZE; i++)
-			awe_write_dram(0);
-		if (sp->mode_flags & AWE_SAMPLE_SINGLESHOT) {
-			sp->loopstart = sp->end + BLANK_LOOP_START;
-			sp->loopend = sp->end + BLANK_LOOP_END;
-		}
-	}
-
-	sflists[current_sf_id-1].mem_ptr += truesize;
-	awe_close_dram();
-
-	/* initialize FM */
-	awe_init_fm();
-
-	return 0;
-}
-
-
-/*----------------------------------------------------------------*/
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-
-/* calculate GUS envelope time:
- * is this correct?  i have no idea..
- */
-static int
-calc_gus_envelope_time(int rate, int start, int end)
-{
-	int r, p, t;
-	r = (3 - ((rate >> 6) & 3)) * 3;
-	p = rate & 0x3f;
-	t = end - start;
-	if (t < 0) t = -t;
-	if (13 > r)
-		t = t << (13 - r);
-	else
-		t = t >> (r - 13);
-	return (t * 10) / (p * 441);
-}
-
-#define calc_gus_sustain(val)  (0x7f - vol_table[(val)/2])
-#define calc_gus_attenuation(val)	vol_table[(val)/2]
-
-/* load GUS patch */
-static int
-awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag)
-{
-	struct patch_info patch;
-	awe_voice_info *rec;
-	awe_sample_info *smp;
-	int sizeof_patch;
-	int note, free_sample, free_info;
-	int rc;
-
-	sizeof_patch = (int)((long)&patch.data[0] - (long)&patch); /* header size */
-	if (size < sizeof_patch) {
-		printk("AWE32 Error: Patch header too short\n");
-		return RET_ERROR(EINVAL);
-	}
-	COPY_FROM_USER(((char*)&patch) + offs, addr, offs, sizeof_patch - offs);
-	size -= sizeof_patch;
-	if (size < patch.len) {
-		printk("AWE32 Warning: Patch record too short (%d<%d)\n",
-		       size, patch.len);
-		return RET_ERROR(EINVAL);
-	}
-	if (check_patch_opened(AWE_PAT_TYPE_GUS, NULL) < 0)
-		return RET_ERROR(ENOSPC);
-	if (alloc_new_sample() < 0)
-		return RET_ERROR(ENOSPC);
-	if (alloc_new_info(1))
-		return RET_ERROR(ENOSPC);
-
-	free_sample = awe_free_sample();
-	smp = &samples[free_sample].v;
-
-	smp->sample = free_sample;
-	smp->start = 0;
-	smp->end = patch.len;
-	smp->loopstart = patch.loop_start;
-	smp->loopend = patch.loop_end;
-	smp->size = patch.len;
-
-	/* set up mode flags */
-	smp->mode_flags = 0;
-	if (!(patch.mode & WAVE_16_BITS))
-		smp->mode_flags |= AWE_SAMPLE_8BITS;
-	if (patch.mode & WAVE_UNSIGNED)
-		smp->mode_flags |= AWE_SAMPLE_UNSIGNED;
-	smp->mode_flags |= AWE_SAMPLE_NO_BLANK;
-	if (!(patch.mode & (WAVE_LOOPING|WAVE_BIDIR_LOOP|WAVE_LOOP_BACK)))
-		smp->mode_flags |= AWE_SAMPLE_SINGLESHOT;
-	if (patch.mode & WAVE_BIDIR_LOOP)
-		smp->mode_flags |= AWE_SAMPLE_BIDIR_LOOP;
-	if (patch.mode & WAVE_LOOP_BACK)
-		smp->mode_flags |= AWE_SAMPLE_REVERSE_LOOP;
-
-	DEBUG(0,printk("AWE32: [sample %d mode %x]\n", patch.instr_no, smp->mode_flags));
-	if (patch.mode & WAVE_16_BITS) {
-		/* convert to word offsets */
-		smp->size /= 2;
-		smp->end /= 2;
-		smp->loopstart /= 2;
-		smp->loopend /= 2;
-	}
-	smp->checksum_flag = 0;
-	smp->checksum = 0;
-
-	if ((rc = awe_write_wave_data(addr, sizeof_patch, smp, -1)) != 0)
-		return rc;
-
-	smp->sf_id = current_sf_id;
-	add_sf_sample(free_sample);
-
-	/* set up voice info */
-	free_info = awe_free_info();
-	rec = &infos[free_info].v;
-	awe_init_voice_info(rec);
-	rec->sample = free_sample; /* the last sample */
-	rec->rate_offset = calc_rate_offset(patch.base_freq);
-	note = freq_to_note(patch.base_note);
-	rec->root = note / 100;
-	rec->tune = -(note % 100);
-	rec->low = freq_to_note(patch.low_note) / 100;
-	rec->high = freq_to_note(patch.high_note) / 100;
-	DEBUG(1,printk("AWE32: [gus base offset=%d, note=%d, range=%d-%d(%d-%d)]\n",
-		       rec->rate_offset, note,
-		       rec->low, rec->high,
-	      patch.low_note, patch.high_note));
-	/* panning position; -128 - 127 => 0-127 */
-	rec->pan = (patch.panning + 128) / 2;
-
-	/* detuning is ignored */
-	/* 6points volume envelope */
-	if (patch.mode & WAVE_ENVELOPES) {
-		int attack, hold, decay, release;
-		attack = calc_gus_envelope_time
-			(patch.env_rate[0], 0, patch.env_offset[0]);
-		hold = calc_gus_envelope_time
-			(patch.env_rate[1], patch.env_offset[0],
-			 patch.env_offset[1]);
-		decay = calc_gus_envelope_time
-			(patch.env_rate[2], patch.env_offset[1],
-			 patch.env_offset[2]);
-		release = calc_gus_envelope_time
-			(patch.env_rate[3], patch.env_offset[1],
-			 patch.env_offset[4]);
-		release += calc_gus_envelope_time
-			(patch.env_rate[4], patch.env_offset[3],
-			 patch.env_offset[4]);
-		release += calc_gus_envelope_time
-			(patch.env_rate[5], patch.env_offset[4],
-			 patch.env_offset[5]);
-		rec->parm.volatkhld = (calc_parm_attack(attack) << 8) |
-			calc_parm_hold(hold);
-		rec->parm.voldcysus = (calc_gus_sustain(patch.env_offset[2]) << 8) |
-			calc_parm_decay(decay);
-		rec->parm.volrelease = 0x8000 | calc_parm_decay(release);
-		DEBUG(2,printk("AWE32: [gusenv atk=%d, hld=%d, dcy=%d, rel=%d]\n", attack, hold, decay, release));
-		rec->attenuation = calc_gus_attenuation(patch.env_offset[0]);
-	}
-
-	/* tremolo effect */
-	if (patch.mode & WAVE_TREMOLO) {
-		int rate = (patch.tremolo_rate * 1000 / 38) / 42;
-		rec->parm.tremfrq = ((patch.tremolo_depth / 2) << 8) | rate;
-		DEBUG(2,printk("AWE32: [gusenv tremolo rate=%d, dep=%d, tremfrq=%x]\n",
-			       patch.tremolo_rate, patch.tremolo_depth,
-			       rec->parm.tremfrq));
-	}
-	/* vibrato effect */
-	if (patch.mode & WAVE_VIBRATO) {
-		int rate = (patch.vibrato_rate * 1000 / 38) / 42;
-		rec->parm.fm2frq2 = ((patch.vibrato_depth / 6) << 8) | rate;
-		DEBUG(2,printk("AWE32: [gusenv vibrato rate=%d, dep=%d, tremfrq=%x]\n",
-			       patch.tremolo_rate, patch.tremolo_depth,
-			       rec->parm.tremfrq));
-	}
-	
-	/* scale_freq, scale_factor, volume, and fractions not implemented */
-
-	/* append to the tail of the list */
-	infos[free_info].bank = ctrls[AWE_MD_GUS_BANK];
-	infos[free_info].instr = patch.instr_no;
-	infos[free_info].disabled = FALSE;
-	infos[free_info].type = V_ST_NORMAL;
-	infos[free_info].v.sf_id = current_sf_id;
-
-	add_info_list(free_info);
-	add_sf_info(free_info);
-
-	/* set the voice index */
-	awe_set_sample(rec);
-
-	return 0;
-}
-
-#endif  /* AWE_HAS_GUS_COMPATIBILITY */
-
-/*----------------------------------------------------------------
- * sample and voice list handlers
- *----------------------------------------------------------------*/
-
-/* append this to the sf list */
-static void add_sf_info(int rec)
-{
-	int sf_id = infos[rec].v.sf_id;
-	if (sf_id <= 0) return;
-	sf_id--;
-	if (sflists[sf_id].infos < 0)
-		sflists[sf_id].infos = rec;
-	else {
-		int i, prev;
-		prev = sflists[sf_id].infos;
-		while ((i = infos[prev].next) >= 0)
-			prev = i;
-		infos[prev].next = rec;
-	}
-	infos[rec].next = -1;
-	sflists[sf_id].num_info++;
-}
-
-/* prepend this sample to sf list */
-static void add_sf_sample(int rec)
-{
-	int sf_id = samples[rec].v.sf_id;
-	if (sf_id <= 0) return;
-	sf_id--;
-	samples[rec].next = sflists[sf_id].samples;
-	sflists[sf_id].samples = rec;
-	sflists[sf_id].num_sample++;
-}
-
-/* purge the old records which don't belong with the same file id */
-static void purge_old_list(int rec, int next)
-{
-	infos[rec].next_instr = next;
-	if (infos[rec].bank == AWE_DRUM_BANK) {
-		/* remove samples with the same note range */
-		int cur, *prevp = &infos[rec].next_instr;
-		int low = infos[rec].v.low;
-		int high = infos[rec].v.high;
-		for (cur = next; cur >= 0; cur = infos[cur].next_instr) {
-			if (infos[cur].v.low == low &&
-			    infos[cur].v.high == high &&
-			    ! is_identical_id(infos[cur].v.sf_id, infos[rec].v.sf_id))
-				*prevp = infos[cur].next_instr;
-			prevp = &infos[cur].next_instr;
-		}
-	} else {
-		if (! is_identical_id(infos[next].v.sf_id, infos[rec].v.sf_id))
-			infos[rec].next_instr = -1;
-	}
-}
-
-/* prepend to top of the preset table */
-static void add_info_list(int rec)
-{
-	int *prevp, cur;
-	int instr;
-	int bank;
-
-	if (infos[rec].disabled)
-		return;
-
-	instr = infos[rec].instr;
-	bank = infos[rec].bank;
-	limitvalue(instr, 0, AWE_MAX_PRESETS-1);
-	prevp = &preset_table[instr];
-	cur = *prevp;
-	while (cur >= 0) {
-		/* search the first record with the same bank number */
-		if (infos[cur].bank == bank) {
-			/* replace the list with the new record */
-			infos[rec].next_bank = infos[cur].next_bank;
-			*prevp = rec;
-			purge_old_list(rec, cur);
-			return;
-		}
-		prevp = &infos[cur].next_bank;
-		cur = infos[cur].next_bank;
-	}
-
-	/* this is the first bank record.. just add this */
-	infos[rec].next_instr = -1;
-	infos[rec].next_bank = preset_table[instr];
-	preset_table[instr] = rec;
-}
-
-/* remove samples later than the specified sf_id */
-static void
-awe_remove_samples(int sf_id)
-{
-	if (sf_id <= 0) {
-		awe_reset_samples();
-		return;
-	}
-	/* already removed? */
-	if (current_sf_id <= sf_id)
-		return;
-
-	current_sf_id = sf_id;
-	if (locked_sf_id > sf_id)
-		locked_sf_id = sf_id;
-
-	rebuild_preset_list();
-}
-
-/* rebuild preset search list */
-static void rebuild_preset_list(void)
-{
-	int i, j;
-
-	for (i = 0; i < AWE_MAX_PRESETS; i++)
-		preset_table[i] = -1;
-
-	for (i = 0; i < current_sf_id; i++) {
-		for (j = sflists[i].infos; j >= 0; j = infos[j].next)
-			add_info_list(j);
-	}
-}
-
-/* compare the given sf_id pair */
-static int is_identical_id(int id1, int id2)
-{
-	if (id1 == id2)
-		return TRUE;
-	if (id1 <= 0 || id2 <= 0) /* this must not happen.. */
-		return FALSE;
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-	{
-		/* compare with the sharing id */
-		int i;
-		if (id1 < id2) { /* make sure id1 > id2 */
-			int tmp; tmp = id1; id1 = id2; id2 = tmp;
-		}
-		for (i = sflists[id1-1].shared; i > 0 && i <= current_sf_id; i = sflists[i-1].shared) {
-			if (i == id2)
-				return TRUE;
-		}
-	}
-#endif /* allow sharing */
-	return FALSE;
-}
-
-/* search the sample index matching with the given sample id */
-static int search_sample_index(int sf, int sample, int level)
-{
-	int i;
-
-	if (sf <= 0 || sf > current_sf_id)
-		return -1; /* this must not happen */
-
-	for (i = sflists[sf-1].samples; i >= 0; i = samples[i].next) {
-		if (samples[i].v.sample == sample)
-			return i;
-	}
-#ifdef AWE_ALLOW_SAMPLE_SHARING
-	if ((i = sflists[sf-1].shared) > 0 && i <= current_sf_id) { /* search recursively */
-		if (level > current_sf_id)
-			return -1; /* strange sharing loop.. quit */
-		return search_sample_index(i, sample, level + 1);
-	}
-#endif
-	return -1;
-}
-
-/* search the specified sample */
-static short
-awe_set_sample(awe_voice_info *vp)
-{
-	int i;
-
-	vp->index = -1;
-	if ((i = search_sample_index(vp->sf_id, vp->sample, 0)) < 0)
-		return -1;
-
-	/* set the actual sample offsets */
-	vp->start += samples[i].v.start;
-	vp->end += samples[i].v.end;
-	vp->loopstart += samples[i].v.loopstart;
-	vp->loopend += samples[i].v.loopend;
-	/* copy mode flags */
-	vp->mode = samples[i].v.mode_flags;
-	/* set index */
-	vp->index = i;
-
-	return i;
-}
-
-
-/*----------------------------------------------------------------
- * voice allocation
- *----------------------------------------------------------------*/
-
-/* look for all voices associated with the specified note & velocity */
-static int
-awe_search_multi_voices(int rec, int note, int velocity, awe_voice_info **vlist)
-{
-	int nvoices;
-
-	nvoices = 0;
-	for (; rec >= 0; rec = infos[rec].next_instr) {
-		if (note >= infos[rec].v.low &&
-		    note <= infos[rec].v.high &&
-		    velocity >= infos[rec].v.vellow &&
-		    velocity <= infos[rec].v.velhigh) {
-			if (infos[rec].type == V_ST_MAPPED) {
-				/* mapper */
-				vlist[0] = &infos[rec].v;
-				return -1;
-			}
-			vlist[nvoices++] = &infos[rec].v;
-			if (nvoices >= AWE_MAX_VOICES)
-				break;
-		}
-	}
-	return nvoices;	
-}
-
-/* store the voice list from the specified note and velocity.
-   if the preset is mapped, seek for the destination preset, and rewrite
-   the note number if necessary.
-   */
-static int
-really_alloc_voices(int vrec, int def_vrec, int *note, int velocity, awe_voice_info **vlist, int level)
-{
-	int nvoices;
-
-	nvoices = awe_search_multi_voices(vrec, *note, velocity, vlist);
-	if (nvoices == 0)
-		nvoices = awe_search_multi_voices(def_vrec, *note, velocity, vlist);
-	if (nvoices < 0) { /* mapping */
-		int preset = vlist[0]->start;
-		int bank = vlist[0]->end;
-		int key = vlist[0]->fixkey;
-		if (level > 5) {
-			printk("AWE32: too deep mapping level\n");
-			return 0;
-		}
-		vrec = awe_search_instr(bank, preset);
-		if (bank == AWE_DRUM_BANK)
-			def_vrec = awe_search_instr(bank, 0);
-		else
-			def_vrec = awe_search_instr(0, preset);
-		if (key >= 0)
-			*note = key;
-		return really_alloc_voices(vrec, def_vrec, note, velocity, vlist, level+1);
-	}
-
-	return nvoices;
-}
-
-/* allocate voices corresponding note and velocity; supports multiple insts. */
-static void
-awe_alloc_multi_voices(int ch, int note, int velocity, int key)
-{
-	int i, v, nvoices;
-	awe_voice_info *vlist[AWE_MAX_VOICES];
-
-	if (channels[ch].vrec < 0 && channels[ch].def_vrec < 0)
-		awe_set_instr(0, ch, channels[ch].instr);
-
-	/* check the possible voices; note may be changeable if mapped */
-	nvoices = really_alloc_voices(channels[ch].vrec, channels[ch].def_vrec,
-				      &note, velocity, vlist, 0);
-
-	/* set the voices */
-	current_alloc_time++;
-	for (i = 0; i < nvoices; i++) {
-		v = awe_clear_voice();
-		voices[v].key = key;
-		voices[v].ch = ch;
-		voices[v].note = note;
-		voices[v].velocity = velocity;
-		voices[v].time = current_alloc_time;
-		voices[v].cinfo = &channels[ch];
-		voices[v].sample = vlist[i];
-		voices[v].state = AWE_ST_MARK;
-		voices[v].layer = nvoices - i - 1;  /* in reverse order */
-	}
-
-	/* clear the mark in allocated voices */
-	for (i = 0; i < awe_max_voices; i++) {
-		if (voices[i].state == AWE_ST_MARK)
-			voices[i].state = AWE_ST_OFF;
-			
-	}
-}
-
-
-/* search the best voice from the specified status condition */
-static int
-search_best_voice(int condition)
-{
-	int i, time, best;
-	int vtarget = 0xffff, min_vtarget = 0xffff;
-
-	best = -1;
-	time = current_alloc_time + 1;
-	for (i = 0; i < awe_max_voices; i++) {
-		if (! (voices[i].state & condition))
-			continue;
-#ifdef AWE_CHECK_VTARGET
-		/* get current volume */
-		vtarget = (awe_peek_dw(AWE_VTFT(i)) >> 16) & 0xffff;
-#endif
-		if (best < 0 || vtarget < min_vtarget ||
-		    (vtarget == min_vtarget && voices[i].time < time)) {
-			best = i;
-			time = voices[i].time;
-			min_vtarget = vtarget;
-		}
-	}
-	/* clear voice */
-	if (best >= 0) {
-		if (voices[best].state != AWE_ST_OFF)
-			awe_terminate(best);
-		awe_voice_init(best, TRUE);
-	}
-
-	return best;
-}
-
-/* search an empty voice.
-   if no empty voice is found, at least terminate a voice
-   */
-static int
-awe_clear_voice(void)
-{
-	int best;
-
-	/* looking for the oldest empty voice */
-	if ((best = search_best_voice(AWE_ST_OFF)) >= 0)
-		return best;
-	if ((best = search_best_voice(AWE_ST_RELEASED)) >= 0)
-		return best;
-	/* looking for the oldest sustained voice */
-	if ((best = search_best_voice(AWE_ST_SUSTAINED)) >= 0)
-		return best;
-
-	if (MULTI_LAYER_MODE() && ctrls[AWE_MD_CHN_PRIOR]) {
-		int ch = -1;
-		int time = current_alloc_time + 1;
-		int i;
-		/* looking for the voices from high channel (except drum ch) */
-		for (i = 0; i < awe_max_voices; i++) {
-			if (IS_DRUM_CHANNEL(voices[i].ch)) continue;
-			if (voices[i].ch < ch) continue;
-			if (voices[i].state != AWE_ST_MARK &&
-			    (voices[i].ch > ch || voices[i].time < time)) {
-				best = i;
-				time = voices[i].time;
-				ch = voices[i].ch;
-			}
-		}
-	}
-	if (best < 0)
-		best = search_best_voice(~AWE_ST_MARK);
-
-	if (best >= 0)
-		return best;
-
-	return 0;
-}
-
-
-/* search sample for the specified note & velocity and set it on the voice;
- * note that voice is the voice index (not channel index)
- */
-static void
-awe_alloc_one_voice(int voice, int note, int velocity)
-{
-	int ch, nvoices;
-	awe_voice_info *vlist[AWE_MAX_VOICES];
-
-	ch = voices[voice].ch;
-	if (channels[ch].vrec < 0 && channels[ch].def_vrec < 0)
-		awe_set_instr(0, ch, channels[ch].instr);
-
-	nvoices = really_alloc_voices(voices[voice].cinfo->vrec,
-				      voices[voice].cinfo->def_vrec,
-				      &note, velocity, vlist, 0);
-	if (nvoices > 0) {
-		voices[voice].time = ++current_alloc_time;
-		voices[voice].sample = vlist[0]; /* use the first one */
-		voices[voice].layer = 0;
-		voices[voice].note = note;
-		voices[voice].velocity = velocity;
-	}
-}
-
-
-/*----------------------------------------------------------------
- * sequencer2 functions
- *----------------------------------------------------------------*/
-
-/* search an empty voice; used by sequencer2 */
-static int
-awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc)
-{
-	playing_mode = AWE_PLAY_MULTI2;
-	awe_info.nr_voices = AWE_MAX_CHANNELS;
-	return awe_clear_voice();
-}
-
-
-/* set up voice; used by sequencer2 */
-static void
-awe_setup_voice(int dev, int voice, int chn)
-{
-	struct channel_info *info;
-	if (synth_devs[dev] == NULL ||
-	    (info = &synth_devs[dev]->chn_info[chn]) == NULL)
-		return;
-
-	if (voice < 0 || voice >= awe_max_voices)
-		return;
-
-	DEBUG(2,printk("AWE32: [setup(%d) ch=%d]\n", voice, chn));
-	channels[chn].expression_vol = info->controllers[CTL_EXPRESSION];
-	channels[chn].main_vol = info->controllers[CTL_MAIN_VOLUME];
-	channels[chn].panning =
-		info->controllers[CTL_PAN] * 2 - 128; /* signed 8bit */
-	channels[chn].bender = info->bender_value; /* zero center */
-	channels[chn].bank = info->controllers[CTL_BANK_SELECT];
-	channels[chn].sustained = info->controllers[CTL_SUSTAIN];
-	if (info->controllers[CTL_EXT_EFF_DEPTH]) {
-		FX_SET(&channels[chn].fx, AWE_FX_REVERB,
-		       info->controllers[CTL_EXT_EFF_DEPTH] * 2);
-	}
-	if (info->controllers[CTL_CHORUS_DEPTH]) {
-		FX_SET(&channels[chn].fx, AWE_FX_CHORUS,
-		       info->controllers[CTL_CHORUS_DEPTH] * 2);
-	}
-	awe_set_instr(dev, chn, info->pgm_num);
-}
-
-
-#ifdef CONFIG_AWE32_MIXER
-/*================================================================
- * AWE32 mixer device control
- *================================================================*/
-
-static int awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg);
-
-static int my_mixerdev = -1;
-
-static struct mixer_operations awe_mixer_operations = {
-#ifndef __FreeBSD__
-	"AWE32",
-#endif
-	"AWE32 Equalizer",
-	awe_mixer_ioctl,
-};
-
-static void attach_mixer(void)
-{
-	if ((my_mixerdev = sound_alloc_mixerdev()) >= 0) {
-		mixer_devs[my_mixerdev] = &awe_mixer_operations;
-	}
-}
-
-static void unload_mixer(void)
-{
-	if (my_mixerdev >= 0)
-		sound_unload_mixerdev(my_mixerdev);
-}
-
-static int
-awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
-{
-	int i, level, value;
-
-	if (((cmd >> 8) & 0xff) != 'M')
-		return RET_ERROR(EINVAL);
-
-	level = (int)IOCTL_IN(arg);
-	level = ((level & 0xff) + (level >> 8)) / 2;
-	DEBUG(0,printk("AWEMix: cmd=%x val=%d\n", cmd & 0xff, level));
-
-	if (IO_WRITE_CHECK(cmd)) {
-		switch (cmd & 0xff) {
-		case SOUND_MIXER_BASS:
-			value = level * 12 / 100;
-			if (value >= 12)
-				value = 11;
-			ctrls[AWE_MD_BASS_LEVEL] = value;
-			awe_update_equalizer();
-			break;
-		case SOUND_MIXER_TREBLE:
-			value = level * 12 / 100;
-			if (value >= 12)
-				value = 11;
-			ctrls[AWE_MD_TREBLE_LEVEL] = value;
-			awe_update_equalizer();
-			break;
-		case SOUND_MIXER_VOLUME:
-			level = level * 127 / 100;
-			if (level >= 128) level = 127;
-			atten_relative = FALSE;
-			atten_offset = vol_table[level];
-			awe_update_volume();
-			break;
-		}
-	}
-	switch (cmd & 0xff) {
-	case SOUND_MIXER_BASS:
-		level = ctrls[AWE_MD_BASS_LEVEL] * 100 / 24;
-		level = (level << 8) | level;
-		break;
-	case SOUND_MIXER_TREBLE:
-		level = ctrls[AWE_MD_TREBLE_LEVEL] * 100 / 24;
-		level = (level << 8) | level;
-		break;
-	case SOUND_MIXER_VOLUME:
-		value = atten_offset;
-		if (atten_relative)
-			value += ctrls[AWE_MD_ZERO_ATTEN];
-		for (i = 127; i > 0; i--) {
-			if (value <= vol_table[i])
-				break;
-		}
-		level = i * 100 / 127;
-		level = (level << 8) | level;
-		break;
-	case SOUND_MIXER_DEVMASK:
-		level = SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_VOLUME;
-		break;
-	default:
-		level = 0;
-		break;
-	}
-	return IOCTL_OUT(arg, level);
-}
-#endif /* CONFIG_AWE32_MIXER */
-
-
-/*================================================================
- * initialization of AWE32
- *================================================================*/
-
-/* intiailize audio channels */
-static void
-awe_init_audio(void)
-{
-	int ch;
-
-	/* turn off envelope engines */
-	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
-		awe_poke(AWE_DCYSUSV(ch), 0x80);
-	}
-  
-	/* reset all other parameters to zero */
-	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
-		awe_poke(AWE_ENVVOL(ch), 0);
-		awe_poke(AWE_ENVVAL(ch), 0);
-		awe_poke(AWE_DCYSUS(ch), 0);
-		awe_poke(AWE_ATKHLDV(ch), 0);
-		awe_poke(AWE_LFO1VAL(ch), 0);
-		awe_poke(AWE_ATKHLD(ch), 0);
-		awe_poke(AWE_LFO2VAL(ch), 0);
-		awe_poke(AWE_IP(ch), 0);
-		awe_poke(AWE_IFATN(ch), 0);
-		awe_poke(AWE_PEFE(ch), 0);
-		awe_poke(AWE_FMMOD(ch), 0);
-		awe_poke(AWE_TREMFRQ(ch), 0);
-		awe_poke(AWE_FM2FRQ2(ch), 0);
-		awe_poke_dw(AWE_PTRX(ch), 0);
-		awe_poke_dw(AWE_VTFT(ch), 0);
-		awe_poke_dw(AWE_PSST(ch), 0);
-		awe_poke_dw(AWE_CSL(ch), 0);
-		awe_poke_dw(AWE_CCCA(ch), 0);
-	}
-
-	for (ch = 0; ch < AWE_MAX_VOICES; ch++) {
-		awe_poke_dw(AWE_CPF(ch), 0);
-		awe_poke_dw(AWE_CVCF(ch), 0);
-	}
-}
-
-
-/* initialize DMA address */
-static void
-awe_init_dma(void)
-{
-	awe_poke_dw(AWE_SMALR, 0);
-	awe_poke_dw(AWE_SMARR, 0);
-	awe_poke_dw(AWE_SMALW, 0);
-	awe_poke_dw(AWE_SMARW, 0);
-}
-
-
-/* initialization arrays; from ADIP */
-
-static unsigned short init1[128] = {
-	0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
-	0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
-	0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
-	0x33ff, 0x0c30,  0x37ff, 0x0d30, 0x3bff, 0x0e30,  0x3fff, 0x0f30,
-
-	0x43ff, 0x0030,  0x47ff, 0x0130, 0x4bff, 0x0230,  0x4fff, 0x0330,
-	0x53ff, 0x0430,  0x57ff, 0x0530, 0x5bff, 0x0630,  0x5fff, 0x0730,
-	0x63ff, 0x0830,  0x67ff, 0x0930, 0x6bff, 0x0a30,  0x6fff, 0x0b30,
-	0x73ff, 0x0c30,  0x77ff, 0x0d30, 0x7bff, 0x0e30,  0x7fff, 0x0f30,
-
-	0x83ff, 0x0030,  0x87ff, 0x0130, 0x8bff, 0x0230,  0x8fff, 0x0330,
-	0x93ff, 0x0430,  0x97ff, 0x0530, 0x9bff, 0x0630,  0x9fff, 0x0730,
-	0xa3ff, 0x0830,  0xa7ff, 0x0930, 0xabff, 0x0a30,  0xafff, 0x0b30,
-	0xb3ff, 0x0c30,  0xb7ff, 0x0d30, 0xbbff, 0x0e30,  0xbfff, 0x0f30,
-
-	0xc3ff, 0x0030,  0xc7ff, 0x0130, 0xcbff, 0x0230,  0xcfff, 0x0330,
-	0xd3ff, 0x0430,  0xd7ff, 0x0530, 0xdbff, 0x0630,  0xdfff, 0x0730,
-	0xe3ff, 0x0830,  0xe7ff, 0x0930, 0xebff, 0x0a30,  0xefff, 0x0b30,
-	0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
-};
-
-static unsigned short init2[128] = {
-	0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
-	0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
-	0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
-	0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
-
-	0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
-	0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
-	0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
-	0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
-
-	0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
-	0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
-	0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
-	0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
-
-	0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
-	0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
-	0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
-	0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
-};
-
-static unsigned short init3[128] = {
-	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
-	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
-	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
-	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
-
-	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
-	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
-	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
-	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
-
-	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
-	0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
-	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
-	0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
-
-	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
-	0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
-	0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
-	0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
-};
-
-static unsigned short init4[128] = {
-	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
-	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
-	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
-	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
-
-	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
-	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
-	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
-	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
-
-	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
-	0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
-	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
-	0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
-
-	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
-	0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
-	0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
-	0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
-};
-
-
-/* send initialization arrays to start up */
-static void
-awe_init_array(void)
-{
-	awe_send_array(init1);
-	awe_wait(1024);
-	awe_send_array(init2);
-	awe_send_array(init3);
-	awe_poke_dw(AWE_HWCF4, 0);
-	awe_poke_dw(AWE_HWCF5, 0x83);
-	awe_poke_dw(AWE_HWCF6, 0x8000);
-	awe_send_array(init4);
-}
-
-/* send an initialization array */
-static void
-awe_send_array(unsigned short *data)
-{
-	int i;
-	unsigned short *p;
-
-	p = data;
-	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
-		awe_poke(AWE_INIT1(i), *p);
-	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
-		awe_poke(AWE_INIT2(i), *p);
-	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
-		awe_poke(AWE_INIT3(i), *p);
-	for (i = 0; i < AWE_MAX_VOICES; i++, p++)
-		awe_poke(AWE_INIT4(i), *p);
-}
-
-
-/*
- * set up awe32 channels to some known state.
- */
-
-/* set the envelope & LFO parameters to the default values; see ADIP */
-static void
-awe_tweak_voice(int i)
-{
-	/* set all mod/vol envelope shape to minimum */
-	awe_poke(AWE_ENVVOL(i), 0x8000);
-	awe_poke(AWE_ENVVAL(i), 0x8000);
-	awe_poke(AWE_DCYSUS(i), 0x7F7F);
-	awe_poke(AWE_ATKHLDV(i), 0x7F7F);
-	awe_poke(AWE_ATKHLD(i), 0x7F7F);
-	awe_poke(AWE_PEFE(i), 0);  /* mod envelope height to zero */
-	awe_poke(AWE_LFO1VAL(i), 0x8000); /* no delay for LFO1 */
-	awe_poke(AWE_LFO2VAL(i), 0x8000);
-	awe_poke(AWE_IP(i), 0xE000);	/* no pitch shift */
-	awe_poke(AWE_IFATN(i), 0xFF00);	/* volume to minimum */
-	awe_poke(AWE_FMMOD(i), 0);
-	awe_poke(AWE_TREMFRQ(i), 0);
-	awe_poke(AWE_FM2FRQ2(i), 0);
-}
-
-static void
-awe_tweak(void)
-{
-	int i;
-	/* reset all channels */
-	for (i = 0; i < awe_max_voices; i++)
-		awe_tweak_voice(i);
-}
-
-
-/*
- *  initializes the FM section of AWE32;
- *   see Vince Vu's unofficial AWE32 programming guide
- */
-
-static void
-awe_init_fm(void)
-{
-#ifndef AWE_ALWAYS_INIT_FM
-	/* if no extended memory is on board.. */
-	if (awe_mem_size <= 0)
-		return;
-#endif
-	DEBUG(3,printk("AWE32: initializing FM\n"));
-
-	/* Initialize the last two channels for DRAM refresh and producing
-	   the reverb and chorus effects for Yamaha OPL-3 synthesizer */
-
-	/* 31: FM left channel, 0xffffe0-0xffffe8 */
-	awe_poke(AWE_DCYSUSV(30), 0x80);
-	awe_poke_dw(AWE_PSST(30), 0xFFFFFFE0); /* full left */
-	awe_poke_dw(AWE_CSL(30), 0x00FFFFE8 |
-		    (DEF_FM_CHORUS_DEPTH << 24));
-	awe_poke_dw(AWE_PTRX(30), (DEF_FM_REVERB_DEPTH << 8));
-	awe_poke_dw(AWE_CPF(30), 0);
-	awe_poke_dw(AWE_CCCA(30), 0x00FFFFE3);
-
-	/* 32: FM right channel, 0xfffff0-0xfffff8 */
-	awe_poke(AWE_DCYSUSV(31), 0x80);
-	awe_poke_dw(AWE_PSST(31), 0x00FFFFF0); /* full right */
-	awe_poke_dw(AWE_CSL(31), 0x00FFFFF8 |
-		    (DEF_FM_CHORUS_DEPTH << 24));
-	awe_poke_dw(AWE_PTRX(31), (DEF_FM_REVERB_DEPTH << 8));
-	awe_poke_dw(AWE_CPF(31), 0x8000);
-	awe_poke_dw(AWE_CCCA(31), 0x00FFFFF3);
-
-	/* skew volume & cutoff */
-	awe_poke_dw(AWE_VTFT(30), 0x8000FFFF);
-	awe_poke_dw(AWE_VTFT(31), 0x8000FFFF);
-
-	voices[30].state = AWE_ST_FM;
-	voices[31].state = AWE_ST_FM;
-
-	/* change maximum channels to 30 */
-	awe_max_voices = AWE_NORMAL_VOICES;
-	if (playing_mode == AWE_PLAY_DIRECT)
-		awe_info.nr_voices = awe_max_voices;
-	else
-		awe_info.nr_voices = AWE_MAX_CHANNELS;
-	voice_alloc->max_voice = awe_max_voices;
-}
-
-/*
- *  AWE32 DRAM access routines
- */
-
-/* open DRAM write accessing mode */
-static int
-awe_open_dram_for_write(int offset, int channels)
-{
-	int vidx[AWE_NORMAL_VOICES];
-	int i;
-
-	if (channels < 0 || channels >= AWE_NORMAL_VOICES) {
-		channels = AWE_NORMAL_VOICES;
-		for (i = 0; i < AWE_NORMAL_VOICES; i++)
-			vidx[i] = i;
-	} else {
-		for (i = 0; i < channels; i++) {
-			vidx[i] = awe_clear_voice();
-			voices[vidx[i]].state = AWE_ST_MARK;
-		}
-	}
-
-	/* use all channels for DMA transfer */
-	for (i = 0; i < channels; i++) {
-		if (vidx[i] < 0) continue;
-		awe_poke(AWE_DCYSUSV(vidx[i]), 0x80);
-		awe_poke_dw(AWE_VTFT(vidx[i]), 0);
-		awe_poke_dw(AWE_CVCF(vidx[i]), 0);
-		awe_poke_dw(AWE_PTRX(vidx[i]), 0x40000000);
-		awe_poke_dw(AWE_CPF(vidx[i]), 0x40000000);
-		awe_poke_dw(AWE_PSST(vidx[i]), 0);
-		awe_poke_dw(AWE_CSL(vidx[i]), 0);
-		awe_poke_dw(AWE_CCCA(vidx[i]), 0x06000000);
-		voices[vidx[i]].state = AWE_ST_DRAM;
-	}
-	/* point channels 31 & 32 to ROM samples for DRAM refresh */
-	awe_poke_dw(AWE_VTFT(30), 0);
-	awe_poke_dw(AWE_PSST(30), 0x1d8);
-	awe_poke_dw(AWE_CSL(30), 0x1e0);
-	awe_poke_dw(AWE_CCCA(30), 0x1d8);
-	awe_poke_dw(AWE_VTFT(31), 0);
-	awe_poke_dw(AWE_PSST(31), 0x1d8);
-	awe_poke_dw(AWE_CSL(31), 0x1e0);
-	awe_poke_dw(AWE_CCCA(31), 0x1d8);
-	voices[30].state = AWE_ST_FM;
-	voices[31].state = AWE_ST_FM;
-
-	/* if full bit is on, not ready to write on */
-	if (awe_peek_dw(AWE_SMALW) & 0x80000000) {
-		for (i = 0; i < channels; i++) {
-			awe_poke_dw(AWE_CCCA(vidx[i]), 0);
-			voices[vidx[i]].state = AWE_ST_OFF;
-		}
-		return RET_ERROR(ENOSPC);
-	}
-
-	/* set address to write */
-	awe_poke_dw(AWE_SMALW, offset);
-
-	return 0;
-}
-
-/* open DRAM for RAM size detection */
-static void
-awe_open_dram_for_check(void)
-{
-	int i;
-	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
-		awe_poke(AWE_DCYSUSV(i), 0x80);
-		awe_poke_dw(AWE_VTFT(i), 0);
-		awe_poke_dw(AWE_CVCF(i), 0);
-		awe_poke_dw(AWE_PTRX(i), 0x40000000);
-		awe_poke_dw(AWE_CPF(i), 0x40000000);
-		awe_poke_dw(AWE_PSST(i), 0);
-		awe_poke_dw(AWE_CSL(i), 0);
-		if (i & 1) /* DMA write */
-			awe_poke_dw(AWE_CCCA(i), 0x06000000);
-		else	   /* DMA read */
-			awe_poke_dw(AWE_CCCA(i), 0x04000000);
-		voices[i].state = AWE_ST_DRAM;
-	}
-}
-
-
-/* close dram access */
-static void
-awe_close_dram(void)
-{
-	int i;
-	/* wait until FULL bit in SMAxW register be false */
-	for (i = 0; i < 10000; i++) {
-		if (!(awe_peek_dw(AWE_SMALW) & 0x80000000))
-			break;
-		awe_wait(10);
-	}
-
-	for (i = 0; i < AWE_NORMAL_VOICES; i++) {
-		if (voices[i].state == AWE_ST_DRAM) {
-			awe_poke_dw(AWE_CCCA(i), 0);
-			awe_poke(AWE_DCYSUSV(i), 0x807F);
-			voices[i].state = AWE_ST_OFF;
-		}
-	}
-}
-
-
-/*================================================================
- * detect presence of AWE32 and check memory size
- *================================================================*/
-
-/* detect emu8000 chip on the specified address; from VV's guide */
-
-static int
-awe_detect_base(int addr)
-{
-	setup_ports(addr, 0, 0);
-	if ((awe_peek(AWE_U1) & 0x000F) != 0x000C)
-		return 0;
-	if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058)
-		return 0;
-	if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003)
-		return 0;
-        DEBUG(0,printk("AWE32 found at %x\n", addr));
-	return 1;
-}
-	
-static int
-awe_detect(void)
-{
-	int base;
-
-	if (port_setuped) /* already initialized by PnP */
-		return 1;
-
-	if (awe_port) /* use default i/o port value */
-		setup_ports(awe_port, 0, 0);
-	else { /* probe it */
-		for (base = 0x620; base <= 0x680; base += 0x20)
-			if (awe_detect_base(base))
-				return 1;
-		DEBUG(0,printk("AWE32 not found\n"));
-		return 0;
-	}
-
-	return 1;
-}
-
-
-/*================================================================
- * check dram size on AWE board
- *================================================================*/
-
-/* any three numbers you like */
-#define UNIQUE_ID1	0x1234
-#define UNIQUE_ID2	0x4321
-#define UNIQUE_ID3	0xFFFF
-
-static void
-awe_check_dram(void)
-{
-	if (awe_present) /* already initialized */
-		return;
-
-	if (awe_mem_size >= 0) { /* given by config file or module option */
-		awe_mem_size *= 1024; /* convert to Kbytes */
-		return;
-	}
-
-	awe_open_dram_for_check();
-
-	awe_mem_size = 0;
-
-	/* set up unique two id numbers */
-	awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET);
-	awe_poke(AWE_SMLD, UNIQUE_ID1);
-	awe_poke(AWE_SMLD, UNIQUE_ID2);
-
-	while (awe_mem_size < AWE_MAX_DRAM_SIZE) {
-		awe_wait(5);
-		/* read a data on the DRAM start address */
-		awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET);
-		awe_peek(AWE_SMLD); /* discard stale data  */
-		if (awe_peek(AWE_SMLD) != UNIQUE_ID1)
-			break;
-		if (awe_peek(AWE_SMLD) != UNIQUE_ID2)
-			break;
-		awe_mem_size += 512;  /* increment 512kbytes */
-		/* Write a unique data on the test address;
-		 * if the address is out of range, the data is written on
-		 * 0x200000(=AWE_DRAM_OFFSET).  Then the two id words are
-		 * broken by this data.
-		 */
-		awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET + awe_mem_size*512L);
-		awe_poke(AWE_SMLD, UNIQUE_ID3);
-		awe_wait(5);
-		/* read a data on the just written DRAM address */
-		awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET + awe_mem_size*512L);
-		awe_peek(AWE_SMLD); /* discard stale data  */
-		if (awe_peek(AWE_SMLD) != UNIQUE_ID3)
-			break;
-	}
-	awe_close_dram();
-
-	DEBUG(0,printk("AWE32: %d Kbytes memory detected\n", awe_mem_size));
-
-	/* convert to Kbytes */
-	awe_mem_size *= 1024;
-}
-
-
-/*================================================================
- * chorus and reverb controls; from VV's guide
- *================================================================*/
-
-/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
-static char chorus_defined[AWE_CHORUS_NUMBERS];
-static awe_chorus_fx_rec chorus_parm[AWE_CHORUS_NUMBERS] = {
-	{0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
-	{0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
-	{0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
-	{0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
-	{0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
-	{0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
-	{0xE600, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay */
-	{0xE6C0, 0x0B06, 0xBC00, 0x0000E000, 0x00000083}, /* short delay + feedback */
-};
-
-static int
-awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count)
-{
-	if (patch->optarg < AWE_CHORUS_PREDEFINED || patch->optarg >= AWE_CHORUS_NUMBERS) {
-		printk("AWE32 Error: illegal chorus mode %d for uploading\n", patch->optarg);
-		return RET_ERROR(EINVAL);
-	}
-	if (count < sizeof(awe_chorus_fx_rec)) {
-		printk("AWE32 Error: too short chorus fx parameters\n");
-		return RET_ERROR(EINVAL);
-	}
-	COPY_FROM_USER(&chorus_parm[patch->optarg], addr, AWE_PATCH_INFO_SIZE,
-		       sizeof(awe_chorus_fx_rec));
-	chorus_defined[patch->optarg] = TRUE;
-	return 0;
-}
-
-static void
-awe_set_chorus_mode(int effect)
-{
-	if (effect < 0 || effect >= AWE_CHORUS_NUMBERS ||
-	    (effect >= AWE_CHORUS_PREDEFINED && !chorus_defined[effect]))
-		return;
-	awe_poke(AWE_INIT3(9), chorus_parm[effect].feedback);
-	awe_poke(AWE_INIT3(12), chorus_parm[effect].delay_offset);
-	awe_poke(AWE_INIT4(3), chorus_parm[effect].lfo_depth);
-	awe_poke_dw(AWE_HWCF4, chorus_parm[effect].delay);
-	awe_poke_dw(AWE_HWCF5, chorus_parm[effect].lfo_freq);
-	awe_poke_dw(AWE_HWCF6, 0x8000);
-	awe_poke_dw(AWE_HWCF7, 0x0000);
-}
-
-static void
-awe_update_chorus_mode(void)
-{
-	awe_set_chorus_mode(ctrls[AWE_MD_CHORUS_MODE]);
-}
-
-/*----------------------------------------------------------------*/
-
-/* reverb mode settings; write the following 28 data of 16 bit length
- *   on the corresponding ports in the reverb_cmds array
- */
-static char reverb_defined[AWE_CHORUS_NUMBERS];
-static awe_reverb_fx_rec reverb_parm[AWE_REVERB_NUMBERS] = {
-{{  /* room 1 */
-	0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
-	0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
-	0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
-	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
-}},
-{{  /* room 2 */
-	0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
-	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
-	0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
-	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
-}},
-{{  /* room 3 */
-	0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
-	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
-	0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
-	0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
-}},
-{{  /* hall 1 */
-	0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
-	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
-	0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
-	0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
-}},
-{{  /* hall 2 */
-	0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
-	0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
-	0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
-	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
-}},
-{{  /* plate */
-	0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
-	0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
-	0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
-	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
-}},
-{{  /* delay */
-	0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
-	0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
-	0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
-	0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
-}},
-{{  /* panning delay */
-	0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
-	0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
-	0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
-	0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
-}},
-};
-
-static struct ReverbCmdPair {
-	unsigned short cmd, port;
-} reverb_cmds[28] = {
-  {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
-  {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
-  {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
-  {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
-  {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
-  {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
-  {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
-};
-
-static int
-awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count)
-{
-	if (patch->optarg < AWE_REVERB_PREDEFINED || patch->optarg >= AWE_REVERB_NUMBERS) {
-		printk("AWE32 Error: illegal reverb mode %d for uploading\n", patch->optarg);
-		return RET_ERROR(EINVAL);
-	}
-	if (count < sizeof(awe_reverb_fx_rec)) {
-		printk("AWE32 Error: too short reverb fx parameters\n");
-		return RET_ERROR(EINVAL);
-	}
-	COPY_FROM_USER(&reverb_parm[patch->optarg], addr, AWE_PATCH_INFO_SIZE,
-		       sizeof(awe_reverb_fx_rec));
-	reverb_defined[patch->optarg] = TRUE;
-	return 0;
-}
-
-static void
-awe_set_reverb_mode(int effect)
-{
-	int i;
-	if (effect < 0 || effect >= AWE_REVERB_NUMBERS ||
-	    (effect >= AWE_REVERB_PREDEFINED && !reverb_defined[effect]))
-		return;
-	for (i = 0; i < 28; i++)
-		awe_poke(reverb_cmds[i].cmd, reverb_cmds[i].port,
-			 reverb_parm[effect].parms[i]);
-}
-
-static void
-awe_update_reverb_mode(void)
-{
-	awe_set_reverb_mode(ctrls[AWE_MD_REVERB_MODE]);
-}
-
-/*================================================================
- * treble/bass equalizer control
- *================================================================*/
-
-static unsigned short bass_parm[12][3] = {
-	{0xD26A, 0xD36A, 0x0000}, /* -12 dB */
-	{0xD25B, 0xD35B, 0x0000}, /*  -8 */
-	{0xD24C, 0xD34C, 0x0000}, /*  -6 */
-	{0xD23D, 0xD33D, 0x0000}, /*  -4 */
-	{0xD21F, 0xD31F, 0x0000}, /*  -2 */
-	{0xC208, 0xC308, 0x0001}, /*   0 (HW default) */
-	{0xC219, 0xC319, 0x0001}, /*  +2 */
-	{0xC22A, 0xC32A, 0x0001}, /*  +4 */
-	{0xC24C, 0xC34C, 0x0001}, /*  +6 */
-	{0xC26E, 0xC36E, 0x0001}, /*  +8 */
-	{0xC248, 0xC348, 0x0002}, /* +10 */
-	{0xC26A, 0xC36A, 0x0002}, /* +12 dB */
-};
-
-static unsigned short treble_parm[12][9] = {
-	{0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
-	{0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
-	{0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
-	{0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
-	{0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
-	{0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
-	{0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
-	{0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
-	{0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
-	{0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
-	{0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
-	{0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +12 dB */
-};
-
-
-/*
- * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
- */
-static void
-awe_equalizer(int bass, int treble)
-{
-	unsigned short w;
-
-	if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
-		return;
-	awe_poke(AWE_INIT4(0x01), bass_parm[bass][0]);
-	awe_poke(AWE_INIT4(0x11), bass_parm[bass][1]);
-	awe_poke(AWE_INIT3(0x11), treble_parm[treble][0]);
-	awe_poke(AWE_INIT3(0x13), treble_parm[treble][1]);
-	awe_poke(AWE_INIT3(0x1B), treble_parm[treble][2]);
-	awe_poke(AWE_INIT4(0x07), treble_parm[treble][3]);
-	awe_poke(AWE_INIT4(0x0B), treble_parm[treble][4]);
-	awe_poke(AWE_INIT4(0x0D), treble_parm[treble][5]);
-	awe_poke(AWE_INIT4(0x17), treble_parm[treble][6]);
-	awe_poke(AWE_INIT4(0x19), treble_parm[treble][7]);
-	w = bass_parm[bass][2] + treble_parm[treble][8];
-	awe_poke(AWE_INIT4(0x15), (unsigned short)(w + 0x0262));
-	awe_poke(AWE_INIT4(0x1D), (unsigned short)(w + 0x8362));
-}
-
-static void awe_update_equalizer(void)
-{
-	awe_equalizer(ctrls[AWE_MD_BASS_LEVEL], ctrls[AWE_MD_TREBLE_LEVEL]);
-}
-
-
-#ifdef CONFIG_AWE32_MIDIEMU
-
-/*================================================================
- * Emu8000 MIDI Emulation
- *================================================================*/
-
-/*================================================================
- * midi queue record
- *================================================================*/
-
-/* queue type */
-enum { Q_NONE, Q_VARLEN, Q_READ, Q_SYSEX, };
-
-#define MAX_MIDIBUF	64
-
-/* midi status */
-typedef struct MidiStatus {
-	int queue;	/* queue type */
-	int qlen;	/* queue length */
-	int read;	/* chars read */
-	int status;	/* current status */
-	int chan;	/* current channel */
-	unsigned char buf[MAX_MIDIBUF];
-} MidiStatus;
-
-/* MIDI mode type */
-enum { MODE_GM, MODE_GS, MODE_XG, };
-
-/* NRPN / CC -> Emu8000 parameter converter */
-typedef struct {
-	int control;
-	int awe_effect;
-	unsigned short (*convert)(int val);
-} ConvTable;
-
-
-/*================================================================
- * prototypes
- *================================================================*/
-
-static int awe_midi_open(int dev, int mode, void (*input)(int,unsigned char), void (*output)(int));
-static void awe_midi_close(int dev);
-static int awe_midi_ioctl(int dev, unsigned cmd, caddr_t arg);
-static int awe_midi_outputc(int dev, unsigned char midi_byte);
-
-static void init_midi_status(MidiStatus *st);
-static void clear_rpn(void);
-static void get_midi_char(MidiStatus *st, int c);
-/*static void queue_varlen(MidiStatus *st, int c);*/
-static void special_event(MidiStatus *st, int c);
-static void queue_read(MidiStatus *st, int c);
-static void midi_note_on(MidiStatus *st);
-static void midi_note_off(MidiStatus *st);
-static void midi_key_pressure(MidiStatus *st);
-static void midi_channel_pressure(MidiStatus *st);
-static void midi_pitch_wheel(MidiStatus *st);
-static void midi_program_change(MidiStatus *st);
-static void midi_control_change(MidiStatus *st);
-static void midi_select_bank(MidiStatus *st, int val);
-static void midi_nrpn_event(MidiStatus *st);
-static void midi_rpn_event(MidiStatus *st);
-static void midi_detune(int chan, int coarse, int fine);
-static void midi_system_exclusive(MidiStatus *st);
-static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val);
-static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val);
-static int xg_control_change(MidiStatus *st, int cmd, int val);
-
-#define numberof(ary)	(sizeof(ary)/sizeof(ary[0]))
-
-
-/*================================================================
- * OSS Midi device record
- *================================================================*/
-
-static struct midi_operations awe_midi_operations =
-{
-	{"AWE Midi Emu", 0, 0, SNDCARD_SB},
-	NULL /*&std_midi_synth*/,
-	{0}, /* input_info */
-	awe_midi_open, /*open*/
-	awe_midi_close, /*close*/
-	awe_midi_ioctl, /*ioctl*/
-	awe_midi_outputc, /*outputc*/
-	NULL /*start_read*/,
-	NULL /*end_read*/,
-	NULL, /* kick */
-	NULL, /* command */
-};
-
-static int my_mididev = -1;
-
-static void attach_midiemu(void)
-{
-	if ((my_mididev = sound_alloc_mididev()) < 0)
-		printk ("Sound: Too many midi devices detected\n");
-	else
-		midi_devs[my_mididev] = &awe_midi_operations;
-}
-
-static void unload_midiemu(void)
-{
-	if (my_mididev >= 0)
-		sound_unload_mididev(my_mididev);
-}
-
-
-/*================================================================
- * open/close midi device
- *================================================================*/
-
-static int midi_opened = FALSE;
-
-static int midi_mode;
-static int coarsetune = 0, finetune = 0;
-
-static int xg_mapping = TRUE;
-static int xg_bankmode = 0;
-
-/* effect sensitivity */
-
-#define FX_CUTOFF	0
-#define FX_RESONANCE	1
-#define FX_ATTACK	2
-#define FX_RELEASE	3
-#define FX_VIBRATE	4
-#define FX_VIBDEPTH	5
-#define FX_VIBDELAY	6
-#define FX_NUMS		7
-
-#define DEF_FX_CUTOFF		170
-#define DEF_FX_RESONANCE	6
-#define DEF_FX_ATTACK		50
-#define DEF_FX_RELEASE		50
-#define DEF_FX_VIBRATE		30
-#define DEF_FX_VIBDEPTH		4
-#define DEF_FX_VIBDELAY		1500
-
-/* effect sense: */
-static int gs_sense[] = 
-{
-	DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
-	DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
-};
-static int xg_sense[] = 
-{
-	DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
-	DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
-};
-
-
-/* current status */
-static MidiStatus curst;
-
-
-static int
-awe_midi_open (int dev, int mode,
-	       void (*input)(int,unsigned char),
-	       void (*output)(int))
-{
-	if (midi_opened)
-		return -EBUSY;
-
-	midi_opened = TRUE;
-
-	midi_mode = MODE_GM;
-
-	curst.queue = Q_NONE;
-	curst.qlen = 0;
-	curst.read = 0;
-	curst.status = 0;
-	curst.chan = 0;
-	BZERO(curst.buf, sizeof(curst.buf));
-
-	init_midi_status(&curst);
-
-	return 0;
-}
-
-static void
-awe_midi_close (int dev)
-{
-	midi_opened = FALSE;
-}
-
-
-static int
-awe_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
-{
-	return -EPERM;
-}
-
-static int
-awe_midi_outputc (int dev, unsigned char midi_byte)
-{
-	if (! midi_opened)
-		return 1;
-
-	/* force to change playing mode */
-	playing_mode = AWE_PLAY_MULTI;
-
-	get_midi_char(&curst, midi_byte);
-	return 1;
-}
-
-
-/*================================================================
- * initialize
- *================================================================*/
-
-static void init_midi_status(MidiStatus *st)
-{
-	clear_rpn();
-	coarsetune = 0;
-	finetune = 0;
-}
-
-
-/*================================================================
- * RPN & NRPN
- *================================================================*/
-
-#define MAX_MIDI_CHANNELS	16
-
-/* RPN & NRPN */
-static unsigned char nrpn[MAX_MIDI_CHANNELS];  /* current event is NRPN? */
-static int msb_bit;  /* current event is msb for RPN/NRPN */
-/* RPN & NRPN indeces */
-static unsigned char rpn_msb[MAX_MIDI_CHANNELS], rpn_lsb[MAX_MIDI_CHANNELS];
-/* RPN & NRPN values */
-static int rpn_val[MAX_MIDI_CHANNELS];
-
-static void clear_rpn(void)
-{
-	int i;
-	for (i = 0; i < MAX_MIDI_CHANNELS; i++) {
-		nrpn[i] = 0;
-		rpn_msb[i] = 127;
-		rpn_lsb[i] = 127;
-		rpn_val[i] = 0;
-	}
-	msb_bit = 0;
-}
-
-
-/*================================================================
- * process midi queue
- *================================================================*/
-
-/* status event types */
-typedef void (*StatusEvent)(MidiStatus *st);
-static struct StatusEventList {
-	StatusEvent process;
-	int qlen;
-} status_event[8] = {
-	{midi_note_off, 2},
-	{midi_note_on, 2},
-	{midi_key_pressure, 2},
-	{midi_control_change, 2},
-	{midi_program_change, 1},
-	{midi_channel_pressure, 1},
-	{midi_pitch_wheel, 2},
-	{NULL, 0},
-};
-
-
-/* read a char from fifo and process it */
-static void get_midi_char(MidiStatus *st, int c)
-{
-	if (c == 0xfe) {
-		/* ignore active sense */
-		st->queue = Q_NONE;
-		return;
-	}
-
-	switch (st->queue) {
-	/* case Q_VARLEN: queue_varlen(st, c); break;*/
-	case Q_READ:
-	case Q_SYSEX:
-		queue_read(st, c);
-		break;
-	case Q_NONE:
-		st->read = 0;
-		if ((c & 0xf0) == 0xf0) {
-			special_event(st, c);
-		} else if (c & 0x80) { /* status change */
-			st->status = (c >> 4) & 0x07;
-			st->chan = c & 0x0f;
-			st->queue = Q_READ;
-			st->qlen = status_event[st->status].qlen;
-			if (st->qlen == 0)
-				st->queue = Q_NONE;
-		}
-		break;
-	}
-}
-
-/* 0xfx events */
-static void special_event(MidiStatus *st, int c)
-{
-	switch (c) {
-	case 0xf0: /* system exclusive */
-		st->queue = Q_SYSEX;
-		st->qlen = 0;
-		break;
-	case 0xf1: /* MTC quarter frame */
-	case 0xf3: /* song select */
-		st->queue = Q_READ;
-		st->qlen = 1;
-		break;
-	case 0xf2: /* song position */
-		st->queue = Q_READ;
-		st->qlen = 2;
-		break;
-	}
-}
-
-#if 0
-/* read variable length value */
-static void queue_varlen(MidiStatus *st, int c)
-{
-	st->qlen += (c & 0x7f);
-	if (c & 0x80) {
-		st->qlen <<= 7;
-		return;
-	}
-	if (st->qlen <= 0) {
-		st->qlen = 0;
-		st->queue = Q_NONE;
-	}
-	st->queue = Q_READ;
-	st->read = 0;
-}
-#endif
-
-
-/* read a char */
-static void queue_read(MidiStatus *st, int c)
-{
-	if (st->read < MAX_MIDIBUF) {
-		if (st->queue != Q_SYSEX)
-			c &= 0x7f;
-		st->buf[st->read] = (unsigned char)c;
-	}
-	st->read++;
-	if (st->queue == Q_SYSEX && c == 0xf7) {
-		midi_system_exclusive(st);
-		st->queue = Q_NONE;
-	} else if (st->queue == Q_READ && st->read >= st->qlen) {
-		if (status_event[st->status].process)
-			status_event[st->status].process(st);
-		st->queue = Q_NONE;
-	}
-}
-
-
-/*================================================================
- * status events
- *================================================================*/
-
-/* note on */
-static void midi_note_on(MidiStatus *st)
-{
-	DEBUG(2,printk("midi: note_on (%d) %d %d\n", st->chan, st->buf[0], st->buf[1]));
-	if (st->buf[1] == 0)
-		midi_note_off(st);
-	else
-		awe_start_note(0, st->chan, st->buf[0], st->buf[1]);
-}
-
-/* note off */
-static void midi_note_off(MidiStatus *st)
-{
-	DEBUG(2,printk("midi: note_off (%d) %d %d\n", st->chan, st->buf[0], st->buf[1]));
-	awe_kill_note(0, st->chan, st->buf[0], st->buf[1]);
-}
-
-/* key pressure change */
-static void midi_key_pressure(MidiStatus *st)
-{
-	awe_key_pressure(0, st->chan, st->buf[0], st->buf[1]);
-}
-
-/* channel pressure change */
-static void midi_channel_pressure(MidiStatus *st)
-{
-	channels[st->chan].chan_press = st->buf[0];
-	awe_modwheel_change(st->chan, st->buf[0]);
-}
-
-/* pitch wheel change */
-static void midi_pitch_wheel(MidiStatus *st)
-{
-	int val = (int)st->buf[1] * 128 + st->buf[0];
-	awe_bender(0, st->chan, val);
-}
-
-/* program change */
-static void midi_program_change(MidiStatus *st)
-{
-	int preset;
-	preset = st->buf[0];
-	if (midi_mode == MODE_GS && IS_DRUM_CHANNEL(st->chan) && preset == 127)
-		preset = 0;
-	else if (midi_mode == MODE_XG && xg_mapping && IS_DRUM_CHANNEL(st->chan))
-		preset += 64;
-
-	awe_set_instr(0, st->chan, preset);
-}
-
-#define send_effect(chan,type,val) awe_send_effect(chan,-1,type,val)
-#define add_effect(chan,type,val) awe_send_effect(chan,-1,(type)|0x80,val)
-#define unset_effect(chan,type) awe_send_effect(chan,-1,(type)|0x40,0)
-
-/* midi control change */
-static void midi_control_change(MidiStatus *st)
-{
-	int cmd = st->buf[0];
-	int val = st->buf[1];
-
-	DEBUG(2,printk("midi: control (%d) %d %d\n", st->chan, cmd, val));
-	if (midi_mode == MODE_XG) {
-		if (xg_control_change(st, cmd, val))
-			return;
-	}
-
-	/* controls #31 - #64 are LSB of #0 - #31 */
-	msb_bit = 1;
-	if (cmd >= 0x20 && cmd < 0x40) {
-		msb_bit = 0;
-		cmd -= 0x20;
-	}
-
-	switch (cmd) {
-	case CTL_SOFT_PEDAL:
-		if (val == 127)
-			add_effect(st->chan, AWE_FX_CUTOFF, -160);
-		else
-			unset_effect(st->chan, AWE_FX_CUTOFF);
-		break;
-
-	case CTL_BANK_SELECT:
-		midi_select_bank(st, val);
-		break;
-		
-	/* set RPN/NRPN parameter */
-	case CTL_REGIST_PARM_NUM_MSB:
-		nrpn[st->chan]=0; rpn_msb[st->chan]=val;
-		break;
-	case CTL_REGIST_PARM_NUM_LSB:
-		nrpn[st->chan]=0; rpn_lsb[st->chan]=val;
-		break;
-	case CTL_NONREG_PARM_NUM_MSB:
-		nrpn[st->chan]=1; rpn_msb[st->chan]=val;
-		break;
-	case CTL_NONREG_PARM_NUM_LSB:
-		nrpn[st->chan]=1; rpn_lsb[st->chan]=val;
-		break;
-
-	/* send RPN/NRPN entry */
-	case CTL_DATA_ENTRY:
-		if (msb_bit)
-			rpn_val[st->chan] = val * 128;
-		else
-			rpn_val[st->chan] |= val;
-		if (nrpn[st->chan])
-			midi_nrpn_event(st);
-		else
-			midi_rpn_event(st);
-		break;
-
-	/* increase/decrease data entry */
-	case CTL_DATA_INCREMENT:
-		rpn_val[st->chan]++;
-		midi_rpn_event(st);
-		break;
-	case CTL_DATA_DECREMENT:
-		rpn_val[st->chan]--;
-		midi_rpn_event(st);
-		break;
-
-	/* default */
-	default:
-		awe_controller(0, st->chan, cmd, val);
-		break;
-	}
-}
-
-/* tone bank change */
-static void midi_select_bank(MidiStatus *st, int val)
-{
-	if (midi_mode == MODE_XG && msb_bit) {
-		xg_bankmode = val;
-		/* XG MSB value; not normal bank selection */
-		switch (val) {
-		case 127: /* remap to drum channel */
-			awe_controller(0, st->chan, CTL_BANK_SELECT, 128);
-			break;
-		default: /* remap to normal channel */
-			awe_controller(0, st->chan, CTL_BANK_SELECT, val);
-			break;
-		}
-		return;
-	} else if (midi_mode == MODE_GS && !msb_bit)
-		/* ignore LSB bank in GS mode (used for mapping) */
-		return;
-
-	/* normal bank controls; accept both MSB and LSB */
-	if (! IS_DRUM_CHANNEL(st->chan)) {
-		if (midi_mode == MODE_XG) {
-			if (xg_bankmode) return;
-			if (val == 64 || val == 126)
-				val = 0;
-		} else if (midi_mode == MODE_GS && val == 127)
-			val = 0;
-		awe_controller(0, st->chan, CTL_BANK_SELECT, val);
-	}
-}
-
-
-/*================================================================
- * RPN events
- *================================================================*/
-
-static void midi_rpn_event(MidiStatus *st)
-{
-	int type;
-	type = (rpn_msb[st->chan]<<8) | rpn_lsb[st->chan];
-	switch (type) {
-	case 0x0000: /* Pitch bend sensitivity */
-		/* MSB only / 1 semitone per 128 */
-		if (msb_bit) {
-			channels[st->chan].bender_range = 
-				rpn_val[st->chan] * 100 / 128;
-		}
-		break;
-					
-	case 0x0001: /* fine tuning: */
-		/* MSB/LSB, 8192=center, 100/8192 cent step */
-		finetune = rpn_val[st->chan] - 8192;
-		midi_detune(st->chan, coarsetune, finetune);
-		break;
-
-	case 0x0002: /* coarse tuning */
-		/* MSB only / 8192=center, 1 semitone per 128 */
-		if (msb_bit) {
-			coarsetune = rpn_val[st->chan] - 8192;
-			midi_detune(st->chan, coarsetune, finetune);
-		}
-		break;
-
-	case 0x7F7F: /* "lock-in" RPN */
-		break;
-	}
-}
-
-
-/* tuning:
- *   coarse = -8192 to 8192 (100 cent per 128)
- *   fine = -8192 to 8192 (max=100cent)
- */
-static void midi_detune(int chan, int coarse, int fine)
-{
-	/* 4096 = 1200 cents in AWE parameter */
-	int val;
-	val = coarse * 4096 / (12 * 128);
-	val += fine / 24;
-	if (val)
-		send_effect(chan, AWE_FX_INIT_PITCH, val);
-	else
-		unset_effect(chan, AWE_FX_INIT_PITCH);
-}
-
-
-/*================================================================
- * system exclusive message
- * GM/GS/XG macros are accepted
- *================================================================*/
-
-static void midi_system_exclusive(MidiStatus *st)
-{
-	/* GM on */
-	static unsigned char gm_on_macro[] = {
-		0x7e,0x7f,0x09,0x01,
-	};
-	/* XG on */
-	static unsigned char xg_on_macro[] = {
-		0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
-	};
-	/* GS prefix
-	 * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off
-	 * reverb mode: XX=0x01, YY=0x30, ZZ=0-7
-	 * chorus mode: XX=0x01, YY=0x38, ZZ=0-7
-	 */
-	static unsigned char gs_pfx_macro[] = {
-		0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/
-	};
-
-#if 0
-	/* SC88 system mode set
-	 * single module mode: XX=1
-	 * double module mode: XX=0
-	 */
-	static unsigned char gs_mode_macro[] = {
-		0x41,0x10,0x42,0x12,0x00,0x00,0x7F,/*ZZ*/
-	};
-	/* SC88 display macro: XX=01:bitmap, 00:text
-	 */
-	static unsigned char gs_disp_macro[] = {
-		0x41,0x10,0x45,0x12,0x10,/*XX,00*/
-	};
-#endif
-
-	/* GM on */
-	if (MEMCMP(st->buf, gm_on_macro, sizeof(gm_on_macro)) == 0) {
-		if (midi_mode != MODE_GS && midi_mode != MODE_XG)
-			midi_mode = MODE_GM;
-		init_midi_status(st);
-	}
-
-	/* GS macros */
-	else if (MEMCMP(st->buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) {
-		if (midi_mode != MODE_GS && midi_mode != MODE_XG)
-			midi_mode = MODE_GS;
-
-		if (st->buf[5] == 0x00 && st->buf[6] == 0x7f && st->buf[7] == 0x00) {
-			/* GS reset */
-			init_midi_status(st);
-		}
-
-		else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x15) {
-			/* drum pattern */
-			int p = st->buf[5] & 0x0f;
-			if (p == 0) p = 9;
-			else if (p < 10) p--;
-			if (st->buf[7] == 0)
-				DRUM_CHANNEL_OFF(p);
-			else
-				DRUM_CHANNEL_ON(p);
-
-		} else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x21) {
-			/* program */
-			int p = st->buf[5] & 0x0f;
-			if (p == 0) p = 9;
-			else if (p < 10) p--;
-			if (! IS_DRUM_CHANNEL(p))
-				awe_set_instr(0, p, st->buf[7]);
-
-		} else if (st->buf[5] == 0x01 && st->buf[6] == 0x30) {
-			/* reverb mode */
-			awe_set_reverb_mode(st->buf[7]);
-
-		} else if (st->buf[5] == 0x01 && st->buf[6] == 0x38) {
-			/* chorus mode */
-			awe_set_chorus_mode(st->buf[7]);
-
-		} else if (st->buf[5] == 0x00 && st->buf[6] == 0x04) {
-			/* master volume */
-			awe_change_master_volume(st->buf[7]);
-
-		}
-	}
-
-	/* XG on */
-	else if (MEMCMP(st->buf, xg_on_macro, sizeof(xg_on_macro)) == 0) {
-		midi_mode = MODE_XG;
-		xg_mapping = TRUE;
-		xg_bankmode = 0;
-	}
-}
-
-
-/*================================================================
- * convert NRPN/control values
- *================================================================*/
-
-static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val)
-{
-	int i, cval;
-	for (i = 0; i < num_tables; i++) {
-		if (table[i].control == type) {
-			cval = table[i].convert(val);
-			send_effect(st->chan, table[i].awe_effect, cval);
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val)
-{
-	int i, cval;
-	for (i = 0; i < num_tables; i++) {
-		if (table[i].control == type) {
-			cval = table[i].convert(val);
-			add_effect(st->chan, table[i].awe_effect|0x80, cval);
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-
-/*----------------------------------------------------------------
- * AWE32 NRPN effects
- *----------------------------------------------------------------*/
-
-static unsigned short fx_delay(int val);
-static unsigned short fx_attack(int val);
-static unsigned short fx_hold(int val);
-static unsigned short fx_decay(int val);
-static unsigned short fx_the_value(int val);
-static unsigned short fx_twice_value(int val);
-static unsigned short fx_conv_pitch(int val);
-static unsigned short fx_conv_Q(int val);
-
-/* function for each NRPN */		/* [range]  units */
-#define fx_env1_delay	fx_delay	/* [0,5900] 4msec */
-#define fx_env1_attack	fx_attack	/* [0,5940] 1msec */
-#define fx_env1_hold	fx_hold		/* [0,8191] 1msec */
-#define fx_env1_decay	fx_decay	/* [0,5940] 4msec */
-#define fx_env1_release	fx_decay	/* [0,5940] 4msec */
-#define fx_env1_sustain	fx_the_value	/* [0,127] 0.75dB */
-#define fx_env1_pitch	fx_the_value	/* [-127,127] 9.375cents */
-#define fx_env1_cutoff	fx_the_value	/* [-127,127] 56.25cents */
-
-#define fx_env2_delay	fx_delay	/* [0,5900] 4msec */
-#define fx_env2_attack	fx_attack	/* [0,5940] 1msec */
-#define fx_env2_hold	fx_hold		/* [0,8191] 1msec */
-#define fx_env2_decay	fx_decay	/* [0,5940] 4msec */
-#define fx_env2_release	fx_decay	/* [0,5940] 4msec */
-#define fx_env2_sustain	fx_the_value	/* [0,127] 0.75dB */
-
-#define fx_lfo1_delay	fx_delay	/* [0,5900] 4msec */
-#define fx_lfo1_freq	fx_twice_value	/* [0,127] 84mHz */
-#define fx_lfo1_volume	fx_twice_value	/* [0,127] 0.1875dB */
-#define fx_lfo1_pitch	fx_the_value	/* [-127,127] 9.375cents */
-#define fx_lfo1_cutoff	fx_twice_value	/* [-64,63] 56.25cents */
-
-#define fx_lfo2_delay	fx_delay	/* [0,5900] 4msec */
-#define fx_lfo2_freq	fx_twice_value	/* [0,127] 84mHz */
-#define fx_lfo2_pitch	fx_the_value	/* [-127,127] 9.375cents */
-
-#define fx_init_pitch	fx_conv_pitch	/* [-8192,8192] cents */
-#define fx_chorus	fx_the_value	/* [0,255] -- */
-#define fx_reverb	fx_the_value	/* [0,255] -- */
-#define fx_cutoff	fx_twice_value	/* [0,127] 62Hz */
-#define fx_filterQ	fx_conv_Q	/* [0,127] -- */
-
-static unsigned short fx_delay(int val)
-{
-	return (unsigned short)calc_parm_delay(val);
-}
-
-static unsigned short fx_attack(int val)
-{
-	return (unsigned short)calc_parm_attack(val);
-}
-
-static unsigned short fx_hold(int val)
-{
-	return (unsigned short)calc_parm_hold(val);
-}
-
-static unsigned short fx_decay(int val)
-{
-	return (unsigned short)calc_parm_decay(val);
-}
-
-static unsigned short fx_the_value(int val)
-{
-	return (unsigned short)(val & 0xff);
-}
-
-static unsigned short fx_twice_value(int val)
-{
-	return (unsigned short)((val * 2) & 0xff);
-}
-
-static unsigned short fx_conv_pitch(int val)
-{
-	return (short)(val * 4096 / 1200);
-}
-
-static unsigned short fx_conv_Q(int val)
-{
-	return (unsigned short)((val / 8) & 0xff);
-}
-
-
-static ConvTable awe_effects[] =
-{
-	{ 0, AWE_FX_LFO1_DELAY,	fx_lfo1_delay},
-	{ 1, AWE_FX_LFO1_FREQ,	fx_lfo1_freq},
-	{ 2, AWE_FX_LFO2_DELAY,	fx_lfo2_delay},
-	{ 3, AWE_FX_LFO2_FREQ,	fx_lfo2_freq},
-
-	{ 4, AWE_FX_ENV1_DELAY,	fx_env1_delay},
-	{ 5, AWE_FX_ENV1_ATTACK,fx_env1_attack},
-	{ 6, AWE_FX_ENV1_HOLD,	fx_env1_hold},
-	{ 7, AWE_FX_ENV1_DECAY,	fx_env1_decay},
-	{ 8, AWE_FX_ENV1_SUSTAIN,	fx_env1_sustain},
-	{ 9, AWE_FX_ENV1_RELEASE,	fx_env1_release},
-
-	{10, AWE_FX_ENV2_DELAY,	fx_env2_delay},
-	{11, AWE_FX_ENV2_ATTACK,	fx_env2_attack},
-	{12, AWE_FX_ENV2_HOLD,	fx_env2_hold},
-	{13, AWE_FX_ENV2_DECAY,	fx_env2_decay},
-	{14, AWE_FX_ENV2_SUSTAIN,	fx_env2_sustain},
-	{15, AWE_FX_ENV2_RELEASE,	fx_env2_release},
-
-	{16, AWE_FX_INIT_PITCH,	fx_init_pitch},
-	{17, AWE_FX_LFO1_PITCH,	fx_lfo1_pitch},
-	{18, AWE_FX_LFO2_PITCH,	fx_lfo2_pitch},
-	{19, AWE_FX_ENV1_PITCH,	fx_env1_pitch},
-	{20, AWE_FX_LFO1_VOLUME,	fx_lfo1_volume},
-	{21, AWE_FX_CUTOFF,		fx_cutoff},
-	{22, AWE_FX_FILTERQ,	fx_filterQ},
-	{23, AWE_FX_LFO1_CUTOFF,	fx_lfo1_cutoff},
-	{24, AWE_FX_ENV1_CUTOFF,	fx_env1_cutoff},
-	{25, AWE_FX_CHORUS,		fx_chorus},
-	{26, AWE_FX_REVERB,		fx_reverb},
-};
-
-static int num_awe_effects = numberof(awe_effects);
-
-
-/*----------------------------------------------------------------
- * GS(SC88) NRPN effects; still experimental
- *----------------------------------------------------------------*/
-
-/* cutoff: quarter semitone step, max=255 */
-static unsigned short gs_cutoff(int val)
-{
-	return (val - 64) * gs_sense[FX_CUTOFF] / 50;
-}
-
-/* resonance: 0 to 15(max) */
-static unsigned short gs_filterQ(int val)
-{
-	return (val - 64) * gs_sense[FX_RESONANCE] / 50;
-}
-
-/* attack: */
-static unsigned short gs_attack(int val)
-{
-	return -(val - 64) * gs_sense[FX_ATTACK] / 50;
-}
-
-/* decay: */
-static unsigned short gs_decay(int val)
-{
-	return -(val - 64) * gs_sense[FX_RELEASE] / 50;
-}
-
-/* release: */
-static unsigned short gs_release(int val)
-{
-	return -(val - 64) * gs_sense[FX_RELEASE] / 50;
-}
-
-/* vibrato freq: 0.042Hz step, max=255 */
-static unsigned short gs_vib_rate(int val)
-{
-	return (val - 64) * gs_sense[FX_VIBRATE] / 50;
-}
-
-/* vibrato depth: max=127, 1 octave */
-static unsigned short gs_vib_depth(int val)
-{
-	return (val - 64) * gs_sense[FX_VIBDEPTH] / 50;
-}
-
-/* vibrato delay: -0.725msec step */
-static unsigned short gs_vib_delay(int val)
-{
-	return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;
-}
-
-static ConvTable gs_effects[] =
-{
-	{32, AWE_FX_CUTOFF,	gs_cutoff},
-	{33, AWE_FX_FILTERQ,	gs_filterQ},
-	{99, AWE_FX_ENV2_ATTACK, gs_attack},
-	{100, AWE_FX_ENV2_DECAY, gs_decay},
-	{102, AWE_FX_ENV2_RELEASE, gs_release},
-	{8, AWE_FX_LFO1_FREQ, gs_vib_rate},
-	{9, AWE_FX_LFO1_VOLUME, gs_vib_depth},
-	{10, AWE_FX_LFO1_DELAY, gs_vib_delay},
-};
-
-static int num_gs_effects = numberof(gs_effects);
-
-
-/*================================================================
- * NRPN events: accept as AWE32/SC88 specific controls
- *================================================================*/
-
-static void midi_nrpn_event(MidiStatus *st)
-{
-	if (rpn_msb[st->chan] == 127 && rpn_lsb[st->chan] <= 26) {
-		if (! msb_bit) /* both MSB/LSB necessary */
-			send_converted_effect(awe_effects, num_awe_effects,
-					      st, rpn_lsb[st->chan],
-					      rpn_val[st->chan] - 8192);
-	} else if (rpn_msb[st->chan] == 1) {
-		if (msb_bit) /* only MSB is valid */
-			add_converted_effect(gs_effects, num_gs_effects,
-					     st, rpn_lsb[st->chan],
-					     rpn_val[st->chan] / 128);
-	}
-}
-
-
-/*----------------------------------------------------------------
- * XG control effects; still experimental
- *----------------------------------------------------------------*/
-
-/* cutoff: quarter semitone step, max=255 */
-static unsigned short xg_cutoff(int val)
-{
-	return (val - 64) * xg_sense[FX_CUTOFF] / 64;
-}
-
-/* resonance: 0(open) to 15(most nasal) */
-static unsigned short xg_filterQ(int val)
-{
-	return (val - 64) * xg_sense[FX_RESONANCE] / 64;
-}
-
-/* attack: */
-static unsigned short xg_attack(int val)
-{
-	return -(val - 64) * xg_sense[FX_ATTACK] / 64;
-}
-
-/* release: */
-static unsigned short xg_release(int val)
-{
-	return -(val - 64) * xg_sense[FX_RELEASE] / 64;
-}
-
-static ConvTable xg_effects[] =
-{
-	{71, AWE_FX_CUTOFF,	xg_cutoff},
-	{74, AWE_FX_FILTERQ,	xg_filterQ},
-	{72, AWE_FX_ENV2_RELEASE, xg_release},
-	{73, AWE_FX_ENV2_ATTACK, xg_attack},
-};
-
-static int num_xg_effects = numberof(xg_effects);
-
-static int xg_control_change(MidiStatus *st, int cmd, int val)
-{
-	return add_converted_effect(xg_effects, num_xg_effects, st, cmd, val);
-}
-
-#endif /* CONFIG_AWE32_MIDIEMU */
-
-#endif /* CONFIG_AWE32_SYNTH */
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/lowlevel.h linux/drivers/sound/lowlevel/lowlevel.h
--- v2.3.50/linux/drivers/sound/lowlevel/lowlevel.h	Tue Oct 28 02:10:53 1997
+++ linux/drivers/sound/lowlevel/lowlevel.h	Wed Dec 31 16:00:00 1969
@@ -1,5 +0,0 @@
-#ifdef LOWLEVEL_MODULE
-#define MODVERSIONS
-#include <linux/modversions.h>
-#include "manual_config.h"
-#endif
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/miroaci.h linux/drivers/sound/lowlevel/miroaci.h
--- v2.3.50/linux/drivers/sound/lowlevel/miroaci.h	Thu Nov 18 20:25:37 1999
+++ linux/drivers/sound/lowlevel/miroaci.h	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-#include <linux/config.h>
-#if defined(CONFIG_ACI_MIXER) || defined(CONFIG_ACI_MIXER_MODULE)
-extern int aci_implied_cmd(unsigned char opcode);
-extern int aci_write_cmd(unsigned char opcode, unsigned char parameter);
-extern int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2);
-extern int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter);
-extern int aci_indexed_cmd(unsigned char opcode, unsigned char index, unsigned char *parameter);
-#else
-
- 
-#error Compiling a driver that needs the ACI-mixer but ACI-mixer support is not configured
-
-#endif
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/lowlevel/soundlow.c linux/drivers/sound/lowlevel/soundlow.c
--- v2.3.50/linux/drivers/sound/lowlevel/soundlow.c	Sun Aug 23 13:32:25 1998
+++ linux/drivers/sound/lowlevel/soundlow.c	Wed Dec 31 16:00:00 1969
@@ -1,67 +0,0 @@
-/*
- * lowlevel/init.c - Calls initialization code for configured drivers.
- */
-
-#include "lowlevel.h"
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include "../soundvers.h"
-
-#ifdef LOWLEVEL_MODULE
-char *lowlevel_version = SOUND_VERSION_STRING;
-#endif
-
-extern int attach_aci(void);
-extern void unload_aci(void);
-extern int attach_awe(void);
-extern void unload_awe(void);
-extern int init_aedsp16(void) __init;
-extern void uninit_aedsp16(void) __init;
-
-/*
- * There are two places where you can insert initialization calls of
- * low level drivers. sound_init_lowlevel_drivers() is called after
- * the sound driver has been initialized (the normal case)
- * while sound_preinit_lowlevel_drivers() is called before that.
- */
-void
-sound_preinit_lowlevel_drivers(void)
-{
-#if defined(CONFIG_AEDSP16) && !defined(MODULE)
-   init_aedsp16();
-#endif
-}
-
-void
-sound_init_lowlevel_drivers(void)
-{
-#ifdef CONFIG_ACI_MIXER
-   attach_aci();
-#endif
-
-#ifdef CONFIG_AWE32_SYNTH
-   attach_awe();
-#endif
-}
-
-void
-sound_unload_lowlevel_drivers(void)
-{
-#ifdef CONFIG_ACI_MIXER
-   unload_aci();
-#endif
-
-#ifdef CONFIG_AWE32_SYNTH
-   unload_awe();
-#endif
-
-#ifdef CONFIG_AEDSP16
-   uninit_aedsp16();
-#endif
-
-}
-
-EXPORT_SYMBOL(sound_init_lowlevel_drivers);
-EXPORT_SYMBOL(sound_unload_lowlevel_drivers);
-EXPORT_SYMBOL(sound_preinit_lowlevel_drivers);
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/mad16.c linux/drivers/sound/mad16.c
--- v2.3.50/linux/drivers/sound/mad16.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/mad16.c	Fri Mar 10 10:55:44 2000
@@ -1107,7 +1107,7 @@
 }
 
 module_init(init_mad16);
-module_exit(exit_mad16);
+module_exit(cleanup_mad16);
 
 #ifndef MODULE
 static int __init setup_mad16(char *str)
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/miroaci.h linux/drivers/sound/miroaci.h
--- v2.3.50/linux/drivers/sound/miroaci.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/miroaci.h	Fri Mar 10 10:52:56 2000
@@ -0,0 +1,6 @@
+#include <linux/config.h>
+extern int aci_implied_cmd(unsigned char opcode);
+extern int aci_write_cmd(unsigned char opcode, unsigned char parameter);
+extern int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2);
+extern int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter);
+extern int aci_indexed_cmd(unsigned char opcode, unsigned char index, unsigned char *parameter);
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.3.50/linux/drivers/sound/sb_card.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/sb_card.c	Tue Mar  7 14:35:24 2000
@@ -285,29 +285,8 @@
 	if((sb_dev = isapnp_find_dev(bus,
 		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), NULL)))
 	{
-#ifdef CMI8330_DMA0BAD
-		int dmahack = 0;
-#endif
 		sb_dev->prepare(sb_dev);
 		
-		/*  This device doesn't work with DMA 0, so we must allocate
-		 *  it to prevent PnP routines to assign it to the card.
-		 *
-		 *  I know i could have inlined the following lines, but it's cleaner
-		 *  this way.
-		 */
-	
-#ifdef CMI8330_DMA0BAD
-		if(sb_dev->dma_resource[0].start == 0)
-		{
-			if(!request_dma(0, "cmi8330 dma hack"))
-			{
-				/* DMA was free, we now have it */
-				dmahack = 1;
-			}
-		}
-#endif
-
 		if((sb_dev = activate_dev("CMI8330", "sb", sb_dev)))
 		{
 			hw_config->io_base 	= sb_dev->resource[0].start;
@@ -318,9 +297,6 @@
 			show_base("CMI8330", "sb", &sb_dev->resource[0]);
 		}
 
-#ifdef CMI8330_DMA0BAD
-		if(dmahack) free_dma(0);
-#endif
 		if(!sb_dev) return(NULL);
 	}
 	else
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.3.50/linux/drivers/sound/sb_common.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/sb_common.c	Wed Mar  8 11:37:48 2000
@@ -21,9 +21,6 @@
  *
  */
 
-/* FIXME: *grr* why can't the f**in Makefile do this for me ? */
-#define EXPORT_SYMTAB
-
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
--- v2.3.50/linux/drivers/sound/sscape.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/sscape.c	Thu Mar  9 23:31:43 2000
@@ -16,7 +16,6 @@
  * Christoph Hellwig	: adapted to module_init/module_exit
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- v2.3.50/linux/drivers/sound/wavfront.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/wavfront.c	Thu Mar  9 23:31:43 2000
@@ -73,7 +73,6 @@
 
 #include <linux/interrupt.h>
 #include <linux/config.h>
-#include <linux/init.h>
 
 #include <linux/delay.h>
 
diff -u --recursive --new-file v2.3.50/linux/drivers/sound/wf_midi.c linux/drivers/sound/wf_midi.c
--- v2.3.50/linux/drivers/sound/wf_midi.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/sound/wf_midi.c	Thu Mar  9 23:31:43 2000
@@ -49,7 +49,6 @@
  * for more info.
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include "sound_config.h"
 #include "soundmodule.h"
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.50/linux/drivers/usb/Config.in	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/Config.in	Fri Mar 10 10:48:47 2000
@@ -12,9 +12,11 @@
    if [ "$CONFIG_USB_UHCI" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
       bool '    USB-UHCI High Bandwidth (EXPERIMENTAL)' CONFIG_USB_UHCI_HIGH_BANDWIDTH
    fi
-   dep_tristate '  UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
-   if [ "$CONFIG_USB_UHCI_ALT" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      bool '    UHCI unlink optimizations (EXPERIMENTAL)' CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
+   if [ "$CONFIG_USB_UHCI" != "y" ]; then
+      dep_tristate '  UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
+      if [ "$CONFIG_USB_UHCI_ALT" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
+         bool '    UHCI unlink optimizations (EXPERIMENTAL)' CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
+      fi
    fi
    dep_tristate '  OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/Makefile linux/drivers/usb/Makefile
--- v2.3.50/linux/drivers/usb/Makefile	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/Makefile	Fri Mar 10 13:19:34 2000
@@ -4,7 +4,7 @@
 
 # Subdirs.
 
-SUB_DIRS	:=
+SUB_DIRS	:= serial
 MOD_SUB_DIRS	:= $(SUB_DIRS)
 ALL_SUB_DIRS	:= $(SUB_DIRS)
 
@@ -57,7 +57,6 @@
 obj-$(CONFIG_USB_SCANNER)	+= scanner.o
 obj-$(CONFIG_USB_ACM)		+= acm.o
 obj-$(CONFIG_USB_PRINTER)	+= printer.o
-obj-$(CONFIG_USB_SERIAL)	+= usb-serial.o
 obj-$(CONFIG_USB_AUDIO)		+= audio.o
 obj-$(CONFIG_USB_CPIA)		+= cpia.o
 obj-$(CONFIG_USB_IBMCAM)	+= ibmcam.o
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.3.50/linux/drivers/usb/acm.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/acm.c	Fri Mar 10 16:18:34 2000
@@ -49,10 +49,8 @@
 #include <linux/tty_flip.h>
 #include <linux/tty.h>
 #include <linux/module.h>
-
 #define DEBUG
-
-#include "usb.h"
+#include <linux/usb.h>
 
 /*
  * CMSPAR, some architectures can't have space and mark parity.
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.3.50/linux/drivers/usb/audio.c	Thu Feb 10 17:11:14 2000
+++ linux/drivers/usb/audio.c	Fri Mar 10 16:18:34 2000
@@ -152,8 +152,8 @@
 #include <linux/bitops.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <linux/usb.h>
 
-#include "usb.h"
 #include "audio.h"
 
 #define AUDIO_DEBUG 1
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/cpia.c linux/drivers/usb/cpia.c
--- v2.3.50/linux/drivers/usb/cpia.c	Thu Feb 10 17:11:14 2000
+++ linux/drivers/usb/cpia.c	Fri Mar 10 16:18:34 2000
@@ -18,10 +18,10 @@
 #include <linux/wrapper.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/usb.h>
 
 #include <asm/io.h>
 
-#include "usb.h"
 #include "cpia.h"
 
 static int debug = 0;
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c
--- v2.3.50/linux/drivers/usb/dabusb.c	Thu Feb 10 17:11:14 2000
+++ linux/drivers/usb/dabusb.c	Fri Mar 10 16:18:34 2000
@@ -37,8 +37,7 @@
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
 #include <linux/delay.h>
-
-#include "usb.h"
+#include <linux/usb.h>
 
 #include "dabusb.h"
 #include "dabfirmware.h"
@@ -801,6 +800,10 @@
 {
 	unsigned u;
 
+	/* register misc device */
+	if (usb_register(&dabusb_driver))
+		return -1;
+
 	/* initialize struct */
 	for (u = 0; u < NRDABUSB; u++) {
 		pdabusb_t s = &dabusb[u];
@@ -815,11 +818,7 @@
 		INIT_LIST_HEAD (&s->rec_buff_list);
 	}
 
-	/* register misc device */
-	usb_register (&dabusb_driver);
-
 	dbg("dabusb_init: driver registered");
-
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/dabusb.h linux/drivers/usb/dabusb.h
--- v2.3.50/linux/drivers/usb/dabusb.h	Thu Feb 10 17:11:14 2000
+++ linux/drivers/usb/dabusb.h	Fri Mar 10 14:55:59 2000
@@ -6,7 +6,7 @@
 	unsigned int pipe;
 }bulk_transfer_t,*pbulk_transfer_t;
 
-#define DABUSB_MINOR 64
+#define DABUSB_MINOR 240		/* some unassigned USB minor */
 #define DABUSB_VERSION 0x1000
 #define IOCTL_DAB_BULK              _IOWR('d', 0x30, bulk_transfer_t)
 #define IOCTL_DAB_OVERRUNS	    _IOR('d',  0x15, int)
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c
--- v2.3.50/linux/drivers/usb/dc2xx.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/dc2xx.c	Fri Mar 10 16:18:34 2000
@@ -57,10 +57,8 @@
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/module.h>
-
 #undef DEBUG
-
-#include "usb.h"
+#include <linux/usb.h>
 
 
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/devices.c linux/drivers/usb/devices.c
--- v2.3.50/linux/drivers/usb/devices.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/devices.c	Fri Mar 10 16:18:34 2000
@@ -53,9 +53,9 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/usb.h>
 #include <asm/uaccess.h>
 
-#include "usb.h"
 #include "usbdevice_fs.h"
 
 #define MAX_TOPO_LEVEL		6
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/devio.c linux/drivers/usb/devio.c
--- v2.3.50/linux/drivers/usb/devio.c	Sat Feb 26 22:31:50 2000
+++ linux/drivers/usb/devio.c	Fri Mar 10 16:18:34 2000
@@ -40,9 +40,9 @@
 #include <linux/smp_lock.h>
 #include <linux/signal.h>
 #include <linux/poll.h>
+#include <linux/usb.h>
 #include <asm/uaccess.h>
 
-#include "usb.h"
 #include "usbdevice_fs.h"
 
 struct async {
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/drivers.c linux/drivers/usb/drivers.c
--- v2.3.50/linux/drivers/usb/drivers.c	Thu Feb 10 17:11:14 2000
+++ linux/drivers/usb/drivers.c	Fri Mar 10 16:18:34 2000
@@ -36,9 +36,9 @@
 
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/usb.h>
 #include <asm/uaccess.h>
 
-#include "usb.h"
 #include "usbdevice_fs.h"
 
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/ftdi_sio.h linux/drivers/usb/ftdi_sio.h
--- v2.3.50/linux/drivers/usb/ftdi_sio.h	Sat Feb 26 22:31:50 2000
+++ linux/drivers/usb/ftdi_sio.h	Wed Dec 31 16:00:00 1969
@@ -1,380 +0,0 @@
-/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
-/* The device is based on the FTDI FT8U100AX chip, DB25 on one side, USB on the other */
-/* Thanx to FTDI for so kindly providing details of the protocol required */
-/* http://www.ftdi.co.uk  */
-
-/* The implementation of the device I have is called a USC-1000 */
-/*  which is available from http://www.dse.co.nz - cat no XH4214 */
-/* It looks similar to this: http://www.dansdata.com/usbser.htm but I can't be sure */
-/* There are other USC-1000s which don't look like my device though so beware */
-
-/* Definitions for the FTDI USB Single Port Serial Converter */
-/* known as FTDI_SIO (Serial Input/Output application of the chipset) */
-
-#define FTDI_VID	0x0403	/* Vendor Id */
-#define FTDI_SIO_PID	0x8372	/* Product Id */
-
-/* Vendor Request Interface */
-#define FTDI_SIO_RESET 		0 /* Reset the port */
-#define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
-#define FTDI_SIO_SET_FLOW_CTRL	2 /* Set flow control register */
-#define FTDI_SIO_SET_BAUD_RATE	3 /* Set baud rate */
-#define FTDI_SIO_SET_DATA	4 /* Set the data characteristics of the port */
-#define FTDI_SIO_GET_MODEM_STATUS	5 /* Retrieve current value of modern status register */
-#define FTDI_SIO_SET_EVENT_CHAR	6 /* Set the event character */
-#define FTDI_SIO_SET_ERROR_CHAR	7 /* Set the error character */
-
-/* Port Identifier Table */
-#define PIT_DEFAULT 		0 /* SIOA */
-#define PIT_SIOA		1 /* SIOA */
-/* The device this is tested with one has one port */
-#define PIT_SIOB		2 /* SIOB */
-#define PIT_PARALLEL		3 /* Parallel */
-
-/* FTDI_SIO_RESET */
-#define FTDI_SIO_RESET_REQUEST FTDI_SIO_RESET
-#define FTDI_SIO_RESET_REQUEST_TYPE 0x40
-#define FTDI_SIO_RESET_SIO 0
-#define FTDI_SIO_RESET_PURGE_RX 1
-#define FTDI_SIO_RESET_PURGE_TX 2
-/* 
-   BmRequestType:  0100 0000B
-   bRequest:       FTDI_SIO_RESET
-   wValue:         Control Value 
-                         0 = Reset SIO
-                         1 = Purge RX buffer
-                         2 = Purge TX buffer
-   wIndex:         Port
-   wLength:        0
-   Data:           None
-
-   */
-
-/* FTDI_SIO_SET_BAUDRATE */
-#define FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE 0x40
-#define FTDI_SIO_SET_BAUDRATE_REQUEST 3
-
-/*
-  BmRequestType:  0100 0000B
-  bRequest:       FTDI_SIO_SET_BAUDRATE
-  wValue:         BaudRate value - see below
-  wIndex:         Port
-  wLength:        0
-  Data:           None
-*/
-
-typedef enum {
- ftdi_sio_b300 = 0, 
- ftdi_sio_b600 = 1, 
- ftdi_sio_b1200 = 2,
- ftdi_sio_b2400 = 3,
- ftdi_sio_b4800 = 4,
- ftdi_sio_b9600 = 5,
- ftdi_sio_b19200 = 6,
- ftdi_sio_b38400 = 7,
- ftdi_sio_b57600 = 8,
- ftdi_sio_b115200 = 9
-} FTDI_SIO_baudrate_t ;
-
-#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
-#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
-#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 )
-#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 )
-#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 )
-
-/* FTDI_SIO_SET_DATA */
-
-/*    BmRequestType:  0100 0000B */
-/*    bRequest:       FTDI_SIO_SET_DATA */
-/*    wValue:         Data characteristics (see below) */
-/*    wIndex:         Port */
-/*    wLength:        0 */
-/*    Data:           None */
-/* 
-  Data characteristics
-
-B0..7   Number of data bits
-B8..10  Parity
-           0 = None
-           1 = Odd
-           2 = Even
-           3 = Mark
-           4 = Space
- B11..13 Stop Bits
-           0 = 1
-           1 = 1.5
-           2 = 2
- B14..15 Reserved
-*/
-
-
-
-/* FTDI_SIO_MODEM_CTRL */
-#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40
-#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL
-
-/* 
-  BmRequestType:   0100 0000B
-  bRequest:        FTDI_SIO_MODEM_CTRL
-  wValue:          ControlValue (see below)
-  wIndex:          Port
-  wLength:         0
-  Data:            None
-
-  NOTE: If the device is in RTS/CTS flow control, the RTS set by this
-        command will be IGNORED without an error being returned
-*/
-
-#define FTDI_SIO_SET_DTR_MASK 0x1
-#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK  << 8))
-#define FTDI_SIO_SET_DTR_LOW  ( 0 | ( FTDI_SIO_SET_DTR_MASK  << 8))
-#define FTDI_SIO_SET_RTS_MASK 0x2
-#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
-#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
-
-/* ControlValue
-   B0    DTR state
-           0 = reset
-           1 = set
-   B1    RTS state
-           0 = reset
-           1 = set
-   B2..7 Reserved
-   B8    DTR state enable
-           0 = ignore
-           1 = use DTR state
-   B9    RTS state enable
-           0 = ignore
-           1 = use RTS state
-   B10..15 Reserved
-*/
-
-/* FTDI_SIO_SET_FLOW_CTRL */
-#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40
-#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL
-#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 
-#define FTDI_SIO_RTS_CTS_HS 0x1
-#define FTDI_SIO_DTR_DSR_HS 0x2
-#define FTDI_SIO_XON_XOFF_HS 0x4
-/* 
-   BmRequestType:  0100 0000b
-   bRequest:       FTDI_SIO_SET_FLOW_CTRL
-   wValue:         Xoff/Xon
-   wIndex:         Protocol/Port - hIndex is protocl / lIndex is port
-   wLength:        0 
-   Data:           None
-
-hIndex - protocol has
- B0 Output handshaking using RTS/CTS
-      0 = disabled
-      1 = enabled
- B1 Output handshaking using DTR/DSR
-      0 = disabled
-      1 = enabled
- B2 Xon/Xoff handshaking
-      0 = disabled
-      1 = enabled
-
-A value of zero in the hIndex field selects no handshaking
-
-If Xon/Xoff handshaking is specified, the hValue field contains the Xoff character 
-and the lValue field contains the Xon character.
-
-*/  
- 
-/* FTDI_SIO_SET_EVENT_CHAR */
-/* Set the special event character for the specified communications port */
-/* If the device sees this character it will immediately return the */
-/* data read so far - rather than wait 40ms or until 62 bytes is read */
-#define  FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR
-#define  FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40
-
-
-/* 
-  BmRequestType:   0100 0000b
-  bRequest:        FTDI_SIO_SET_EVENT_CHAR
-  wValue:          EventChar
-  wIndex:          Port
-  wLength:         0
-  Data:            None
-
-wValue:
-   B0..7   Event Character
-   B8      Event Character Processing
-             0 = disabled
-             1 = enabled
-   B9..15  Reserved
-
-*/
-          
-/* FTDI_SIO_SET_ERROR_CHAR */
-/* Set the parity error replacement character for the specified communications port */
-
-/* 
-  BmRequestType:  0100 0000b
-  bRequest:       FTDI_SIO_SET_EVENT_CHAR
-  wValue:         Error Char
-  wIndex:         Port
-  wLength:        0
-  Data:           None
-
-Error Char
-  B0..7  Error Character
-  B8     Error Character Processing
-           0 = disabled
-           1 = enabled
-  B9..15 Reserved
-
-*/
-
-/* FTDI_SIO_GET_MODEM_STATUS */
-/* Retreive the current value of the modem status register */
-
-#define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0
-#define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS
-#define FTDI_SIO_CTS_MASK 0x10
-#define FTDI_SIO_DSR_MASK 0x20
-#define FTDI_SIO_RI_MASK  0x40
-#define FTDI_SIO_RLSD_MASK 0x80
-/* 
-  BmRequestType:   1100 0000b
-  bRequest:        FTDI_SIO_GET_MODEM_STATUS
-  wValue:          zero
-  wIndex:          Port
-  wLength:         1
-  Data:            Status
-
-One byte of data is returned 
-B0..3 0
-B4    CTS
-        0 = inactive
-        1 = active
-B5    DSR
-        0 = inactive
-        1 = active
-B6    Ring Indicator (RI)
-        0 = inactive
-        1 = active
-B7    Receive Line Signal Detect (RLSD)
-        0 = inactive
-        1 = active 
-*/
-
-
-
-/* Descriptors returned by the device 
-
- Device Descriptor
-
-Offset	Field		Size	Value	Description
-0	bLength		1	0x12	Size of descriptor in bytes
-1	bDescriptorType	1	0x01	DEVICE Descriptor Type
-2	bcdUSB		2	0x0110	USB Spec Release Number
-4	bDeviceClass	1	0x00	Class Code
-5	bDeviceSubClass	1	0x00	SubClass Code
-6	bDeviceProtocol	1	0x00	Protocol Code
-7	bMaxPacketSize0 1	0x08	Maximum packet size for endpoint 0
-8	idVendor	2	0x0403	Vendor ID
-10	idProduct	2	0x8372	Product ID (FTDI_SIO_PID)
-12	bcdDevice	2	0x0001	Device release number
-14	iManufacturer	1	0x01	Index of man. string desc
-15	iProduct	1	0x02	Index of prod string desc
-16	iSerialNumber	1	0x02	Index of serial nmr string desc
-17	bNumConfigurations 1    0x01	Number of possible configurations
-
-Configuration Descriptor
-
-Offset	Field			Size	Value
-0	bLength			1	0x09	Size of descriptor in bytes
-1	bDescriptorType		1	0x02	CONFIGURATION Descriptor Type
-2	wTotalLength		2	0x0020	Total length of data
-4	bNumInterfaces		1	0x01	Number of interfaces supported
-5	bConfigurationValue	1	0x01	Argument for SetCOnfiguration() req
-6	iConfiguration		1	0x02	Index of config string descriptor
-7	bmAttributes		1	0x20	Config characteristics Remote Wakeup
-8	MaxPower		1	0x1E	Max power consumption
-
-Interface Descriptor
-
-Offset	Field			Size	Value
-0	bLength			1	0x09	Size of descriptor in bytes
-1	bDescriptorType		1	0x04	INTERFACE Descriptor Type
-2	bInterfaceNumber	1	0x00	Number of interface
-3	bAlternateSetting	1	0x00	Value used to select alternate
-4	bNumEndpoints		1	0x02	Number of endpoints
-5	bInterfaceClass		1	0xFF	Class Code
-6	bInterfaceSubClass	1	0xFF	Subclass Code
-7	bInterfaceProtocol	1	0xFF	Protocol Code
-8	iInterface		1	0x02	Index of interface string description
-
-IN Endpoint Descriptor
-
-Offset	Field			Size	Value
-0	bLength			1	0x07	Size of descriptor in bytes
-1	bDescriptorType		1	0x05	ENDPOINT descriptor type
-2	bEndpointAddress	1	0x82	Address of endpoint
-3	bmAttributes		1	0x02	Endpoint attributes - Bulk
-4	bNumEndpoints		2	0x0040	maximum packet size
-5	bInterval		1	0x00	Interval for polling endpoint
-
-OUT Endpoint Descriptor
-
-Offset	Field			Size	Value
-0	bLength			1	0x07	Size of descriptor in bytes
-1	bDescriptorType		1	0x05	ENDPOINT descriptor type
-2	bEndpointAddress	1	0x02	Address of endpoint
-3	bmAttributes		1	0x02	Endpoint attributes - Bulk
-4	bNumEndpoints		2	0x0040	maximum packet size
-5	bInterval		1	0x00	Interval for polling endpoint
-    
-DATA FORMAT
-
-IN Endpoint
-
-The device reserves the first two bytes of data on this endpoint to contain the current
-values of the modem and line status registers. In the absence of data, the device 
-generates a message consisting of these two status bytes every 40 ms
-
-Byte 0: Modem Status
-
-Offset	Description
-B0	Reserved - must be 1
-B1	Reserved - must be 0
-B2	Reserved - must be 0
-B3	Reserved - must be 0
-B4	Clear to Send (CTS)
-B5	Data Set Ready (DSR)
-B6	Ring Indicator (RI)
-B7	Receive Line Signal Detect (RLSD)
-
-Byte 1: Line Status
-
-Offset	Description
-B0	Data Ready (DR)
-B1	Overrun Error (OE)
-B2	Parity Error (PE)
-B3	Framing Error (FE)
-B4	Break Interrupt (BI)
-B5	Transmitter Holding Register (THRE)
-B6	Transmitter Empty (TEMT)
-B7	Error in RCVR FIFO
-
-OUT Endpoint
-
-This device reserves the first bytes of data on this endpoint contain the length
-and port identifier of the message. For the FTDI USB Serial converter the port 
-identifier is always 1.
-
-Byte 0: Line Status
-
-Offset	Description
-B0	Reserved - must be 1
-B1	Reserved - must be 0
-B2..7	Length of message - (not including Byte 0)
-
-*/
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/hid.c linux/drivers/usb/hid.c
--- v2.3.50/linux/drivers/usb/hid.c	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/hid.c	Fri Mar 10 16:18:34 2000
@@ -39,13 +39,12 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
-
-#include <asm/unaligned.h>
-
 #undef DEBUG
 #undef DEBUG_DATA
+#include <linux/usb.h>
+
+#include <asm/unaligned.h>
 
-#include "usb.h"
 #include "hid.h"
 
 #ifdef DEBUG
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.50/linux/drivers/usb/hub.c	Sat Feb 12 11:22:11 2000
+++ linux/drivers/usb/hub.c	Fri Mar 10 16:18:34 2000
@@ -13,13 +13,12 @@
 #include <linux/list.h>
 #include <linux/malloc.h>
 #include <linux/smp_lock.h>
+#define DEBUG
+#include <linux/usb.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
 
-#define DEBUG
-
-#include "usb.h"
 #include "hub.h"
 
 /* Wakes up khubd */
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c
--- v2.3.50/linux/drivers/usb/ibmcam.c	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/ibmcam.c	Fri Mar 10 16:18:34 2000
@@ -20,10 +20,10 @@
 #include <linux/wrapper.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/usb.h>
 
 #include <asm/io.h>
 
-#include "usb.h"
 #include "ibmcam.h"
 
 /*
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/inode.c linux/drivers/usb/inode.c
--- v2.3.50/linux/drivers/usb/inode.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/inode.c	Fri Mar 10 16:18:34 2000
@@ -36,9 +36,9 @@
 #include <linux/locks.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
+#include <linux/usb.h>
 #include <asm/uaccess.h>
 
-#include "usb.h"
 #include "usbdevice_fs.h"
 
 /* --------------------------------------------------------------------- */
@@ -446,22 +446,17 @@
 	INIT_LIST_HEAD(&sb->u.usbdevfs_sb.slist);
 	while (!list_empty(&sb->u.usbdevfs_sb.ilist))
 		free_inode(list_entry(sb->u.usbdevfs_sb.ilist.next, struct inode, u.usbdev_i.slist));
-        MOD_DEC_USE_COUNT;
 }
 
-static int usbdevfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int usbdevfs_statfs(struct super_block *sb, struct statfs *buf)
 {
-        struct statfs tmp;
-
-        tmp.f_type = USBDEVICE_SUPER_MAGIC;
-        tmp.f_bsize = PAGE_SIZE/sizeof(long);   /* ??? */
-        tmp.f_blocks = 0;
-        tmp.f_bfree = 0;
-        tmp.f_bavail = 0;
-        tmp.f_files = 0;
-        tmp.f_ffree = 0;
-        tmp.f_namelen = NAME_MAX;
-        return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+        buf->f_type = USBDEVICE_SUPER_MAGIC;
+        buf->f_bsize = PAGE_SIZE/sizeof(long);   /* ??? */
+        buf->f_bfree = 0;
+        buf->f_bavail = 0;
+        buf->f_ffree = 0;
+        buf->f_namelen = NAME_MAX;
+        return 0;
 }
 
 static struct super_operations usbdevfs_sops = { 
@@ -552,8 +547,6 @@
 		}
 	}
 	/* fill superblock */
-        MOD_INC_USE_COUNT;
-        lock_super(s);
         s->s_blocksize = 1024;
         s->s_blocksize_bits = 10;
         s->s_magic = USBDEVICE_SUPER_MAGIC;
@@ -573,7 +566,6 @@
         if (!s->s_root)
                 goto out_no_root;
 	list_add_tail(&s->u.usbdevfs_sb.slist, &superlist);
-	unlock_super(s);
 	for (i = 0; i < NRSPECIAL; i++) {
 		if (!(inode = iget(s, IROOT+1+i)))
 			continue;
@@ -595,23 +587,14 @@
  out_no_root:
         printk("usbdevfs_read_super: get root inode failed\n");
         iput(root_inode);
-        s->s_dev = 0;
-        unlock_super(s);
-	MOD_DEC_USE_COUNT;
         return NULL;
 
  opterr:
         printk(KERN_WARNING "usbdevfs: mount parameter error\n");
-	s->s_dev = 0;
 	return NULL;
 }
 
-static struct file_system_type usbdevice_fs_type = {
-        "usbdevfs",
-        0,
-        usbdevfs_read_super,
-        NULL
-};
+static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, 0);
 
 /* --------------------------------------------------------------------- */
 
@@ -675,7 +658,9 @@
 
 /* --------------------------------------------------------------------- */
 
+#ifdef CONFIG_PROC_FS		
 static struct proc_dir_entry *usbdir = NULL;
+#endif	
 
 int __init usbdevfs_init(void)
 {
@@ -688,8 +673,10 @@
 		return ret;
 	if ((ret = register_filesystem(&usbdevice_fs_type)))
 		usb_deregister(&usbdevfs_driver);
+#ifdef CONFIG_PROC_FS		
 	/* create mount point for usbdevfs */
 	usbdir = proc_mkdir("usb", proc_bus);
+#endif	
 	return ret;
 }
 
@@ -697,8 +684,10 @@
 {
 	usb_deregister(&usbdevfs_driver);
 	unregister_filesystem(&usbdevice_fs_type);
+#ifdef CONFIG_PROC_FS	
         if (usbdir)
                 remove_proc_entry("usb", proc_bus);
+#endif
 }
 
 #if 0
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/keyspan_pda_fw.h linux/drivers/usb/keyspan_pda_fw.h
--- v2.3.50/linux/drivers/usb/keyspan_pda_fw.h	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/keyspan_pda_fw.h	Wed Dec 31 16:00:00 1969
@@ -1,93 +0,0 @@
-/*
- * keyspan_pda_fw.h
- *
- * Generated from keyspan_pda.s by ezusb_convert.pl
- * This file is presumed to be under the same copyright as the source file
- * from which it was derived.
- */
-
-static const struct ezusb_hex_record keyspan_pda_firmware[] = {
-{ 0x0000,	3,	{0x02, 0x02, 0x00} },
-{ 0x0023,	4,	{0x02, 0x05, 0x5f, 0x00} },
-{ 0x0043,	4,	{0x02, 0x01, 0x00, 0x00} },
-{ 0x0030,	5,	{0x00, 0x00, 0x00, 0x00, 0x00} },
-{ 0x0100,	16,	{0x02, 0x02, 0x96, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00} },
-{ 0x0110,	16,	{0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00} },
-{ 0x0120,	16,	{0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x04, 0x61, 0x00, 0x02, 0x04, 0x89, 0x00} },
-{ 0x0200,	16,	{0x75, 0x81, 0x5e, 0xe4, 0xf5, 0x32, 0xf5, 0x33, 0xf5, 0x30, 0xf5, 0x31, 0xf5, 0x34, 0xc2, 0x00} },
-{ 0x0210,	16,	{0xc2, 0x01, 0xa9, 0x00, 0x74, 0xfe, 0x90, 0x10, 0x00, 0xf0, 0xa3, 0xd9, 0xfc, 0x74, 0xfd, 0x90} },
-{ 0x0220,	16,	{0x11, 0x00, 0xf0, 0xa3, 0xd9, 0xfc, 0x74, 0x02, 0x90, 0x7f, 0x9d, 0xf0, 0x74, 0x00, 0x90, 0x7f} },
-{ 0x0230,	16,	{0x97, 0xf0, 0x74, 0x86, 0x90, 0x7f, 0x9e, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0x03, 0xf0, 0x90, 0x7f} },
-{ 0x0240,	16,	{0xaf, 0xe0, 0xd2, 0xe0, 0xf0, 0x74, 0x01, 0x90, 0x7f, 0xab, 0xf0, 0x90, 0x7f, 0xae, 0xf0, 0x90} },
-{ 0x0250,	16,	{0x7f, 0xac, 0x74, 0x04, 0xf0, 0x90, 0x7f, 0xad, 0x74, 0x04, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x74} },
-{ 0x0260,	16,	{0x84, 0x90, 0x7f, 0x98, 0xf0, 0x74, 0x00, 0xf5, 0x98, 0x75, 0xc8, 0x30, 0x7b, 0x05, 0x91, 0x20} },
-{ 0x0270,	16,	{0xd2, 0xca, 0x75, 0x98, 0x50, 0xd2, 0xe8, 0xd2, 0xaf, 0xd2, 0xac, 0x74, 0x00, 0xf5, 0x86, 0x90} },
-{ 0x0280,	16,	{0x7f, 0xd6, 0x74, 0x02, 0xf0, 0x79, 0x2e, 0x7a, 0x00, 0x7b, 0x00, 0xdb, 0xfe, 0xda, 0xfa, 0xd9} },
-{ 0x0290,	16,	{0xf6, 0x74, 0x06, 0xf0, 0x80, 0xfe, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x84, 0xc0, 0x85} },
-{ 0x02a0,	16,	{0xc0, 0xe0, 0xe5, 0x91, 0xc2, 0xe4, 0xf5, 0x91, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0x90, 0x7f} },
-{ 0x02b0,	16,	{0xe8, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0xa3, 0xe0, 0xfc, 0xe9, 0x54, 0x60, 0xb4} },
-{ 0x02c0,	16,	{0x00, 0x03, 0x02, 0x03, 0x39, 0xb4, 0x40, 0x6e, 0xba, 0x00, 0x0b, 0x12, 0x04, 0x20, 0x40, 0x03} },
-{ 0x02d0,	16,	{0x02, 0x04, 0x02, 0x02, 0x04, 0x0a, 0xba, 0x01, 0x03, 0x02, 0x04, 0x0a, 0xba, 0x02, 0x03, 0x02} },
-{ 0x02e0,	16,	{0x04, 0x0a, 0xba, 0x03, 0x03, 0x02, 0x04, 0x44, 0xba, 0x04, 0x1e, 0xbb, 0x00, 0x0a, 0x90, 0x7f} },
-{ 0x02f0,	16,	{0x95, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x04, 0x02, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfd, 0xf0, 0x90} },
-{ 0x0300,	16,	{0x7f, 0x95, 0xe0, 0x54, 0xfd, 0xf0, 0x02, 0x04, 0x02, 0xba, 0x05, 0x03, 0x02, 0x04, 0x0a, 0xba} },
-{ 0x0310,	16,	{0x06, 0x19, 0xbb, 0x00, 0x08, 0xe5, 0x33, 0xd3, 0x95, 0x32, 0x02, 0x03, 0xde, 0xbb, 0x01, 0x08} },
-{ 0x0320,	16,	{0xe5, 0x32, 0xc3, 0x95, 0x33, 0x02, 0x03, 0xde, 0x02, 0x04, 0x0a, 0xba, 0x07, 0x05, 0x8b, 0x34} },
-{ 0x0330,	16,	{0x02, 0x04, 0x02, 0x02, 0x04, 0x0a, 0x02, 0x04, 0x0a, 0xba, 0x00, 0x20, 0xb9, 0x80, 0x10, 0x90} },
-{ 0x0340,	16,	{0x7f, 0x00, 0xe4, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x04, 0x02, 0xb9} },
-{ 0x0350,	16,	{0x82, 0x02, 0x80, 0xeb, 0xb9, 0x81, 0x02, 0x80, 0xe6, 0x02, 0x04, 0x0a, 0xba, 0x01, 0x0f, 0xbb} },
-{ 0x0360,	16,	{0x00, 0x03, 0x02, 0x04, 0x0a, 0xbb, 0x01, 0x03, 0x02, 0x04, 0x02, 0x02, 0x04, 0x0a, 0xba, 0x03} },
-{ 0x0370,	16,	{0x0f, 0xbb, 0x00, 0x03, 0x02, 0x04, 0x0a, 0xbb, 0x01, 0x03, 0x02, 0x04, 0x02, 0x02, 0x04, 0x0a} },
-{ 0x0380,	16,	{0xba, 0x06, 0x56, 0xbc, 0x01, 0x0f, 0x90, 0x7f, 0xd4, 0x74, 0x06, 0xf0, 0x90, 0x7f, 0xd5, 0x74} },
-{ 0x0390,	16,	{0x12, 0xf0, 0x02, 0x04, 0x02, 0xbc, 0x02, 0x12, 0xbb, 0x00, 0x6f, 0x90, 0x7f, 0xd4, 0x74, 0x06} },
-{ 0x03a0,	16,	{0xf0, 0x90, 0x7f, 0xd5, 0x74, 0x24, 0xf0, 0x02, 0x04, 0x02, 0xbc, 0x03, 0x29, 0x74, 0x04, 0xc3} },
-{ 0x03b0,	16,	{0x9b, 0x40, 0x57, 0x60, 0x55, 0xeb, 0x2b, 0x90, 0x06, 0x44, 0x25, 0x82, 0xf5, 0x82, 0x74, 0x00} },
-{ 0x03c0,	16,	{0x35, 0x83, 0xf5, 0x83, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0x90, 0x7f, 0xd4, 0xe9, 0xf0, 0x90, 0x7f} },
-{ 0x03d0,	16,	{0xd5, 0xea, 0xf0, 0x02, 0x04, 0x02, 0x02, 0x04, 0x0a, 0xba, 0x08, 0x0f, 0x74, 0x01, 0x90, 0x7f} },
-{ 0x03e0,	16,	{0x00, 0xf0, 0x74, 0x01, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x04, 0x02, 0xba, 0x09, 0x03, 0x02, 0x04} },
-{ 0x03f0,	16,	{0x02, 0xba, 0x0a, 0x05, 0x74, 0x00, 0x02, 0x03, 0xde, 0xba, 0x0b, 0x03, 0x02, 0x04, 0x02, 0x02} },
-{ 0x0400,	16,	{0x04, 0x0a, 0x90, 0x7f, 0xb4, 0x74, 0x02, 0xf0, 0x80, 0x09, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} },
-{ 0x0410,	16,	{0xf0, 0x80, 0x00, 0xd0, 0xe0, 0xd0, 0x85, 0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32} },
-{ 0x0420,	16,	{0xeb, 0x20, 0xe7, 0x1e, 0xc3, 0x94, 0x0a, 0x50, 0x19, 0xeb, 0x23, 0x24, 0xfe, 0xf5, 0x82, 0x74} },
-{ 0x0430,	16,	{0x05, 0x34, 0x00, 0xf5, 0x83, 0xe0, 0xf5, 0xcb, 0xf5, 0xcd, 0xa3, 0xe0, 0xf5, 0xca, 0xf5, 0xcc} },
-{ 0x0440,	16,	{0xc3, 0x22, 0xd3, 0x22, 0xb9, 0x41, 0x11, 0xeb, 0x64, 0xff, 0x54, 0x84, 0xfb, 0x90, 0x7f, 0x98} },
-{ 0x0450,	16,	{0xe0, 0x54, 0x7b, 0x4b, 0xf0, 0x02, 0x04, 0x02, 0x90, 0x7f, 0x9b, 0xe0, 0x64, 0xff, 0x02, 0x03} },
-{ 0x0460,	16,	{0xde, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x84, 0xc0, 0x85, 0xc0, 0xe0, 0xe5, 0x91, 0xc2} },
-{ 0x0470,	16,	{0xe4, 0xf5, 0x91, 0x90, 0x7f, 0xa9, 0x74, 0x04, 0xf0, 0x12, 0x05, 0xa0, 0xd0, 0xe0, 0xd0, 0x85} },
-{ 0x0480,	16,	{0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0} },
-{ 0x0490,	16,	{0x84, 0xc0, 0x85, 0xc0, 0xe0, 0xe5, 0x91, 0xc2, 0xe4, 0xf5, 0x91, 0x90, 0x7f, 0xaa, 0x74, 0x04} },
-{ 0x04a0,	16,	{0xf0, 0x90, 0x7f, 0xc9, 0xe0, 0xf9, 0xe4, 0xf5, 0x86, 0x90, 0x7d, 0xc0, 0x75, 0x85, 0x10, 0x85} },
-{ 0x04b0,	16,	{0x32, 0x84, 0xe0, 0x05, 0x86, 0x05, 0x84, 0xf0, 0xe5, 0x84, 0xb5, 0x33, 0x02, 0x80, 0x09, 0x05} },
-{ 0x04c0,	16,	{0x32, 0x05, 0x86, 0xa3, 0xd9, 0xec, 0x80, 0x00, 0x90, 0x7f, 0xc9, 0xf0, 0xb1, 0x31, 0xd0, 0xe0} },
-{ 0x04d0,	16,	{0xd0, 0x85, 0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0xe4, 0xf5, 0x86, 0x90, 0x7f} },
-{ 0x04e0,	16,	{0xbc, 0xe0, 0x20, 0xe1, 0x4b, 0x90, 0x7d, 0x00, 0xe5, 0x32, 0xf0, 0xa3, 0xe5, 0x33, 0xf0, 0xa3} },
-{ 0x04f0,	16,	{0xe5, 0x30, 0xf0, 0xa3, 0xe5, 0x31, 0xf0, 0xa3, 0xe4, 0x30, 0x00, 0x01, 0x04, 0xf0, 0xa3, 0x05} },
-{ 0x0500,	16,	{0x86, 0x90, 0x10, 0x00, 0x79, 0x10, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xd9, 0xf6} },
-{ 0x0510,	16,	{0x05, 0x86, 0x74, 0xfc, 0xf0, 0xa3, 0x05, 0x86, 0x90, 0x11, 0x00, 0x79, 0x10, 0xe0, 0xa3, 0x05} },
-{ 0x0520,	16,	{0x86, 0xf0, 0xa3, 0x05, 0x86, 0xd9, 0xf6, 0xe4, 0xf5, 0x86, 0x90, 0x7f, 0xbd, 0x74, 0x26, 0xf0} },
-{ 0x0530,	16,	{0x22, 0x20, 0x00, 0x13, 0xe5, 0x32, 0xb5, 0x33, 0x01, 0x22, 0x05, 0x33, 0x75, 0x83, 0x10, 0x85} },
-{ 0x0540,	16,	{0x33, 0x82, 0xe0, 0xf5, 0x99, 0xd2, 0x00, 0x74, 0x00, 0xb5, 0x34, 0x01, 0x22, 0xe5, 0x33, 0xd3} },
-{ 0x0550,	16,	{0x95, 0x32, 0xc3, 0x95, 0x34, 0x40, 0xf5, 0x75, 0x34, 0x00, 0xd2, 0x01, 0x02, 0x05, 0xa0, 0xc0} },
-{ 0x0560,	16,	{0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x84, 0xc0, 0x85, 0xc0, 0xe0, 0x30, 0x99, 0x07, 0xc2, 0x99} },
-{ 0x0570,	16,	{0xc2, 0x00, 0x12, 0x05, 0x34, 0x30, 0x98, 0x05, 0x12, 0x05, 0x8a, 0xc2, 0x98, 0xd0, 0xe0, 0xd0} },
-{ 0x0580,	16,	{0x85, 0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0x75, 0x83, 0x11, 0x85, 0x30, 0x82} },
-{ 0x0590,	16,	{0x05, 0x82, 0xe5, 0x99, 0xf0, 0xe5, 0x82, 0xb5, 0x31, 0x01, 0x22, 0x05, 0x30, 0xb1, 0xa0, 0x22} },
-{ 0x05a0,	16,	{0x90, 0x7f, 0xb8, 0xe0, 0x20, 0xe1, 0x38, 0x20, 0x01, 0x36, 0xe5, 0x30, 0xb5, 0x31, 0x01, 0x22} },
-{ 0x05b0,	16,	{0xe4, 0xf5, 0x86, 0x75, 0x83, 0x11, 0x05, 0x86, 0x90, 0x7e, 0x00, 0xf0, 0xa3, 0x05, 0x86, 0x79} },
-{ 0x05c0,	16,	{0x01, 0xe5, 0x30, 0xb5, 0x31, 0x02, 0x80, 0x10, 0x05, 0x31, 0x85, 0x31, 0x82, 0xe0, 0x05, 0x86} },
-{ 0x05d0,	16,	{0xf0, 0xa3, 0x05, 0x86, 0x09, 0xb9, 0x40, 0xe9, 0x90, 0x7f, 0xb9, 0xe9, 0x60, 0x01, 0xf0, 0x22} },
-{ 0x05e0,	16,	{0xc2, 0x01, 0xe4, 0xf5, 0x86, 0x90, 0x7e, 0x00, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x90} },
-{ 0x05f0,	16,	{0x7f, 0xb9, 0xf0, 0x22, 0xc2, 0x99, 0xf5, 0x99, 0x30, 0x99, 0xfd, 0xc2, 0x99, 0x22, 0xe5, 0x5e} },
-{ 0x0600,	16,	{0xf6, 0x3c, 0xfd, 0x8f, 0xfe, 0xc8, 0xff, 0x64, 0xff, 0xb2, 0xff, 0xd9, 0xff, 0xed, 0xff, 0xf3} },
-{ 0x0610,	16,	{0xff, 0xfa, 0x12, 0x01, 0x00, 0x01, 0xff, 0xff, 0xff, 0x40, 0xcd, 0x06, 0x04, 0x01, 0x89, 0xab} },
-{ 0x0620,	16,	{0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00} },
-{ 0x0630,	16,	{0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x82, 0x03, 0x40, 0x00, 0x01, 0x07, 0x05, 0x02} },
-{ 0x0640,	16,	{0x02, 0x40, 0x00, 0x00, 0x06, 0x4c, 0x06, 0x50, 0x06, 0x72, 0x06, 0xa0, 0x04, 0x03, 0x00, 0x00} },
-{ 0x0650,	16,	{0x22, 0x03, 0x41, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00} },
-{ 0x0660,	16,	{0x62, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x65, 0x00, 0x74, 0x00} },
-{ 0x0670,	16,	{0x73, 0x00, 0x2e, 0x03, 0x41, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x20, 0x00, 0x55, 0x00} },
-{ 0x0680,	16,	{0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x61, 0x00} },
-{ 0x0690,	16,	{0x6c, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x65, 0x00, 0x74, 0x00} },
-{ 0x06a0,	6,	{0x06, 0x03, 0x34, 0x00, 0x37, 0x00} },
-{ 0xffff,	0,	{0x00} }
-};
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/mousedev.c linux/drivers/usb/mousedev.c
--- v2.3.50/linux/drivers/usb/mousedev.c	Sat Feb 26 22:31:50 2000
+++ linux/drivers/usb/mousedev.c	Fri Mar 10 13:18:42 2000
@@ -87,8 +87,6 @@
 	while (list) {
 		switch (type) {
 			case EV_ABS:
-				if (test_bit(EV_REL, handle->dev->evbit) && test_bit(REL_X, handle->dev->relbit))
-					return;
 				switch (code) {
 					case ABS_X:	
 						size = handle->dev->absmax[ABS_X] - handle->dev->absmin[ABS_X];
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- v2.3.50/linux/drivers/usb/ov511.c	Thu Feb 10 17:11:15 2000
+++ linux/drivers/usb/ov511.c	Fri Mar 10 16:18:34 2000
@@ -60,9 +60,9 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/time.h>
+#include <linux/usb.h>
 #include <asm/io.h>
 
-#include "usb.h"
 #include "ov511.h"
 
 #define OV511_I2C_RETRIES 3
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c
--- v2.3.50/linux/drivers/usb/pegasus.c	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/pegasus.c	Fri Mar 10 16:18:34 2000
@@ -13,11 +13,10 @@
 #include <linux/malloc.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/usb.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
-
-#include "usb.h"
 
 #if LINUX_VERSION_CODE<0x2032d || !defined(__KERNEL__) || !defined(__OPTIMIZE__)
 #error You can not compile this driver on this kernel with this C options!
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/plusb.c linux/drivers/usb/plusb.c
--- v2.3.50/linux/drivers/usb/plusb.c	Sun Feb 20 21:12:39 2000
+++ linux/drivers/usb/plusb.c	Fri Mar 10 16:18:34 2000
@@ -40,10 +40,9 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-
 //#define DEBUG
+#include <linux/usb.h>
 
-#include "usb.h"
 #include "plusb.h"
 
 /* --------------------------------------------------------------------- */
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.3.50/linux/drivers/usb/printer.c	Sat Feb 26 22:31:50 2000
+++ linux/drivers/usb/printer.c	Fri Mar 10 16:18:34 2000
@@ -39,10 +39,8 @@
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/lp.h>
-
 #define DEBUG
-
-#include "usb.h"
+#include <linux/usb.h>
 
 #define USBLP_BUF_SIZE		8192
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c
--- v2.3.50/linux/drivers/usb/rio500.c	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/rio500.c	Fri Mar 10 16:18:34 2000
@@ -35,8 +35,7 @@
 #include <linux/init.h>
 #include <linux/malloc.h>
 #include <linux/spinlock.h>
-
-#include "usb.h"
+#include <linux/usb.h>
 
 #include "rio500_usb.h"
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/scanner.h linux/drivers/usb/scanner.h
--- v2.3.50/linux/drivers/usb/scanner.h	Wed Feb 16 17:03:52 2000
+++ linux/drivers/usb/scanner.h	Fri Mar 10 16:18:34 2000
@@ -6,10 +6,8 @@
 #include <linux/malloc.h>
 #include <linux/delay.h>
 #include <linux/ioctl.h>
-
 // #define DEBUG
-
-#include "usb.h"
+#include <linux/usb.h>
 
 /* WARNING: These DATA_DUMP's can produce a lot of data. Caveat Emptor. */
 // #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile
--- v2.3.50/linux/drivers/usb/serial/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/Makefile	Fri Mar 10 13:19:34 2000
@@ -0,0 +1,66 @@
+#
+# Makefile for the kernel USB device drivers.
+#
+
+# Subdirs.
+
+SUB_DIRS	:=
+MOD_SUB_DIRS	:= $(SUB_DIRS)
+ALL_SUB_DIRS	:= $(SUB_DIRS)
+
+# The target object and module list name.
+
+O_TARGET	:= usbdrv.o
+M_OBJS		:=
+O_OBJS		:=
+MOD_LIST_NAME	:= USB_MODULES
+
+# Objects that export symbols.
+
+# Multipart objects.
+
+# Optional parts of multipart objects.
+
+# Object file lists.
+
+obj-y	:=
+obj-m	:=
+obj-n	:=
+obj-	:=
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_USB_SERIAL)	+= usb-serial.o
+
+# Extract lists of the multi-part drivers.
+# The 'int-*' lists are the intermediate files used to build the multi's.
+
+multi-y		:= $(filter $(list-multi), $(obj-y))
+multi-m		:= $(filter $(list-multi), $(obj-m))
+int-y		:= $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
+int-m		:= $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
+
+# Files that are both resident and modular: remove from modular.
+
+obj-m		:= $(filter-out $(obj-y), $(obj-m))
+int-m		:= $(filter-out $(int-y), $(int-m))
+
+# Take multi-part drivers out of obj-y and put components in.
+
+obj-y		:= $(filter-out $(list-multi), $(obj-y)) $(int-y)
+
+# Translate to Rules.make lists.
+
+O_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-y)))
+OX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-y)))
+M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
+MX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-m)))
+MI_OBJS		:= $(sort $(filter-out $(export-objs), $(int-m)))
+MIX_OBJS	:= $(sort $(filter     $(export-objs), $(int-m)))
+
+# The global Rules.make.
+
+include $(TOPDIR)/Rules.make
+
+# Link rules for multi-part drivers.
+
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/serial/Makefile-keyspan_pda_fw linux/drivers/usb/serial/Makefile-keyspan_pda_fw
--- v2.3.50/linux/drivers/usb/serial/Makefile-keyspan_pda_fw	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/Makefile-keyspan_pda_fw	Fri Mar 10 13:19:34 2000
@@ -0,0 +1,16 @@
+
+# some rules to handle the quirks of the 'as31' assembler, like
+# insisting upon fixed suffixes for the input and output files,
+# and its lack of preprocessor support
+
+all: keyspan_pda_fw.h
+
+%.asm: %.s
+	gcc -x assembler-with-cpp -P -E -o $@ $<
+
+%.hex: %.asm
+	as31 -l $<
+	mv $*.obj $@
+
+%_fw.h: %.hex ezusb_convert.pl
+	perl ezusb_convert.pl $* < $< > $@
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/serial/ezusb_convert.pl linux/drivers/usb/serial/ezusb_convert.pl
--- v2.3.50/linux/drivers/usb/serial/ezusb_convert.pl	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/ezusb_convert.pl	Fri Mar 10 13:19:34 2000
@@ -0,0 +1,48 @@
+#! /usr/bin/perl -w
+
+
+# convert an Intel HEX file into a set of C records usable by the firmware
+# loading code in usb-serial.c (or others)
+
+# accepts the .hex file(s) on stdin, a basename (to name the initialized
+# array) as an argument, and prints the .h file to stdout. Typical usage:
+#  perl ezusb_convert.pl foo <foo.hex >fw_foo.h
+
+
+my $basename = $ARGV[0];
+die "no base name specified" unless $basename;
+
+while (<STDIN>) {
+    # ':' <len> <addr> <type> <len-data> <crc> '\r'
+    #  len, type, crc are 2-char hex, addr is 4-char hex. type is 00 for
+    # normal records, 01 for EOF
+    my($lenstring, $addrstring, $typestring, $reststring) =
+      /^:(\w\w)(\w\w\w\w)(\w\w)(\w+)$/;
+    die "malformed line: $_" unless $reststring;
+    last if $typestring eq '01';
+    my($len) = hex($lenstring);
+    my($addr) = hex($addrstring);
+    my(@bytes) = unpack("C*", pack("H".(2*$len), $reststring));
+    #pop(@bytes); # last byte is a CRC
+    push(@records, [$addr, \@bytes]);
+}
+
+print <<"EOF";
+/*
+ * ${basename}_fw.h
+ *
+ * Generated from ${basename}.s by ezusb_convert.pl
+ * This file is presumed to be under the same copyright as the source file
+ * from which it was derived.
+ */
+
+EOF
+
+print "static const struct ezusb_hex_record ${basename}_firmware[] = {\n";
+foreach $r (@records) {
+    printf("{ 0x%04x,\t%d,\t{", $r->[0], scalar(@{$r->[1]}));
+    print join(", ", map {sprintf('0x%02x', $_);} @{$r->[1]});
+    print "} },\n";
+}
+print "{ 0xffff,\t0,\t{0x00} }\n";
+print "};\n";
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/serial/ftdi_sio.h linux/drivers/usb/serial/ftdi_sio.h
--- v2.3.50/linux/drivers/usb/serial/ftdi_sio.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/ftdi_sio.h	Fri Mar 10 13:19:34 2000
@@ -0,0 +1,380 @@
+/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
+/* The device is based on the FTDI FT8U100AX chip, DB25 on one side, USB on the other */
+/* Thanx to FTDI for so kindly providing details of the protocol required */
+/* http://www.ftdi.co.uk  */
+
+/* The implementation of the device I have is called a USC-1000 */
+/*  which is available from http://www.dse.co.nz - cat no XH4214 */
+/* It looks similar to this: http://www.dansdata.com/usbser.htm but I can't be sure */
+/* There are other USC-1000s which don't look like my device though so beware */
+
+/* Definitions for the FTDI USB Single Port Serial Converter */
+/* known as FTDI_SIO (Serial Input/Output application of the chipset) */
+
+#define FTDI_VID	0x0403	/* Vendor Id */
+#define FTDI_SIO_PID	0x8372	/* Product Id */
+
+/* Vendor Request Interface */
+#define FTDI_SIO_RESET 		0 /* Reset the port */
+#define FTDI_SIO_MODEM_CTRL 	1 /* Set the modem control register */
+#define FTDI_SIO_SET_FLOW_CTRL	2 /* Set flow control register */
+#define FTDI_SIO_SET_BAUD_RATE	3 /* Set baud rate */
+#define FTDI_SIO_SET_DATA	4 /* Set the data characteristics of the port */
+#define FTDI_SIO_GET_MODEM_STATUS	5 /* Retrieve current value of modern status register */
+#define FTDI_SIO_SET_EVENT_CHAR	6 /* Set the event character */
+#define FTDI_SIO_SET_ERROR_CHAR	7 /* Set the error character */
+
+/* Port Identifier Table */
+#define PIT_DEFAULT 		0 /* SIOA */
+#define PIT_SIOA		1 /* SIOA */
+/* The device this is tested with one has one port */
+#define PIT_SIOB		2 /* SIOB */
+#define PIT_PARALLEL		3 /* Parallel */
+
+/* FTDI_SIO_RESET */
+#define FTDI_SIO_RESET_REQUEST FTDI_SIO_RESET
+#define FTDI_SIO_RESET_REQUEST_TYPE 0x40
+#define FTDI_SIO_RESET_SIO 0
+#define FTDI_SIO_RESET_PURGE_RX 1
+#define FTDI_SIO_RESET_PURGE_TX 2
+/* 
+   BmRequestType:  0100 0000B
+   bRequest:       FTDI_SIO_RESET
+   wValue:         Control Value 
+                         0 = Reset SIO
+                         1 = Purge RX buffer
+                         2 = Purge TX buffer
+   wIndex:         Port
+   wLength:        0
+   Data:           None
+
+   */
+
+/* FTDI_SIO_SET_BAUDRATE */
+#define FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE 0x40
+#define FTDI_SIO_SET_BAUDRATE_REQUEST 3
+
+/*
+  BmRequestType:  0100 0000B
+  bRequest:       FTDI_SIO_SET_BAUDRATE
+  wValue:         BaudRate value - see below
+  wIndex:         Port
+  wLength:        0
+  Data:           None
+*/
+
+typedef enum {
+ ftdi_sio_b300 = 0, 
+ ftdi_sio_b600 = 1, 
+ ftdi_sio_b1200 = 2,
+ ftdi_sio_b2400 = 3,
+ ftdi_sio_b4800 = 4,
+ ftdi_sio_b9600 = 5,
+ ftdi_sio_b19200 = 6,
+ ftdi_sio_b38400 = 7,
+ ftdi_sio_b57600 = 8,
+ ftdi_sio_b115200 = 9
+} FTDI_SIO_baudrate_t ;
+
+#define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA
+#define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40
+#define FTDI_SIO_SET_DATA_PARITY_NONE (0x0 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_ODD (0x1 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_EVEN (0x2 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_MARK (0x3 << 8 )
+#define FTDI_SIO_SET_DATA_PARITY_SPACE (0x4 << 8 )
+#define FTDI_SIO_SET_DATA_STOP_BITS_1 (0x0 << 11 )
+#define FTDI_SIO_SET_DATA_STOP_BITS_15 (0x1 << 11 )
+#define FTDI_SIO_SET_DATA_STOP_BITS_2 (0x2 << 11 )
+
+/* FTDI_SIO_SET_DATA */
+
+/*    BmRequestType:  0100 0000B */
+/*    bRequest:       FTDI_SIO_SET_DATA */
+/*    wValue:         Data characteristics (see below) */
+/*    wIndex:         Port */
+/*    wLength:        0 */
+/*    Data:           None */
+/* 
+  Data characteristics
+
+B0..7   Number of data bits
+B8..10  Parity
+           0 = None
+           1 = Odd
+           2 = Even
+           3 = Mark
+           4 = Space
+ B11..13 Stop Bits
+           0 = 1
+           1 = 1.5
+           2 = 2
+ B14..15 Reserved
+*/
+
+
+
+/* FTDI_SIO_MODEM_CTRL */
+#define FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE 0x40
+#define FTDI_SIO_SET_MODEM_CTRL_REQUEST FTDI_SIO_MODEM_CTRL
+
+/* 
+  BmRequestType:   0100 0000B
+  bRequest:        FTDI_SIO_MODEM_CTRL
+  wValue:          ControlValue (see below)
+  wIndex:          Port
+  wLength:         0
+  Data:            None
+
+  NOTE: If the device is in RTS/CTS flow control, the RTS set by this
+        command will be IGNORED without an error being returned
+*/
+
+#define FTDI_SIO_SET_DTR_MASK 0x1
+#define FTDI_SIO_SET_DTR_HIGH ( 1 | ( FTDI_SIO_SET_DTR_MASK  << 8))
+#define FTDI_SIO_SET_DTR_LOW  ( 0 | ( FTDI_SIO_SET_DTR_MASK  << 8))
+#define FTDI_SIO_SET_RTS_MASK 0x2
+#define FTDI_SIO_SET_RTS_HIGH ( 2 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+#define FTDI_SIO_SET_RTS_LOW ( 0 | ( FTDI_SIO_SET_RTS_MASK << 8 ))
+
+/* ControlValue
+   B0    DTR state
+           0 = reset
+           1 = set
+   B1    RTS state
+           0 = reset
+           1 = set
+   B2..7 Reserved
+   B8    DTR state enable
+           0 = ignore
+           1 = use DTR state
+   B9    RTS state enable
+           0 = ignore
+           1 = use RTS state
+   B10..15 Reserved
+*/
+
+/* FTDI_SIO_SET_FLOW_CTRL */
+#define FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE 0x40
+#define FTDI_SIO_SET_FLOW_CTRL_REQUEST FTDI_SIO_SET_FLOW_CTRL
+#define FTDI_SIO_DISABLE_FLOW_CTRL 0x0 
+#define FTDI_SIO_RTS_CTS_HS 0x1
+#define FTDI_SIO_DTR_DSR_HS 0x2
+#define FTDI_SIO_XON_XOFF_HS 0x4
+/* 
+   BmRequestType:  0100 0000b
+   bRequest:       FTDI_SIO_SET_FLOW_CTRL
+   wValue:         Xoff/Xon
+   wIndex:         Protocol/Port - hIndex is protocl / lIndex is port
+   wLength:        0 
+   Data:           None
+
+hIndex - protocol has
+ B0 Output handshaking using RTS/CTS
+      0 = disabled
+      1 = enabled
+ B1 Output handshaking using DTR/DSR
+      0 = disabled
+      1 = enabled
+ B2 Xon/Xoff handshaking
+      0 = disabled
+      1 = enabled
+
+A value of zero in the hIndex field selects no handshaking
+
+If Xon/Xoff handshaking is specified, the hValue field contains the Xoff character 
+and the lValue field contains the Xon character.
+
+*/  
+ 
+/* FTDI_SIO_SET_EVENT_CHAR */
+/* Set the special event character for the specified communications port */
+/* If the device sees this character it will immediately return the */
+/* data read so far - rather than wait 40ms or until 62 bytes is read */
+#define  FTDI_SIO_SET_EVENT_CHAR_REQUEST FTDI_SIO_SET_EVENT_CHAR
+#define  FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE 0x40
+
+
+/* 
+  BmRequestType:   0100 0000b
+  bRequest:        FTDI_SIO_SET_EVENT_CHAR
+  wValue:          EventChar
+  wIndex:          Port
+  wLength:         0
+  Data:            None
+
+wValue:
+   B0..7   Event Character
+   B8      Event Character Processing
+             0 = disabled
+             1 = enabled
+   B9..15  Reserved
+
+*/
+          
+/* FTDI_SIO_SET_ERROR_CHAR */
+/* Set the parity error replacement character for the specified communications port */
+
+/* 
+  BmRequestType:  0100 0000b
+  bRequest:       FTDI_SIO_SET_EVENT_CHAR
+  wValue:         Error Char
+  wIndex:         Port
+  wLength:        0
+  Data:           None
+
+Error Char
+  B0..7  Error Character
+  B8     Error Character Processing
+           0 = disabled
+           1 = enabled
+  B9..15 Reserved
+
+*/
+
+/* FTDI_SIO_GET_MODEM_STATUS */
+/* Retreive the current value of the modem status register */
+
+#define FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE 0xc0
+#define FTDI_SIO_GET_MODEM_STATUS_REQUEST FTDI_SIO_GET_MODEM_STATUS
+#define FTDI_SIO_CTS_MASK 0x10
+#define FTDI_SIO_DSR_MASK 0x20
+#define FTDI_SIO_RI_MASK  0x40
+#define FTDI_SIO_RLSD_MASK 0x80
+/* 
+  BmRequestType:   1100 0000b
+  bRequest:        FTDI_SIO_GET_MODEM_STATUS
+  wValue:          zero
+  wIndex:          Port
+  wLength:         1
+  Data:            Status
+
+One byte of data is returned 
+B0..3 0
+B4    CTS
+        0 = inactive
+        1 = active
+B5    DSR
+        0 = inactive
+        1 = active
+B6    Ring Indicator (RI)
+        0 = inactive
+        1 = active
+B7    Receive Line Signal Detect (RLSD)
+        0 = inactive
+        1 = active 
+*/
+
+
+
+/* Descriptors returned by the device 
+
+ Device Descriptor
+
+Offset	Field		Size	Value	Description
+0	bLength		1	0x12	Size of descriptor in bytes
+1	bDescriptorType	1	0x01	DEVICE Descriptor Type
+2	bcdUSB		2	0x0110	USB Spec Release Number
+4	bDeviceClass	1	0x00	Class Code
+5	bDeviceSubClass	1	0x00	SubClass Code
+6	bDeviceProtocol	1	0x00	Protocol Code
+7	bMaxPacketSize0 1	0x08	Maximum packet size for endpoint 0
+8	idVendor	2	0x0403	Vendor ID
+10	idProduct	2	0x8372	Product ID (FTDI_SIO_PID)
+12	bcdDevice	2	0x0001	Device release number
+14	iManufacturer	1	0x01	Index of man. string desc
+15	iProduct	1	0x02	Index of prod string desc
+16	iSerialNumber	1	0x02	Index of serial nmr string desc
+17	bNumConfigurations 1    0x01	Number of possible configurations
+
+Configuration Descriptor
+
+Offset	Field			Size	Value
+0	bLength			1	0x09	Size of descriptor in bytes
+1	bDescriptorType		1	0x02	CONFIGURATION Descriptor Type
+2	wTotalLength		2	0x0020	Total length of data
+4	bNumInterfaces		1	0x01	Number of interfaces supported
+5	bConfigurationValue	1	0x01	Argument for SetCOnfiguration() req
+6	iConfiguration		1	0x02	Index of config string descriptor
+7	bmAttributes		1	0x20	Config characteristics Remote Wakeup
+8	MaxPower		1	0x1E	Max power consumption
+
+Interface Descriptor
+
+Offset	Field			Size	Value
+0	bLength			1	0x09	Size of descriptor in bytes
+1	bDescriptorType		1	0x04	INTERFACE Descriptor Type
+2	bInterfaceNumber	1	0x00	Number of interface
+3	bAlternateSetting	1	0x00	Value used to select alternate
+4	bNumEndpoints		1	0x02	Number of endpoints
+5	bInterfaceClass		1	0xFF	Class Code
+6	bInterfaceSubClass	1	0xFF	Subclass Code
+7	bInterfaceProtocol	1	0xFF	Protocol Code
+8	iInterface		1	0x02	Index of interface string description
+
+IN Endpoint Descriptor
+
+Offset	Field			Size	Value
+0	bLength			1	0x07	Size of descriptor in bytes
+1	bDescriptorType		1	0x05	ENDPOINT descriptor type
+2	bEndpointAddress	1	0x82	Address of endpoint
+3	bmAttributes		1	0x02	Endpoint attributes - Bulk
+4	bNumEndpoints		2	0x0040	maximum packet size
+5	bInterval		1	0x00	Interval for polling endpoint
+
+OUT Endpoint Descriptor
+
+Offset	Field			Size	Value
+0	bLength			1	0x07	Size of descriptor in bytes
+1	bDescriptorType		1	0x05	ENDPOINT descriptor type
+2	bEndpointAddress	1	0x02	Address of endpoint
+3	bmAttributes		1	0x02	Endpoint attributes - Bulk
+4	bNumEndpoints		2	0x0040	maximum packet size
+5	bInterval		1	0x00	Interval for polling endpoint
+    
+DATA FORMAT
+
+IN Endpoint
+
+The device reserves the first two bytes of data on this endpoint to contain the current
+values of the modem and line status registers. In the absence of data, the device 
+generates a message consisting of these two status bytes every 40 ms
+
+Byte 0: Modem Status
+
+Offset	Description
+B0	Reserved - must be 1
+B1	Reserved - must be 0
+B2	Reserved - must be 0
+B3	Reserved - must be 0
+B4	Clear to Send (CTS)
+B5	Data Set Ready (DSR)
+B6	Ring Indicator (RI)
+B7	Receive Line Signal Detect (RLSD)
+
+Byte 1: Line Status
+
+Offset	Description
+B0	Data Ready (DR)
+B1	Overrun Error (OE)
+B2	Parity Error (PE)
+B3	Framing Error (FE)
+B4	Break Interrupt (BI)
+B5	Transmitter Holding Register (THRE)
+B6	Transmitter Empty (TEMT)
+B7	Error in RCVR FIFO
+
+OUT Endpoint
+
+This device reserves the first bytes of data on this endpoint contain the length
+and port identifier of the message. For the FTDI USB Serial converter the port 
+identifier is always 1.
+
+Byte 0: Line Status
+
+Offset	Description
+B0	Reserved - must be 1
+B1	Reserved - must be 0
+B2..7	Length of message - (not including Byte 0)
+
+*/
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/serial/keyspan_pda_fw.h linux/drivers/usb/serial/keyspan_pda_fw.h
--- v2.3.50/linux/drivers/usb/serial/keyspan_pda_fw.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/keyspan_pda_fw.h	Fri Mar 10 13:19:34 2000
@@ -0,0 +1,93 @@
+/*
+ * keyspan_pda_fw.h
+ *
+ * Generated from keyspan_pda.s by ezusb_convert.pl
+ * This file is presumed to be under the same copyright as the source file
+ * from which it was derived.
+ */
+
+static const struct ezusb_hex_record keyspan_pda_firmware[] = {
+{ 0x0000,	3,	{0x02, 0x02, 0x00} },
+{ 0x0023,	4,	{0x02, 0x05, 0x5f, 0x00} },
+{ 0x0043,	4,	{0x02, 0x01, 0x00, 0x00} },
+{ 0x0030,	5,	{0x00, 0x00, 0x00, 0x00, 0x00} },
+{ 0x0100,	16,	{0x02, 0x02, 0x96, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00} },
+{ 0x0110,	16,	{0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00} },
+{ 0x0120,	16,	{0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x04, 0x61, 0x00, 0x02, 0x04, 0x89, 0x00} },
+{ 0x0200,	16,	{0x75, 0x81, 0x5e, 0xe4, 0xf5, 0x32, 0xf5, 0x33, 0xf5, 0x30, 0xf5, 0x31, 0xf5, 0x34, 0xc2, 0x00} },
+{ 0x0210,	16,	{0xc2, 0x01, 0xa9, 0x00, 0x74, 0xfe, 0x90, 0x10, 0x00, 0xf0, 0xa3, 0xd9, 0xfc, 0x74, 0xfd, 0x90} },
+{ 0x0220,	16,	{0x11, 0x00, 0xf0, 0xa3, 0xd9, 0xfc, 0x74, 0x02, 0x90, 0x7f, 0x9d, 0xf0, 0x74, 0x00, 0x90, 0x7f} },
+{ 0x0230,	16,	{0x97, 0xf0, 0x74, 0x86, 0x90, 0x7f, 0x9e, 0xf0, 0x90, 0x7f, 0x95, 0x74, 0x03, 0xf0, 0x90, 0x7f} },
+{ 0x0240,	16,	{0xaf, 0xe0, 0xd2, 0xe0, 0xf0, 0x74, 0x01, 0x90, 0x7f, 0xab, 0xf0, 0x90, 0x7f, 0xae, 0xf0, 0x90} },
+{ 0x0250,	16,	{0x7f, 0xac, 0x74, 0x04, 0xf0, 0x90, 0x7f, 0xad, 0x74, 0x04, 0xf0, 0x90, 0x7f, 0xc9, 0xf0, 0x74} },
+{ 0x0260,	16,	{0x84, 0x90, 0x7f, 0x98, 0xf0, 0x74, 0x00, 0xf5, 0x98, 0x75, 0xc8, 0x30, 0x7b, 0x05, 0x91, 0x20} },
+{ 0x0270,	16,	{0xd2, 0xca, 0x75, 0x98, 0x50, 0xd2, 0xe8, 0xd2, 0xaf, 0xd2, 0xac, 0x74, 0x00, 0xf5, 0x86, 0x90} },
+{ 0x0280,	16,	{0x7f, 0xd6, 0x74, 0x02, 0xf0, 0x79, 0x2e, 0x7a, 0x00, 0x7b, 0x00, 0xdb, 0xfe, 0xda, 0xfa, 0xd9} },
+{ 0x0290,	16,	{0xf6, 0x74, 0x06, 0xf0, 0x80, 0xfe, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x84, 0xc0, 0x85} },
+{ 0x02a0,	16,	{0xc0, 0xe0, 0xe5, 0x91, 0xc2, 0xe4, 0xf5, 0x91, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0x90, 0x7f} },
+{ 0x02b0,	16,	{0xe8, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xa3, 0xe0, 0xfb, 0xa3, 0xe0, 0xfc, 0xe9, 0x54, 0x60, 0xb4} },
+{ 0x02c0,	16,	{0x00, 0x03, 0x02, 0x03, 0x39, 0xb4, 0x40, 0x6e, 0xba, 0x00, 0x0b, 0x12, 0x04, 0x20, 0x40, 0x03} },
+{ 0x02d0,	16,	{0x02, 0x04, 0x02, 0x02, 0x04, 0x0a, 0xba, 0x01, 0x03, 0x02, 0x04, 0x0a, 0xba, 0x02, 0x03, 0x02} },
+{ 0x02e0,	16,	{0x04, 0x0a, 0xba, 0x03, 0x03, 0x02, 0x04, 0x44, 0xba, 0x04, 0x1e, 0xbb, 0x00, 0x0a, 0x90, 0x7f} },
+{ 0x02f0,	16,	{0x95, 0xe0, 0x44, 0x02, 0xf0, 0x02, 0x04, 0x02, 0x90, 0x7f, 0x98, 0xe0, 0x54, 0xfd, 0xf0, 0x90} },
+{ 0x0300,	16,	{0x7f, 0x95, 0xe0, 0x54, 0xfd, 0xf0, 0x02, 0x04, 0x02, 0xba, 0x05, 0x03, 0x02, 0x04, 0x0a, 0xba} },
+{ 0x0310,	16,	{0x06, 0x19, 0xbb, 0x00, 0x08, 0xe5, 0x33, 0xd3, 0x95, 0x32, 0x02, 0x03, 0xde, 0xbb, 0x01, 0x08} },
+{ 0x0320,	16,	{0xe5, 0x32, 0xc3, 0x95, 0x33, 0x02, 0x03, 0xde, 0x02, 0x04, 0x0a, 0xba, 0x07, 0x05, 0x8b, 0x34} },
+{ 0x0330,	16,	{0x02, 0x04, 0x02, 0x02, 0x04, 0x0a, 0x02, 0x04, 0x0a, 0xba, 0x00, 0x20, 0xb9, 0x80, 0x10, 0x90} },
+{ 0x0340,	16,	{0x7f, 0x00, 0xe4, 0xf0, 0xa3, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x04, 0x02, 0xb9} },
+{ 0x0350,	16,	{0x82, 0x02, 0x80, 0xeb, 0xb9, 0x81, 0x02, 0x80, 0xe6, 0x02, 0x04, 0x0a, 0xba, 0x01, 0x0f, 0xbb} },
+{ 0x0360,	16,	{0x00, 0x03, 0x02, 0x04, 0x0a, 0xbb, 0x01, 0x03, 0x02, 0x04, 0x02, 0x02, 0x04, 0x0a, 0xba, 0x03} },
+{ 0x0370,	16,	{0x0f, 0xbb, 0x00, 0x03, 0x02, 0x04, 0x0a, 0xbb, 0x01, 0x03, 0x02, 0x04, 0x02, 0x02, 0x04, 0x0a} },
+{ 0x0380,	16,	{0xba, 0x06, 0x56, 0xbc, 0x01, 0x0f, 0x90, 0x7f, 0xd4, 0x74, 0x06, 0xf0, 0x90, 0x7f, 0xd5, 0x74} },
+{ 0x0390,	16,	{0x12, 0xf0, 0x02, 0x04, 0x02, 0xbc, 0x02, 0x12, 0xbb, 0x00, 0x6f, 0x90, 0x7f, 0xd4, 0x74, 0x06} },
+{ 0x03a0,	16,	{0xf0, 0x90, 0x7f, 0xd5, 0x74, 0x24, 0xf0, 0x02, 0x04, 0x02, 0xbc, 0x03, 0x29, 0x74, 0x04, 0xc3} },
+{ 0x03b0,	16,	{0x9b, 0x40, 0x57, 0x60, 0x55, 0xeb, 0x2b, 0x90, 0x06, 0x44, 0x25, 0x82, 0xf5, 0x82, 0x74, 0x00} },
+{ 0x03c0,	16,	{0x35, 0x83, 0xf5, 0x83, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0x90, 0x7f, 0xd4, 0xe9, 0xf0, 0x90, 0x7f} },
+{ 0x03d0,	16,	{0xd5, 0xea, 0xf0, 0x02, 0x04, 0x02, 0x02, 0x04, 0x0a, 0xba, 0x08, 0x0f, 0x74, 0x01, 0x90, 0x7f} },
+{ 0x03e0,	16,	{0x00, 0xf0, 0x74, 0x01, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x04, 0x02, 0xba, 0x09, 0x03, 0x02, 0x04} },
+{ 0x03f0,	16,	{0x02, 0xba, 0x0a, 0x05, 0x74, 0x00, 0x02, 0x03, 0xde, 0xba, 0x0b, 0x03, 0x02, 0x04, 0x02, 0x02} },
+{ 0x0400,	16,	{0x04, 0x0a, 0x90, 0x7f, 0xb4, 0x74, 0x02, 0xf0, 0x80, 0x09, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01} },
+{ 0x0410,	16,	{0xf0, 0x80, 0x00, 0xd0, 0xe0, 0xd0, 0x85, 0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32} },
+{ 0x0420,	16,	{0xeb, 0x20, 0xe7, 0x1e, 0xc3, 0x94, 0x0a, 0x50, 0x19, 0xeb, 0x23, 0x24, 0xfe, 0xf5, 0x82, 0x74} },
+{ 0x0430,	16,	{0x05, 0x34, 0x00, 0xf5, 0x83, 0xe0, 0xf5, 0xcb, 0xf5, 0xcd, 0xa3, 0xe0, 0xf5, 0xca, 0xf5, 0xcc} },
+{ 0x0440,	16,	{0xc3, 0x22, 0xd3, 0x22, 0xb9, 0x41, 0x11, 0xeb, 0x64, 0xff, 0x54, 0x84, 0xfb, 0x90, 0x7f, 0x98} },
+{ 0x0450,	16,	{0xe0, 0x54, 0x7b, 0x4b, 0xf0, 0x02, 0x04, 0x02, 0x90, 0x7f, 0x9b, 0xe0, 0x64, 0xff, 0x02, 0x03} },
+{ 0x0460,	16,	{0xde, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x84, 0xc0, 0x85, 0xc0, 0xe0, 0xe5, 0x91, 0xc2} },
+{ 0x0470,	16,	{0xe4, 0xf5, 0x91, 0x90, 0x7f, 0xa9, 0x74, 0x04, 0xf0, 0x12, 0x05, 0xa0, 0xd0, 0xe0, 0xd0, 0x85} },
+{ 0x0480,	16,	{0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0xc0, 0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0} },
+{ 0x0490,	16,	{0x84, 0xc0, 0x85, 0xc0, 0xe0, 0xe5, 0x91, 0xc2, 0xe4, 0xf5, 0x91, 0x90, 0x7f, 0xaa, 0x74, 0x04} },
+{ 0x04a0,	16,	{0xf0, 0x90, 0x7f, 0xc9, 0xe0, 0xf9, 0xe4, 0xf5, 0x86, 0x90, 0x7d, 0xc0, 0x75, 0x85, 0x10, 0x85} },
+{ 0x04b0,	16,	{0x32, 0x84, 0xe0, 0x05, 0x86, 0x05, 0x84, 0xf0, 0xe5, 0x84, 0xb5, 0x33, 0x02, 0x80, 0x09, 0x05} },
+{ 0x04c0,	16,	{0x32, 0x05, 0x86, 0xa3, 0xd9, 0xec, 0x80, 0x00, 0x90, 0x7f, 0xc9, 0xf0, 0xb1, 0x31, 0xd0, 0xe0} },
+{ 0x04d0,	16,	{0xd0, 0x85, 0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0xe4, 0xf5, 0x86, 0x90, 0x7f} },
+{ 0x04e0,	16,	{0xbc, 0xe0, 0x20, 0xe1, 0x4b, 0x90, 0x7d, 0x00, 0xe5, 0x32, 0xf0, 0xa3, 0xe5, 0x33, 0xf0, 0xa3} },
+{ 0x04f0,	16,	{0xe5, 0x30, 0xf0, 0xa3, 0xe5, 0x31, 0xf0, 0xa3, 0xe4, 0x30, 0x00, 0x01, 0x04, 0xf0, 0xa3, 0x05} },
+{ 0x0500,	16,	{0x86, 0x90, 0x10, 0x00, 0x79, 0x10, 0xe0, 0xa3, 0x05, 0x86, 0xf0, 0xa3, 0x05, 0x86, 0xd9, 0xf6} },
+{ 0x0510,	16,	{0x05, 0x86, 0x74, 0xfc, 0xf0, 0xa3, 0x05, 0x86, 0x90, 0x11, 0x00, 0x79, 0x10, 0xe0, 0xa3, 0x05} },
+{ 0x0520,	16,	{0x86, 0xf0, 0xa3, 0x05, 0x86, 0xd9, 0xf6, 0xe4, 0xf5, 0x86, 0x90, 0x7f, 0xbd, 0x74, 0x26, 0xf0} },
+{ 0x0530,	16,	{0x22, 0x20, 0x00, 0x13, 0xe5, 0x32, 0xb5, 0x33, 0x01, 0x22, 0x05, 0x33, 0x75, 0x83, 0x10, 0x85} },
+{ 0x0540,	16,	{0x33, 0x82, 0xe0, 0xf5, 0x99, 0xd2, 0x00, 0x74, 0x00, 0xb5, 0x34, 0x01, 0x22, 0xe5, 0x33, 0xd3} },
+{ 0x0550,	16,	{0x95, 0x32, 0xc3, 0x95, 0x34, 0x40, 0xf5, 0x75, 0x34, 0x00, 0xd2, 0x01, 0x02, 0x05, 0xa0, 0xc0} },
+{ 0x0560,	16,	{0x86, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x84, 0xc0, 0x85, 0xc0, 0xe0, 0x30, 0x99, 0x07, 0xc2, 0x99} },
+{ 0x0570,	16,	{0xc2, 0x00, 0x12, 0x05, 0x34, 0x30, 0x98, 0x05, 0x12, 0x05, 0x8a, 0xc2, 0x98, 0xd0, 0xe0, 0xd0} },
+{ 0x0580,	16,	{0x85, 0xd0, 0x84, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0x86, 0x32, 0x75, 0x83, 0x11, 0x85, 0x30, 0x82} },
+{ 0x0590,	16,	{0x05, 0x82, 0xe5, 0x99, 0xf0, 0xe5, 0x82, 0xb5, 0x31, 0x01, 0x22, 0x05, 0x30, 0xb1, 0xa0, 0x22} },
+{ 0x05a0,	16,	{0x90, 0x7f, 0xb8, 0xe0, 0x20, 0xe1, 0x38, 0x20, 0x01, 0x36, 0xe5, 0x30, 0xb5, 0x31, 0x01, 0x22} },
+{ 0x05b0,	16,	{0xe4, 0xf5, 0x86, 0x75, 0x83, 0x11, 0x05, 0x86, 0x90, 0x7e, 0x00, 0xf0, 0xa3, 0x05, 0x86, 0x79} },
+{ 0x05c0,	16,	{0x01, 0xe5, 0x30, 0xb5, 0x31, 0x02, 0x80, 0x10, 0x05, 0x31, 0x85, 0x31, 0x82, 0xe0, 0x05, 0x86} },
+{ 0x05d0,	16,	{0xf0, 0xa3, 0x05, 0x86, 0x09, 0xb9, 0x40, 0xe9, 0x90, 0x7f, 0xb9, 0xe9, 0x60, 0x01, 0xf0, 0x22} },
+{ 0x05e0,	16,	{0xc2, 0x01, 0xe4, 0xf5, 0x86, 0x90, 0x7e, 0x00, 0x74, 0x01, 0xf0, 0xa3, 0x74, 0x02, 0xf0, 0x90} },
+{ 0x05f0,	16,	{0x7f, 0xb9, 0xf0, 0x22, 0xc2, 0x99, 0xf5, 0x99, 0x30, 0x99, 0xfd, 0xc2, 0x99, 0x22, 0xe5, 0x5e} },
+{ 0x0600,	16,	{0xf6, 0x3c, 0xfd, 0x8f, 0xfe, 0xc8, 0xff, 0x64, 0xff, 0xb2, 0xff, 0xd9, 0xff, 0xed, 0xff, 0xf3} },
+{ 0x0610,	16,	{0xff, 0xfa, 0x12, 0x01, 0x00, 0x01, 0xff, 0xff, 0xff, 0x40, 0xcd, 0x06, 0x04, 0x01, 0x89, 0xab} },
+{ 0x0620,	16,	{0x01, 0x02, 0x03, 0x01, 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00} },
+{ 0x0630,	16,	{0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 0x07, 0x05, 0x82, 0x03, 0x40, 0x00, 0x01, 0x07, 0x05, 0x02} },
+{ 0x0640,	16,	{0x02, 0x40, 0x00, 0x00, 0x06, 0x4c, 0x06, 0x50, 0x06, 0x72, 0x06, 0xa0, 0x04, 0x03, 0x00, 0x00} },
+{ 0x0650,	16,	{0x22, 0x03, 0x41, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x20, 0x00, 0x75, 0x00, 0x73, 0x00} },
+{ 0x0660,	16,	{0x62, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x65, 0x00, 0x74, 0x00} },
+{ 0x0670,	16,	{0x73, 0x00, 0x2e, 0x03, 0x41, 0x00, 0x43, 0x00, 0x4d, 0x00, 0x45, 0x00, 0x20, 0x00, 0x55, 0x00} },
+{ 0x0680,	16,	{0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x69, 0x00, 0x61, 0x00} },
+{ 0x0690,	16,	{0x6c, 0x00, 0x20, 0x00, 0x77, 0x00, 0x69, 0x00, 0x64, 0x00, 0x67, 0x00, 0x65, 0x00, 0x74, 0x00} },
+{ 0x06a0,	6,	{0x06, 0x03, 0x34, 0x00, 0x37, 0x00} },
+{ 0xffff,	0,	{0x00} }
+};
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/serial/usb-serial.c linux/drivers/usb/serial/usb-serial.c
--- v2.3.50/linux/drivers/usb/serial/usb-serial.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/usb-serial.c	Fri Mar 10 16:18:34 2000
@@ -0,0 +1,2549 @@
+/*
+ * USB Serial Converter driver
+ *
+ *	(C) Copyright (C) 1999, 2000
+ *	    Greg Kroah-Hartman (greg@kroah.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 driver was originally based on the ACM driver by Armin Fuerst (which was 
+ * based on a driver by Brad Keryan)
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ * (03/06/2000) gkh
+ *	Added the keyspan pda code from Brian Warner <warner@lothar.com>
+ *	Moved a bunch of the port specific stuff into its own structure. This
+ *	is in anticipation of the true multiport devices (there's a bug if you
+ *	try to access more than one port of any multiport device right now)
+ *
+ * (02/21/2000) gkh
+ *	Made it so that any serial devices only have to specify which functions
+ *	they want to overload from the generic function calls (great, 
+ *	inheritance in C, in a driver, just what I wanted...)
+ *	Added support for set_termios and ioctl function calls. No drivers take
+ *	advantage of this yet.
+ *	Removed the #ifdef MODULE, now there is no module specific code.
+ *	Cleaned up a few comments in usb-serial.h that were wrong (thanks again
+ *	to Miles Lott).
+ *	Small fix to get_free_serial.
+ *
+ * (02/14/2000) gkh
+ *	Removed the Belkin and Peracom functionality from the driver due to
+ *	the lack of support from the vendor, and me not wanting people to 
+ *	accidenatly buy the device, expecting it to work with Linux.
+ *	Added read_bulk_callback and write_bulk_callback to the type structure
+ *	for the needs of the FTDI and WhiteHEAT driver.
+ *	Changed all reverences to FTDI to FTDI_SIO at the request of Bill
+ *	Ryder.
+ *	Changed the output urb size back to the max endpoint size to make
+ *	the ftdi_sio driver have it easier, and due to the fact that it didn't
+ *	really increase the speed any.
+ *
+ * (02/11/2000) gkh
+ *	Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
+ *	patch from Miles Lott (milos@insync.net).
+ *	Fixed bug with not restoring the minor range that a device grabs, if
+ *	the startup function fails (thanks Miles for finding this).
+ *
+ * (02/05/2000) gkh
+ *	Added initial framework for the Keyspan PDA serial converter so that
+ *	Brian Warner has a place to put his code.
+ *	Made the ezusb specific functions generic enough that different
+ *	devices can use them (whiteheat and keyspan_pda both need them).
+ *	Split out a whole bunch of structure and other stuff to a seperate
+ *	usb-serial.h file.
+ *	Made the Visor connection messages a little more understandable, now
+ *	that Miles Lott (milos@insync.net) has gotten the Generic channel to
+ *	work. Also made them always show up in the log file.
+ * 
+ * (01/25/2000) gkh
+ *	Added initial framework for FTDI serial converter so that Bill Ryder
+ *	has a place to put his code.
+ *	Added the vendor specific info from Handspring. Now we can print out
+ *	informational debug messages as well as understand what is happening.
+ *
+ * (01/23/2000) gkh
+ *	Fixed problem of crash when trying to open a port that didn't have a
+ *	device assigned to it. Made the minor node finding a little smarter,
+ *	now it looks to find a continous space for the new device.
+ *
+ * (01/21/2000) gkh
+ *	Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
+ *	Fixed get_serial_by_minor which was all messed up for multi port 
+ *	devices. Fixed multi port problem for generic devices. Now the number
+ *	of ports is determined by the number of bulk out endpoints for the
+ *	generic device.
+ *
+ * (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
+ *      the Handspring Visor to be attached successfully. Only the first
+ *      bulk in / bulk out endpoint pair is being used right now.
+ *
+ * version 0.3.0 (12/27/99) gkh
+ *	Added initial support for the Handspring Visor based on a patch from
+ *	Miles Lott (milos@sneety.insync.net)
+ *	Cleaned up the code a bunch and converted over to using urbs only.
+ *
+ * version 0.2.3 (12/21/99) gkh
+ *	Added initial support for the Connect Tech WhiteHEAT converter.
+ *	Incremented the number of ports in expectation of getting the
+ *	WhiteHEAT to work properly (4 ports per connection).
+ *	Added notification on insertion and removal of what port the
+ *	device is/was connected to (and what kind of device it was).
+ *
+ * version 0.2.2 (12/16/99) gkh
+ *	Changed major number to the new allocated number. We're legal now!
+ *
+ * version 0.2.1 (12/14/99) gkh
+ *	Fixed bug that happens when device node is opened when there isn't a
+ *	device attached to it. Thanks to marek@webdesign.no for noticing this.
+ *
+ * version 0.2.0 (11/10/99) gkh
+ *	Split up internals to make it easier to add different types of serial 
+ *	converters to the code.
+ *	Added a "generic" driver that gets it's vendor and product id
+ *	from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
+ *	for the idea and sample code (from the usb scanner driver.)
+ *	Cleared up any licensing questions by releasing it under the GNU GPL.
+ *
+ * version 0.1.2 (10/25/99) gkh
+ * 	Fixed bug in detecting device.
+ *
+ * version 0.1.1 (10/05/99) gkh
+ * 	Changed the major number to not conflict with anything else.
+ *
+ * version 0.1 (09/28/99) gkh
+ * 	Can recognize the two different devices and start up a read from
+ *	device when asked to. Writes also work. No control signals yet, this
+ *	all is vendor specific data (i.e. no spec), also no control for
+ *	different baud rates or other bit settings.
+ *	Currently we are using the same devid as the acm driver. This needs
+ *	to change.
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/fcntl.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/tty.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#define DEBUG
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB_SERIAL_WHITEHEAT
+#include "whiteheat.h"		/* firmware for the ConnectTech WhiteHEAT device */
+#endif
+
+#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
+struct ezusb_hex_record {
+	__u16 address;
+	__u8 data_size;
+	__u8 data[16];
+};
+#include "keyspan_pda_fw.h"
+#endif
+
+#include "usb-serial.h"
+
+/* parity check flag */
+#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+/* local function prototypes */
+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 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);
+static void serial_unthrottle (struct tty_struct * tty);
+static int  serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
+static void serial_set_termios (struct tty_struct *tty, struct termios * old);
+
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
+static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
+
+static struct usb_driver usb_serial_driver = {
+	"serial",
+	usb_serial_probe,
+	usb_serial_disconnect,
+	{ NULL, NULL }
+};
+
+static int			serial_refcount;
+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, };
+
+
+
+static struct usb_serial *get_serial_by_minor (int minor)
+{
+	dbg("get_serial_by_minor %d", minor);
+
+	return serial_table[minor];
+}
+
+
+static struct usb_serial *get_free_serial (int num_ports, int *minor)
+{
+	struct usb_serial *serial = NULL;
+	int i, j;
+	int good_spot;
+
+	dbg("get_free_serial %d", num_ports);
+
+	*minor = 0;
+	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+		if (serial_table[i])
+			continue;
+
+		good_spot = 1;
+		for (j = 1; j <= num_ports-1; ++j)
+			if (serial_table[i+j])
+				good_spot = 0;
+		if (good_spot == 0)
+			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 < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
+			serial_table[i] = serial;
+		return serial;
+		}
+	return NULL;
+}
+
+
+static void return_serial (struct usb_serial *serial)
+{
+	int i;
+
+	dbg("return_serial");
+
+	if (serial == NULL)
+		return;
+
+	for (i = 0; i < serial->num_ports; ++i) {
+		serial_table[serial->minor + i] = NULL;
+	}
+
+	return;
+}
+
+
+#ifdef USES_EZUSB_FUNCTIONS
+/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
+#define CPUCS_REG    0x7F92
+
+static int ezusb_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("ezusb_writememory %x, %d", address, length);
+
+	if (!transfer_buffer) {
+		err("ezusb_writememory: kmalloc(%d) failed.", 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;
+}
+
+
+static int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
+{
+	int	response;
+	dbg("ezusb_set_reset: %d", reset_bit);
+	response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
+	if (response < 0) {
+		err("ezusb_set_reset %d failed", reset_bit);
+	}
+	return response;
+}
+
+#endif	/* USES_EZUSB_FUNCTIONS */
+
+
+/*****************************************************************************
+ * Driver tty interface functions
+ *****************************************************************************/
+static int serial_open (struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial *serial;
+	
+	dbg("serial_open");
+
+	/* initialize the pointer incase something fails */
+	tty->driver_data = NULL;
+
+	/* 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) {
+		dbg("serial == NULL!");
+		return (-ENODEV);
+	}
+	if (!serial->type) {
+		dbg("serial->type == NULL!");
+		return (-ENODEV);
+	}
+
+	/* make the tty driver remember our serial object, and us it */
+	tty->driver_data = serial;
+	serial->tty = tty;
+	 
+	/* pass on to the driver specific version of this function if it is available */
+	if (serial->type->open) {
+		return (serial->type->open(tty, filp));
+	} else {
+		return (generic_serial_open(tty, filp));
+	}
+}
+
+
+static void serial_close(struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port;	
+
+	dbg("serial_close");
+
+	if (!serial) {
+		dbg("serial == NULL!");
+		return;
+	}
+
+	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->type) {
+		dbg("serial->type == NULL!");
+		return;
+	}
+	if (!serial->port[port].active) {
+		dbg ("device not opened");
+		return;
+	}
+
+	/* pass on to the driver specific version of this function if it is available */
+	if (serial->type->close) {
+		serial->type->close(tty, filp);
+	} else {
+		generic_serial_close(tty, filp);
+	}
+}	
+
+
+static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+	
+	dbg("serial_write port %d, %d byte(s)", port, count);
+
+	/* do some sanity checking that we really have a device present */
+	if (!serial) {
+		dbg("serial == NULL!");
+		return (-ENODEV);
+	}
+	if (!serial->type) {
+		dbg("serial->type == NULL!");
+		return (-ENODEV);
+	}
+	if (!serial->port[port].active) {
+		dbg ("device not opened");
+		return (-EINVAL);
+	}
+	
+	/* pass on to the driver specific version of this function if it is available */
+	if (serial->type->write) {
+		return (serial->type->write(tty, from_user, buf, count));
+	} else {
+		return (generic_serial_write(tty, from_user, buf, count));
+	}
+}
+
+
+static int serial_write_room (struct tty_struct *tty) 
+{
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("serial_write_room port %d", port);
+	
+	/* do some sanity checking that we really have a device present */
+	if (!serial) {
+		dbg("serial == NULL!");
+		return (-ENODEV);
+	}
+	if (!serial->type) {
+		dbg("serial->type == NULL!");
+		return (-ENODEV);
+	}
+	if (!serial->port[port].active) {
+		dbg ("device not open");
+		return (-EINVAL);
+	}
+	
+	/* pass on to the driver specific version of this function if it is available */
+	if (serial->type->write_room) {
+		return (serial->type->write_room(tty));
+	} else {
+		return (generic_write_room(tty));
+	}
+}
+
+
+static int serial_chars_in_buffer (struct tty_struct *tty) 
+{
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("serial_chars_in_buffer port %d", port);
+	
+	/* do some sanity checking that we really have a device present */
+	if (!serial) {
+		dbg("serial == NULL!");
+		return (-ENODEV);
+	}
+	if (!serial->type) {
+		dbg("serial->type == NULL!");
+		return (-ENODEV);
+	}
+	if (!serial->port[port].active) {
+		dbg ("device not open");
+		return (-EINVAL);
+	}
+	
+	/* pass on to the driver specific version of this function if it is available */
+	if (serial->type->chars_in_buffer) {
+		return (serial->type->chars_in_buffer(tty));
+	} else {
+		return (generic_chars_in_buffer(tty));
+	}
+}
+
+
+static void serial_throttle (struct tty_struct * tty)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("serial_throttle port %d", port);
+	
+	/* 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->port[port].active) {
+		dbg ("device not open");
+		return;
+	}
+
+	/* pass on to the driver specific version of this function */
+	if (serial->type->throttle) {
+		serial->type->throttle(tty);
+	} else {
+		generic_throttle(tty);
+	}
+
+	return;
+}
+
+
+static void serial_unthrottle (struct tty_struct * tty)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("serial_unthrottle port %d", port);
+	
+	/* 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->port[port].active) {
+		dbg ("device not open");
+		return;
+	}
+
+	/* pass on to the driver specific version of this function */
+	if (serial->type->unthrottle) {
+		serial->type->unthrottle(tty);
+	} else {
+		generic_unthrottle(tty);
+	}
+
+	return;
+}
+
+
+static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port;	
+
+	dbg("serial_ioctl");
+
+	if (!serial) {
+		dbg("serial == NULL!");
+		return -ENODEV;
+	}
+
+	port = MINOR(tty->device) - serial->minor;
+
+	dbg("serial_ioctl port %d", port);
+	
+	/* do some sanity checking that we really have a device present */
+	if (!serial->type) {
+		dbg("serial->type == NULL!");
+		return -ENODEV;
+	}
+	if (!serial->port[port].active) {
+		dbg ("device not open");
+		return -ENODEV;
+	}
+
+	/* pass on to the driver specific version of this function if it is available */
+	if (serial->type->ioctl) {
+		return (serial->type->ioctl(tty, file, cmd, arg));
+	} else {
+		return (generic_ioctl (tty, file, cmd, arg));
+	}
+}
+
+
+static void serial_set_termios (struct tty_struct *tty, struct termios * old)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port;	
+
+	dbg("serial_set_termios");
+
+	if (!serial) {
+		dbg("serial == NULL!");
+		return;
+	}
+
+	port = MINOR(tty->device) - serial->minor;
+
+	dbg("serial_set_termios port %d", port);
+	
+	/* do some sanity checking that we really have a device present */
+	if (!serial->type) {
+		dbg("serial->type == NULL!");
+		return;
+	}
+	if (!serial->port[port].active) {
+		dbg ("device not open");
+		return;
+	}
+
+	/* pass on to the driver specific version of this function if it is available */
+	if (serial->type->set_termios) {
+		serial->type->set_termios(tty, old);
+	} else {
+		generic_set_termios (tty, old);
+	}
+	
+	return;
+}
+
+
+static void serial_break (struct tty_struct *tty, int break_state)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port;	
+
+	if (!serial) {
+		dbg("serial == NULL!");
+		return;
+	}
+
+	port = MINOR(tty->device) - serial->minor;
+
+	dbg("serial_break port %d", port);
+	
+	/* do some sanity checking that we really have a device present */
+	if (!serial->type) {
+		dbg("serial->type == NULL!");
+		return;
+	}
+	if (!serial->port[port].active) {
+		dbg ("device not open");
+		return;
+	}
+
+	/* pass on to the driver specific version of this function if it is
+           available */
+	if (serial->type->break_ctl) {
+		serial->type->break_ctl(tty, break_state);
+	}
+}
+
+
+#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 *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+
+	dbg("whiteheat_serial_open port %d", portNumber);
+
+	if (port->active) {
+		dbg ("device already open");
+		return -EINVAL;
+	}
+	port->active = 1;
+ 
+	/*Start reading from the device*/
+	if (usb_submit_urb(&port->read_urb))
+		dbg("usb_submit_urb(read bulk) failed");
+
+	/* Need to do device specific setup here (control lines, baud rate, etc.) */
+	/* FIXME!!! */
+
+	return (0);
+}
+
+
+static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+
+	dbg("whiteheat_serial_close port %d", portNumber);
+	
+	/* Need to change the control lines here */
+	/* FIXME */
+	
+	/* shutdown our bulk reads and writes */
+	usb_unlink_urb (&port->write_urb);
+	usb_unlink_urb (&port->read_urb);
+	port->active = 0;
+}
+
+
+static void whiteheat_set_termios (struct tty_struct *tty, struct termios *old_termios)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+	unsigned int cflag = tty->termios->c_cflag;
+
+	dbg("whiteheat_set_termios port %d", port);
+
+	/* check that they really want us to change something */
+	if (old_termios) {
+		if ((cflag == old_termios->c_cflag) &&
+		    (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
+			dbg("nothing to change...");
+			return;
+		}
+	}
+
+	/* do the parsing of the cflag to see what to set the line to */
+	/* FIXME!! */
+
+	return;
+}
+
+static void whiteheat_throttle (struct tty_struct * tty)
+{
+	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!!! */
+
+	return;
+}
+
+
+static void whiteheat_unthrottle (struct tty_struct * tty)
+{
+	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!!! */
+
+	return;
+}
+
+
+/* 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 = ezusb_set_reset (serial, 1);
+
+	record = &whiteheat_loader[0];
+	while (record->address != 0xffff) {
+		response = ezusb_writememory (serial, record->address, 
+				(unsigned char *)record->data, record->data_size, 0xa0);
+		if (response < 0) {
+			err("ezusb_writememory failed for loader (%d %04X %p %d)", 
+				response, record->address, record->data, record->data_size);
+			break;
+		}
+		++record;
+	}
+
+	response = ezusb_set_reset (serial, 0);
+
+	record = &whiteheat_firmware[0];
+	while (record->address < 0x1b40) {
+		++record;
+	}
+	while (record->address != 0xffff) {
+		response = ezusb_writememory (serial, record->address, 
+				(unsigned char *)record->data, record->data_size, 0xa0);
+		if (response < 0) {
+			err("ezusb_writememory failed for first firmware step (%d %04X %p %d)", 
+				response, record->address, record->data, record->data_size);
+			break;
+		}
+		++record;
+	}
+	
+	response = ezusb_set_reset (serial, 1);
+
+	record = &whiteheat_firmware[0];
+	while (record->address < 0x1b40) {
+		response = ezusb_writememory (serial, record->address, 
+				(unsigned char *)record->data, record->data_size, 0xa0);
+		if (response < 0) {
+			err("ezusb_writememory failed for second firmware step (%d %04X %p %d)", 
+				response, record->address, record->data, record->data_size);
+			break;
+		}
+		++record;
+	}
+
+	response = ezusb_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 *serial = (struct usb_serial *) tty->driver_data;
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+
+	dbg("visor_serial_open port %d", portNumber);
+
+	if (port->active) {
+		dbg ("device already open");
+		return -EINVAL;
+	}
+
+	port->active = 1;
+
+	/*Start reading from the device*/
+	if (usb_submit_urb(&port->read_urb))
+		dbg("usb_submit_urb(read bulk) failed");
+
+	return (0);
+}
+
+static void visor_serial_close(struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+	unsigned char *transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
+	
+	dbg("visor_serial_close port %d", portNumber);
+			 
+	if (!transfer_buffer) {
+		err("visor_serial_close: kmalloc(%d) failed.", 0x12);
+	} else {
+		/* send a shutdown message to the device */
+		usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION,
+				0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
+	}
+
+	/* shutdown our bulk reads and writes */
+	usb_unlink_urb (&port->write_urb);
+	usb_unlink_urb (&port->read_urb);
+	port->active = 0;
+}
+
+
+static void visor_throttle (struct tty_struct * tty)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("visor_throttle port %d", port);
+
+	usb_unlink_urb (&serial->port[port].read_urb);
+
+	return;
+}
+
+
+static void visor_unthrottle (struct tty_struct * tty)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int port = MINOR(tty->device) - serial->minor;
+
+	dbg("visor_unthrottle port %d", port);
+
+	if (usb_unlink_urb (&serial->port[port].read_urb))
+		dbg("usb_submit_urb(read bulk) failed");
+
+	return;
+}
+
+
+static int  visor_startup (struct usb_serial *serial)
+{
+	int response;
+	int i;
+	unsigned char *transfer_buffer =  kmalloc (256, GFP_KERNEL);
+
+	if (!transfer_buffer) {
+		err("visor_startup: kmalloc(%d) failed.", 256);
+		return -ENOMEM;
+	}
+
+	dbg("visor_startup");
+
+	dbg("visor_setup: Set config to 1");
+	usb_set_configuration (serial->dev, 1);
+
+	/* send a get connection info request */
+	response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION,
+					0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
+	if (response < 0) {
+		err("visor_startup: error getting connection information");
+	} else {
+		struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer;
+		char *string;
+		info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports);
+		for (i = 0; i < connection_info->num_ports; ++i) {
+			switch (connection_info->connections[i].port_function_id) {
+				case VISOR_FUNCTION_GENERIC:
+					string = "Generic";
+					break;
+				case VISOR_FUNCTION_DEBUGGER:
+					string = "Debugger";
+					break;
+				case VISOR_FUNCTION_HOTSYNC:
+					string = "HotSync";
+					break;
+				case VISOR_FUNCTION_CONSOLE:
+					string = "Console";
+					break;
+				case VISOR_FUNCTION_REMOTE_FILE_SYS:
+					string = "Remote File System";
+					break;
+				default:
+					string = "unknown";
+					break;	
+			}
+			info("%s: port %d, is for %s use and is bound to ttyUSB%d", serial->type->name, connection_info->connections[i].port, string, serial->minor + i);
+		}
+	}
+
+	/* ask for the number of bytes available, but ignore the response as it is broken */
+	response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE,
+					0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
+	if (response < 0) {
+		err("visor_startup: error getting bytes available request");
+	}
+
+	kfree (transfer_buffer);
+
+	/* continue on with initialization */
+	return (0);
+}
+
+
+#endif	/* CONFIG_USB_SERIAL_VISOR*/
+
+
+#ifdef CONFIG_USB_SERIAL_FTDI_SIO
+/******************************************************************************
+ * FTDI SIO Serial Converter specific driver functions
+ ******************************************************************************/
+
+/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
+/* Thanx to FTDI for so kindly providing details of the protocol required */
+/*   to talk to the device */
+
+#include "ftdi_sio.h"
+
+static int  ftdi_sio_serial_open (struct tty_struct *tty, struct file *filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+	char buf[1]; /* Needed for the usb_control_msg I think */
+
+	dbg("ftdi_sio_serial_open port %d", portNumber);
+
+	if (port->active) {
+		dbg ("device already open");
+		return -EINVAL;
+	}
+	port->active = 1;
+
+	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
+			FTDI_SIO_RESET_SIO, 
+			0, buf, 0, HZ * 5);
+
+	/* FIXME - Should I really purge the buffers? */
+	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
+			FTDI_SIO_RESET_PURGE_RX, 
+			0, buf, 0, HZ * 5);
+
+	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
+			FTDI_SIO_RESET_PURGE_TX, 
+			0, buf, 0, HZ * 5);	
+
+
+	/* As per usb_serial_init s/be CS8, B9600, 1 STOP BIT */
+	if ( usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			     FTDI_SIO_SET_BAUDRATE_REQUEST,
+			     FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
+			     ftdi_sio_b9600, 0, 
+			     buf, 0, HZ * 5) < 0){
+		dbg("Error from baudrate urb");
+		return(-EINVAL);
+	}
+
+	if ( usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			     FTDI_SIO_SET_DATA_REQUEST, 
+			     FTDI_SIO_SET_DATA_REQUEST_TYPE,
+			     8 | FTDI_SIO_SET_DATA_PARITY_NONE | 
+			     FTDI_SIO_SET_DATA_STOP_BITS_1, 0,
+			     buf, 0, HZ * 5) < 0){
+		dbg("Error from cs8/noparity/1 stopbit urb");
+		return(-EINVAL);
+	}
+
+	/* Disable flow control */
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
+			    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+			    0, 0, 
+			    buf, 0, HZ * 5) < 0) {
+		dbg("error from flowcontrol urb");
+		return(-EINVAL);
+	}	    
+
+	/* Turn on RTS and DTR since we are not flow controlling*/
+	/* FIXME - check for correct behaviour clocal vs non clocal */
+	/* FIXME - might be able to do both simultaneously */
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
+			    FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
+			    (unsigned)FTDI_SIO_SET_DTR_HIGH, 0, 
+			    buf, 0, HZ * 5) < 0) {
+		dbg("Error from DTR HIGH urb");
+	}
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
+			    FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
+			    (unsigned)FTDI_SIO_SET_RTS_HIGH, 0, 
+			    buf, 0, HZ * 5) < 0) {
+		dbg("Error from RTS HIGH urb");
+	}
+	
+	/*Start reading from the device*/
+	if (usb_submit_urb(&port->read_urb))
+		dbg("usb_submit_urb(read bulk) failed");
+
+	return (0);
+}
+
+
+static void ftdi_sio_serial_close (struct tty_struct *tty, struct file *filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+	char buf[1];
+
+	dbg("ftdi_sio_serial_close port %d", portNumber);
+	
+	/* FIXME - might be able to do both simultaneously */
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
+			    FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
+			    (unsigned)FTDI_SIO_SET_DTR_LOW, 0, 
+			    buf, 0, HZ * 5) < 0) {
+		dbg("Error from DTR LOW urb");
+	}
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
+			    FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
+			    (unsigned)FTDI_SIO_SET_RTS_LOW, 0, 
+			    buf, 0, HZ * 5) < 0) {
+		dbg("Error from RTS LOW urb");
+	}	
+
+	/* FIXME Should I flush the device here? - not doing it for now */
+
+	/* shutdown our bulk reads and writes */
+	usb_unlink_urb (&port->write_urb);
+	usb_unlink_urb (&port->read_urb);
+	port->active = 0;
+}
+
+
+  
+/* The ftdi_sio requires the first byte to have:
+   B0 1
+   B1 0
+   B2..7 length of message excluding byte 0
+*/
+static int ftdi_sio_serial_write (struct tty_struct * tty, int from_user, 
+				  const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+	const int data_offset = 1;
+
+	dbg("ftdi_sio_serial_write port %d, %d bytes", portNumber, count);
+
+	if (count == 0) {
+		dbg("write request of 0 bytes");
+		return 0;
+	}
+
+	/* only do something if we have a bulk out endpoint */
+	if (serial->num_bulk_out) {
+		unsigned char *first_byte = port->write_urb.transfer_buffer;
+
+		if (port->write_urb.status == -EINPROGRESS) {
+			dbg ("already writing");
+			return 0;
+		}
+
+		count += data_offset;
+		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+		if (count == 0) {
+			return 0;
+		}
+
+		/* Copy in the data to send */
+		if (from_user) {
+			copy_from_user(port->write_urb.transfer_buffer + data_offset , 
+				       buf, count - data_offset );
+		}
+		else {
+			memcpy(port->write_urb.transfer_buffer + data_offset,
+			       buf, count - data_offset );
+		}  
+
+		/* Write the control byte at the front of the packet*/
+		first_byte = port->write_urb.transfer_buffer;
+		*first_byte = 1 | ((count-data_offset) << 2) ; 
+
+#ifdef DEBUG
+		dbg("Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]);
+
+		if (count) {
+			int i;
+			printk (KERN_DEBUG __FILE__ ": data written - length = %d, data = ", count);
+			for (i = 0; i < count; ++i) {
+				printk ("0x%02x ", first_byte[i]);
+				if (first_byte[i] > ' ' && first_byte[i] < '~') {
+					printk("%c ", first_byte[i]);
+				} else {
+					printk("  ");
+				}
+			}
+
+		     
+			printk ("\n");
+		}
+
+#endif
+		/* send the data out the bulk port */
+		port->write_urb.transfer_buffer_length = count;
+
+		if (usb_submit_urb(&port->write_urb))
+			dbg("usb_submit_urb(write bulk) failed");
+
+		dbg("write returning: %d", count - data_offset);
+		return (count - data_offset);
+	}
+	
+	/* no bulk out, so return 0 bytes written */
+	return 0;
+} 
+
+
+static void ftdi_sio_read_bulk_callback (struct urb *urb)
+{ /* ftdi_sio_serial_buld_callback */
+	struct usb_serial *serial = (struct usb_serial *)urb->context;
+       	struct tty_struct *tty = serial->tty; 
+       	unsigned char *data = urb->transfer_buffer;
+	const int data_offset = 2;
+	int i;
+
+	dbg("ftdi_sio_read_bulk_callback");
+
+	if (urb->status) {
+		dbg("nonzero read bulk status received: %d", urb->status);
+		return;
+	}
+
+#ifdef DEBUG
+	if (urb->actual_length > 2) {
+		printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length);
+		for (i = 0; i < urb->actual_length; ++i) {
+			printk ("0x%.2x ", data[i]);
+			if (data[i] > ' ' && data[i] < '~') {
+				printk("%c ", data[i]);
+			} else {
+				printk("  ");
+			}
+		}
+		printk ("\n");
+	}
+#endif
+	
+
+	if (urb->actual_length > data_offset) {
+		for (i = data_offset ; i < urb->actual_length ; ++i) {
+			tty_insert_flip_char(tty, data[i], 0);
+	  	}
+	  	tty_flip_buffer_push(tty);
+	}
+
+	/* Continue trying to always read  */
+	if (usb_submit_urb(urb))
+		dbg("failed resubmitting read urb");
+
+	return;
+} /* ftdi_sio_serial_read_bulk_callback */
+
+
+static void ftdi_sio_set_termios (struct tty_struct *tty, struct termios *old_termios)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+	unsigned int cflag = tty->termios->c_cflag;
+	__u16 urb_value; /* Will hold the new flags */
+	char buf[1]; /* Perhaps I should dynamically alloc this? */
+	dbg("ftdi_sio_set_termios port %d", port);
+
+	/* FIXME - we should keep the old termios really */
+	/* FIXME -For this cut I don't care if the line is really changing or 
+	   not  - so just do the change regardless */
+	
+	/* Set number of data bits, parity, stop bits */
+	
+	urb_value = 0;
+	urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
+		      FTDI_SIO_SET_DATA_STOP_BITS_1);
+	urb_value |= (cflag & PARENB ? 
+		      (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : 
+		       FTDI_SIO_SET_DATA_PARITY_EVEN) :
+		      FTDI_SIO_SET_DATA_PARITY_NONE);
+	if (cflag & CSIZE) {
+		switch (cflag & CSIZE) {
+		case CS5: urb_value |= 5; dbg("Setting CS5"); break;
+		case CS6: urb_value |= 6; dbg("Setting CS6"); break;
+		case CS7: urb_value |= 7; dbg("Setting CS7"); break;
+		case CS8: urb_value |= 8; dbg("Setting CS8"); break;
+		default:
+			dbg("CSIZE was set but not CS5-CS8");
+		}
+	}
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_DATA_REQUEST, 
+			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
+			    urb_value , 0,
+			    buf, 0, 100) < 0) {
+		dbg("FAILED to set databits/stopbits/parity");
+	}	   
+
+	/* Now do the baudrate */
+	/* FIXME - should drop lines on B0 */
+	/* FIXME Should also handle CLOCAL here  */
+     
+	switch(cflag & CBAUD){
+	case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break;
+	case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break;
+	case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break;
+	case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break;
+	case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break;
+	case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break;
+	case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break;
+	case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break;
+	case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break;
+	case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break;
+	default: dbg("FTDI_SIO does not support the baudrate requested"); 
+		/* FIXME - how to return an error for this? */ break;
+	}
+	/* Send the URB */
+	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			    FTDI_SIO_SET_BAUDRATE_REQUEST, 
+			    FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
+			    urb_value, 0, 
+			    buf, 0, 100) < 0) {
+		dbg("urb failed to set baurdrate");
+	}
+	return;
+}
+
+
+/*FIXME - the beginnings of this implementation - not even hooked into the driver yet */
+static int ftdi_sio_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+	__u16 urb_value=0; /* Will hold the new flags */
+	char buf[1];
+	int  ret, mask;
+	dbg("ftdi_sio_ioctl port %d", port);
+
+	/* Based on code from acm.c */
+	switch (cmd) {
+
+		case TIOCMGET:
+			/* Request the status from the device */
+			if ((ret = usb_control_msg(serial->dev, 
+					    usb_sndctrlpipe(serial->dev, 0),
+					    FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
+					    FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
+					    0, 0, 
+					    buf, 1, HZ * 5)) < 0 ) {
+				dbg("Get not get modem status of device");
+				return(ret);
+			}
+
+			return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
+					(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
+					(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
+					(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0),
+					(unsigned long *) arg);
+			break;
+
+		case TIOCMSET:
+		case TIOCMBIS:
+		case TIOCMBIC:
+			if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
+
+			/* FIXME Need to remember if we have set DTR or RTS since we
+			   can't ask the device  */
+			/* FIXME - also need to find the meaning of TIOCMBIS/BIC/SET */
+			if (mask & TIOCM_DTR) {
+				switch(cmd) {
+				case TIOCMSET:
+					urb_value = FTDI_SIO_SET_DTR_HIGH | FTDI_SIO_SET_RTS_LOW;
+					break;
+
+				case TIOCMBIS:
+					/* Will leave RTS alone and set DTR */
+					urb_value =  FTDI_SIO_SET_DTR_HIGH;
+					break;
+					
+				case TIOCMBIC:
+					urb_value = FTDI_SIO_SET_DTR_LOW;
+					break;
+				}
+			}
+
+			if (mask & TIOCM_RTS) {
+				switch(cmd) {
+				case TIOCMSET:
+					urb_value = FTDI_SIO_SET_DTR_LOW | FTDI_SIO_SET_RTS_HIGH;
+					break;
+
+				case TIOCMBIS:
+					/* Will leave DTR and set RTS */
+					urb_value = FTDI_SIO_SET_RTS_HIGH;
+					break;
+
+				case TIOCMBIC:
+					/* Will unset RTS */
+					urb_value = FTDI_SIO_SET_RTS_LOW;
+					break;
+				}
+			}	
+
+			
+			return(usb_control_msg(serial->dev, 
+					       usb_sndctrlpipe(serial->dev, 0),
+					       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
+					       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
+					       urb_value , 0,
+					       buf, 0, HZ * 5));
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+#endif	/* CONFIG_USB_SERIAL_FTDI_SIO */
+
+
+#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
+/*****************************************************************************
+ * Keyspan PDA specific driver functions
+ *****************************************************************************/
+
+static void keyspan_pda_rx_interrupt (struct urb *urb)
+{
+	struct usb_serial *serial = (struct usb_serial *) urb->context;
+	struct tty_struct *tty = serial->tty;
+	unsigned char *data = urb->transfer_buffer;
+	int i;
+
+	/* the urb might have been killed. */
+	if (urb->status)
+		return;
+	
+	/* see if the message is data or a status interrupt */
+	switch (data[0]) {
+	case 0:
+		/* rest of message is rx data */
+		if (urb->actual_length) {
+			for (i = 1; i < urb->actual_length ; ++i) {
+				tty_insert_flip_char(tty, data[i], 0);
+			}
+			tty_flip_buffer_push(tty);
+		}
+		break;
+	case 1:
+		/* status interrupt */
+		dbg(" rx int, d1=%d, d2=%d", data[1], data[2]);
+		switch (data[1]) {
+		case 1: /* modemline change */
+			break;
+		case 2: /* tx unthrottle interrupt */
+			serial->tx_throttled = 0;
+			wake_up(&serial->write_wait); /* wake up writer */
+			break;
+		default:
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+	/* INT urbs are automatically re-submitted */
+}
+
+
+static void keyspan_pda_rx_throttle (struct tty_struct *tty)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	/* stop receiving characters. We just turn off the URB request, and
+	   let chars pile up in the device. If we're doing hardware
+	   flowcontrol, the device will signal the other end when its buffer
+	   fills up. If we're doing XON/XOFF, this would be a good time to
+	   send an XOFF, although it might make sense to foist that off
+	   upon the device too. */
+
+	dbg("keyspan_pda_rx_throttle port %d", port);
+	usb_unlink_urb(&serial->port[port].read_urb);
+}
+
+
+static void keyspan_pda_rx_unthrottle (struct tty_struct *tty)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+
+	/* just restart the receive interrupt URB */
+	dbg("keyspan_pda_rx_unthrottle port %d", port);
+	if (usb_submit_urb(&serial->port[port].read_urb))
+		dbg(" usb_submit_urb(read urb) failed");
+	return;
+}
+
+
+static int keyspan_pda_setbaud (struct usb_serial *serial, int baud)
+{
+	int rc;
+	int bindex;
+
+	switch(baud) {
+		case 110: bindex = 0; break;
+		case 300: bindex = 1; break;
+		case 1200: bindex = 2; break;
+		case 2400: bindex = 3; break;
+		case 4800: bindex = 4; break;
+		case 9600: bindex = 5; break;
+		case 19200: bindex = 6; break;
+		case 38400: bindex = 7; break;
+		case 57600: bindex = 8; break;
+		case 115200: bindex = 9; break;
+		default: return -EINVAL;
+	}
+
+	/* rather than figure out how to sleep while waiting for this
+	   to complete, I just use the "legacy" API. */
+	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			     0, /* set baud */
+			     USB_TYPE_VENDOR 
+			     | USB_RECIP_INTERFACE
+			     | USB_DIR_OUT, /* type */
+			     bindex, /* value */
+			     0, /* index */
+			     NULL, /* &data */
+			     0, /* size */
+			     2*HZ); /* timeout */
+	return(rc);
+}
+
+
+static void keyspan_pda_break_ctl (struct tty_struct *tty, int break_state)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int value;
+	if (break_state == -1)
+		value = 1; /* start break */
+	else
+		value = 0; /* clear break */
+	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			4, /* set break */
+			USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			value, 0, NULL, 0, 2*HZ);
+	/* there is something funky about this.. the TCSBRK that 'cu' performs
+	   ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
+	   seconds apart, but it feels like the break sent isn't as long as it
+	   is on /dev/ttyS0 */
+}
+
+
+static void keyspan_pda_set_termios (struct tty_struct *tty,
+				     struct termios *old_termios)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	unsigned int cflag = tty->termios->c_cflag;
+
+	/* cflag specifies lots of stuff: number of stop bits, parity, number
+	   of data bits, baud. What can the device actually handle?:
+	   CSTOPB (1 stop bit or 2)
+	   PARENB (parity)
+	   CSIZE (5bit .. 8bit)
+	   There is minimal hw support for parity (a PSW bit seems to hold the
+	   parity of whatever is in the accumulator). The UART either deals
+	   with 10 bits (start, 8 data, stop) or 11 bits (start, 8 data,
+	   1 special, stop). So, with firmware changes, we could do:
+	   8N1: 10 bit
+	   8N2: 11 bit, extra bit always (mark?)
+	   8[EOMS]1: 11 bit, extra bit is parity
+	   7[EOMS]1: 10 bit, b0/b7 is parity
+	   7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?)
+
+	   HW flow control is dictated by the tty->termios->c_cflags & CRTSCTS
+	   bit.
+
+	   For now, just do baud. */
+
+	switch (cflag & CBAUD) {
+		/* we could support more values here, just need to calculate
+		   the necessary divisors in the firmware. <asm/termbits.h>
+		   has the Bnnn constants. */
+		case B110: keyspan_pda_setbaud(serial, 110); break;
+		case B300: keyspan_pda_setbaud(serial, 300); break;
+		case B1200: keyspan_pda_setbaud(serial, 1200); break;
+		case B2400: keyspan_pda_setbaud(serial, 2400); break;
+		case B4800: keyspan_pda_setbaud(serial, 4800); break;
+		case B9600: keyspan_pda_setbaud(serial, 9600); break;
+		case B19200: keyspan_pda_setbaud(serial, 19200); break;
+		case B38400: keyspan_pda_setbaud(serial, 38400); break;
+		case B57600: keyspan_pda_setbaud(serial, 57600); break;
+		case B115200: keyspan_pda_setbaud(serial, 115200); break;
+		default: dbg("can't handle requested baud rate"); break;
+	}
+}
+
+
+/* modem control pins: DTR and RTS are outputs and can be controlled.
+   DCD, RI, DSR, CTS are inputs and can be read. All outputs can also be
+   read. The byte passed is: DTR(b7) DCD RI DSR CTS RTS(b2) unused unused */
+
+static int keyspan_pda_get_modem_info(struct usb_serial *serial,
+				      unsigned char *value)
+{
+	int rc;
+	unsigned char data;
+	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+			     3, /* get pins */
+			     USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN,
+			     0, 0, &data, 1, 2*HZ);
+	if (rc > 0)
+		*value = data;
+	return rc;
+}
+
+
+static int keyspan_pda_set_modem_info(struct usb_serial *serial,
+				      unsigned char value)
+{
+	int rc;
+	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+			     3, /* set pins */
+			     USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_OUT,
+			     value, 0, NULL, 0, 2*HZ);
+	return rc;
+}
+
+
+static int keyspan_pda_ioctl(struct tty_struct *tty, struct file *file,
+			     unsigned int cmd, unsigned long arg)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
+	int rc;
+	unsigned int value;
+	unsigned char status, mask;
+
+	switch (cmd) {
+	case TIOCMGET: /* get modem pins state */
+		rc = keyspan_pda_get_modem_info(serial, &status);
+		if (rc < 0)
+			return rc;
+		value =
+			((status & (1<<7)) ? TIOCM_DTR : 0) |
+			((status & (1<<6)) ? TIOCM_CAR : 0) |
+			((status & (1<<5)) ? TIOCM_RNG : 0) |
+			((status & (1<<4)) ? TIOCM_DSR : 0) |
+			((status & (1<<3)) ? TIOCM_CTS : 0) |
+			((status & (1<<2)) ? TIOCM_RTS : 0);
+		if (copy_to_user((unsigned int *)arg, &value, sizeof(int)))
+			return -EFAULT;
+		return 0;
+	case TIOCMSET: /* set a state as returned by MGET */
+		if (copy_from_user(&value, (unsigned int *)arg, sizeof(int)))
+			return -EFAULT;
+		status =
+			((value & TIOCM_DTR) ? (1<<7) : 0) |
+			((value & TIOCM_CAR) ? (1<<6) : 0) |
+			((value & TIOCM_RNG) ? (1<<5) : 0) |
+			((value & TIOCM_DSR) ? (1<<4) : 0) |
+			((value & TIOCM_CTS) ? (1<<3) : 0) |
+			((value & TIOCM_RTS) ? (1<<2) : 0);
+		rc = keyspan_pda_set_modem_info(serial, status);
+		if (rc < 0)
+			return rc;
+		return 0;
+	case TIOCMBIS: /* set bits in bitmask <arg> */
+	case TIOCMBIC: /* clear bits from bitmask <arg> */
+		if (copy_from_user(&value, (unsigned int *)arg, sizeof(int)))
+			return -EFAULT;
+		rc = keyspan_pda_get_modem_info(serial, &status);
+		if (rc < 0)
+			return rc;
+		mask =
+			((value & TIOCM_RTS) ? (1<<2) : 0) |
+			((value & TIOCM_DTR) ? (1<<7) : 0);
+		if (cmd == TIOCMBIS)
+			status |= mask;
+		else
+			status &= ~mask;
+		rc = keyspan_pda_set_modem_info(serial, status);
+		if (rc < 0)
+			return rc;
+		return 0;
+	case TIOCMIWAIT:
+		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
+		/* TODO */
+	case TIOCGICOUNT:
+		/* return count of modemline transitions */
+		return 0; /* TODO */
+	}
+	
+	return -ENOIOCTLCMD;
+}
+
+static int keyspan_pda_write(struct tty_struct * tty, int from_user, 
+			     const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int port = MINOR(tty->device) - serial->minor;
+	int request_unthrottle = 0;
+	int rc = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	/* guess how much room is left in the device's ring buffer, and if we
+	   want to send more than that, check first, updating our notion of
+	   what is left. If our write will result in no room left, ask the
+	   device to give us an interrupt when the room available rises above
+	   a threshold, and hold off all writers (eventually, those using
+	   select() or poll() too) until we receive that unthrottle interrupt.
+	   Block if we can't write anything at all, otherwise write as much as
+	   we can. */
+
+	if (count == 0) {
+		dbg(" write request of 0 bytes");
+		return (0);
+	}
+
+	/* we might block because of:
+	   the TX urb is in-flight (wait until it completes)
+	   the device is full (wait until it says there is room)
+	*/
+	while (serial->port[port].write_urb.status == -EINPROGRESS) {
+		if (0 /* file->f_flags & O_NONBLOCK */) {
+			rc = -EAGAIN;
+			goto err;
+		}
+		interruptible_sleep_on(&serial->write_wait);
+		if (signal_pending(current)) {
+			rc = -ERESTARTSYS;
+			goto err;
+		}
+	}
+
+	/* at this point the URB is in our control, nobody else can submit it
+	   again (the only sudden transition was the one from EINPROGRESS to
+	   finished) */
+
+	/* the next potential block is that our TX process might be throttled.
+	   The transition from throttled->not happens because of an Rx
+	   interrupt, and the wake_up occurs during the same interrupt, so we
+	   have to be careful to avoid a race that would cause us to sleep
+	   forever. */
+
+	add_wait_queue(&serial->write_wait, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (serial->tx_throttled) {
+		/* device can't accomodate any more characters. Sleep until it
+		   can. Woken up by an Rx interrupt message, which clears
+		   tx_throttled first. */
+		dbg(" tx_throttled, going to sleep");
+		if (signal_pending(current)) {
+			current->state = TASK_RUNNING;
+			remove_wait_queue(&serial->write_wait, &wait);
+			dbg(" woke up because of signal");
+			rc = -ERESTARTSYS;
+			goto err;
+		}
+		schedule();
+		dbg(" woke up");
+	}
+	remove_wait_queue(&serial->write_wait, &wait);
+	set_current_state(TASK_RUNNING);
+
+	count = (count > serial->port[port].bulk_out_size) ? 
+		serial->port[port].bulk_out_size : count;
+	if (count > serial->tx_room) {
+		unsigned char room;
+		/* Looks like we might overrun the Tx buffer. Ask the device
+		   how much room it really has */
+		rc = usb_control_msg(serial->dev, 
+				     usb_rcvctrlpipe(serial->dev, 0),
+				     6, /* write_room */
+				     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
+				     | USB_DIR_IN,
+				     0, /* value: 0 means "remaining room" */
+				     0, /* index */
+				     &room,
+				     1,
+				     2*HZ);
+		if (rc < 0) {
+			dbg(" roomquery failed");
+			return rc; /* failed */
+		}
+		if (rc == 0) {
+			dbg(" roomquery returned 0 bytes");
+			return -EIO; /* device didn't return any data */
+		}
+		dbg(" roomquery says %d", room);
+		serial->tx_room = room;
+		if (count > serial->tx_room) {
+			/* we're about to completely fill the Tx buffer, so
+			   we'll be throttled afterwards. */
+			count = serial->tx_room;
+			request_unthrottle = 1;
+		}
+	}
+	serial->tx_room -= count;
+
+	if (count) {
+		/* now transfer data */
+		if (from_user) {
+			copy_from_user(serial->port[port].write_urb.transfer_buffer,
+				       buf, count);
+		}
+		else {
+			memcpy (serial->port[port].write_urb.transfer_buffer, 
+				buf, count);
+		}  
+		/* send the data out the bulk port */
+		serial->port[port].write_urb.transfer_buffer_length = count;
+		
+		if (usb_submit_urb(&serial->port[port].write_urb))
+			dbg(" usb_submit_urb(write bulk) failed");
+	}
+	else {
+		/* There wasn't any room left, so we are throttled until
+		   the buffer empties a bit */
+		request_unthrottle = 1;
+	}
+
+	if (request_unthrottle) {
+		dbg(" request_unthrottle");
+		/* ask the device to tell us when the tx buffer becomes
+		   sufficiently empty */
+		serial->tx_throttled = 1; /* block writers */
+		rc = usb_control_msg(serial->dev, 
+				     usb_sndctrlpipe(serial->dev, 0),
+				     7, /* request_unthrottle */
+				     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
+				     | USB_DIR_OUT,
+				     16, /* value: threshold */
+				     0, /* index */
+				     NULL,
+				     0,
+				     2*HZ);
+	}
+
+	return (count);
+ err:
+	return (rc);
+}
+
+
+static void keyspan_pda_write_bulk_callback (struct urb *urb)
+{
+	struct usb_serial *serial = (struct usb_serial *) urb->context;
+	struct tty_struct *tty = serial->tty; 
+
+	wake_up_interruptible(&serial->write_wait);
+
+	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 keyspan_pda_write_room (struct tty_struct *tty)
+{
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+
+	/* used by n_tty.c for processing of tabs and such. Giving it our
+	   conservative guess is probably good enough, but needs testing by
+	   running a console through the device. */
+
+	return (serial->tx_room);
+}
+
+
+static int keyspan_pda_chars_in_buffer (struct tty_struct *tty) 
+{
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	unsigned char count;
+	int rc;
+
+	/* used by tty stuff to wait for output to drain. Go ask the
+	   device how much is still queued in the tx ring */
+	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+			     6, /* write_room */
+			     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
+			     | USB_DIR_IN,
+			     1, /* value: 1 means chars_in_buffer */
+			     0, /* index */
+			     &count,
+			     1,
+			     2*HZ);
+	if (rc < 0)
+		return rc; /* failed */
+	if (rc == 0)
+		return -EIO; /* device didn't return any data */
+	return (count);
+}
+
+
+static int keyspan_pda_serial_open (struct tty_struct *tty, struct file *filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+	unsigned char room;
+	int rc;
+
+	if (port->active) {
+		return -EINVAL;
+	}
+	port->active = 1;
+ 
+	/* find out how much room is in the Tx ring */
+	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+			     6, /* write_room */
+			     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
+			     | USB_DIR_IN,
+			     0, /* value */
+			     0, /* index */
+			     &room,
+			     1,
+			     2*HZ);
+	if (rc < 0) {
+		dbg(" roomquery failed");
+		return rc; /* failed */
+	}
+	if (rc == 0) {
+		dbg(" roomquery returned 0 bytes");
+		return -EIO; /* device didn't return any data */
+	}
+	serial->tx_room = room;
+	serial->tx_throttled = room ? 0 : 1;
+
+	/* the normal serial device seems to always turn on DTR and RTS here,
+	   so do the same */
+	if (tty->termios->c_cflag & CBAUD)
+		keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
+	else
+		keyspan_pda_set_modem_info(serial, 0);
+
+	/*Start reading from the device*/
+	if (usb_submit_urb(&port->read_urb))
+		dbg(" usb_submit_urb(read int) failed");
+
+	return (0);
+}
+
+
+static void keyspan_pda_serial_close(struct tty_struct *tty, 
+				     struct file *filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+
+	/* the normal serial device seems to always shut off DTR and RTS now */
+	if (tty->termios->c_cflag & HUPCL)
+		keyspan_pda_set_modem_info(serial, 0);
+
+	/* shutdown our bulk reads and writes */
+	usb_unlink_urb (&port->write_urb);
+	usb_unlink_urb (&port->read_urb);
+	port->active = 0;
+}
+
+
+/* download the firmware to a "fake" device (pre-renumeration) */
+static int keyspan_pda_fake_startup (struct usb_serial *serial)
+{
+	int response;
+	const struct ezusb_hex_record *record;
+
+	/* download the firmware here ... */
+	response = ezusb_set_reset(serial, 1);
+
+	record = &keyspan_pda_firmware[0];
+	while(record->address != 0xffff) {
+		response = ezusb_writememory(serial, record->address,
+					     (unsigned char *)record->data,
+					     record->data_size, 0xa0);
+		if (response < 0) {
+			err("ezusb_writememory failed for Keyspan PDA "
+			    "firmware (%d %04X %p %d)",
+			    response, 
+			    record->address, record->data, record->data_size);
+			break;
+		}
+		record++;
+	}
+	/* bring device out of reset. Renumeration will occur in a moment
+	   and the new device will bind to the real driver */
+	response = ezusb_set_reset(serial, 0);
+
+	/* we want this device to fail to have a driver assigned to it. */
+	return (1);
+}
+
+
+/* do some startup allocations not currently performed by usb_serial_probe() */
+static int keyspan_pda_startup (struct usb_serial *serial)
+{
+	struct usb_endpoint_descriptor *intin;
+	intin = serial->port[0].interrupt_in_endpoint;
+
+	/* set up the receive interrupt urb */
+	FILL_INT_URB(&serial->port[0].read_urb, serial->dev,
+		     usb_rcvintpipe(serial->dev, intin->bEndpointAddress),
+		     serial->port[0].interrupt_in_buffer,
+		     intin->wMaxPacketSize,
+		     keyspan_pda_rx_interrupt,
+		     serial,
+		     intin->bInterval);
+
+	init_waitqueue_head(&serial->write_wait);
+	
+	return (0);
+}
+
+#endif	/* CONFIG_USB_SERIAL_KEYSPAN_PDA */
+
+
+/*****************************************************************************
+ * generic devices specific driver functions
+ *****************************************************************************/
+static int generic_serial_open (struct tty_struct *tty, struct file *filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+
+	dbg("generic_serial_open port %d", portNumber);
+
+	if (port->active) {
+		dbg ("device already open");
+		return -EINVAL;
+	}
+	port->active = 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(&port->read_urb))
+			dbg("usb_submit_urb(read bulk) failed");
+	}
+
+	return (0);
+}
+
+
+static void generic_serial_close(struct tty_struct *tty, struct file * filp)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+
+	dbg("generic_serial_close port %d", portNumber);
+	
+	/* shutdown any bulk reads that might be going on */
+	if (serial->num_bulk_out) {
+		usb_unlink_urb (&port->write_urb);
+	}
+	if (serial->num_bulk_in) {
+		usb_unlink_urb (&port->read_urb);
+	}
+
+	port->active = 0;
+}
+
+
+static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
+{
+	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+
+	dbg("generic_serial_write port %d", portNumber);
+
+	if (count == 0) {
+		dbg("write request of 0 bytes");
+		return (0);
+	}
+
+	/* only do something if we have a bulk out endpoint */
+	if (serial->num_bulk_out) {
+		if (port->write_urb.status == -EINPROGRESS) {
+			dbg ("already writing");
+			return (0);
+		}
+
+		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+
+		if (from_user) {
+			copy_from_user(port->write_urb.transfer_buffer, buf, count);
+		}
+		else {
+			memcpy (port->write_urb.transfer_buffer, buf, count);
+		}  
+
+		/* send the data out the bulk port */
+		port->write_urb.transfer_buffer_length = count;
+
+		if (usb_submit_urb(&port->write_urb))
+			dbg("usb_submit_urb(write bulk) failed");
+
+		return (count);
+	}
+	
+	/* no bulk out, so return 0 bytes written */
+	return (0);
+} 
+
+
+static int generic_write_room (struct tty_struct *tty) 
+{
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+	int room;
+
+	dbg("generic_write_room port %d", portNumber);
+	
+	if (serial->num_bulk_out) {
+		if (port->write_urb.status == -EINPROGRESS)
+			room = 0;
+		else
+			room = port->bulk_out_size;
+		dbg("generic_write_room returns %d", room);
+		return (room);
+	}
+	
+	return (0);
+}
+
+
+static int generic_chars_in_buffer (struct tty_struct *tty) 
+{
+	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
+	int portNumber = MINOR(tty->device) - serial->minor;
+	struct usb_serial_port *port = &serial->port[portNumber];
+
+	dbg("generic_chars_in_buffer port %d", portNumber);
+	
+	if (serial->num_bulk_out) {
+		if (port->write_urb.status == -EINPROGRESS) {
+			return (port->bulk_out_size);
+		}
+	}
+
+	return (0);
+}
+
+
+static void generic_throttle (struct tty_struct *tty) 
+{
+	/* do nothing for the generic device */
+	return;
+}
+
+
+static void generic_unthrottle (struct tty_struct *tty) 
+{
+	/* do nothing for the generic device */
+	return;
+}
+
+
+static int generic_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
+{
+	/* generic driver doesn't support any ioctls yet */
+	return -ENOIOCTLCMD;
+}
+
+
+static void generic_set_termios (struct tty_struct *tty, struct termios * old)
+{
+	/* generic driver doesn't really care about setting any line settings */
+	return;
+}
+
+
+static void generic_read_bulk_callback (struct urb *urb)
+{
+	struct usb_serial *serial = (struct usb_serial *)urb->context;
+       	struct tty_struct *tty = serial->tty; 
+       	unsigned char *data = urb->transfer_buffer;
+	int i;
+
+	dbg("generic_read_bulk_callback");
+
+	if (urb->status) {
+		dbg("nonzero read bulk status received: %d", urb->status);
+		return;
+	}
+
+#ifdef DEBUG
+	if (urb->actual_length) {
+		printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length);
+		for (i = 0; i < urb->actual_length; ++i) {
+			printk ("%.2x ", data[i]);
+		}
+		printk ("\n");
+	}
+#endif
+	
+	if (urb->actual_length) {
+		for (i = 0; i < urb->actual_length ; ++i) {
+			 tty_insert_flip_char(tty, data[i], 0);
+	  	}
+	  	tty_flip_buffer_push(tty);
+	}
+
+	/* Continue trying to always read  */
+	if (usb_submit_urb(urb))
+		dbg("failed resubmitting read urb");
+
+	return;
+}
+
+
+static void generic_write_bulk_callback (struct urb *urb)
+{
+	struct usb_serial *serial = (struct usb_serial *) urb->context; 
+       	struct tty_struct *tty = serial->tty; 
+
+	dbg("generic_write_bulk_callback");
+
+	if (urb->status) {
+		dbg("nonzero write bulk status received: %d", urb->status);
+		return;
+	}
+
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+
+	wake_up_interruptible(&tty->write_wait);
+	
+	return;
+}
+
+
+
+static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
+{
+	struct usb_serial *serial = NULL;
+	struct usb_serial_port *port;
+	struct usb_interface_descriptor *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	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 minor;
+	int buffer_size;
+	int i;
+	char interrupt_pipe;
+	char bulk_in_pipe;
+	char bulk_out_pipe;
+	int num_interrupt_in = 0;
+	int num_bulk_in = 0;
+	int num_bulk_out = 0;
+	int num_ports;
+	
+	/* loop through our list of known serial converters, and see if this device matches */
+	device_num = 0;
+	while (usb_serial_devices[device_num] != NULL) {
+		type = usb_serial_devices[device_num];
+		dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct));
+
+		/* look at the device descriptor */
+		if ((dev->descriptor.idVendor == *(type->idVendor)) &&
+		    (dev->descriptor.idProduct == *(type->idProduct))) {
+
+			dbg("descriptor matches...looking at the endpoints");
+
+			/* descriptor matches, let's try to find the endpoints needed */
+			interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
+			
+			/* check out the endpoints */
+			interface = &dev->actconfig->interface[ifnum].altsetting[0];
+			for (i = 0; i < interface->bNumEndpoints; ++i) {
+				endpoint = &interface->endpoint[i];
+		
+				if ((endpoint->bEndpointAddress & 0x80) &&
+				    ((endpoint->bmAttributes & 3) == 0x02)) {
+					/* we found a bulk in endpoint */
+					dbg("found bulk in");
+					bulk_in_pipe = HAS;
+					bulk_in_endpoint[num_bulk_in] = endpoint;
+					++num_bulk_in;
+				}
+
+				if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
+				    ((endpoint->bmAttributes & 3) == 0x02)) {
+					/* we found a bulk out endpoint */
+					dbg("found bulk out");
+					bulk_out_pipe = HAS;
+					bulk_out_endpoint[num_bulk_out] = endpoint;
+					++num_bulk_out;
+				}
+		
+				if ((endpoint->bEndpointAddress & 0x80) &&
+				    ((endpoint->bmAttributes & 3) == 0x03)) {
+					/* we found a interrupt in endpoint */
+					dbg("found interrupt in");
+					interrupt_pipe = HAS;
+					interrupt_in_endpoint[num_interrupt_in] = endpoint;
+					++num_interrupt_in;
+				}
+
+			}
+	
+			/* verify that we found all of the endpoints that we need */
+			if ((interrupt_pipe & type->needs_interrupt_in) &&
+			    (bulk_in_pipe & type->needs_bulk_in) &&
+			    (bulk_out_pipe & type->needs_bulk_out)) {
+				/* found all that we need */
+				info("%s converter detected", type->name);
+
+#ifdef CONFIG_USB_SERIAL_GENERIC
+				if (type == &generic_device)
+					num_ports = num_bulk_out;
+				else
+#endif
+					num_ports = type->num_ports;
+
+				serial = get_free_serial (num_ports, &minor);
+				if (serial == NULL) {
+					err("No more free serial devices");
+					return NULL;
+				}
+	
+			       	serial->dev = dev;
+				serial->type = type;
+				serial->minor = minor;
+				serial->num_ports = num_ports;
+				serial->num_bulk_in = num_bulk_in;
+				serial->num_bulk_out = num_bulk_out;
+				serial->num_interrupt_in = num_interrupt_in;
+
+				/* collect interrupt_in endpoints now, because
+				   the keyspan_pda startup function needs
+				   to know about them */
+				for (i = 0; i < num_interrupt_in; ++i) {
+					port = &serial->port[i];
+					buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize;
+					port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+					if (!port->interrupt_in_buffer) {
+						err("Couldn't allocate interrupt_in_buffer");
+						goto probe_error;
+					}
+					port->interrupt_in_endpoint = interrupt_in_endpoint[i];
+				}
+
+				/* if this device type has a startup function, call it */
+				if (type->startup) {
+					if (type->startup (serial)) {
+						return_serial (serial);
+						return NULL;
+					}
+				}
+
+				/* set up the endpoint information */
+				for (i = 0; i < num_bulk_in; ++i) {
+					port = &serial->port[i];
+					buffer_size = bulk_in_endpoint[i]->wMaxPacketSize;
+					port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
+					if (!port->bulk_in_buffer) {
+						err("Couldn't allocate bulk_in_buffer");
+						goto probe_error;
+					}
+					if (serial->type->read_bulk_callback) {
+						FILL_BULK_URB(&port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
+								port->bulk_in_buffer, buffer_size, serial->type->read_bulk_callback, serial);
+					} else {
+						FILL_BULK_URB(&port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
+								port->bulk_in_buffer, buffer_size, generic_read_bulk_callback, serial);
+					}
+				}
+
+				for (i = 0; i < num_bulk_out; ++i) {
+					port = &serial->port[i];
+					port->bulk_out_size = bulk_out_endpoint[i]->wMaxPacketSize;
+					port->bulk_out_buffer = kmalloc (port->bulk_out_size, GFP_KERNEL);
+					if (!port->bulk_out_buffer) {
+						err("Couldn't allocate bulk_out_buffer");
+						goto probe_error;
+					}
+					if (serial->type->write_bulk_callback) {
+						FILL_BULK_URB(&port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
+								port->bulk_out_buffer, port->bulk_out_size, serial->type->write_bulk_callback, serial);
+					} else {
+						FILL_BULK_URB(&port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
+								port->bulk_out_buffer, port->bulk_out_size, generic_write_bulk_callback, serial);
+					}
+				}
+
+#if 0 /* use this code when WhiteHEAT is up and running */
+				for (i = 0; i < num_interrupt_in; ++i) {
+					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
+
+				for (i = 0; i < serial->num_ports; ++i) {
+					info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i);
+				}
+
+				MOD_INC_USE_COUNT;
+
+				return serial;
+			} else {
+				info("descriptors matched, but endpoints did not");
+			}
+		}
+
+		/* look at the next type in our list */
+		++device_num;
+	}
+
+probe_error:
+	if (serial) {
+		for (i = 0; i < num_bulk_in; ++i)
+			if (serial->port[i].bulk_in_buffer[i])
+				kfree (serial->port[i].bulk_in_buffer);
+		for (i = 0; i < num_bulk_out; ++i)
+			if (serial->port[i].bulk_out_buffer)
+				kfree (serial->port[i].bulk_out_buffer);
+		for (i = 0; i < num_interrupt_in; ++i)
+			if (serial->port[i].interrupt_in_buffer)
+				kfree (serial->port[i].interrupt_in_buffer);
+		
+		/* return the minor range that this device had */
+		return_serial (serial);
+
+		/* free up any memory that we allocated */
+		kfree (serial);
+	}
+	return NULL;
+}
+
+
+static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
+{
+	struct usb_serial *serial = (struct usb_serial *) ptr;
+	struct usb_serial_port *port;
+	int i;
+
+	if (serial) {
+		/* need to stop any transfers...*/
+		for (i = 0; i < serial->num_ports; ++i) {
+			port = &serial->port[i];
+			usb_unlink_urb (&port->write_urb);
+			usb_unlink_urb (&port->read_urb);
+			port->active = 0;
+		}
+
+		/* free up any memory that we allocated */
+		for (i = 0; i < serial->num_bulk_in; ++i) {
+			port = &serial->port[i];
+			if (port->bulk_in_buffer)
+				kfree (port->bulk_in_buffer);
+		}
+		for (i = 0; i < serial->num_bulk_out; ++i) {
+			port = &serial->port[i];
+			if (port->bulk_out_buffer)
+				kfree (port->bulk_out_buffer);
+		}
+		for (i = 0; i < serial->num_interrupt_in; ++i) {
+			port = &serial->port[i];
+			if (port->interrupt_in_buffer)
+				kfree (port->interrupt_in_buffer);
+		}
+
+		for (i = 0; i < serial->num_ports; ++i) {
+			info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->minor + i);
+		}
+
+		/* return the minor range that this device had */
+		return_serial (serial);
+
+		/* free up any memory that we allocated */
+		kfree (serial);
+
+	} else {
+		info("device disconnected");
+	}
+	
+	MOD_DEC_USE_COUNT;
+}
+
+
+static struct tty_driver serial_tty_driver = {
+	magic:			TTY_DRIVER_MAGIC,
+	driver_name:		"usb",
+	name:			"ttyUSB",
+	major:			SERIAL_TTY_MAJOR,
+	minor_start:		0,
+	num:			SERIAL_TTY_MINORS,
+	type:			TTY_DRIVER_TYPE_SERIAL,
+	subtype:		SERIAL_TYPE_NORMAL,
+	flags:			TTY_DRIVER_REAL_RAW,
+	refcount:		&serial_refcount,
+	table:			serial_tty,
+	proc_entry:		NULL,
+	other:			NULL,
+	termios:		serial_termios,
+	termios_locked:		serial_termios_locked,
+	
+	open:			serial_open,
+	close:			serial_close,
+	write:			serial_write,
+	put_char:		NULL,
+	flush_chars:		NULL,
+	write_room:		serial_write_room,
+	ioctl:			serial_ioctl,
+	set_termios:		serial_set_termios,
+	set_ldisc:		NULL, 
+	throttle:		serial_throttle,
+	unthrottle:		serial_unthrottle,
+	stop:			NULL,
+	start:			NULL,
+	hangup:			NULL,
+	break_ctl:		serial_break,
+	wait_until_sent:	NULL,
+	send_xchar:		NULL,
+	read_proc:		NULL,
+	chars_in_buffer:	serial_chars_in_buffer,
+	flush_buffer:		NULL
+};
+
+
+int usb_serial_init(void)
+{
+	int i;
+
+	/* Initalize our global data */
+	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
+		serial_table[i] = NULL;
+	}
+
+	/* register the tty driver */
+	serial_tty_driver.init_termios		= tty_std_termios;
+	serial_tty_driver.init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	if (tty_register_driver (&serial_tty_driver)) {
+		err("failed to register tty driver");
+		return -EPERM;
+	}
+	
+	/* register the USB driver */
+	if (usb_register(&usb_serial_driver) < 0) {
+		tty_unregister_driver(&serial_tty_driver);
+		return -1;
+	}
+
+	info("support registered");
+	return 0;
+}
+
+
+void usb_serial_exit(void)
+{
+	tty_unregister_driver(&serial_tty_driver);
+	usb_deregister(&usb_serial_driver);
+}
+
+
+module_init(usb_serial_init);
+module_exit(usb_serial_exit);
+
+
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h
--- v2.3.50/linux/drivers/usb/serial/usb-serial.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/usb-serial.h	Fri Mar 10 13:19:34 2000
@@ -0,0 +1,436 @@
+/*
+ * USB Serial Converter driver
+ *
+ *	(C) Copyright (C) 1999, 2000
+ *	    Greg Kroah-Hartman (greg@kroah.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.
+ *
+ * See Documentation/usb/usb-serial.txt for more information on using this driver
+ * 
+ */
+
+
+#ifndef __LINUX_USB_SERIAL_H
+#define __LINUX_USB_SERIAL_H
+
+#include <linux/config.h>
+
+/* Module information */
+MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
+MODULE_DESCRIPTION("USB Serial Driver");
+
+#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
+
+
+/* USB Serial devices vendor ids and device ids that this driver supports */
+#define CONNECT_TECH_VENDOR_ID		0x0710
+#define CONNECT_TECH_FAKE_WHITE_HEAT_ID	0x0001
+#define CONNECT_TECH_WHITE_HEAT_ID	0x8001
+#define HANDSPRING_VENDOR_ID		0x082d
+#define HANDSPRING_VISOR_ID		0x0100
+#define FTDI_VENDOR_ID			0x0403
+#define FTDI_SIO_SERIAL_CONVERTER_ID	0x8372
+#define KEYSPAN_VENDOR_ID		0x06cd
+#define KEYSPAN_PDA_FAKE_ID		0x0103
+#define KEYSPAN_PDA_ID			0x0104 /* no clue */
+
+#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 */
+
+
+#define MAX_NUM_PORTS	8	/* The maximum number of ports one device can grab at once */
+
+
+struct usb_serial_port {
+	struct usb_serial	*serial;	/* pointer back to the owner of this port */
+	struct tty_struct *	tty;		/* the coresponding tty for this device */
+	unsigned char		minor;
+	unsigned char		number;
+	char			active;		/* someone has this device open */
+
+	struct usb_endpoint_descriptor * interrupt_in_endpoint;
+	__u8			interrupt_in_interval;
+	unsigned char *		interrupt_in_buffer;
+	struct urb		control_urb;
+
+	unsigned char *		bulk_in_buffer;
+	struct urb		read_urb;
+
+	unsigned char *		bulk_out_buffer;
+	int			bulk_out_size;
+	struct urb		write_urb;
+	void *			private;	/* data private to the specific driver */
+};
+
+struct usb_serial {
+	struct usb_device *		dev;
+	struct usb_serial_device_type *	type;
+	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				num_interrupt_in;	/* number of interrupt in endpoints we have */
+	char				num_bulk_in;		/* number of bulk in endpoints we have */
+	char				num_bulk_out;		/* number of bulk out endpoints we have */
+	struct usb_serial_port		port[MAX_NUM_PORTS];
+
+	/* FIXME! These should move to the private area of the keyspan driver */
+	int			tx_room;
+	int			tx_throttled;
+	wait_queue_head_t 	write_wait;
+
+	void *			private;		/* data private to the specific driver */
+};
+
+
+#define MUST_HAVE_NOT	0x01
+#define MUST_HAVE	0x02
+#define DONT_CARE	0x03
+
+#define	HAS		0x02
+#define HAS_NOT		0x01
+
+#define NUM_DONT_CARE	(-1)
+
+
+/* This structure defines the individual serial converter. */
+struct usb_serial_device_type {
+	char	*name;
+	__u16	*idVendor;
+	__u16	*idProduct;
+	char	needs_interrupt_in;
+	char	needs_bulk_in;
+	char	needs_bulk_out;
+	char	num_interrupt_in;
+	char	num_bulk_in;
+	char	num_bulk_out;
+	char	num_ports;		/* number of serial ports this device has */
+
+	/* function call to make before accepting driver */
+	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);
+	int  (*write_room)(struct tty_struct *tty);
+	int  (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
+	void (*set_termios)(struct tty_struct *tty, struct termios * old);
+	void (*break_ctl)(struct tty_struct *tty, int break_state);
+	int  (*chars_in_buffer)(struct tty_struct *tty);
+	void (*throttle)(struct tty_struct * tty);
+	void (*unthrottle)(struct tty_struct * tty);
+	
+	void (*read_bulk_callback)(struct urb *urb);
+	void (*write_bulk_callback)(struct urb *urb);
+};
+
+
+/* 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. */
+/* if a driver does not provide a function pointer, the generic function will be called. */
+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 int  generic_write_room		(struct tty_struct *tty);
+static int  generic_ioctl		(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
+static void generic_set_termios		(struct tty_struct *tty, struct termios * old);
+static int  generic_chars_in_buffer	(struct tty_struct *tty);
+static void generic_throttle		(struct tty_struct *tty);
+static void generic_unthrottle		(struct tty_struct *tty);
+static void generic_read_bulk_callback	(struct urb *urb);
+static void generic_write_bulk_callback	(struct urb *urb);
+
+
+#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",
+	idVendor:		&vendor,		/* use the user specified vendor id */
+	idProduct:		&product,		/* use the user specified product id */
+	needs_interrupt_in:	DONT_CARE,		/* don't have to have an interrupt in endpoint */
+	needs_bulk_in:		DONT_CARE,		/* don't have to have a bulk in endpoint */
+	needs_bulk_out:		DONT_CARE,		/* don't have to have a bulk out endpoint */
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	num_ports:		1,
+};
+#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_set_termios	(struct tty_struct *tty, struct termios * old);
+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;
+static __u16	connecttech_whiteheat_fake_product_id	= CONNECT_TECH_FAKE_WHITE_HEAT_ID;
+static __u16	connecttech_whiteheat_product_id	= CONNECT_TECH_WHITE_HEAT_ID;
+static struct usb_serial_device_type whiteheat_fake_device = {
+	name:			"Connect Tech - WhiteHEAT - (prerenumeration)",
+	idVendor:		&connecttech_vendor_id,			/* the Connect Tech vendor id */
+	idProduct:		&connecttech_whiteheat_fake_product_id,	/* the White Heat initial product id */
+	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
+	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
+	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	startup:		whiteheat_startup	
+};
+static struct usb_serial_device_type whiteheat_device = {
+	name:			"Connect Tech - WhiteHEAT",
+	idVendor:		&connecttech_vendor_id,			/* the Connect Tech vendor id */
+	idProduct:		&connecttech_whiteheat_product_id,	/* the White Heat real product id */
+	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
+	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
+	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	num_ports:		4,
+	open:			whiteheat_serial_open,
+	close:			whiteheat_serial_close,
+	throttle:		whiteheat_throttle,
+	unthrottle:		whiteheat_unthrottle,
+	set_termios:		whiteheat_set_termios,
+};
+#endif
+
+
+#ifdef CONFIG_USB_SERIAL_VISOR
+
+/****************************************************************************
+ * Handspring Visor Vendor specific request codes (bRequest values)
+ * A big thank you to Handspring for providing the following information.
+ * If anyone wants the original file where these values and structures came
+ * from, send email to <greg@kroah.com>.
+ ****************************************************************************/
+
+/****************************************************************************
+ * VISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
+ * are available to be transfered to the host for the specified endpoint.
+ * Currently this is not used, and always returns 0x0001
+ ****************************************************************************/
+#define VISOR_REQUEST_BYTES_AVAILABLE		0x01
+
+/****************************************************************************
+ * VISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
+ * is now closing the pipe. An empty packet is sent in response.
+ ****************************************************************************/
+#define VISOR_CLOSE_NOTIFICATION		0x02
+
+/****************************************************************************
+ * VISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
+ * get the endpoints used by the connection.
+ ****************************************************************************/
+#define VISOR_GET_CONNECTION_INFORMATION	0x03
+
+
+/****************************************************************************
+ * VISOR_GET_CONNECTION_INFORMATION returns data in the following format
+ ****************************************************************************/
+struct visor_connection_info {
+	__u16	num_ports;
+	struct {
+		__u8	port_function_id;
+		__u8	port;
+	} connections[2];
+};
+
+
+/* struct visor_connection_info.connection[x].port defines: */
+#define VISOR_ENDPOINT_1		0x01
+#define VISOR_ENDPOINT_2		0x02
+
+/* struct visor_connection_info.connection[x].port_function_id defines: */
+#define VISOR_FUNCTION_GENERIC		0x00
+#define VISOR_FUNCTION_DEBUGGER		0x01
+#define VISOR_FUNCTION_HOTSYNC		0x02
+#define VISOR_FUNCTION_CONSOLE		0x03
+#define VISOR_FUNCTION_REMOTE_FILE_SYS	0x04
+
+
+/* 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;
+static __u16	handspring_product_id	= HANDSPRING_VISOR_ID;
+static struct usb_serial_device_type handspring_device = {
+	name:			"Handspring Visor",
+	idVendor:		&handspring_vendor_id,	/* the Handspring vendor ID */
+	idProduct:		&handspring_product_id,	/* the Handspring Visor product id */
+	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
+	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
+	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
+	num_interrupt_in:	0,
+	num_bulk_in:		2,
+	num_bulk_out:		2,
+	num_ports:		2,
+	open:			visor_serial_open,
+	close:			visor_serial_close,
+	throttle:		visor_throttle,
+	unthrottle:		visor_unthrottle,
+	startup:		visor_startup,
+};
+#endif
+
+
+#ifdef CONFIG_USB_SERIAL_FTDI_SIO
+/* function prototypes for a FTDI serial converter */
+static int  ftdi_sio_serial_open	(struct tty_struct *tty, struct file *filp);
+static void ftdi_sio_serial_close	(struct tty_struct *tty, struct file *filp);
+static int  ftdi_sio_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static void ftdi_sio_read_bulk_callback	(struct urb *urb);
+static void ftdi_sio_set_termios		(struct tty_struct *tty, struct termios * old);
+static int ftdi_sio_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
+
+/* All of the device info needed for the FTDI SIO serial converter */
+static __u16	ftdi_vendor_id		= FTDI_VENDOR_ID;
+static __u16	ftdi_sio_product_id	= FTDI_SIO_SERIAL_CONVERTER_ID;
+static struct usb_serial_device_type ftdi_sio_device = {
+	name:			"FTDI SIO",
+	idVendor:		&ftdi_vendor_id,	/* the FTDI vendor ID */
+	idProduct:		&ftdi_sio_product_id,	/* the FTDI SIO product id */
+	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
+	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
+	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
+	num_interrupt_in:	0,
+	num_bulk_in:		1,
+	num_bulk_out:		1,
+	num_ports:		1,
+	open:			ftdi_sio_serial_open,
+	close:			ftdi_sio_serial_close,
+	write:			ftdi_sio_serial_write,
+	read_bulk_callback:	ftdi_sio_read_bulk_callback,
+	set_termios:		ftdi_sio_set_termios
+};
+#endif
+
+
+#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
+/* function prototypes for a Keyspan PDA serial converter */
+static int  keyspan_pda_serial_open	(struct tty_struct *tty, 
+					 struct file *filp);
+static void keyspan_pda_serial_close	(struct tty_struct *tty, 
+					 struct file *filp);
+static int  keyspan_pda_startup		(struct usb_serial *serial);
+static void keyspan_pda_rx_throttle	(struct tty_struct *tty);
+static void keyspan_pda_rx_unthrottle	(struct tty_struct *tty);
+static int  keyspan_pda_setbaud		(struct usb_serial *serial, int baud);
+static int  keyspan_pda_write_room	(struct tty_struct *tty);
+static int  keyspan_pda_write		(struct tty_struct *tty,
+					 int from_user,
+					 const unsigned char *buf,
+					 int count);
+static void keyspan_pda_write_bulk_callback (struct urb *urb);
+static int  keyspan_pda_chars_in_buffer (struct tty_struct *tty);
+static int  keyspan_pda_ioctl		(struct tty_struct *tty,
+					 struct file *file,
+					 unsigned int cmd,
+					 unsigned long arg);
+static void keyspan_pda_set_termios	(struct tty_struct *tty,
+					 struct termios *old);
+static void keyspan_pda_break_ctl	(struct tty_struct *tty,
+					 int break_state);
+static int  keyspan_pda_fake_startup	(struct usb_serial *serial);
+
+/* All of the device info needed for the Keyspan PDA serial converter */
+static __u16	keyspan_vendor_id		= KEYSPAN_VENDOR_ID;
+static __u16	keyspan_pda_fake_product_id	= KEYSPAN_PDA_FAKE_ID;
+static __u16	keyspan_pda_product_id		= KEYSPAN_PDA_ID;
+static struct usb_serial_device_type keyspan_pda_fake_device = {
+	name:			"Keyspan PDA - (prerenumeration)",
+	idVendor:		&keyspan_vendor_id,		/* the Keyspan PDA vendor ID */
+	idProduct:		&keyspan_pda_fake_product_id,	/* the Keyspan PDA initial product id */
+	needs_interrupt_in:	DONT_CARE,			/* don't have to have an interrupt in endpoint */
+	needs_bulk_in:		DONT_CARE,			/* don't have to have a bulk in endpoint */
+	needs_bulk_out:		DONT_CARE,			/* don't have to have a bulk out endpoint */
+	num_interrupt_in:	NUM_DONT_CARE,
+	num_bulk_in:		NUM_DONT_CARE,
+	num_bulk_out:		NUM_DONT_CARE,
+	startup:		keyspan_pda_fake_startup
+};
+static struct usb_serial_device_type keyspan_pda_device = {
+	name:			"Keyspan PDA",
+	idVendor:		&keyspan_vendor_id,		/* the Keyspan PDA vendor ID */
+	idProduct:		&keyspan_pda_product_id,	/* the Keyspan PDA product id */
+	needs_interrupt_in:	MUST_HAVE,
+	needs_bulk_in:		DONT_CARE,
+	needs_bulk_out:		MUST_HAVE,
+	num_interrupt_in:	1,
+	num_bulk_in:		0,
+	num_bulk_out:		1,
+	num_ports:		1,
+	open:			keyspan_pda_serial_open,
+	close:			keyspan_pda_serial_close,
+	write:			keyspan_pda_write,
+	write_room:		keyspan_pda_write_room,
+	write_bulk_callback: 	keyspan_pda_write_bulk_callback,
+	chars_in_buffer:	keyspan_pda_chars_in_buffer,
+	throttle:		keyspan_pda_rx_throttle,
+	unthrottle:		keyspan_pda_rx_unthrottle,
+	startup:		keyspan_pda_startup,
+	ioctl:			keyspan_pda_ioctl,
+	set_termios:		keyspan_pda_set_termios,
+	break_ctl:		keyspan_pda_break_ctl,
+};
+#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_VISOR
+	&handspring_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_FTDI_SIO
+	&ftdi_sio_device,
+#endif
+#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
+	&keyspan_pda_fake_device,
+	&keyspan_pda_device,
+#endif
+	NULL
+};
+
+
+/* determine if we should include the EzUSB loader functions */
+#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_WHITEHEAT)
+	#define	USES_EZUSB_FUNCTIONS
+#else
+	#undef 	USES_EZUSB_FUNCTIONS
+#endif
+
+#endif	/* ifdef __LINUX_USB_SERIAL_H */
+
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/serial/whiteheat.h linux/drivers/usb/serial/whiteheat.h
--- v2.3.50/linux/drivers/usb/serial/whiteheat.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/usb/serial/whiteheat.h	Fri Mar 10 13:19:34 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.50/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.50/linux/drivers/usb/uhci.c	Thu Feb 10 17:11:15 2000
+++ linux/drivers/usb/uhci.c	Fri Mar 10 16:18:34 2000
@@ -21,7 +21,6 @@
  *  - working around the horridness of the rest
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
@@ -34,15 +33,14 @@
 #include <linux/unistd.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#define DEBUG
+#include <linux/usb.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 
-#define DEBUG
-#include "usb.h"
-
 #include "uhci.h"
 #include "uhci-debug.h"
 
@@ -54,18 +52,21 @@
 
 static kmem_cache_t *uhci_td_cachep;
 static kmem_cache_t *uhci_qh_cachep;
+static kmem_cache_t *uhci_up_cachep;	/* urb_priv */
 
 static LIST_HEAD(uhci_list);
 
 static int rh_submit_urb(urb_t *urb);
 static int rh_unlink_urb(urb_t *urb);
 static int uhci_get_current_frame_number(struct usb_device *dev);
-static void uhci_stop_hc_schedule(struct uhci *uhci);
-static void uhci_start_hc_schedule(struct uhci *uhci);
+static int uhci_unlink_generic(urb_t *urb);
 static int uhci_unlink_urb(urb_t *urb);
 
 #define min(a,b) (((a)<(b))?(a):(b))
 
+/* If a transfer is still active after this much time, turn off FSBR */
+#define IDLE_TIMEOUT	(HZ / 20)	/* 50 ms */
+
 /*
  * Only the USB core should call uhci_alloc_dev and uhci_free_dev
  */
@@ -78,7 +79,7 @@
 {
 	urb_t *u;
 	struct uhci *uhci = (struct uhci *)dev->bus->hcpriv;
-	struct list_head *tmp, *head = &uhci->urb_list;
+	struct list_head *tmp, *next, *head = &uhci->urb_list;
 	unsigned long flags;
 
 	/* Walk through the entire URB list and forcefully remove any */
@@ -88,38 +89,18 @@
 	while (tmp != head) {
 		u = list_entry(tmp, urb_t, urb_list);
 
+		next = tmp->next;
+
 		if (u->dev == dev)
 			uhci_unlink_urb(u);
+
+		tmp = next;
 	}
 	nested_unlock(&uhci->urblist_lock, flags);
 
 	return 0;
 }
 
-/*
- * UHCI interrupt list operations..
- */
-static void uhci_add_irq_list(struct uhci *uhci, struct uhci_td *td)
-{
-	unsigned long flags;
-
-	nested_lock(&uhci->irqlist_lock, flags);
-	list_add(&td->irq_list, &uhci->interrupt_list);
-	nested_unlock(&uhci->irqlist_lock, flags);
-}
-
-static void uhci_remove_irq_list(struct uhci *uhci, struct uhci_td *td)
-{
-	unsigned long flags;
-
-	nested_lock(&uhci->irqlist_lock, flags);
-	if (td->irq_list.next != &td->irq_list) {
-		list_del(&td->irq_list);
-		INIT_LIST_HEAD(&td->irq_list);
-	}
-	nested_unlock(&uhci->irqlist_lock, flags);
-}
-
 static void uhci_add_urb_list(struct uhci *uhci, struct urb *urb)
 {
 	unsigned long flags;
@@ -141,6 +122,54 @@
 	nested_unlock(&uhci->urblist_lock, flags);
 }
 
+static struct uhci_td *uhci_alloc_td(struct usb_device *dev)
+{
+	struct uhci_td *td;
+
+	td = kmem_cache_alloc(uhci_td_cachep, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
+	if (!td)
+		return NULL;
+
+	td->link = UHCI_PTR_TERM;
+	td->buffer = 0;
+
+	td->frameptr = NULL;
+	td->nexttd = td->prevtd = NULL;
+	td->list.next = td->list.prev = NULL;
+	td->dev = dev;
+
+	usb_inc_dev_use(dev);
+
+	return td;
+}
+
+static void inline uhci_fill_td(struct uhci_td *td, __u32 status,
+		__u32 info, __u32 buffer)
+{
+	td->status = status;
+	td->info = info;
+	td->buffer = buffer;
+}
+
+static void uhci_insert_td(struct uhci *uhci, struct uhci_td *skeltd, struct uhci_td *td)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&uhci->framelist_lock, flags);
+
+	/* Fix the linked list pointers */
+	td->nexttd = skeltd->nexttd;
+	td->prevtd = skeltd;
+	if (skeltd->nexttd)
+		skeltd->nexttd->prevtd = td;
+	skeltd->nexttd = td;
+
+	td->link = skeltd->link;
+	skeltd->link = virt_to_bus(td);
+
+	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+}
+
 /*
  * We insert Isochronous transfers directly into the frame list at the
  * beginning
@@ -157,6 +186,7 @@
 	framenum %= UHCI_NUMFRAMES;
 
 	spin_lock_irqsave(&uhci->framelist_lock, flags);
+
 	td->frameptr = &uhci->fl->frame[framenum];
 	td->link = uhci->fl->frame[framenum];
 	if (!(td->link & (UHCI_PTR_TERM | UHCI_PTR_QH))) {
@@ -166,6 +196,7 @@
 		nexttd->frameptr = NULL;
 	}
 	uhci->fl->frame[framenum] = virt_to_bus(td);
+
 	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
 }
 
@@ -173,6 +204,10 @@
 {
 	unsigned long flags;
 
+	/* If it's not inserted, don't remove it */
+	if (!td->frameptr && !td->prevtd && !td->nexttd)
+		return;
+
 	spin_lock_irqsave(&uhci->framelist_lock, flags);
 	if (td->frameptr) {
 		*(td->frameptr) = td->link;
@@ -195,77 +230,41 @@
 	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
 }
 
-static void uhci_insert_td(struct uhci *uhci, struct uhci_td *skeltd, struct uhci_td *td)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&uhci->framelist_lock, flags);
-
-	/* Fix the linked list pointers */
-	td->nexttd = skeltd->nexttd;
-	td->prevtd = skeltd;
-	if (skeltd->nexttd)
-		skeltd->nexttd->prevtd = td;
-	skeltd->nexttd = td;
-
-	td->link = skeltd->link;
-	skeltd->link = virt_to_bus(td);
-
-	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
-}
-
 /*
  * Inserts a td into qh list at the top.
  */
-static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct uhci_td *begin)
+static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, int breadth)
 {
-	struct uhci_td *td, *prevtd;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci_td *td, *prevtd = NULL;
+
+	if (!urbp)
+		return;
 
-	if (!begin)		/* Nothing to do */
+	td = urbp->list.begin;
+	if (!td)
 		return;
 
-	/* Grab the first TD and add it to the QH */
-	td = begin;
-	qh->element = virt_to_bus(td) | UHCI_PTR_DEPTH;
+	/* Add the first TD to the QH element pointer */
+	qh->element = virt_to_bus(td) | (breadth ? 0 : UHCI_PTR_DEPTH);
 
-	/* Go through the rest of the TD's, link them together */
 	prevtd = td;
-	td = td->next;
-	while (td) {
-		prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH;
+
+	/* Then link the rest of the TD's */
+	for (td = td->list.next; td; td = td->list.next) {
+		prevtd->link = virt_to_bus(td) | (breadth ? 0 : UHCI_PTR_DEPTH);
 
 		prevtd = td;
-		td = td->next;
 	}
 
 	prevtd->link = UHCI_PTR_TERM;
 }
 
-static struct uhci_td *uhci_alloc_td(struct usb_device *dev)
-{
-	struct uhci_td *td;
-
-	td = kmem_cache_alloc(uhci_td_cachep, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
-	if (!td)
-		return NULL;
-
-	td->link = UHCI_PTR_TERM;
-	td->buffer = 0;
-
-	td->frameptr = NULL;
-	td->nexttd = td->prevtd = NULL;
-	td->next = NULL;
-	td->dev = dev;
-	INIT_LIST_HEAD(&td->irq_list);
-	INIT_LIST_HEAD(&td->list);
-
-	usb_inc_dev_use(dev);
-
-	return td;
-}
-
 static void uhci_free_td(struct uhci_td *td)
 {
+	if (td->list.next || td->list.prev)
+		dbg("td is still in URB list!");
+
 	kmem_cache_free(uhci_td_cachep, td);
 
 	if (td->dev)
@@ -286,7 +285,7 @@
 	qh->dev = dev;
 	qh->prevqh = qh->nextqh = NULL;
 
-	INIT_LIST_HEAD(&qh->list);
+	INIT_LIST_HEAD(&qh->remove_list);
 
 	usb_inc_dev_use(dev);
 
@@ -333,14 +332,31 @@
 		qh->nextqh->prevqh = qh->prevqh;
 	qh->prevqh = qh->nextqh = NULL;
 	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+
+	spin_lock_irqsave(&uhci->qh_remove_lock, flags);
+	list_add(&qh->remove_list, &uhci->qh_remove_list);
+	spin_unlock_irqrestore(&uhci->qh_remove_lock, flags);
 }
 
-static void inline uhci_fill_td(struct uhci_td *td, __u32 status,
-		__u32 info, __u32 buffer)
+struct urb_priv *uhci_alloc_urb_priv(struct urb *urb)
 {
-	td->status = status;
-	td->info = info;
-	td->buffer = buffer;
+	struct urb_priv *urbp;
+
+	urbp = kmem_cache_alloc(uhci_up_cachep, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
+	if (!urbp)
+		return NULL;
+
+	memset((void *)urbp, 0, sizeof(*urbp));
+
+	urbp->list.begin = urbp->list.end = NULL;
+
+	urb->hcpriv = urbp;
+
+	urbp->inserttime = jiffies;
+
+	usb_inc_dev_use(urb->dev);
+
+	return urbp;
 }
 
 static void uhci_add_td_to_urb(urb_t *urb, struct uhci_td *td)
@@ -349,35 +365,110 @@
 
 	td->urb = urb;
 
-	if (urbp->end)
-		urbp->end->next = td;
+	if (!urbp->list.begin)
+		urbp->list.begin = td;
+
+	if (urbp->list.end) {
+		urbp->list.end->list.next = td;
+		td->list.prev = urbp->list.end;
+	}
+	urbp->list.end = td;
+}
+
+static void uhci_remove_td_from_urb(urb_t *urb, struct uhci_td *td)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	if (!urbp->list.begin && !urbp->list.end)
+		return;
+
+	if (td->list.prev)
+		td->list.prev->list.next = td->list.next;
+	else
+		urbp->list.begin = td->list.next;
+
+	if (td->list.next)
+		td->list.next->list.prev = td->list.prev;
+	else
+		urbp->list.end = td->list.prev;
+
+	td->list.next = td->list.prev = NULL;
+	td->urb = NULL;
+}
+
+static void uhci_destroy_urb_priv(urb_t *urb)
+{
+	struct urb_priv *urbp;
+	struct uhci *uhci;
+	struct uhci_td *td, *nexttd;
+	unsigned long flags;
+
+	spin_lock_irqsave(&urb->lock, flags);
+
+	urbp = (struct urb_priv *)urb->hcpriv;
+	if (!urbp)
+		return;
+
+	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv)
+		return;
 
-	urbp->end = td;
+	uhci = urb->dev->bus->hcpriv;
+
+	td = urbp->list.begin;
+	while (td) {
+		nexttd = td->list.next;
+
+		uhci_remove_td_from_urb(urb, td);
+
+		uhci_remove_td(uhci, td);
+
+		uhci_free_td(td);
+		
+		td = nexttd;
+	}
+
+	urb->hcpriv = NULL;
+	kmem_cache_free(uhci_up_cachep, urbp);
 
-	if (!urbp->begin)
-		urbp->begin = td;
+	spin_unlock_irqrestore(&urb->lock, flags);
+
+	usb_dec_dev_use(urb->dev);
 }
 
-void uhci_inc_fsbr(struct uhci *uhci)
+static void uhci_inc_fsbr(struct uhci *uhci, struct urb *urb)
 {
 	unsigned long flags;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	if (!urbp)
+		return;
 
 	spin_lock_irqsave(&uhci->framelist_lock, flags);
 
-	if (!uhci->fsbr++)
-		uhci->skel_term_qh.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH;
+	if (!urbp->fsbr) {
+		urbp->fsbr = 1;
+		if (!uhci->fsbr++)
+			uhci->skel_term_td.link = virt_to_bus(&uhci->skel_hs_control_qh) | UHCI_PTR_QH;
+	}
 
 	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
 }
 
-void uhci_dec_fsbr(struct uhci *uhci)
+static void uhci_dec_fsbr(struct uhci *uhci, struct urb *urb)
 {
 	unsigned long flags;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	if (!urbp)
+		return;
 
 	spin_lock_irqsave(&uhci->framelist_lock, flags);
 
-	if (!--uhci->fsbr)
-		uhci->skel_term_qh.link = UHCI_PTR_TERM;
+	if (urbp->fsbr) {
+		urbp->fsbr = 0;
+		if (!--uhci->fsbr)
+			uhci->skel_term_td.link = UHCI_PTR_TERM;
+	}
 
 	spin_unlock_irqrestore(&uhci->framelist_lock, flags);
 }
@@ -419,14 +510,14 @@
  */
 static int uhci_submit_control(urb_t *urb)
 {
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	struct uhci_td *td;
 	struct uhci_qh *qh;
 	unsigned long destination, status;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 	int len = urb->transfer_buffer_length;
 	unsigned char *data = urb->transfer_buffer;
-	struct urb_priv *urbp;
 
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
@@ -434,14 +525,6 @@
 	/* 3 errors */
 	status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
 
-	urbp = kmalloc(sizeof(*urbp), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-	if (!urbp)
-		return -ENOMEM;
-
-	urbp->begin = urbp->end = NULL;
-
-	urb->hcpriv = urbp;
-
 	/*
 	 * Build the TD for the control request
 	 */
@@ -465,18 +548,16 @@
 	/*
 	 * Build the DATA TD's
 	 */
-	td = uhci_alloc_td(urb->dev);
-	if (!td) {
-		/* FIXME: Free the TD's */
-		return -ENOMEM;
-	}
-
 	while (len > 0) {
 		int pktsze = len;
 
 		if (pktsze > maxsze)
 			pktsze = maxsze;
 
+		td = uhci_alloc_td(urb->dev);
+		if (!td)
+			return -ENOMEM;
+
 		/* Alternate Data0/1 (start with Data1) */
 		destination ^= 1 << TD_TOKEN_TOGGLE;
 	
@@ -486,16 +567,16 @@
 
 		data += pktsze;
 		len -= pktsze;
-
-		td = uhci_alloc_td(urb->dev);
-		if (!td)
-			/* FIXME: Free all of the previously allocated td's */
-			return -ENOMEM;
 	}
 
 	/*
 	 * Build the final TD for control status 
-	 *
+	 */
+	td = uhci_alloc_td(urb->dev);
+	if (!td)
+		return -ENOMEM;
+
+	/*
 	 * It's IN if the pipe is an output pipe or we're not expecting
 	 * data back.
 	 */
@@ -513,20 +594,19 @@
 	uhci_fill_td(td, status | TD_CTRL_IOC,
 		destination | (UHCI_NULL_DATA_SIZE << 21), 0);
 
-	uhci_add_irq_list(uhci, td);
-
 	qh = uhci_alloc_qh(urb->dev);
-	if (!qh) {
-		/* FIXME: Free all of the TD's */
+	if (!qh)
 		return -ENOMEM;
-	}
-	uhci_insert_tds_in_qh(qh, urbp->begin);
 
-	if (!(urb->pipe & TD_CTRL_LS)) {
-		uhci_insert_qh(uhci, &uhci->skel_hs_control_qh, qh);
-		uhci_inc_fsbr(uhci);
-	} else
+	/* Low speed or small transfers gets a different queue and treatment */
+	if (urb->pipe & TD_CTRL_LS) {
+		uhci_insert_tds_in_qh(qh, urb, 0);
 		uhci_insert_qh(uhci, &uhci->skel_ls_control_qh, qh);
+	} else {
+		uhci_insert_tds_in_qh(qh, urb, 1);
+		uhci_insert_qh(uhci, &uhci->skel_hs_control_qh, qh);
+		uhci_inc_fsbr(uhci, urb);
+	}
 
 	urbp->qh = qh;
 
@@ -537,66 +617,22 @@
 	return -EINPROGRESS;
 }
 
-/* This is also the uhci_unlink_bulk function */
-static int uhci_unlink_control(urb_t *urb)
+static int uhci_result_control(urb_t *urb)
 {
 	struct urb_priv *urbp = urb->hcpriv;
 	struct uhci_td *td;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	int notfinished;
+	unsigned int status;
 
 	if (!urbp)
 		return -EINVAL;
 
-	notfinished = (urb->status == -EINPROGRESS);
-
-	if (notfinished)
-		uhci_stop_hc_schedule(uhci);
-
-	if (!(urb->pipe & TD_CTRL_LS))
-		uhci_dec_fsbr(uhci);
-
-	uhci_remove_qh(uhci, urbp->qh);
-	uhci_free_qh(urbp->qh);
-
-	/* Go through the rest of the TD's, deleting them, then scheduling */
-	/*  their deletion */
-	td = urbp->begin;
-	while (td) {
-		struct uhci_td *next = td->next;
-
-		if (td->status & TD_CTRL_IOC)
-			uhci_remove_irq_list(uhci, td);
-
-		uhci_free_td(td);
-
-		td = next;
-	}
-
-	if (notfinished)
-		uhci_start_hc_schedule(uhci);
-
-	kfree(urbp);
-	urb->hcpriv = NULL;
-
-	uhci_remove_urb_list(uhci, urb);
-
-	return 0;
-}
-
-static int uhci_result_control(urb_t *urb)
-{
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	unsigned int status;
-
-	td = urbp->begin;
-	if (!td)		/* Nothing to do */
+	td = urbp->list.begin;
+	if (!td)
 		return -EINVAL;
 
 	/* The first TD is the SETUP phase, check the status, but skip */
 	/*  the count */
-	status =  uhci_status_bits(td->status);
+	status = uhci_status_bits(td->status);
 	if (status & TD_CTRL_ACTIVE)
 		return -EINPROGRESS;
 
@@ -605,9 +641,10 @@
 
 	urb->actual_length = 0;
 
+	td = td->list.next;
+
 	/* The rest of the TD's (but the last) are data */
-	td = td->next;
-	while (td && td->next) {
+	while (td && td->list.next) {
 		status = uhci_status_bits(td->status);
 		if (status & TD_CTRL_ACTIVE)
 			return -EINPROGRESS;
@@ -617,13 +654,14 @@
 		/* If SPD is set then we received a short packet */
 		/*  There will be no status phase at the end */
 		/* FIXME: Re-setup the queue to run the STATUS phase? */
-		if (td->status & TD_CTRL_SPD && (uhci_actual_length(td->status) < uhci_expected_length(td->info)))
+		if ((td->status & TD_CTRL_SPD) &&
+		    (uhci_actual_length(td->status) < uhci_expected_length(td->info)))
 			return 0;
 
 		if (status)
 			goto td_error;
 
-		td = td->next;
+		td = td->list.next;
 	}
 
 	/* Control status phase */
@@ -648,18 +686,16 @@
 td_error:
 	/* Some debugging code */
 	if (debug) {
-		dbg("uhci_result_control() failed with status %x",
-			status);
+		dbg("uhci_result_control() failed with status %x", status);
 
 		/* Print the chain for debugging purposes */
 		uhci_show_queue(urbp->qh);
 	}
 
-	if (status & TD_CTRL_STALLED) {
+	if (status & TD_CTRL_STALLED)
 		/* endpoint has stalled - mark it halted */
 		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
 	    			uhci_packetout(td->info));
-	}
 
 	return uhci_map_status(status, uhci_packetout(td->info));
 }
@@ -672,7 +708,6 @@
 	struct uhci_td *td;
 	unsigned long destination, status;
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp;
 
 	if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
 		return -EINVAL;
@@ -680,16 +715,7 @@
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
 
-	status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD |
-			TD_CTRL_IOC;
-
-	urbp = kmalloc(sizeof(*urbp), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-	if (!urbp)
-		return -ENOMEM;
-
-	urbp->begin = urbp->end = NULL;
-
-	urb->hcpriv = urbp;
+	status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
 
 	td = uhci_alloc_td(urb->dev);
 	if (!td)
@@ -698,72 +724,70 @@
 	destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
 	destination |= ((urb->transfer_buffer_length - 1) << 21);
 
+	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+
 	uhci_add_td_to_urb(urb, td);
 	uhci_fill_td(td, status, destination,
 		virt_to_bus(urb->transfer_buffer));
 
-	uhci_add_irq_list(uhci, td);
-
 	uhci_insert_td(uhci, &uhci->skeltd[__interval_to_skel(urb->interval)], td);
 
 	uhci_add_urb_list(uhci, urb);
 
-	usb_inc_dev_use(urb->dev);
-
 	return -EINPROGRESS;
 }
 
-static int uhci_unlink_interrupt(urb_t *urb)
+static int uhci_result_interrupt(urb_t *urb)
 {
 	struct urb_priv *urbp = urb->hcpriv;
 	struct uhci_td *td;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	int notfinished;
+	unsigned int status;
 
 	if (!urbp)
 		return -EINVAL;
 
-	notfinished = (urb->status == -EINPROGRESS);
+	urb->actual_length = 0;
 
-	if (notfinished)
-		uhci_stop_hc_schedule(uhci);
+	for (td = urbp->list.begin; td; td = td->list.next) {
+		status = uhci_status_bits(td->status);
+		if (status & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
 
-	td = urbp->begin;
-	uhci_remove_td(uhci, td);
-	if (td->status & TD_CTRL_IOC)
-		uhci_remove_irq_list(uhci, td);
-	uhci_free_td(td);
+		urb->actual_length += uhci_actual_length(td->status);
 
-	if (notfinished)
-		uhci_start_hc_schedule(uhci);
+		/* If SPD is set then we received a short packet */
+		if ((td->status & TD_CTRL_SPD) &&
+		    (uhci_actual_length(td->status) < uhci_expected_length(td->info))) {
+			usb_settoggle(urb->dev, uhci_endpoint(td->info),
+				uhci_packetout(td->info),
+				uhci_toggle(td->info) ^ 1);
 
-	kfree(urbp);
-	urb->hcpriv = NULL;
+			return 0;
+		}
 
-	uhci_remove_urb_list(uhci, urb);
+		if (status)
+			goto td_error;
+	}
 
 	return 0;
-}
-
-static int uhci_result_interrupt(urb_t *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td;
-	int status;
 
-	if (!urbp)
-		return -EINVAL;
-
-	td = urbp->begin;
-	if (!td)
-		return -EINVAL;
+td_error:
+	/* Some debugging code */
+	if (debug) {
+		dbg("uhci_result_interrupt/bulk() failed with status %x",
+			status);
 
-	status =  uhci_status_bits(td->status);
-	if (status & TD_CTRL_ACTIVE)
-		return -EINPROGRESS;
+		/* Print the chain for debugging purposes */
+		if (urbp->qh)
+			uhci_show_queue(urbp->qh);
+		else
+			uhci_show_td(td);
+	}
 
-	if (!status)
-		urb->actual_length = uhci_actual_length(td->status);
+	if (status & TD_CTRL_STALLED)
+		/* endpoint has stalled - mark it halted */
+		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
+	    			uhci_packetout(td->info));
 
 	return uhci_map_status(status, uhci_packetout(td->info));
 }
@@ -773,12 +797,17 @@
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 	struct uhci_td *td;
 
-	td = urbp->begin;
+	if (!urbp)
+		return;
+
+	td = urbp->list.begin;
+	if (!td)
+		return;
 
-	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
 	td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
 	td->info &= ~(1 << TD_TOKEN_TOGGLE);
 	td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
+	usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
 
 	urb->status = -EINPROGRESS;
 }
@@ -795,27 +824,23 @@
 	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
 	int len = urb->transfer_buffer_length;
 	unsigned char *data = urb->transfer_buffer;
-	struct urb_priv *urbp;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 
 	if (len < 0)
 		return -EINVAL;
 
+	/* Can't have low speed bulk transfers */
+	if (urb->pipe & TD_CTRL_LS)
+		return -EINVAL;
+
 	/* The "pipe" thing contains the destination in bits 8--18 */
 	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
 
 	/* 3 errors */
-	status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
+	status = TD_CTRL_ACTIVE | (3 << 27);
 	if (!(urb->transfer_flags & USB_DISABLE_SPD))
 		status |= TD_CTRL_SPD;
 
-	urbp = kmalloc(sizeof(*urbp), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-	if (!urbp)
-		return -ENOMEM;
-
-	urbp->begin = urbp->end = NULL;
-
-	urb->hcpriv = urbp;
-
 	/*
 	 * Build the DATA TD's
 	 */
@@ -826,10 +851,8 @@
 			pktsze = maxsze;
 
 		td = uhci_alloc_td(urb->dev);
-		if (!td) {
-			/* FIXME: Free the TD's */
+		if (!td)
 			return -ENOMEM;
-		}
 
 		uhci_add_td_to_urb(urb, td);
 		uhci_fill_td(td, status, destination | ((pktsze - 1) << 21) |
@@ -840,86 +863,31 @@
 		data += pktsze;
 		len -= maxsze;
 
-		if (len <= 0) {
+		if (len <= 0)
 			td->status |= TD_CTRL_IOC;
-			uhci_add_irq_list(uhci, td);
-		}
 
 		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
 			usb_pipeout(urb->pipe));
 	}
 
 	qh = uhci_alloc_qh(urb->dev);
-	if (!qh) {
-		/* FIXME: Free all of the TD's */
+	if (!qh)
 		return -ENOMEM;
-	}
-	uhci_insert_tds_in_qh(qh, urbp->begin);
+
+	uhci_insert_tds_in_qh(qh, urb, 1);
 
 	uhci_insert_qh(uhci, &uhci->skel_bulk_qh, qh);
 	urbp->qh = qh;
 
 	uhci_add_urb_list(uhci, urb);
 
-	usb_inc_dev_use(urb->dev);
-
-	uhci_inc_fsbr(uhci);
+	uhci_inc_fsbr(uhci, urb);
 
 	return -EINPROGRESS;
 }
 
-/* We can use the control unlink since they're identical */
-#define uhci_unlink_bulk uhci_unlink_control
-
-static int uhci_result_bulk(urb_t *urb)
-{
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	unsigned int status;
-
-	urb->actual_length = 0;
-
-	/* The rest of the TD's (but the last) are data */
-	for (td = urbp->begin; td; td = td->next) {
-		status = uhci_status_bits(td->status);
-		if (status & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		urb->actual_length += uhci_actual_length(td->status);
-
-		/* If SPD is set then we received a short packet */
-		if (td->status & TD_CTRL_SPD && (uhci_actual_length(td->status) < uhci_expected_length(td->info))) {
-			usb_settoggle(urb->dev, uhci_endpoint(td->info),
-				uhci_packetout(td->info),
-				uhci_toggle(td->info) ^ 1);
-
-			return 0;
-		}
-
-		if (status)
-			goto td_error;
-	}
-
-	return 0;
-
-td_error:
-	/* Some debugging code */
-	if (debug) {
-		dbg("uhci_result_bulk() failed with status %x",
-			status);
-
-		/* Print the chain for debugging purposes */
-		uhci_show_queue(urbp->qh);
-	}
-
-	if (status & TD_CTRL_STALLED) {
-		/* endpoint has stalled - mark it halted */
-		usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
-	    			uhci_packetout(td->info));
-	}
-
-	return uhci_map_status(status, uhci_packetout(td->info));
-}
+/* We can use the result interrupt since they're identical */
+#define uhci_result_bulk uhci_result_interrupt
 
 /*
  * Isochronous transfers
@@ -929,6 +897,7 @@
 	urb_t *u, *last_urb = NULL;
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
 	struct list_head *tmp, *head = &uhci->urb_list;
+	int ret = 0;
 	unsigned long flags;
 
 	nested_lock(&uhci->urblist_lock, flags);
@@ -945,14 +914,16 @@
 		}
 		tmp = tmp->next;
 	}
-	nested_unlock(&uhci->urblist_lock, flags);
 
 	if (last_urb) {
 		*end = (last_urb->start_frame + last_urb->number_of_packets) & 1023;
-		return 0;
+		ret = 0;
 	} else
-		return -1;	// no previous urb found
+		ret = -1;	/* no previous urb found */
+
+	nested_unlock(&uhci->urblist_lock, flags);
 
+	return ret;
 }
 
 static int isochronous_find_start(urb_t *urb)
@@ -985,7 +956,6 @@
 {
 	struct uhci_td *td;
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	struct urb_priv *urbp;
 	int i, ret, framenum;
 	int status, destination;
 
@@ -996,85 +966,30 @@
 	if (ret)
 		return ret;
 
-	urbp = kmalloc(sizeof(*urbp), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-	if (!urbp)
-		return -ENOMEM;
-
-	urbp->begin = urbp->end = NULL;
-
-	urb->hcpriv = urbp;
-
 	framenum = urb->start_frame;
 	for (i = 0; i < urb->number_of_packets; i++, framenum++) {
 		if (!urb->iso_frame_desc[i].length)
 			continue;
 
 		td = uhci_alloc_td(urb->dev);
-		if (!td) {
-			/* FIXME: Free the TD's */
+		if (!td)
 			return -ENOMEM;
-		}
 
 		uhci_add_td_to_urb(urb, td);
 		uhci_fill_td(td, status, destination | ((urb->iso_frame_desc[i].length - 1) << 21),
 			virt_to_bus(urb->transfer_buffer + urb->iso_frame_desc[i].offset));
 
-		if (i + 1 >= urb->number_of_packets) {
+		if (i + 1 >= urb->number_of_packets)
 			td->status |= TD_CTRL_IOC;
-			uhci_add_irq_list(uhci, td);
-		}
 
 		uhci_insert_td_frame_list(uhci, td, framenum);
 	}
 
 	uhci_add_urb_list(uhci, urb);
 
-	usb_inc_dev_use(urb->dev);
-
 	return -EINPROGRESS;
 }
 
-static int uhci_unlink_isochronous(urb_t *urb)
-{
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
-	int notfinished;
-
-	if (!urbp)
-		return -EINVAL;
-
-	notfinished = (urb->status == -EINPROGRESS);
-
-	if (notfinished)
-		uhci_stop_hc_schedule(uhci);
-
-	/* Go through the rest of the TD's, deleting them, then scheduling */
-	/*  their deletion */
-	td = urbp->begin;
-	while (td) {
-		struct uhci_td *next = td->next;
-
-		uhci_remove_td(uhci, td);
-
-		if (td->status & TD_CTRL_IOC)
-			uhci_remove_irq_list(uhci, td);
-		uhci_free_td(td);
-
-		td = next;
-	}
-
-	if (notfinished)
-		uhci_start_hc_schedule(uhci);
-
-	kfree(urbp);
-	urb->hcpriv = NULL;
-
-	uhci_remove_urb_list(uhci, urb);
-
-	return 0;
-}
-
 static int uhci_result_isochronous(urb_t *urb)
 {
 	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
@@ -1082,19 +997,17 @@
 	int status;
 	int i, ret = 0;
 
-	td = urbp->end;
-	if (!td)		/* Nothing to do */
+	if (!urbp)
 		return -EINVAL;
 
-	status = uhci_status_bits(td->status);
-	if (status & TD_CTRL_ACTIVE)
-		return -EINPROGRESS;
-
 	urb->actual_length = 0;
 
-	for (i = 0, td = urbp->begin; td; i++, td = td->next) {
+	for (i = 0, td = urbp->list.begin; td; i++, td = td->list.next) {
 		int actlength;
 
+		if (td->status & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
+
 		actlength = uhci_actual_length(td->status);
 		urb->iso_frame_desc[i].actual_length = actlength;
 		urb->actual_length += actlength;
@@ -1114,17 +1027,26 @@
 {
 	int ret = -EINVAL;
 	struct uhci *uhci;
+	unsigned long flags;
 
 	if (!urb)
 		return -EINVAL;
 
-	if (!urb->dev || !urb->dev->bus)
+	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv)
 		return -ENODEV;
 
 	uhci = (struct uhci *)urb->dev->bus->hcpriv;
 
+	/* Short circuit the virtual root hub */
 	if (usb_pipedevice(urb->pipe) == uhci->rh.devnum)
-		return rh_submit_urb(urb);	/* Virtual root hub */
+		return rh_submit_urb(urb);
+
+	spin_lock_irqsave(&urb->lock, flags);
+
+	if (!uhci_alloc_urb_priv(urb)) {
+		spin_unlock_irqrestore(&urb->lock, flags);
+		return -ENOMEM;
+	}
 
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
@@ -1142,20 +1064,30 @@
 	}
 
 	urb->status = ret;
+
+	spin_unlock_irqrestore(&urb->lock, flags);
+
 	if (ret == -EINPROGRESS)
-		return 0;
+		ret = 0;
+	else
+		uhci_unlink_generic(urb);
 
 	return ret;
 }
 
 /*
  * Return the result of a transfer
+ *
+ * Must be called with urblist_lock acquired
  */
 static void uhci_transfer_result(urb_t *urb)
 {
 	urb_t *turb;
 	int proceed = 0, is_ring = 0;
 	int ret = -EINVAL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&urb->lock, flags);
 
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
@@ -1173,12 +1105,17 @@
 	}
 
 	urb->status = ret;
-	if (urb->status == -EINPROGRESS)
+
+	spin_unlock_irqrestore(&urb->lock, flags);
+
+	if (ret == -EINPROGRESS)
 		return;
 
 	switch (usb_pipetype(urb->pipe)) {
 	case PIPE_CONTROL:
-		uhci_unlink_control(urb);
+	case PIPE_BULK:
+	case PIPE_ISOCHRONOUS:
+		uhci_unlink_generic(urb);
 		break;
 	case PIPE_INTERRUPT:
 		/* Interrupts are an exception */
@@ -1186,14 +1123,8 @@
 		if (urb->interval)
 			uhci_reset_interrupt(urb);
 		else
-			uhci_unlink_interrupt(urb);
-		return;
-	case PIPE_BULK:
-		uhci_unlink_bulk(urb);
-		break;
-	case PIPE_ISOCHRONOUS:
-		uhci_unlink_isochronous(urb);
-		break;
+			uhci_unlink_generic(urb);
+		return;		/* <-- Note the return */
 	}
 
 	if (urb->next) {
@@ -1231,10 +1162,32 @@
 	}
 }
 
+static int uhci_unlink_generic(urb_t *urb)
+{
+	struct urb_priv *urbp = urb->hcpriv;
+	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+	if (!urbp)
+		return -EINVAL;
+
+	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
+
+	uhci_remove_urb_list(uhci, urb);
+
+	if (urbp->qh)
+		/* The interrupt loop will reclaim the QH's */
+		uhci_remove_qh(uhci, urbp->qh);
+
+	uhci_destroy_urb_priv(urb);
+
+	return 0;
+}
+
 static int uhci_unlink_urb(urb_t *urb)
 {
 	struct uhci *uhci;
 	int ret = 0;
+	unsigned long flags;
 
 	if (!urb)
 		return -EINVAL;
@@ -1244,40 +1197,34 @@
 
 	uhci = (struct uhci *)urb->dev->bus->hcpriv;
 
+	/* Short circuit the virtual root hub */
 	if (usb_pipedevice(urb->pipe) == uhci->rh.devnum)
 		return rh_unlink_urb(urb);
 
 	if (urb->status == -EINPROGRESS) {
-		switch (usb_pipetype(urb->pipe)) {
-		case PIPE_CONTROL:
-			ret = uhci_unlink_control(urb);
-			break;
-		case PIPE_INTERRUPT:
-			ret = uhci_unlink_interrupt(urb);
-			break;
-		case PIPE_BULK:
-			ret = uhci_unlink_bulk(urb);
-			break;
-		case PIPE_ISOCHRONOUS:
-			ret = uhci_unlink_isochronous(urb);
-			break;
-		}
+		uhci_unlink_generic(urb);
 
-		if (urb->complete)
-			urb->complete(urb);
+		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
+			spin_lock_irqsave(&uhci->urb_remove_lock, flags);
+			list_add(&urb->urb_list, &uhci->urb_remove_list);
+			spin_unlock_irqrestore(&uhci->urb_remove_lock, flags);
+
+			urb->status = -ECONNABORTED;
+		} else {
+			if (in_interrupt()) {	/* wait at least 1 frame */
+				static int errorcount = 10;
+
+				if (errorcount--)
+					dbg("uhci_unlink_urb called from interrupt for urb %p", urb);
+				udelay(1000);
+			} else
+				schedule_timeout(1+1*HZ/1000); 
 
-#ifndef CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
-		if (in_interrupt()) {		/* wait at least 1 frame */
-			int errorcount = 10;
-
-			if (errorcount--)
-				dbg("uhci_unlink_urb called from interrupt for urb %p", urb);
-			udelay(1000);
-		} else
-			schedule_timeout(1+1*HZ/1000); 
-#endif
+			if (urb->complete)
+				urb->complete(urb);
 
-		urb->status = -ENOENT;
+			urb->status = -ENOENT;
+		}
 	}
 
 	return ret;
@@ -1412,9 +1359,12 @@
 
 static void rh_int_timer_do(unsigned long ptr)
 {
-	int len;
-	urb_t *urb = (urb_t *)ptr;
+	urb_t *urb = (urb_t *)ptr, *u;
 	struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+	struct list_head *tmp, *head = &uhci->urb_list;
+	struct urb_priv *urbp;
+	int len;
+	unsigned long flags;
 
 	if (uhci->rh.send) {
 		len = rh_send_irq(urb);
@@ -1425,6 +1375,21 @@
 		}
 	}
 
+	nested_lock(&uhci->urblist_lock, flags);
+	tmp = head->next;
+	while (tmp != head) {
+		u = list_entry(tmp, urb_t, urb_list);
+
+		urbp = (struct urb_priv *)u->hcpriv;
+		if (urbp) {
+			if (urbp->fsbr && time_after(jiffies, urbp->inserttime + IDLE_TIMEOUT))
+				uhci_dec_fsbr(uhci, u);
+		}
+
+		tmp = tmp->next;
+	}
+	nested_unlock(&uhci->urblist_lock, flags);
+
 	rh_init_int_timer(urb);
 }
 
@@ -1645,6 +1610,27 @@
 }
 /*-------------------------------------------------------------------*/
 
+void uhci_free_pending_qhs(struct uhci *uhci)
+{
+	struct list_head *tmp, *head;
+	unsigned long flags;
+
+	/* Free any pending QH's */
+	spin_lock_irqsave(&uhci->qh_remove_lock, flags);
+	head = &uhci->qh_remove_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, remove_list);
+
+		tmp = tmp->next;
+
+		list_del(&qh->remove_list);
+
+		uhci_free_qh(qh);
+	}
+	spin_unlock_irqrestore(&uhci->qh_remove_lock, flags);
+}
+
 static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs)
 {
 	struct uhci *uhci = __uhci;
@@ -1652,7 +1638,6 @@
 	unsigned short status;
 	unsigned long flags;
 	struct list_head *tmp, *head;
-	urb_t *urb;
 
 	/*
 	 * Read the interrupt status, and write it back to clear the
@@ -1676,55 +1661,36 @@
 		}
 	}
 
-	/* Walk the list of pending TD's to see which ones completed.. */
-	nested_lock(&uhci->irqlist_lock, flags);
-	head = &uhci->interrupt_list;
+	uhci_free_pending_qhs(uhci);
+
+	spin_lock(&uhci->urb_remove_lock);
+	head = &uhci->urb_remove_list;
 	tmp = head->next;
 	while (tmp != head) {
-		struct uhci_td *td = list_entry(tmp, struct uhci_td, irq_list);
-
-		urb = td->urb;
+		struct urb *urb = list_entry(tmp, struct urb, urb_list);
 
 		tmp = tmp->next;
 
-		/* Checks the status and does all of the magic necessary */
-		uhci_transfer_result(urb);
-	}
-	nested_unlock(&uhci->irqlist_lock, flags);
-}
-
-static void uhci_stop_hc_schedule(struct uhci *uhci)
-{
-#ifdef CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
-	unsigned int cmdreg, timeout = 1000;
-
-	cmdreg = inw(uhci->io_addr + USBCMD);
-	outw(cmdreg & ~USBCMD_RS, uhci->io_addr + USBCMD);
+		list_del(&urb->urb_list);
 
-	while (!(inw(uhci->io_addr + USBSTS) & USBSTS_HCH)) {
-		if (!--timeout) {
-			printk(KERN_ERR "uhci: stop_hc_schedule failed, HC still running\n");
-			break;
-		}
+		if (urb->complete)
+			urb->complete(urb);
 	}
-#endif
-}
+	spin_unlock(&uhci->urb_remove_lock);
 
-static void uhci_start_hc_schedule(struct uhci *uhci)
-{
-#ifdef CONFIG_USB_UHCI_ALT_UNLINK_OPTIMIZE
-	unsigned int cmdreg, timeout = 1000;
+	/* Walk the list of pending TD's to see which ones completed */
+	nested_lock(&uhci->urblist_lock, flags);
+	head = &uhci->urb_list;
+	tmp = head->next;
+	while (tmp != head) {
+		struct urb *urb = list_entry(tmp, struct urb, urb_list);
 
-	cmdreg = inw(uhci->io_addr + USBCMD);
-	outw(cmdreg | USBCMD_RS, uhci->io_addr + USBCMD);
+		tmp = tmp->next;
 
-	while (inw(uhci->io_addr + USBSTS) & USBSTS_HCH) {
-		if (!--timeout) {
-			printk(KERN_ERR "uhci: start_hc_schedule failed, HC still halted\n");
-			break;
-		}
+		/* Checks the status and does all of the magic necessary */
+		uhci_transfer_result(urb);
 	}
-#endif
+	nested_unlock(&uhci->urblist_lock, flags);
 }
 
 static void reset_hc(struct uhci *uhci)
@@ -1780,7 +1746,7 @@
  *    of the queues. We don't do that here, because
  *    we'll create the actual TD entries on demand.
  *  - The first queue is the "interrupt queue".
- *  - The second queue is the "control queue".
+ *  - The second queue is the "control queue", split into low and high speed
  *  - The third queue is "bulk data".
  */
 static struct uhci *alloc_uhci(unsigned int io_addr, unsigned int io_size)
@@ -1799,14 +1765,16 @@
 	uhci->io_addr = io_addr;
 	uhci->io_size = io_size;
 
-	INIT_LIST_HEAD(&uhci->interrupt_list);
-	INIT_LIST_HEAD(&uhci->urb_list);
+	spin_lock_init(&uhci->qh_remove_lock);
+	INIT_LIST_HEAD(&uhci->qh_remove_list);
+
+	spin_lock_init(&uhci->urb_remove_lock);
+	INIT_LIST_HEAD(&uhci->urb_remove_list);
 
-	spin_lock_init(&uhci->framelist_lock);
 	nested_init(&uhci->urblist_lock);
-	nested_init(&uhci->irqlist_lock);
+	INIT_LIST_HEAD(&uhci->urb_list);
 
-	uhci->fsbr = 0;
+	spin_lock_init(&uhci->framelist_lock);
 
 	/* We need exactly one page (per UHCI specs), how convenient */
 	/* We assume that one page is atleast 4k (1024 frames * 4 bytes) */
@@ -1870,8 +1838,12 @@
 	uhci->skel_bulk_qh.link = virt_to_bus(&uhci->skel_term_qh) | UHCI_PTR_QH;
 	uhci->skel_bulk_qh.element = UHCI_PTR_TERM;
 
+	/* This dummy TD is to work around a bug in Intel PIIX controllers */
+	uhci_fill_td(&uhci->skel_term_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
+	uhci->skel_term_td.link = UHCI_PTR_TERM;
+
 	uhci->skel_term_qh.link = UHCI_PTR_TERM;
-	uhci->skel_term_qh.element = UHCI_PTR_TERM;
+	uhci->skel_term_qh.element = virt_to_bus(&uhci->skel_term_td);
 
 	/*
 	 * Fill the frame list: make all entries point to
@@ -2022,23 +1994,24 @@
 			dev->resource[i].end - dev->resource[i].start + 1;
 
 		/* IO address? */
-		if (!(dev->resource[i].flags & 1))
+		if (!(dev->resource[i].flags & IORESOURCE_IO))
 			continue;
 
 		/* Is it already in use? */
 		if (check_region(io_addr, io_size))
 			break;
 
-		/* disable legacy emulation */
-		pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
-
-		pci_enable_device(dev);
-
 		if (!dev->irq) {
 			err("found UHCI device with no IRQ assigned. check BIOS settings!");
 			continue;
 		}
 
+		/* disable legacy emulation */
+		pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
+		if (pci_enable_device(dev) < 0)
+			continue;
+
 		return setup_uhci(dev, dev->irq, io_addr, io_size);
 	}
 
@@ -2081,6 +2054,12 @@
 	if (!uhci_qh_cachep)
 		goto qh_failed;
 
+	uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
+		sizeof(struct urb_priv), 0, 0, NULL, NULL);
+
+	if (!uhci_up_cachep)
+		goto up_failed;
+
 	retval = -ENODEV;
 	dev = NULL;
 	for (;;) {
@@ -2105,6 +2084,10 @@
 	return 0;
 
 init_failed:
+	if (kmem_cache_destroy(uhci_up_cachep))
+		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
+
+up_failed:
 	if (kmem_cache_destroy(uhci_qh_cachep))
 		printk(KERN_INFO "uhci: not all QH's were freed\n");
 
@@ -2118,13 +2101,13 @@
 
 void uhci_cleanup(void)
 {
-	struct list_head *next, *tmp, *head = &uhci_list;
+	struct list_head *tmp, *head = &uhci_list;
 
 	tmp = head->next;
 	while (tmp != head) {
 		struct uhci *uhci = list_entry(tmp, struct uhci, uhci_list);
 
-		next = tmp->next;
+		tmp = tmp->next;
 
 		list_del(&uhci->uhci_list);
 		INIT_LIST_HEAD(&uhci->uhci_list);
@@ -2137,10 +2120,13 @@
 		reset_hc(uhci);
 		release_region(uhci->io_addr, uhci->io_size);
 
-		release_uhci(uhci);
+		uhci_free_pending_qhs(uhci);
 
-		tmp = next;
+		release_uhci(uhci);
 	}
+
+	if (kmem_cache_destroy(uhci_up_cachep))
+		printk(KERN_INFO "uhci: not all urb_priv's were freed\n");
 
 	if (kmem_cache_destroy(uhci_qh_cachep))
 		printk(KERN_INFO "uhci: not all QH's were freed\n");
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/uhci.h linux/drivers/usb/uhci.h
--- v2.3.50/linux/drivers/usb/uhci.h	Thu Feb 10 17:11:15 2000
+++ linux/drivers/usb/uhci.h	Fri Mar 10 16:18:34 2000
@@ -2,8 +2,7 @@
 #define __LINUX_UHCI_H
 
 #include <linux/list.h>
-
-#include "usb.h"
+#include <linux/usb.h>
 
 /*
  * This nested spinlock code is courtesy of Davide Libenzi <dlibenzi@maticad.it>
@@ -106,11 +105,12 @@
 	__u32 element;				/* Queue element pointer */
 
 	/* Software fields */
-	struct uhci_qh *prevqh, *nextqh;	/* Previous and next TD in queue */
+	/* Can't use list_head since we want a specific order */
+	struct uhci_qh *prevqh, *nextqh;
 
 	struct usb_device *dev;			/* The owning device */
 
-	struct list_head list;
+	struct list_head remove_list;
 } __attribute__((aligned(16)));
 
 struct uhci_framelist {
@@ -184,10 +184,10 @@
 
 	struct usb_device *dev;
 	struct urb *urb;		/* URB this TD belongs to */
-	struct uhci_td *next;		/* List of chained TD's for an URB */
-
-	struct list_head irq_list;	/* Active interrupt list.. */
-	struct list_head list;
+	/* We can't use list_head since we need a specific order */
+	struct ut_list {
+		struct uhci_td *prev, *next;
+	} list;
 } __attribute__((aligned(16)));
 
 /*
@@ -233,7 +233,7 @@
  * labels (below) are only signficant to the root hub's QH's
  */
 
-#define UHCI_NUM_SKELTD		9
+#define UHCI_NUM_SKELTD		10
 #define skel_int1_td		skeltd[0]
 #define skel_int2_td		skeltd[1]
 #define skel_int4_td		skeltd[2]
@@ -243,6 +243,7 @@
 #define skel_int64_td		skeltd[6]
 #define skel_int128_td		skeltd[7]
 #define skel_int256_td		skeltd[8]
+#define skel_term_td		skeltd[9]	/* To work around PIIX UHCI bug */
 
 #define UHCI_NUM_SKELQH		4
 #define skel_ls_control_qh	skelqh[0]
@@ -306,6 +307,7 @@
  * a subset of what the full implementation needs.
  */
 struct uhci {
+	/* Grabbed from PCI */
 	int irq;
 	unsigned int io_addr;
 	unsigned int io_size;
@@ -317,25 +319,32 @@
 	struct uhci_td skeltd[UHCI_NUM_SKELTD];	/* Skeleton TD's */
 	struct uhci_qh skelqh[UHCI_NUM_SKELQH];	/* Skeleton QH's */
 
+	spinlock_t framelist_lock;
 	struct uhci_framelist *fl;		/* Frame list */
+	int fsbr;				/* Full speed bandwidth reclamation */
 
-	struct s_nested_lock irqlist_lock;
-	struct list_head interrupt_list;	/* List of interrupt-active TD's for this uhci */
+	spinlock_t qh_remove_lock;
+	struct list_head qh_remove_list;
+
+	spinlock_t urb_remove_lock;
+	struct list_head urb_remove_list;
 
 	struct s_nested_lock urblist_lock;
 	struct list_head urb_list;
 
-	spinlock_t framelist_lock;
-
-	int fsbr;			/* Full speed bandwidth reclamation */
-
 	struct virt_root_hub rh;	/* private data of the virtual root hub */
 };
 
 struct urb_priv {
 	struct uhci_qh *qh;		/* QH for this URB */
-	struct uhci_td *begin;
-	struct uhci_td *end;
+
+	int fsbr;
+
+	unsigned long inserttime;	/* In jiffies */
+
+	struct up_list {
+		struct uhci_td *begin, *end;
+	} list;
 };
 
 /* -------------------------------------------------------------------------
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb-core.c linux/drivers/usb/usb-core.c
--- v2.3.50/linux/drivers/usb/usb-core.c	Sat Feb 26 22:31:50 2000
+++ linux/drivers/usb/usb-core.c	Fri Mar 10 16:18:34 2000
@@ -13,8 +13,7 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/config.h>
-
-#include "usb.h"
+#include <linux/usb.h>
 
 /*
  * USB core
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c
--- v2.3.50/linux/drivers/usb/usb-debug.c	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/usb-debug.c	Fri Mar 10 16:18:34 2000
@@ -9,8 +9,7 @@
 #include <linux/mm.h>
 #include <linux/malloc.h>
 #define DEBUG
-
-#include "usb.h"
+#include <linux/usb.h>
 
 static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint)
 {
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- v2.3.50/linux/drivers/usb/usb-ohci.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/usb-ohci.c	Fri Mar 10 16:18:34 2000
@@ -41,16 +41,16 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>  /* for in_interrupt() */
+#undef DEBUG
+#include <linux/usb.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/unaligned.h>
 
-#undef DEBUG
 #define OHCI_USE_NPS
 
-#include "usb.h"
 #include "usb-ohci.h"
 
 #include <linux/pm.h>
@@ -1675,20 +1675,24 @@
  
 static int hc_start_ohci (struct pci_dev * dev)
 {
-	u32 cmd;
+	unsigned long mem_base;
+
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
-	unsigned long mem_base = dev->resource[0].start;
+	mem_base = dev->resource[0].start;
+	if (pci_enable_device(dev) < 0)
+		return -ENODEV;
 #else
-	unsigned long mem_base = dev->base_address[0];
+	u16 cmd;
+
+	mem_base = dev->base_address[0];
 	if (mem_base & PCI_BASE_ADDRESS_SPACE_IO) return -ENODEV;
 	mem_base &= PCI_BASE_ADDRESS_MEM_MASK;
+
+	/* Some Mac firmware will switch memory response off */
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY);
 #endif
 	
-	/* Some Mac firmware will switch memory response off */
-	pci_read_config_dword(dev, PCI_COMMAND, &cmd);
-	cmd = (cmd | PCI_COMMAND_MEMORY);
-	pci_write_config_dword(dev, PCI_COMMAND, cmd);
-
 	pci_set_master (dev);
 	mem_base = (unsigned long) ioremap_nocache (mem_base, 4096);
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb-serial.c linux/drivers/usb/usb-serial.c
--- v2.3.50/linux/drivers/usb/usb-serial.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/usb-serial.c	Wed Dec 31 16:00:00 1969
@@ -1,2551 +0,0 @@
-/*
- * USB Serial Converter driver
- *
- *	(C) Copyright (C) 1999, 2000
- *	    Greg Kroah-Hartman (greg@kroah.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 driver was originally based on the ACM driver by Armin Fuerst (which was 
- * based on a driver by Brad Keryan)
- *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- * 
- * (03/06/2000) gkh
- *	Added the keyspan pda code from Brian Warner <warner@lothar.com>
- *	Moved a bunch of the port specific stuff into its own structure. This
- *	is in anticipation of the true multiport devices (there's a bug if you
- *	try to access more than one port of any multiport device right now)
- *
- * (02/21/2000) gkh
- *	Made it so that any serial devices only have to specify which functions
- *	they want to overload from the generic function calls (great, 
- *	inheritance in C, in a driver, just what I wanted...)
- *	Added support for set_termios and ioctl function calls. No drivers take
- *	advantage of this yet.
- *	Removed the #ifdef MODULE, now there is no module specific code.
- *	Cleaned up a few comments in usb-serial.h that were wrong (thanks again
- *	to Miles Lott).
- *	Small fix to get_free_serial.
- *
- * (02/14/2000) gkh
- *	Removed the Belkin and Peracom functionality from the driver due to
- *	the lack of support from the vendor, and me not wanting people to 
- *	accidenatly buy the device, expecting it to work with Linux.
- *	Added read_bulk_callback and write_bulk_callback to the type structure
- *	for the needs of the FTDI and WhiteHEAT driver.
- *	Changed all reverences to FTDI to FTDI_SIO at the request of Bill
- *	Ryder.
- *	Changed the output urb size back to the max endpoint size to make
- *	the ftdi_sio driver have it easier, and due to the fact that it didn't
- *	really increase the speed any.
- *
- * (02/11/2000) gkh
- *	Added VISOR_FUNCTION_CONSOLE to the visor startup function. This was a
- *	patch from Miles Lott (milos@insync.net).
- *	Fixed bug with not restoring the minor range that a device grabs, if
- *	the startup function fails (thanks Miles for finding this).
- *
- * (02/05/2000) gkh
- *	Added initial framework for the Keyspan PDA serial converter so that
- *	Brian Warner has a place to put his code.
- *	Made the ezusb specific functions generic enough that different
- *	devices can use them (whiteheat and keyspan_pda both need them).
- *	Split out a whole bunch of structure and other stuff to a seperate
- *	usb-serial.h file.
- *	Made the Visor connection messages a little more understandable, now
- *	that Miles Lott (milos@insync.net) has gotten the Generic channel to
- *	work. Also made them always show up in the log file.
- * 
- * (01/25/2000) gkh
- *	Added initial framework for FTDI serial converter so that Bill Ryder
- *	has a place to put his code.
- *	Added the vendor specific info from Handspring. Now we can print out
- *	informational debug messages as well as understand what is happening.
- *
- * (01/23/2000) gkh
- *	Fixed problem of crash when trying to open a port that didn't have a
- *	device assigned to it. Made the minor node finding a little smarter,
- *	now it looks to find a continous space for the new device.
- *
- * (01/21/2000) gkh
- *	Fixed bug in visor_startup with patch from Miles Lott (milos@insync.net)
- *	Fixed get_serial_by_minor which was all messed up for multi port 
- *	devices. Fixed multi port problem for generic devices. Now the number
- *	of ports is determined by the number of bulk out endpoints for the
- *	generic device.
- *
- * (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
- *      the Handspring Visor to be attached successfully. Only the first
- *      bulk in / bulk out endpoint pair is being used right now.
- *
- * version 0.3.0 (12/27/99) gkh
- *	Added initial support for the Handspring Visor based on a patch from
- *	Miles Lott (milos@sneety.insync.net)
- *	Cleaned up the code a bunch and converted over to using urbs only.
- *
- * version 0.2.3 (12/21/99) gkh
- *	Added initial support for the Connect Tech WhiteHEAT converter.
- *	Incremented the number of ports in expectation of getting the
- *	WhiteHEAT to work properly (4 ports per connection).
- *	Added notification on insertion and removal of what port the
- *	device is/was connected to (and what kind of device it was).
- *
- * version 0.2.2 (12/16/99) gkh
- *	Changed major number to the new allocated number. We're legal now!
- *
- * version 0.2.1 (12/14/99) gkh
- *	Fixed bug that happens when device node is opened when there isn't a
- *	device attached to it. Thanks to marek@webdesign.no for noticing this.
- *
- * version 0.2.0 (11/10/99) gkh
- *	Split up internals to make it easier to add different types of serial 
- *	converters to the code.
- *	Added a "generic" driver that gets it's vendor and product id
- *	from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net)
- *	for the idea and sample code (from the usb scanner driver.)
- *	Cleared up any licensing questions by releasing it under the GNU GPL.
- *
- * version 0.1.2 (10/25/99) gkh
- * 	Fixed bug in detecting device.
- *
- * version 0.1.1 (10/05/99) gkh
- * 	Changed the major number to not conflict with anything else.
- *
- * version 0.1 (09/28/99) gkh
- * 	Can recognize the two different devices and start up a read from
- *	device when asked to. Writes also work. No control signals yet, this
- *	all is vendor specific data (i.e. no spec), also no control for
- *	different baud rates or other bit settings.
- *	Currently we are using the same devid as the acm driver. This needs
- *	to change.
- * 
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-#include <linux/malloc.h>
-#include <linux/fcntl.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/tty.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-
-#define DEBUG
-
-#include "usb.h"
-
-#ifdef CONFIG_USB_SERIAL_WHITEHEAT
-#include "whiteheat.h"		/* firmware for the ConnectTech WhiteHEAT device */
-#endif
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
-struct ezusb_hex_record {
-	__u16 address;
-	__u8 data_size;
-	__u8 data[16];
-};
-#include "keyspan_pda_fw.h"
-#endif
-
-#include "usb-serial.h"
-
-/* parity check flag */
-#define RELEVANT_IFLAG(iflag)	(iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
-
-/* local function prototypes */
-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 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);
-static void serial_unthrottle (struct tty_struct * tty);
-static int  serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
-static void serial_set_termios (struct tty_struct *tty, struct termios * old);
-
-static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum);
-static void usb_serial_disconnect(struct usb_device *dev, void *ptr);
-
-static struct usb_driver usb_serial_driver = {
-	"serial",
-	usb_serial_probe,
-	usb_serial_disconnect,
-	{ NULL, NULL }
-};
-
-static int			serial_refcount;
-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, };
-
-
-
-static struct usb_serial *get_serial_by_minor (int minor)
-{
-	dbg("get_serial_by_minor %d", minor);
-
-	return serial_table[minor];
-}
-
-
-static struct usb_serial *get_free_serial (int num_ports, int *minor)
-{
-	struct usb_serial *serial = NULL;
-	int i, j;
-	int good_spot;
-
-	dbg("get_free_serial %d", num_ports);
-
-	*minor = 0;
-	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
-		if (serial_table[i])
-			continue;
-
-		good_spot = 1;
-		for (j = 1; j <= num_ports-1; ++j)
-			if (serial_table[i+j])
-				good_spot = 0;
-		if (good_spot == 0)
-			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 < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i)
-			serial_table[i] = serial;
-		return serial;
-		}
-	return NULL;
-}
-
-
-static void return_serial (struct usb_serial *serial)
-{
-	int i;
-
-	dbg("return_serial");
-
-	if (serial == NULL)
-		return;
-
-	for (i = 0; i < serial->num_ports; ++i) {
-		serial_table[serial->minor + i] = NULL;
-	}
-
-	return;
-}
-
-
-#ifdef USES_EZUSB_FUNCTIONS
-/* EZ-USB Control and Status Register.  Bit 0 controls 8051 reset */
-#define CPUCS_REG    0x7F92
-
-static int ezusb_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("ezusb_writememory %x, %d", address, length);
-
-	if (!transfer_buffer) {
-		err("ezusb_writememory: kmalloc(%d) failed.", 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;
-}
-
-
-static int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit)
-{
-	int	response;
-	dbg("ezusb_set_reset: %d", reset_bit);
-	response = ezusb_writememory (serial, CPUCS_REG, &reset_bit, 1, 0xa0);
-	if (response < 0) {
-		err("ezusb_set_reset %d failed", reset_bit);
-	}
-	return response;
-}
-
-#endif	/* USES_EZUSB_FUNCTIONS */
-
-
-/*****************************************************************************
- * Driver tty interface functions
- *****************************************************************************/
-static int serial_open (struct tty_struct *tty, struct file * filp)
-{
-	struct usb_serial *serial;
-	
-	dbg("serial_open");
-
-	/* initialize the pointer incase something fails */
-	tty->driver_data = NULL;
-
-	/* 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) {
-		dbg("serial == NULL!");
-		return (-ENODEV);
-	}
-	if (!serial->type) {
-		dbg("serial->type == NULL!");
-		return (-ENODEV);
-	}
-
-	/* make the tty driver remember our serial object, and us it */
-	tty->driver_data = serial;
-	serial->tty = tty;
-	 
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->open) {
-		return (serial->type->open(tty, filp));
-	} else {
-		return (generic_serial_open(tty, filp));
-	}
-}
-
-
-static void serial_close(struct tty_struct *tty, struct file * filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port;	
-
-	dbg("serial_close");
-
-	if (!serial) {
-		dbg("serial == NULL!");
-		return;
-	}
-
-	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->type) {
-		dbg("serial->type == NULL!");
-		return;
-	}
-	if (!serial->port[port].active) {
-		dbg ("device not opened");
-		return;
-	}
-
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->close) {
-		serial->type->close(tty, filp);
-	} else {
-		generic_serial_close(tty, filp);
-	}
-}	
-
-
-static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-	
-	dbg("serial_write port %d, %d byte(s)", port, count);
-
-	/* do some sanity checking that we really have a device present */
-	if (!serial) {
-		dbg("serial == NULL!");
-		return (-ENODEV);
-	}
-	if (!serial->type) {
-		dbg("serial->type == NULL!");
-		return (-ENODEV);
-	}
-	if (!serial->port[port].active) {
-		dbg ("device not opened");
-		return (-EINVAL);
-	}
-	
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->write) {
-		return (serial->type->write(tty, from_user, buf, count));
-	} else {
-		return (generic_serial_write(tty, from_user, buf, count));
-	}
-}
-
-
-static int serial_write_room (struct tty_struct *tty) 
-{
-	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-
-	dbg("serial_write_room port %d", port);
-	
-	/* do some sanity checking that we really have a device present */
-	if (!serial) {
-		dbg("serial == NULL!");
-		return (-ENODEV);
-	}
-	if (!serial->type) {
-		dbg("serial->type == NULL!");
-		return (-ENODEV);
-	}
-	if (!serial->port[port].active) {
-		dbg ("device not open");
-		return (-EINVAL);
-	}
-	
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->write_room) {
-		return (serial->type->write_room(tty));
-	} else {
-		return (generic_write_room(tty));
-	}
-}
-
-
-static int serial_chars_in_buffer (struct tty_struct *tty) 
-{
-	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-
-	dbg("serial_chars_in_buffer port %d", port);
-	
-	/* do some sanity checking that we really have a device present */
-	if (!serial) {
-		dbg("serial == NULL!");
-		return (-ENODEV);
-	}
-	if (!serial->type) {
-		dbg("serial->type == NULL!");
-		return (-ENODEV);
-	}
-	if (!serial->port[port].active) {
-		dbg ("device not open");
-		return (-EINVAL);
-	}
-	
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->chars_in_buffer) {
-		return (serial->type->chars_in_buffer(tty));
-	} else {
-		return (generic_chars_in_buffer(tty));
-	}
-}
-
-
-static void serial_throttle (struct tty_struct * tty)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-
-	dbg("serial_throttle port %d", port);
-	
-	/* 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->port[port].active) {
-		dbg ("device not open");
-		return;
-	}
-
-	/* pass on to the driver specific version of this function */
-	if (serial->type->throttle) {
-		serial->type->throttle(tty);
-	} else {
-		generic_throttle(tty);
-	}
-
-	return;
-}
-
-
-static void serial_unthrottle (struct tty_struct * tty)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-
-	dbg("serial_unthrottle port %d", port);
-	
-	/* 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->port[port].active) {
-		dbg ("device not open");
-		return;
-	}
-
-	/* pass on to the driver specific version of this function */
-	if (serial->type->unthrottle) {
-		serial->type->unthrottle(tty);
-	} else {
-		generic_unthrottle(tty);
-	}
-
-	return;
-}
-
-
-static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port;	
-
-	dbg("serial_ioctl");
-
-	if (!serial) {
-		dbg("serial == NULL!");
-		return -ENODEV;
-	}
-
-	port = MINOR(tty->device) - serial->minor;
-
-	dbg("serial_ioctl port %d", port);
-	
-	/* do some sanity checking that we really have a device present */
-	if (!serial->type) {
-		dbg("serial->type == NULL!");
-		return -ENODEV;
-	}
-	if (!serial->port[port].active) {
-		dbg ("device not open");
-		return -ENODEV;
-	}
-
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->ioctl) {
-		return (serial->type->ioctl(tty, file, cmd, arg));
-	} else {
-		return (generic_ioctl (tty, file, cmd, arg));
-	}
-}
-
-
-static void serial_set_termios (struct tty_struct *tty, struct termios * old)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port;	
-
-	dbg("serial_set_termios");
-
-	if (!serial) {
-		dbg("serial == NULL!");
-		return;
-	}
-
-	port = MINOR(tty->device) - serial->minor;
-
-	dbg("serial_set_termios port %d", port);
-	
-	/* do some sanity checking that we really have a device present */
-	if (!serial->type) {
-		dbg("serial->type == NULL!");
-		return;
-	}
-	if (!serial->port[port].active) {
-		dbg ("device not open");
-		return;
-	}
-
-	/* pass on to the driver specific version of this function if it is available */
-	if (serial->type->set_termios) {
-		serial->type->set_termios(tty, old);
-	} else {
-		generic_set_termios (tty, old);
-	}
-	
-	return;
-}
-
-
-static void serial_break (struct tty_struct *tty, int break_state)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port;	
-
-	if (!serial) {
-		dbg("serial == NULL!");
-		return;
-	}
-
-	port = MINOR(tty->device) - serial->minor;
-
-	dbg("serial_break port %d", port);
-	
-	/* do some sanity checking that we really have a device present */
-	if (!serial->type) {
-		dbg("serial->type == NULL!");
-		return;
-	}
-	if (!serial->port[port].active) {
-		dbg ("device not open");
-		return;
-	}
-
-	/* pass on to the driver specific version of this function if it is
-           available */
-	if (serial->type->break_ctl) {
-		serial->type->break_ctl(tty, break_state);
-	}
-}
-
-
-#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 *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-
-	dbg("whiteheat_serial_open port %d", portNumber);
-
-	if (port->active) {
-		dbg ("device already open");
-		return -EINVAL;
-	}
-	port->active = 1;
- 
-	/*Start reading from the device*/
-	if (usb_submit_urb(&port->read_urb))
-		dbg("usb_submit_urb(read bulk) failed");
-
-	/* Need to do device specific setup here (control lines, baud rate, etc.) */
-	/* FIXME!!! */
-
-	return (0);
-}
-
-
-static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-
-	dbg("whiteheat_serial_close port %d", portNumber);
-	
-	/* Need to change the control lines here */
-	/* FIXME */
-	
-	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (&port->write_urb);
-	usb_unlink_urb (&port->read_urb);
-	port->active = 0;
-}
-
-
-static void whiteheat_set_termios (struct tty_struct *tty, struct termios *old_termios)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-	unsigned int cflag = tty->termios->c_cflag;
-
-	dbg("whiteheat_set_termios port %d", port);
-
-	/* check that they really want us to change something */
-	if (old_termios) {
-		if ((cflag == old_termios->c_cflag) &&
-		    (RELEVANT_IFLAG(tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) {
-			dbg("nothing to change...");
-			return;
-		}
-	}
-
-	/* do the parsing of the cflag to see what to set the line to */
-	/* FIXME!! */
-
-	return;
-}
-
-static void whiteheat_throttle (struct tty_struct * tty)
-{
-	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!!! */
-
-	return;
-}
-
-
-static void whiteheat_unthrottle (struct tty_struct * tty)
-{
-	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!!! */
-
-	return;
-}
-
-
-/* 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 = ezusb_set_reset (serial, 1);
-
-	record = &whiteheat_loader[0];
-	while (record->address != 0xffff) {
-		response = ezusb_writememory (serial, record->address, 
-				(unsigned char *)record->data, record->data_size, 0xa0);
-		if (response < 0) {
-			err("ezusb_writememory failed for loader (%d %04X %p %d)", 
-				response, record->address, record->data, record->data_size);
-			break;
-		}
-		++record;
-	}
-
-	response = ezusb_set_reset (serial, 0);
-
-	record = &whiteheat_firmware[0];
-	while (record->address < 0x1b40) {
-		++record;
-	}
-	while (record->address != 0xffff) {
-		response = ezusb_writememory (serial, record->address, 
-				(unsigned char *)record->data, record->data_size, 0xa0);
-		if (response < 0) {
-			err("ezusb_writememory failed for first firmware step (%d %04X %p %d)", 
-				response, record->address, record->data, record->data_size);
-			break;
-		}
-		++record;
-	}
-	
-	response = ezusb_set_reset (serial, 1);
-
-	record = &whiteheat_firmware[0];
-	while (record->address < 0x1b40) {
-		response = ezusb_writememory (serial, record->address, 
-				(unsigned char *)record->data, record->data_size, 0xa0);
-		if (response < 0) {
-			err("ezusb_writememory failed for second firmware step (%d %04X %p %d)", 
-				response, record->address, record->data, record->data_size);
-			break;
-		}
-		++record;
-	}
-
-	response = ezusb_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 *serial = (struct usb_serial *) tty->driver_data;
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-
-	dbg("visor_serial_open port %d", portNumber);
-
-	if (port->active) {
-		dbg ("device already open");
-		return -EINVAL;
-	}
-
-	port->active = 1;
-
-	/*Start reading from the device*/
-	if (usb_submit_urb(&port->read_urb))
-		dbg("usb_submit_urb(read bulk) failed");
-
-	return (0);
-}
-
-static void visor_serial_close(struct tty_struct *tty, struct file * filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-	unsigned char *transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
-	
-	dbg("visor_serial_close port %d", portNumber);
-			 
-	if (!transfer_buffer) {
-		err("visor_serial_close: kmalloc(%d) failed.", 0x12);
-	} else {
-		/* send a shutdown message to the device */
-		usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION,
-				0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
-	}
-
-	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (&port->write_urb);
-	usb_unlink_urb (&port->read_urb);
-	port->active = 0;
-}
-
-
-static void visor_throttle (struct tty_struct * tty)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
-	int port = MINOR(tty->device) - serial->minor;
-
-	dbg("visor_throttle port %d", port);
-
-	usb_unlink_urb (&serial->port[port].read_urb);
-
-	return;
-}
-
-
-static void visor_unthrottle (struct tty_struct * tty)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
-	int port = MINOR(tty->device) - serial->minor;
-
-	dbg("visor_unthrottle port %d", port);
-
-	if (usb_unlink_urb (&serial->port[port].read_urb))
-		dbg("usb_submit_urb(read bulk) failed");
-
-	return;
-}
-
-
-static int  visor_startup (struct usb_serial *serial)
-{
-	int response;
-	int i;
-	unsigned char *transfer_buffer =  kmalloc (256, GFP_KERNEL);
-
-	if (!transfer_buffer) {
-		err("visor_startup: kmalloc(%d) failed.", 256);
-		return -ENOMEM;
-	}
-
-	dbg("visor_startup");
-
-	dbg("visor_setup: Set config to 1");
-	usb_set_configuration (serial->dev, 1);
-
-	/* send a get connection info request */
-	response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_GET_CONNECTION_INFORMATION,
-					0xc2, 0x0000, 0x0000, transfer_buffer, 0x12, 300);
-	if (response < 0) {
-		err("visor_startup: error getting connection information");
-	} else {
-		struct visor_connection_info *connection_info = (struct visor_connection_info *)transfer_buffer;
-		char *string;
-		info("%s: Number of ports: %d", serial->type->name, connection_info->num_ports);
-		for (i = 0; i < connection_info->num_ports; ++i) {
-			switch (connection_info->connections[i].port_function_id) {
-				case VISOR_FUNCTION_GENERIC:
-					string = "Generic";
-					break;
-				case VISOR_FUNCTION_DEBUGGER:
-					string = "Debugger";
-					break;
-				case VISOR_FUNCTION_HOTSYNC:
-					string = "HotSync";
-					break;
-				case VISOR_FUNCTION_CONSOLE:
-					string = "Console";
-					break;
-				case VISOR_FUNCTION_REMOTE_FILE_SYS:
-					string = "Remote File System";
-					break;
-				default:
-					string = "unknown";
-					break;	
-			}
-			info("%s: port %d, is for %s use and is bound to ttyUSB%d", serial->type->name, connection_info->connections[i].port, string, serial->minor + i);
-		}
-	}
-
-	/* ask for the number of bytes available, but ignore the response as it is broken */
-	response = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_REQUEST_BYTES_AVAILABLE,
-					0xc2, 0x0000, 0x0005, transfer_buffer, 0x02, 300);
-	if (response < 0) {
-		err("visor_startup: error getting bytes available request");
-	}
-
-	kfree (transfer_buffer);
-
-	/* continue on with initialization */
-	return (0);
-}
-
-
-#endif	/* CONFIG_USB_SERIAL_VISOR*/
-
-
-#ifdef CONFIG_USB_SERIAL_FTDI_SIO
-/******************************************************************************
- * FTDI SIO Serial Converter specific driver functions
- ******************************************************************************/
-
-/* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */
-/* Thanx to FTDI for so kindly providing details of the protocol required */
-/*   to talk to the device */
-
-#include "ftdi_sio.h"
-
-static int  ftdi_sio_serial_open (struct tty_struct *tty, struct file *filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-	char buf[1]; /* Needed for the usb_control_msg I think */
-
-	dbg("ftdi_sio_serial_open port %d", portNumber);
-
-	if (port->active) {
-		dbg ("device already open");
-		return -EINVAL;
-	}
-	port->active = 1;
-
-	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
-			FTDI_SIO_RESET_SIO, 
-			0, buf, 0, HZ * 5);
-
-	/* FIXME - Should I really purge the buffers? */
-	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
-			FTDI_SIO_RESET_PURGE_RX, 
-			0, buf, 0, HZ * 5);
-
-	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, 
-			FTDI_SIO_RESET_PURGE_TX, 
-			0, buf, 0, HZ * 5);	
-
-
-	/* As per usb_serial_init s/be CS8, B9600, 1 STOP BIT */
-	if ( usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			     FTDI_SIO_SET_BAUDRATE_REQUEST,
-			     FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
-			     ftdi_sio_b9600, 0, 
-			     buf, 0, HZ * 5) < 0){
-		dbg("Error from baudrate urb");
-		return(-EINVAL);
-	}
-
-	if ( usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			     FTDI_SIO_SET_DATA_REQUEST, 
-			     FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			     8 | FTDI_SIO_SET_DATA_PARITY_NONE | 
-			     FTDI_SIO_SET_DATA_STOP_BITS_1, 0,
-			     buf, 0, HZ * 5) < 0){
-		dbg("Error from cs8/noparity/1 stopbit urb");
-		return(-EINVAL);
-	}
-
-	/* Disable flow control */
-	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			    FTDI_SIO_SET_FLOW_CTRL_REQUEST, 
-			    FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-			    0, 0, 
-			    buf, 0, HZ * 5) < 0) {
-		dbg("error from flowcontrol urb");
-		return(-EINVAL);
-	}	    
-
-	/* Turn on RTS and DTR since we are not flow controlling*/
-	/* FIXME - check for correct behaviour clocal vs non clocal */
-	/* FIXME - might be able to do both simultaneously */
-	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			    FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
-			    FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			    (unsigned)FTDI_SIO_SET_DTR_HIGH, 0, 
-			    buf, 0, HZ * 5) < 0) {
-		dbg("Error from DTR HIGH urb");
-	}
-	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			    FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
-			    FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			    (unsigned)FTDI_SIO_SET_RTS_HIGH, 0, 
-			    buf, 0, HZ * 5) < 0) {
-		dbg("Error from RTS HIGH urb");
-	}
-	
-	/*Start reading from the device*/
-	if (usb_submit_urb(&port->read_urb))
-		dbg("usb_submit_urb(read bulk) failed");
-
-	return (0);
-}
-
-
-static void ftdi_sio_serial_close (struct tty_struct *tty, struct file *filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-	char buf[1];
-
-	dbg("ftdi_sio_serial_close port %d", portNumber);
-	
-	/* FIXME - might be able to do both simultaneously */
-	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			    FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
-			    FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			    (unsigned)FTDI_SIO_SET_DTR_LOW, 0, 
-			    buf, 0, HZ * 5) < 0) {
-		dbg("Error from DTR LOW urb");
-	}
-	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			    FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
-			    FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-			    (unsigned)FTDI_SIO_SET_RTS_LOW, 0, 
-			    buf, 0, HZ * 5) < 0) {
-		dbg("Error from RTS LOW urb");
-	}	
-
-	/* FIXME Should I flush the device here? - not doing it for now */
-
-	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (&port->write_urb);
-	usb_unlink_urb (&port->read_urb);
-	port->active = 0;
-}
-
-
-  
-/* The ftdi_sio requires the first byte to have:
-   B0 1
-   B1 0
-   B2..7 length of message excluding byte 0
-*/
-static int ftdi_sio_serial_write (struct tty_struct * tty, int from_user, 
-				  const unsigned char *buf, int count)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-	const int data_offset = 1;
-
-	dbg("ftdi_sio_serial_write port %d, %d bytes", portNumber, count);
-
-	if (count == 0) {
-		dbg("write request of 0 bytes");
-		return 0;
-	}
-
-	/* only do something if we have a bulk out endpoint */
-	if (serial->num_bulk_out) {
-		unsigned char *first_byte = port->write_urb.transfer_buffer;
-
-		if (port->write_urb.status == -EINPROGRESS) {
-			dbg ("already writing");
-			return 0;
-		}
-
-		count += data_offset;
-		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-		if (count == 0) {
-			return 0;
-		}
-
-		/* Copy in the data to send */
-		if (from_user) {
-			copy_from_user(port->write_urb.transfer_buffer + data_offset , 
-				       buf, count - data_offset );
-		}
-		else {
-			memcpy(port->write_urb.transfer_buffer + data_offset,
-			       buf, count - data_offset );
-		}  
-
-		/* Write the control byte at the front of the packet*/
-		first_byte = port->write_urb.transfer_buffer;
-		*first_byte = 1 | ((count-data_offset) << 2) ; 
-
-#ifdef DEBUG
-		dbg("Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]);
-
-		if (count) {
-			int i;
-			printk (KERN_DEBUG __FILE__ ": data written - length = %d, data = ", count);
-			for (i = 0; i < count; ++i) {
-				printk ("0x%02x ", first_byte[i]);
-				if (first_byte[i] > ' ' && first_byte[i] < '~') {
-					printk("%c ", first_byte[i]);
-				} else {
-					printk("  ");
-				}
-			}
-
-		     
-			printk ("\n");
-		}
-
-#endif
-		/* send the data out the bulk port */
-		port->write_urb.transfer_buffer_length = count;
-
-		if (usb_submit_urb(&port->write_urb))
-			dbg("usb_submit_urb(write bulk) failed");
-
-		dbg("write returning: %d", count - data_offset);
-		return (count - data_offset);
-	}
-	
-	/* no bulk out, so return 0 bytes written */
-	return 0;
-} 
-
-
-static void ftdi_sio_read_bulk_callback (struct urb *urb)
-{ /* ftdi_sio_serial_buld_callback */
-	struct usb_serial *serial = (struct usb_serial *)urb->context;
-       	struct tty_struct *tty = serial->tty; 
-       	unsigned char *data = urb->transfer_buffer;
-	const int data_offset = 2;
-	int i;
-
-	dbg("ftdi_sio_read_bulk_callback");
-
-	if (urb->status) {
-		dbg("nonzero read bulk status received: %d", urb->status);
-		return;
-	}
-
-#ifdef DEBUG
-	if (urb->actual_length > 2) {
-		printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length);
-		for (i = 0; i < urb->actual_length; ++i) {
-			printk ("0x%.2x ", data[i]);
-			if (data[i] > ' ' && data[i] < '~') {
-				printk("%c ", data[i]);
-			} else {
-				printk("  ");
-			}
-		}
-		printk ("\n");
-	}
-#endif
-	
-
-	if (urb->actual_length > data_offset) {
-		for (i = data_offset ; i < urb->actual_length ; ++i) {
-			tty_insert_flip_char(tty, data[i], 0);
-	  	}
-	  	tty_flip_buffer_push(tty);
-	}
-
-	/* Continue trying to always read  */
-	if (usb_submit_urb(urb))
-		dbg("failed resubmitting read urb");
-
-	return;
-} /* ftdi_sio_serial_read_bulk_callback */
-
-
-static void ftdi_sio_set_termios (struct tty_struct *tty, struct termios *old_termios)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-	unsigned int cflag = tty->termios->c_cflag;
-	__u16 urb_value; /* Will hold the new flags */
-	char buf[1]; /* Perhaps I should dynamically alloc this? */
-	dbg("ftdi_sio_set_termios port %d", port);
-
-	/* FIXME - we should keep the old termios really */
-	/* FIXME -For this cut I don't care if the line is really changing or 
-	   not  - so just do the change regardless */
-	
-	/* Set number of data bits, parity, stop bits */
-	
-	urb_value = 0;
-	urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 :
-		      FTDI_SIO_SET_DATA_STOP_BITS_1);
-	urb_value |= (cflag & PARENB ? 
-		      (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : 
-		       FTDI_SIO_SET_DATA_PARITY_EVEN) :
-		      FTDI_SIO_SET_DATA_PARITY_NONE);
-	if (cflag & CSIZE) {
-		switch (cflag & CSIZE) {
-		case CS5: urb_value |= 5; dbg("Setting CS5"); break;
-		case CS6: urb_value |= 6; dbg("Setting CS6"); break;
-		case CS7: urb_value |= 7; dbg("Setting CS7"); break;
-		case CS8: urb_value |= 8; dbg("Setting CS8"); break;
-		default:
-			dbg("CSIZE was set but not CS5-CS8");
-		}
-	}
-	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			    FTDI_SIO_SET_DATA_REQUEST, 
-			    FTDI_SIO_SET_DATA_REQUEST_TYPE,
-			    urb_value , 0,
-			    buf, 0, 100) < 0) {
-		dbg("FAILED to set databits/stopbits/parity");
-	}	   
-
-	/* Now do the baudrate */
-	/* FIXME - should drop lines on B0 */
-	/* FIXME Should also handle CLOCAL here  */
-     
-	switch(cflag & CBAUD){
-	case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break;
-	case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break;
-	case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break;
-	case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break;
-	case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break;
-	case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break;
-	case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break;
-	case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break;
-	case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break;
-	case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break;
-	default: dbg("FTDI_SIO does not support the baudrate requested"); 
-		/* FIXME - how to return an error for this? */ break;
-	}
-	/* Send the URB */
-	if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			    FTDI_SIO_SET_BAUDRATE_REQUEST, 
-			    FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE,
-			    urb_value, 0, 
-			    buf, 0, 100) < 0) {
-		dbg("urb failed to set baurdrate");
-	}
-	return;
-}
-
-
-/*FIXME - the beginnings of this implementation - not even hooked into the driver yet */
-static int ftdi_sio_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-	__u16 urb_value=0; /* Will hold the new flags */
-	char buf[1];
-	int  ret, mask;
-	dbg("ftdi_sio_ioctl port %d", port);
-
-	/* Based on code from acm.c */
-	switch (cmd) {
-
-		case TIOCMGET:
-			/* Request the status from the device */
-			if ((ret = usb_control_msg(serial->dev, 
-					    usb_sndctrlpipe(serial->dev, 0),
-					    FTDI_SIO_GET_MODEM_STATUS_REQUEST, 
-					    FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE,
-					    0, 0, 
-					    buf, 1, HZ * 5)) < 0 ) {
-				dbg("Get not get modem status of device");
-				return(ret);
-			}
-
-			return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) |
-					(buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) |
-					(buf[0]  & FTDI_SIO_RI_MASK  ? TIOCM_RI  : 0) |
-					(buf[0]  & FTDI_SIO_RLSD_MASK ? TIOCM_CD  : 0),
-					(unsigned long *) arg);
-			break;
-
-		case TIOCMSET:
-		case TIOCMBIS:
-		case TIOCMBIC:
-			if ((ret = get_user(mask, (unsigned long *) arg))) return ret;
-
-			/* FIXME Need to remember if we have set DTR or RTS since we
-			   can't ask the device  */
-			/* FIXME - also need to find the meaning of TIOCMBIS/BIC/SET */
-			if (mask & TIOCM_DTR) {
-				switch(cmd) {
-				case TIOCMSET:
-					urb_value = FTDI_SIO_SET_DTR_HIGH | FTDI_SIO_SET_RTS_LOW;
-					break;
-
-				case TIOCMBIS:
-					/* Will leave RTS alone and set DTR */
-					urb_value =  FTDI_SIO_SET_DTR_HIGH;
-					break;
-					
-				case TIOCMBIC:
-					urb_value = FTDI_SIO_SET_DTR_LOW;
-					break;
-				}
-			}
-
-			if (mask & TIOCM_RTS) {
-				switch(cmd) {
-				case TIOCMSET:
-					urb_value = FTDI_SIO_SET_DTR_LOW | FTDI_SIO_SET_RTS_HIGH;
-					break;
-
-				case TIOCMBIS:
-					/* Will leave DTR and set RTS */
-					urb_value = FTDI_SIO_SET_RTS_HIGH;
-					break;
-
-				case TIOCMBIC:
-					/* Will unset RTS */
-					urb_value = FTDI_SIO_SET_RTS_LOW;
-					break;
-				}
-			}	
-
-			
-			return(usb_control_msg(serial->dev, 
-					       usb_sndctrlpipe(serial->dev, 0),
-					       FTDI_SIO_SET_MODEM_CTRL_REQUEST, 
-					       FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE,
-					       urb_value , 0,
-					       buf, 0, HZ * 5));
-	}
-
-	return -ENOIOCTLCMD;
-}
-
-#endif	/* CONFIG_USB_SERIAL_FTDI_SIO */
-
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
-/*****************************************************************************
- * Keyspan PDA specific driver functions
- *****************************************************************************/
-
-static void keyspan_pda_rx_interrupt (struct urb *urb)
-{
-	struct usb_serial *serial = (struct usb_serial *) urb->context;
-	struct tty_struct *tty = serial->tty;
-	unsigned char *data = urb->transfer_buffer;
-	int i;
-
-	/* the urb might have been killed. */
-	if (urb->status)
-		return;
-	
-	/* see if the message is data or a status interrupt */
-	switch (data[0]) {
-	case 0:
-		/* rest of message is rx data */
-		if (urb->actual_length) {
-			for (i = 1; i < urb->actual_length ; ++i) {
-				tty_insert_flip_char(tty, data[i], 0);
-			}
-			tty_flip_buffer_push(tty);
-		}
-		break;
-	case 1:
-		/* status interrupt */
-		dbg(" rx int, d1=%d, d2=%d", data[1], data[2]);
-		switch (data[1]) {
-		case 1: /* modemline change */
-			break;
-		case 2: /* tx unthrottle interrupt */
-			serial->tx_throttled = 0;
-			wake_up(&serial->write_wait); /* wake up writer */
-			break;
-		default:
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-
-	/* INT urbs are automatically re-submitted */
-}
-
-
-static void keyspan_pda_rx_throttle (struct tty_struct *tty)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-
-	/* stop receiving characters. We just turn off the URB request, and
-	   let chars pile up in the device. If we're doing hardware
-	   flowcontrol, the device will signal the other end when its buffer
-	   fills up. If we're doing XON/XOFF, this would be a good time to
-	   send an XOFF, although it might make sense to foist that off
-	   upon the device too. */
-
-	dbg("keyspan_pda_rx_throttle port %d", port);
-	usb_unlink_urb(&serial->port[port].read_urb);
-}
-
-
-static void keyspan_pda_rx_unthrottle (struct tty_struct *tty)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-
-	/* just restart the receive interrupt URB */
-	dbg("keyspan_pda_rx_unthrottle port %d", port);
-	if (usb_submit_urb(&serial->port[port].read_urb))
-		dbg(" usb_submit_urb(read urb) failed");
-	return;
-}
-
-
-static int keyspan_pda_setbaud (struct usb_serial *serial, int baud)
-{
-	int rc;
-	int bindex;
-
-	switch(baud) {
-		case 110: bindex = 0; break;
-		case 300: bindex = 1; break;
-		case 1200: bindex = 2; break;
-		case 2400: bindex = 3; break;
-		case 4800: bindex = 4; break;
-		case 9600: bindex = 5; break;
-		case 19200: bindex = 6; break;
-		case 38400: bindex = 7; break;
-		case 57600: bindex = 8; break;
-		case 115200: bindex = 9; break;
-		default: return -EINVAL;
-	}
-
-	/* rather than figure out how to sleep while waiting for this
-	   to complete, I just use the "legacy" API. */
-	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			     0, /* set baud */
-			     USB_TYPE_VENDOR 
-			     | USB_RECIP_INTERFACE
-			     | USB_DIR_OUT, /* type */
-			     bindex, /* value */
-			     0, /* index */
-			     NULL, /* &data */
-			     0, /* size */
-			     2*HZ); /* timeout */
-	return(rc);
-}
-
-
-static void keyspan_pda_break_ctl (struct tty_struct *tty, int break_state)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
-	int value;
-	if (break_state == -1)
-		value = 1; /* start break */
-	else
-		value = 0; /* clear break */
-	usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			4, /* set break */
-			USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			value, 0, NULL, 0, 2*HZ);
-	/* there is something funky about this.. the TCSBRK that 'cu' performs
-	   ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
-	   seconds apart, but it feels like the break sent isn't as long as it
-	   is on /dev/ttyS0 */
-}
-
-
-static void keyspan_pda_set_termios (struct tty_struct *tty,
-				     struct termios *old_termios)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	unsigned int cflag = tty->termios->c_cflag;
-
-	/* cflag specifies lots of stuff: number of stop bits, parity, number
-	   of data bits, baud. What can the device actually handle?:
-	   CSTOPB (1 stop bit or 2)
-	   PARENB (parity)
-	   CSIZE (5bit .. 8bit)
-	   There is minimal hw support for parity (a PSW bit seems to hold the
-	   parity of whatever is in the accumulator). The UART either deals
-	   with 10 bits (start, 8 data, stop) or 11 bits (start, 8 data,
-	   1 special, stop). So, with firmware changes, we could do:
-	   8N1: 10 bit
-	   8N2: 11 bit, extra bit always (mark?)
-	   8[EOMS]1: 11 bit, extra bit is parity
-	   7[EOMS]1: 10 bit, b0/b7 is parity
-	   7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?)
-
-	   HW flow control is dictated by the tty->termios->c_cflags & CRTSCTS
-	   bit.
-
-	   For now, just do baud. */
-
-	switch (cflag & CBAUD) {
-		/* we could support more values here, just need to calculate
-		   the necessary divisors in the firmware. <asm/termbits.h>
-		   has the Bnnn constants. */
-		case B110: keyspan_pda_setbaud(serial, 110); break;
-		case B300: keyspan_pda_setbaud(serial, 300); break;
-		case B1200: keyspan_pda_setbaud(serial, 1200); break;
-		case B2400: keyspan_pda_setbaud(serial, 2400); break;
-		case B4800: keyspan_pda_setbaud(serial, 4800); break;
-		case B9600: keyspan_pda_setbaud(serial, 9600); break;
-		case B19200: keyspan_pda_setbaud(serial, 19200); break;
-		case B38400: keyspan_pda_setbaud(serial, 38400); break;
-		case B57600: keyspan_pda_setbaud(serial, 57600); break;
-		case B115200: keyspan_pda_setbaud(serial, 115200); break;
-		default: dbg("can't handle requested baud rate"); break;
-	}
-}
-
-
-/* modem control pins: DTR and RTS are outputs and can be controlled.
-   DCD, RI, DSR, CTS are inputs and can be read. All outputs can also be
-   read. The byte passed is: DTR(b7) DCD RI DSR CTS RTS(b2) unused unused */
-
-static int keyspan_pda_get_modem_info(struct usb_serial *serial,
-				      unsigned char *value)
-{
-	int rc;
-	unsigned char data;
-	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-			     3, /* get pins */
-			     USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN,
-			     0, 0, &data, 1, 2*HZ);
-	if (rc > 0)
-		*value = data;
-	return rc;
-}
-
-
-static int keyspan_pda_set_modem_info(struct usb_serial *serial,
-				      unsigned char value)
-{
-	int rc;
-	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-			     3, /* set pins */
-			     USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_OUT,
-			     value, 0, NULL, 0, 2*HZ);
-	return rc;
-}
-
-
-static int keyspan_pda_ioctl(struct tty_struct *tty, struct file *file,
-			     unsigned int cmd, unsigned long arg)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data;
-	int rc;
-	unsigned int value;
-	unsigned char status, mask;
-
-	switch (cmd) {
-	case TIOCMGET: /* get modem pins state */
-		rc = keyspan_pda_get_modem_info(serial, &status);
-		if (rc < 0)
-			return rc;
-		value =
-			((status & (1<<7)) ? TIOCM_DTR : 0) |
-			((status & (1<<6)) ? TIOCM_CAR : 0) |
-			((status & (1<<5)) ? TIOCM_RNG : 0) |
-			((status & (1<<4)) ? TIOCM_DSR : 0) |
-			((status & (1<<3)) ? TIOCM_CTS : 0) |
-			((status & (1<<2)) ? TIOCM_RTS : 0);
-		if (copy_to_user((unsigned int *)arg, &value, sizeof(int)))
-			return -EFAULT;
-		return 0;
-	case TIOCMSET: /* set a state as returned by MGET */
-		if (copy_from_user(&value, (unsigned int *)arg, sizeof(int)))
-			return -EFAULT;
-		status =
-			((value & TIOCM_DTR) ? (1<<7) : 0) |
-			((value & TIOCM_CAR) ? (1<<6) : 0) |
-			((value & TIOCM_RNG) ? (1<<5) : 0) |
-			((value & TIOCM_DSR) ? (1<<4) : 0) |
-			((value & TIOCM_CTS) ? (1<<3) : 0) |
-			((value & TIOCM_RTS) ? (1<<2) : 0);
-		rc = keyspan_pda_set_modem_info(serial, status);
-		if (rc < 0)
-			return rc;
-		return 0;
-	case TIOCMBIS: /* set bits in bitmask <arg> */
-	case TIOCMBIC: /* clear bits from bitmask <arg> */
-		if (copy_from_user(&value, (unsigned int *)arg, sizeof(int)))
-			return -EFAULT;
-		rc = keyspan_pda_get_modem_info(serial, &status);
-		if (rc < 0)
-			return rc;
-		mask =
-			((value & TIOCM_RTS) ? (1<<2) : 0) |
-			((value & TIOCM_DTR) ? (1<<7) : 0);
-		if (cmd == TIOCMBIS)
-			status |= mask;
-		else
-			status &= ~mask;
-		rc = keyspan_pda_set_modem_info(serial, status);
-		if (rc < 0)
-			return rc;
-		return 0;
-	case TIOCMIWAIT:
-		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
-		/* TODO */
-	case TIOCGICOUNT:
-		/* return count of modemline transitions */
-		return 0; /* TODO */
-	}
-	
-	return -ENOIOCTLCMD;
-}
-
-static int keyspan_pda_write(struct tty_struct * tty, int from_user, 
-			     const unsigned char *buf, int count)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int port = MINOR(tty->device) - serial->minor;
-	int request_unthrottle = 0;
-	int rc = 0;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/* guess how much room is left in the device's ring buffer, and if we
-	   want to send more than that, check first, updating our notion of
-	   what is left. If our write will result in no room left, ask the
-	   device to give us an interrupt when the room available rises above
-	   a threshold, and hold off all writers (eventually, those using
-	   select() or poll() too) until we receive that unthrottle interrupt.
-	   Block if we can't write anything at all, otherwise write as much as
-	   we can. */
-
-	if (count == 0) {
-		dbg(" write request of 0 bytes");
-		return (0);
-	}
-
-	/* we might block because of:
-	   the TX urb is in-flight (wait until it completes)
-	   the device is full (wait until it says there is room)
-	*/
-	while (serial->port[port].write_urb.status == -EINPROGRESS) {
-		if (0 /* file->f_flags & O_NONBLOCK */) {
-			rc = -EAGAIN;
-			goto err;
-		}
-		interruptible_sleep_on(&serial->write_wait);
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			goto err;
-		}
-	}
-
-	/* at this point the URB is in our control, nobody else can submit it
-	   again (the only sudden transition was the one from EINPROGRESS to
-	   finished) */
-
-	/* the next potential block is that our TX process might be throttled.
-	   The transition from throttled->not happens because of an Rx
-	   interrupt, and the wake_up occurs during the same interrupt, so we
-	   have to be careful to avoid a race that would cause us to sleep
-	   forever. */
-
-	add_wait_queue(&serial->write_wait, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	while (serial->tx_throttled) {
-		/* device can't accomodate any more characters. Sleep until it
-		   can. Woken up by an Rx interrupt message, which clears
-		   tx_throttled first. */
-		dbg(" tx_throttled, going to sleep");
-		if (signal_pending(current)) {
-			current->state = TASK_RUNNING;
-			remove_wait_queue(&serial->write_wait, &wait);
-			dbg(" woke up because of signal");
-			rc = -ERESTARTSYS;
-			goto err;
-		}
-		schedule();
-		dbg(" woke up");
-	}
-	remove_wait_queue(&serial->write_wait, &wait);
-	set_current_state(TASK_RUNNING);
-
-	count = (count > serial->port[port].bulk_out_size) ? 
-		serial->port[port].bulk_out_size : count;
-	if (count > serial->tx_room) {
-		unsigned char room;
-		/* Looks like we might overrun the Tx buffer. Ask the device
-		   how much room it really has */
-		rc = usb_control_msg(serial->dev, 
-				     usb_rcvctrlpipe(serial->dev, 0),
-				     6, /* write_room */
-				     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
-				     | USB_DIR_IN,
-				     0, /* value: 0 means "remaining room" */
-				     0, /* index */
-				     &room,
-				     1,
-				     2*HZ);
-		if (rc < 0) {
-			dbg(" roomquery failed");
-			return rc; /* failed */
-		}
-		if (rc == 0) {
-			dbg(" roomquery returned 0 bytes");
-			return -EIO; /* device didn't return any data */
-		}
-		dbg(" roomquery says %d", room);
-		serial->tx_room = room;
-		if (count > serial->tx_room) {
-			/* we're about to completely fill the Tx buffer, so
-			   we'll be throttled afterwards. */
-			count = serial->tx_room;
-			request_unthrottle = 1;
-		}
-	}
-	serial->tx_room -= count;
-
-	if (count) {
-		/* now transfer data */
-		if (from_user) {
-			copy_from_user(serial->port[port].write_urb.transfer_buffer,
-				       buf, count);
-		}
-		else {
-			memcpy (serial->port[port].write_urb.transfer_buffer, 
-				buf, count);
-		}  
-		/* send the data out the bulk port */
-		serial->port[port].write_urb.transfer_buffer_length = count;
-		
-		if (usb_submit_urb(&serial->port[port].write_urb))
-			dbg(" usb_submit_urb(write bulk) failed");
-	}
-	else {
-		/* There wasn't any room left, so we are throttled until
-		   the buffer empties a bit */
-		request_unthrottle = 1;
-	}
-
-	if (request_unthrottle) {
-		dbg(" request_unthrottle");
-		/* ask the device to tell us when the tx buffer becomes
-		   sufficiently empty */
-		serial->tx_throttled = 1; /* block writers */
-		rc = usb_control_msg(serial->dev, 
-				     usb_sndctrlpipe(serial->dev, 0),
-				     7, /* request_unthrottle */
-				     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
-				     | USB_DIR_OUT,
-				     16, /* value: threshold */
-				     0, /* index */
-				     NULL,
-				     0,
-				     2*HZ);
-	}
-
-	return (count);
- err:
-	return (rc);
-}
-
-
-static void keyspan_pda_write_bulk_callback (struct urb *urb)
-{
-	struct usb_serial *serial = (struct usb_serial *) urb->context;
-	struct tty_struct *tty = serial->tty; 
-
-	wake_up_interruptible(&serial->write_wait);
-
-	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 keyspan_pda_write_room (struct tty_struct *tty)
-{
-	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
-
-	/* used by n_tty.c for processing of tabs and such. Giving it our
-	   conservative guess is probably good enough, but needs testing by
-	   running a console through the device. */
-
-	return (serial->tx_room);
-}
-
-
-static int keyspan_pda_chars_in_buffer (struct tty_struct *tty) 
-{
-	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
-	unsigned char count;
-	int rc;
-
-	/* used by tty stuff to wait for output to drain. Go ask the
-	   device how much is still queued in the tx ring */
-	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-			     6, /* write_room */
-			     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
-			     | USB_DIR_IN,
-			     1, /* value: 1 means chars_in_buffer */
-			     0, /* index */
-			     &count,
-			     1,
-			     2*HZ);
-	if (rc < 0)
-		return rc; /* failed */
-	if (rc == 0)
-		return -EIO; /* device didn't return any data */
-	return (count);
-}
-
-
-static int keyspan_pda_serial_open (struct tty_struct *tty, struct file *filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-	unsigned char room;
-	int rc;
-
-	if (port->active) {
-		return -EINVAL;
-	}
-	port->active = 1;
- 
-	/* find out how much room is in the Tx ring */
-	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
-			     6, /* write_room */
-			     USB_TYPE_VENDOR | USB_RECIP_INTERFACE
-			     | USB_DIR_IN,
-			     0, /* value */
-			     0, /* index */
-			     &room,
-			     1,
-			     2*HZ);
-	if (rc < 0) {
-		dbg(" roomquery failed");
-		return rc; /* failed */
-	}
-	if (rc == 0) {
-		dbg(" roomquery returned 0 bytes");
-		return -EIO; /* device didn't return any data */
-	}
-	serial->tx_room = room;
-	serial->tx_throttled = room ? 0 : 1;
-
-	/* the normal serial device seems to always turn on DTR and RTS here,
-	   so do the same */
-	if (tty->termios->c_cflag & CBAUD)
-		keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2) );
-	else
-		keyspan_pda_set_modem_info(serial, 0);
-
-	/*Start reading from the device*/
-	if (usb_submit_urb(&port->read_urb))
-		dbg(" usb_submit_urb(read int) failed");
-
-	return (0);
-}
-
-
-static void keyspan_pda_serial_close(struct tty_struct *tty, 
-				     struct file *filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-
-	/* the normal serial device seems to always shut off DTR and RTS now */
-	if (tty->termios->c_cflag & HUPCL)
-		keyspan_pda_set_modem_info(serial, 0);
-
-	/* shutdown our bulk reads and writes */
-	usb_unlink_urb (&port->write_urb);
-	usb_unlink_urb (&port->read_urb);
-	port->active = 0;
-}
-
-
-/* download the firmware to a "fake" device (pre-renumeration) */
-static int keyspan_pda_fake_startup (struct usb_serial *serial)
-{
-	int response;
-	const struct ezusb_hex_record *record;
-
-	/* download the firmware here ... */
-	response = ezusb_set_reset(serial, 1);
-
-	record = &keyspan_pda_firmware[0];
-	while(record->address != 0xffff) {
-		response = ezusb_writememory(serial, record->address,
-					     (unsigned char *)record->data,
-					     record->data_size, 0xa0);
-		if (response < 0) {
-			err("ezusb_writememory failed for Keyspan PDA "
-			    "firmware (%d %04X %p %d)",
-			    response, 
-			    record->address, record->data, record->data_size);
-			break;
-		}
-		record++;
-	}
-	/* bring device out of reset. Renumeration will occur in a moment
-	   and the new device will bind to the real driver */
-	response = ezusb_set_reset(serial, 0);
-
-	/* we want this device to fail to have a driver assigned to it. */
-	return (1);
-}
-
-
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int keyspan_pda_startup (struct usb_serial *serial)
-{
-	struct usb_endpoint_descriptor *intin;
-	intin = serial->port[0].interrupt_in_endpoint;
-
-	/* set up the receive interrupt urb */
-	FILL_INT_URB(&serial->port[0].read_urb, serial->dev,
-		     usb_rcvintpipe(serial->dev, intin->bEndpointAddress),
-		     serial->port[0].interrupt_in_buffer,
-		     intin->wMaxPacketSize,
-		     keyspan_pda_rx_interrupt,
-		     serial,
-		     intin->bInterval);
-
-	init_waitqueue_head(&serial->write_wait);
-	
-	return (0);
-}
-
-#endif	/* CONFIG_USB_SERIAL_KEYSPAN_PDA */
-
-
-/*****************************************************************************
- * generic devices specific driver functions
- *****************************************************************************/
-static int generic_serial_open (struct tty_struct *tty, struct file *filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-
-	dbg("generic_serial_open port %d", portNumber);
-
-	if (port->active) {
-		dbg ("device already open");
-		return -EINVAL;
-	}
-	port->active = 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(&port->read_urb))
-			dbg("usb_submit_urb(read bulk) failed");
-	}
-
-	return (0);
-}
-
-
-static void generic_serial_close(struct tty_struct *tty, struct file * filp)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-
-	dbg("generic_serial_close port %d", portNumber);
-	
-	/* shutdown any bulk reads that might be going on */
-	if (serial->num_bulk_out) {
-		usb_unlink_urb (&port->write_urb);
-	}
-	if (serial->num_bulk_in) {
-		usb_unlink_urb (&port->read_urb);
-	}
-
-	port->active = 0;
-}
-
-
-static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count)
-{
-	struct usb_serial *serial = (struct usb_serial *) tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-
-	dbg("generic_serial_write port %d", portNumber);
-
-	if (count == 0) {
-		dbg("write request of 0 bytes");
-		return (0);
-	}
-
-	/* only do something if we have a bulk out endpoint */
-	if (serial->num_bulk_out) {
-		if (port->write_urb.status == -EINPROGRESS) {
-			dbg ("already writing");
-			return (0);
-		}
-
-		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-
-		if (from_user) {
-			copy_from_user(port->write_urb.transfer_buffer, buf, count);
-		}
-		else {
-			memcpy (port->write_urb.transfer_buffer, buf, count);
-		}  
-
-		/* send the data out the bulk port */
-		port->write_urb.transfer_buffer_length = count;
-
-		if (usb_submit_urb(&port->write_urb))
-			dbg("usb_submit_urb(write bulk) failed");
-
-		return (count);
-	}
-	
-	/* no bulk out, so return 0 bytes written */
-	return (0);
-} 
-
-
-static int generic_write_room (struct tty_struct *tty) 
-{
-	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-	int room;
-
-	dbg("generic_write_room port %d", portNumber);
-	
-	if (serial->num_bulk_out) {
-		if (port->write_urb.status == -EINPROGRESS)
-			room = 0;
-		else
-			room = port->bulk_out_size;
-		dbg("generic_write_room returns %d", room);
-		return (room);
-	}
-	
-	return (0);
-}
-
-
-static int generic_chars_in_buffer (struct tty_struct *tty) 
-{
-	struct usb_serial *serial = (struct usb_serial *)tty->driver_data; 
-	int portNumber = MINOR(tty->device) - serial->minor;
-	struct usb_serial_port *port = &serial->port[portNumber];
-
-	dbg("generic_chars_in_buffer port %d", portNumber);
-	
-	if (serial->num_bulk_out) {
-		if (port->write_urb.status == -EINPROGRESS) {
-			return (port->bulk_out_size);
-		}
-	}
-
-	return (0);
-}
-
-
-static void generic_throttle (struct tty_struct *tty) 
-{
-	/* do nothing for the generic device */
-	return;
-}
-
-
-static void generic_unthrottle (struct tty_struct *tty) 
-{
-	/* do nothing for the generic device */
-	return;
-}
-
-
-static int generic_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg)
-{
-	/* generic driver doesn't support any ioctls yet */
-	return -ENOIOCTLCMD;
-}
-
-
-static void generic_set_termios (struct tty_struct *tty, struct termios * old)
-{
-	/* generic driver doesn't really care about setting any line settings */
-	return;
-}
-
-
-static void generic_read_bulk_callback (struct urb *urb)
-{
-	struct usb_serial *serial = (struct usb_serial *)urb->context;
-       	struct tty_struct *tty = serial->tty; 
-       	unsigned char *data = urb->transfer_buffer;
-	int i;
-
-	dbg("generic_read_bulk_callback");
-
-	if (urb->status) {
-		dbg("nonzero read bulk status received: %d", urb->status);
-		return;
-	}
-
-#ifdef DEBUG
-	if (urb->actual_length) {
-		printk (KERN_DEBUG __FILE__ ": data read - length = %d, data = ", urb->actual_length);
-		for (i = 0; i < urb->actual_length; ++i) {
-			printk ("%.2x ", data[i]);
-		}
-		printk ("\n");
-	}
-#endif
-	
-	if (urb->actual_length) {
-		for (i = 0; i < urb->actual_length ; ++i) {
-			 tty_insert_flip_char(tty, data[i], 0);
-	  	}
-	  	tty_flip_buffer_push(tty);
-	}
-
-	/* Continue trying to always read  */
-	if (usb_submit_urb(urb))
-		dbg("failed resubmitting read urb");
-
-	return;
-}
-
-
-static void generic_write_bulk_callback (struct urb *urb)
-{
-	struct usb_serial *serial = (struct usb_serial *) urb->context; 
-       	struct tty_struct *tty = serial->tty; 
-
-	dbg("generic_write_bulk_callback");
-
-	if (urb->status) {
-		dbg("nonzero write bulk status received: %d", urb->status);
-		return;
-	}
-
-	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
-		(tty->ldisc.write_wakeup)(tty);
-
-	wake_up_interruptible(&tty->write_wait);
-	
-	return;
-}
-
-
-
-static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
-{
-	struct usb_serial *serial = NULL;
-	struct usb_serial_port *port;
-	struct usb_interface_descriptor *interface;
-	struct usb_endpoint_descriptor *endpoint;
-	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 minor;
-	int buffer_size;
-	int i;
-	char interrupt_pipe;
-	char bulk_in_pipe;
-	char bulk_out_pipe;
-	int num_interrupt_in = 0;
-	int num_bulk_in = 0;
-	int num_bulk_out = 0;
-	int num_ports;
-	
-	/* loop through our list of known serial converters, and see if this device matches */
-	device_num = 0;
-	while (usb_serial_devices[device_num] != NULL) {
-		type = usb_serial_devices[device_num];
-		dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct));
-
-		/* look at the device descriptor */
-		if ((dev->descriptor.idVendor == *(type->idVendor)) &&
-		    (dev->descriptor.idProduct == *(type->idProduct))) {
-
-			dbg("descriptor matches...looking at the endpoints");
-
-			/* descriptor matches, let's try to find the endpoints needed */
-			interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
-			
-			/* check out the endpoints */
-			interface = &dev->actconfig->interface[ifnum].altsetting[0];
-			for (i = 0; i < interface->bNumEndpoints; ++i) {
-				endpoint = &interface->endpoint[i];
-		
-				if ((endpoint->bEndpointAddress & 0x80) &&
-				    ((endpoint->bmAttributes & 3) == 0x02)) {
-					/* we found a bulk in endpoint */
-					dbg("found bulk in");
-					bulk_in_pipe = HAS;
-					bulk_in_endpoint[num_bulk_in] = endpoint;
-					++num_bulk_in;
-				}
-
-				if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
-				    ((endpoint->bmAttributes & 3) == 0x02)) {
-					/* we found a bulk out endpoint */
-					dbg("found bulk out");
-					bulk_out_pipe = HAS;
-					bulk_out_endpoint[num_bulk_out] = endpoint;
-					++num_bulk_out;
-				}
-		
-				if ((endpoint->bEndpointAddress & 0x80) &&
-				    ((endpoint->bmAttributes & 3) == 0x03)) {
-					/* we found a interrupt in endpoint */
-					dbg("found interrupt in");
-					interrupt_pipe = HAS;
-					interrupt_in_endpoint[num_interrupt_in] = endpoint;
-					++num_interrupt_in;
-				}
-
-			}
-	
-			/* verify that we found all of the endpoints that we need */
-			if ((interrupt_pipe & type->needs_interrupt_in) &&
-			    (bulk_in_pipe & type->needs_bulk_in) &&
-			    (bulk_out_pipe & type->needs_bulk_out)) {
-				/* found all that we need */
-				info("%s converter detected", type->name);
-
-#ifdef CONFIG_USB_SERIAL_GENERIC
-				if (type == &generic_device)
-					num_ports = num_bulk_out;
-				else
-#endif
-					num_ports = type->num_ports;
-
-				serial = get_free_serial (num_ports, &minor);
-				if (serial == NULL) {
-					err("No more free serial devices");
-					return NULL;
-				}
-	
-			       	serial->dev = dev;
-				serial->type = type;
-				serial->minor = minor;
-				serial->num_ports = num_ports;
-				serial->num_bulk_in = num_bulk_in;
-				serial->num_bulk_out = num_bulk_out;
-				serial->num_interrupt_in = num_interrupt_in;
-
-				/* collect interrupt_in endpoints now, because
-				   the keyspan_pda startup function needs
-				   to know about them */
-				for (i = 0; i < num_interrupt_in; ++i) {
-					port = &serial->port[i];
-					buffer_size = interrupt_in_endpoint[i]->wMaxPacketSize;
-					port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
-					if (!port->interrupt_in_buffer) {
-						err("Couldn't allocate interrupt_in_buffer");
-						goto probe_error;
-					}
-					port->interrupt_in_endpoint = interrupt_in_endpoint[i];
-				}
-
-				/* if this device type has a startup function, call it */
-				if (type->startup) {
-					if (type->startup (serial)) {
-						return_serial (serial);
-						return NULL;
-					}
-				}
-
-				/* set up the endpoint information */
-				for (i = 0; i < num_bulk_in; ++i) {
-					port = &serial->port[i];
-					buffer_size = bulk_in_endpoint[i]->wMaxPacketSize;
-					port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
-					if (!port->bulk_in_buffer) {
-						err("Couldn't allocate bulk_in_buffer");
-						goto probe_error;
-					}
-					if (serial->type->read_bulk_callback) {
-						FILL_BULK_URB(&port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
-								port->bulk_in_buffer, buffer_size, serial->type->read_bulk_callback, serial);
-					} else {
-						FILL_BULK_URB(&port->read_urb, dev, usb_rcvbulkpipe (dev, bulk_in_endpoint[i]->bEndpointAddress),
-								port->bulk_in_buffer, buffer_size, generic_read_bulk_callback, serial);
-					}
-				}
-
-				for (i = 0; i < num_bulk_out; ++i) {
-					port = &serial->port[i];
-					port->bulk_out_size = bulk_out_endpoint[i]->wMaxPacketSize;
-					port->bulk_out_buffer = kmalloc (port->bulk_out_size, GFP_KERNEL);
-					if (!port->bulk_out_buffer) {
-						err("Couldn't allocate bulk_out_buffer");
-						goto probe_error;
-					}
-					if (serial->type->write_bulk_callback) {
-						FILL_BULK_URB(&port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
-								port->bulk_out_buffer, port->bulk_out_size, serial->type->write_bulk_callback, serial);
-					} else {
-						FILL_BULK_URB(&port->write_urb, dev, usb_sndbulkpipe (dev, bulk_out_endpoint[i]->bEndpointAddress),
-								port->bulk_out_buffer, port->bulk_out_size, generic_write_bulk_callback, serial);
-					}
-				}
-
-#if 0 /* use this code when WhiteHEAT is up and running */
-				for (i = 0; i < num_interrupt_in; ++i) {
-					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
-
-				for (i = 0; i < serial->num_ports; ++i) {
-					info("%s converter now attached to ttyUSB%d", type->name, serial->minor + i);
-				}
-
-				MOD_INC_USE_COUNT;
-
-				return serial;
-			} else {
-				info("descriptors matched, but endpoints did not");
-			}
-		}
-
-		/* look at the next type in our list */
-		++device_num;
-	}
-
-probe_error:
-	if (serial) {
-		for (i = 0; i < num_bulk_in; ++i)
-			if (serial->port[i].bulk_in_buffer[i])
-				kfree (serial->port[i].bulk_in_buffer);
-		for (i = 0; i < num_bulk_out; ++i)
-			if (serial->port[i].bulk_out_buffer)
-				kfree (serial->port[i].bulk_out_buffer);
-		for (i = 0; i < num_interrupt_in; ++i)
-			if (serial->port[i].interrupt_in_buffer)
-				kfree (serial->port[i].interrupt_in_buffer);
-		
-		/* return the minor range that this device had */
-		return_serial (serial);
-
-		/* free up any memory that we allocated */
-		kfree (serial);
-	}
-	return NULL;
-}
-
-
-static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
-{
-	struct usb_serial *serial = (struct usb_serial *) ptr;
-	struct usb_serial_port *port;
-	int i;
-
-	if (serial) {
-		/* need to stop any transfers...*/
-		for (i = 0; i < serial->num_ports; ++i) {
-			port = &serial->port[i];
-			usb_unlink_urb (&port->write_urb);
-			usb_unlink_urb (&port->read_urb);
-			port->active = 0;
-		}
-
-		/* free up any memory that we allocated */
-		for (i = 0; i < serial->num_bulk_in; ++i) {
-			port = &serial->port[i];
-			if (port->bulk_in_buffer)
-				kfree (port->bulk_in_buffer);
-		}
-		for (i = 0; i < serial->num_bulk_out; ++i) {
-			port = &serial->port[i];
-			if (port->bulk_out_buffer)
-				kfree (port->bulk_out_buffer);
-		}
-		for (i = 0; i < serial->num_interrupt_in; ++i) {
-			port = &serial->port[i];
-			if (port->interrupt_in_buffer)
-				kfree (port->interrupt_in_buffer);
-		}
-
-		for (i = 0; i < serial->num_ports; ++i) {
-			info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->minor + i);
-		}
-
-		/* return the minor range that this device had */
-		return_serial (serial);
-
-		/* free up any memory that we allocated */
-		kfree (serial);
-
-	} else {
-		info("device disconnected");
-	}
-	
-	MOD_DEC_USE_COUNT;
-}
-
-
-static struct tty_driver serial_tty_driver = {
-	magic:			TTY_DRIVER_MAGIC,
-	driver_name:		"usb",
-	name:			"ttyUSB",
-	major:			SERIAL_TTY_MAJOR,
-	minor_start:		0,
-	num:			SERIAL_TTY_MINORS,
-	type:			TTY_DRIVER_TYPE_SERIAL,
-	subtype:		SERIAL_TYPE_NORMAL,
-	flags:			TTY_DRIVER_REAL_RAW,
-	refcount:		&serial_refcount,
-	table:			serial_tty,
-	proc_entry:		NULL,
-	other:			NULL,
-	termios:		serial_termios,
-	termios_locked:		serial_termios_locked,
-	
-	open:			serial_open,
-	close:			serial_close,
-	write:			serial_write,
-	put_char:		NULL,
-	flush_chars:		NULL,
-	write_room:		serial_write_room,
-	ioctl:			serial_ioctl,
-	set_termios:		serial_set_termios,
-	set_ldisc:		NULL, 
-	throttle:		serial_throttle,
-	unthrottle:		serial_unthrottle,
-	stop:			NULL,
-	start:			NULL,
-	hangup:			NULL,
-	break_ctl:		serial_break,
-	wait_until_sent:	NULL,
-	send_xchar:		NULL,
-	read_proc:		NULL,
-	chars_in_buffer:	serial_chars_in_buffer,
-	flush_buffer:		NULL
-};
-
-
-int usb_serial_init(void)
-{
-	int i;
-
-	/* Initalize our global data */
-	for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
-		serial_table[i] = NULL;
-	}
-
-	/* register the tty driver */
-	serial_tty_driver.init_termios		= tty_std_termios;
-	serial_tty_driver.init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	if (tty_register_driver (&serial_tty_driver)) {
-		err("failed to register tty driver");
-		return -EPERM;
-	}
-	
-	/* register the USB driver */
-	if (usb_register(&usb_serial_driver) < 0) {
-		tty_unregister_driver(&serial_tty_driver);
-		return -1;
-	}
-
-	info("support registered");
-	return 0;
-}
-
-
-void usb_serial_exit(void)
-{
-	tty_unregister_driver(&serial_tty_driver);
-	usb_deregister(&usb_serial_driver);
-}
-
-
-module_init(usb_serial_init);
-module_exit(usb_serial_exit);
-
-
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb-serial.h linux/drivers/usb/usb-serial.h
--- v2.3.50/linux/drivers/usb/usb-serial.h	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/usb-serial.h	Wed Dec 31 16:00:00 1969
@@ -1,436 +0,0 @@
-/*
- * USB Serial Converter driver
- *
- *	(C) Copyright (C) 1999, 2000
- *	    Greg Kroah-Hartman (greg@kroah.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.
- *
- * See Documentation/usb/usb-serial.txt for more information on using this driver
- * 
- */
-
-
-#ifndef __LINUX_USB_SERIAL_H
-#define __LINUX_USB_SERIAL_H
-
-#include <linux/config.h>
-
-/* Module information */
-MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
-MODULE_DESCRIPTION("USB Serial Driver");
-
-#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
-
-
-/* USB Serial devices vendor ids and device ids that this driver supports */
-#define CONNECT_TECH_VENDOR_ID		0x0710
-#define CONNECT_TECH_FAKE_WHITE_HEAT_ID	0x0001
-#define CONNECT_TECH_WHITE_HEAT_ID	0x8001
-#define HANDSPRING_VENDOR_ID		0x082d
-#define HANDSPRING_VISOR_ID		0x0100
-#define FTDI_VENDOR_ID			0x0403
-#define FTDI_SIO_SERIAL_CONVERTER_ID	0x8372
-#define KEYSPAN_VENDOR_ID		0x06cd
-#define KEYSPAN_PDA_FAKE_ID		0x0103
-#define KEYSPAN_PDA_ID			0x0104 /* no clue */
-
-#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 */
-
-
-#define MAX_NUM_PORTS	8	/* The maximum number of ports one device can grab at once */
-
-
-struct usb_serial_port {
-	struct usb_serial	*serial;	/* pointer back to the owner of this port */
-	struct tty_struct *	tty;		/* the coresponding tty for this device */
-	unsigned char		minor;
-	unsigned char		number;
-	char			active;		/* someone has this device open */
-
-	struct usb_endpoint_descriptor * interrupt_in_endpoint;
-	__u8			interrupt_in_interval;
-	unsigned char *		interrupt_in_buffer;
-	struct urb		control_urb;
-
-	unsigned char *		bulk_in_buffer;
-	struct urb		read_urb;
-
-	unsigned char *		bulk_out_buffer;
-	int			bulk_out_size;
-	struct urb		write_urb;
-	void *			private;	/* data private to the specific driver */
-};
-
-struct usb_serial {
-	struct usb_device *		dev;
-	struct usb_serial_device_type *	type;
-	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				num_interrupt_in;	/* number of interrupt in endpoints we have */
-	char				num_bulk_in;		/* number of bulk in endpoints we have */
-	char				num_bulk_out;		/* number of bulk out endpoints we have */
-	struct usb_serial_port		port[MAX_NUM_PORTS];
-
-	/* FIXME! These should move to the private area of the keyspan driver */
-	int			tx_room;
-	int			tx_throttled;
-	wait_queue_head_t 	write_wait;
-
-	void *			private;		/* data private to the specific driver */
-};
-
-
-#define MUST_HAVE_NOT	0x01
-#define MUST_HAVE	0x02
-#define DONT_CARE	0x03
-
-#define	HAS		0x02
-#define HAS_NOT		0x01
-
-#define NUM_DONT_CARE	(-1)
-
-
-/* This structure defines the individual serial converter. */
-struct usb_serial_device_type {
-	char	*name;
-	__u16	*idVendor;
-	__u16	*idProduct;
-	char	needs_interrupt_in;
-	char	needs_bulk_in;
-	char	needs_bulk_out;
-	char	num_interrupt_in;
-	char	num_bulk_in;
-	char	num_bulk_out;
-	char	num_ports;		/* number of serial ports this device has */
-
-	/* function call to make before accepting driver */
-	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);
-	int  (*write_room)(struct tty_struct *tty);
-	int  (*ioctl)(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
-	void (*set_termios)(struct tty_struct *tty, struct termios * old);
-	void (*break_ctl)(struct tty_struct *tty, int break_state);
-	int  (*chars_in_buffer)(struct tty_struct *tty);
-	void (*throttle)(struct tty_struct * tty);
-	void (*unthrottle)(struct tty_struct * tty);
-	
-	void (*read_bulk_callback)(struct urb *urb);
-	void (*write_bulk_callback)(struct urb *urb);
-};
-
-
-/* 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. */
-/* if a driver does not provide a function pointer, the generic function will be called. */
-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 int  generic_write_room		(struct tty_struct *tty);
-static int  generic_ioctl		(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
-static void generic_set_termios		(struct tty_struct *tty, struct termios * old);
-static int  generic_chars_in_buffer	(struct tty_struct *tty);
-static void generic_throttle		(struct tty_struct *tty);
-static void generic_unthrottle		(struct tty_struct *tty);
-static void generic_read_bulk_callback	(struct urb *urb);
-static void generic_write_bulk_callback	(struct urb *urb);
-
-
-#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",
-	idVendor:		&vendor,		/* use the user specified vendor id */
-	idProduct:		&product,		/* use the user specified product id */
-	needs_interrupt_in:	DONT_CARE,		/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,		/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,		/* don't have to have a bulk out endpoint */
-	num_interrupt_in:	NUM_DONT_CARE,
-	num_bulk_in:		NUM_DONT_CARE,
-	num_bulk_out:		NUM_DONT_CARE,
-	num_ports:		1,
-};
-#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_set_termios	(struct tty_struct *tty, struct termios * old);
-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;
-static __u16	connecttech_whiteheat_fake_product_id	= CONNECT_TECH_FAKE_WHITE_HEAT_ID;
-static __u16	connecttech_whiteheat_product_id	= CONNECT_TECH_WHITE_HEAT_ID;
-static struct usb_serial_device_type whiteheat_fake_device = {
-	name:			"Connect Tech - WhiteHEAT - (prerenumeration)",
-	idVendor:		&connecttech_vendor_id,			/* the Connect Tech vendor id */
-	idProduct:		&connecttech_whiteheat_fake_product_id,	/* the White Heat initial product id */
-	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
-	num_interrupt_in:	NUM_DONT_CARE,
-	num_bulk_in:		NUM_DONT_CARE,
-	num_bulk_out:		NUM_DONT_CARE,
-	startup:		whiteheat_startup	
-};
-static struct usb_serial_device_type whiteheat_device = {
-	name:			"Connect Tech - WhiteHEAT",
-	idVendor:		&connecttech_vendor_id,			/* the Connect Tech vendor id */
-	idProduct:		&connecttech_whiteheat_product_id,	/* the White Heat real product id */
-	needs_interrupt_in:	DONT_CARE,				/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,				/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,				/* don't have to have a bulk out endpoint */
-	num_interrupt_in:	NUM_DONT_CARE,
-	num_bulk_in:		NUM_DONT_CARE,
-	num_bulk_out:		NUM_DONT_CARE,
-	num_ports:		4,
-	open:			whiteheat_serial_open,
-	close:			whiteheat_serial_close,
-	throttle:		whiteheat_throttle,
-	unthrottle:		whiteheat_unthrottle,
-	set_termios:		whiteheat_set_termios,
-};
-#endif
-
-
-#ifdef CONFIG_USB_SERIAL_VISOR
-
-/****************************************************************************
- * Handspring Visor Vendor specific request codes (bRequest values)
- * A big thank you to Handspring for providing the following information.
- * If anyone wants the original file where these values and structures came
- * from, send email to <greg@kroah.com>.
- ****************************************************************************/
-
-/****************************************************************************
- * VISOR_REQUEST_BYTES_AVAILABLE asks the visor for the number of bytes that
- * are available to be transfered to the host for the specified endpoint.
- * Currently this is not used, and always returns 0x0001
- ****************************************************************************/
-#define VISOR_REQUEST_BYTES_AVAILABLE		0x01
-
-/****************************************************************************
- * VISOR_CLOSE_NOTIFICATION is set to the device to notify it that the host
- * is now closing the pipe. An empty packet is sent in response.
- ****************************************************************************/
-#define VISOR_CLOSE_NOTIFICATION		0x02
-
-/****************************************************************************
- * VISOR_GET_CONNECTION_INFORMATION is sent by the host during enumeration to
- * get the endpoints used by the connection.
- ****************************************************************************/
-#define VISOR_GET_CONNECTION_INFORMATION	0x03
-
-
-/****************************************************************************
- * VISOR_GET_CONNECTION_INFORMATION returns data in the following format
- ****************************************************************************/
-struct visor_connection_info {
-	__u16	num_ports;
-	struct {
-		__u8	port_function_id;
-		__u8	port;
-	} connections[2];
-};
-
-
-/* struct visor_connection_info.connection[x].port defines: */
-#define VISOR_ENDPOINT_1		0x01
-#define VISOR_ENDPOINT_2		0x02
-
-/* struct visor_connection_info.connection[x].port_function_id defines: */
-#define VISOR_FUNCTION_GENERIC		0x00
-#define VISOR_FUNCTION_DEBUGGER		0x01
-#define VISOR_FUNCTION_HOTSYNC		0x02
-#define VISOR_FUNCTION_CONSOLE		0x03
-#define VISOR_FUNCTION_REMOTE_FILE_SYS	0x04
-
-
-/* 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;
-static __u16	handspring_product_id	= HANDSPRING_VISOR_ID;
-static struct usb_serial_device_type handspring_device = {
-	name:			"Handspring Visor",
-	idVendor:		&handspring_vendor_id,	/* the Handspring vendor ID */
-	idProduct:		&handspring_product_id,	/* the Handspring Visor product id */
-	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
-	num_interrupt_in:	0,
-	num_bulk_in:		2,
-	num_bulk_out:		2,
-	num_ports:		2,
-	open:			visor_serial_open,
-	close:			visor_serial_close,
-	throttle:		visor_throttle,
-	unthrottle:		visor_unthrottle,
-	startup:		visor_startup,
-};
-#endif
-
-
-#ifdef CONFIG_USB_SERIAL_FTDI_SIO
-/* function prototypes for a FTDI serial converter */
-static int  ftdi_sio_serial_open	(struct tty_struct *tty, struct file *filp);
-static void ftdi_sio_serial_close	(struct tty_struct *tty, struct file *filp);
-static int  ftdi_sio_serial_write	(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
-static void ftdi_sio_read_bulk_callback	(struct urb *urb);
-static void ftdi_sio_set_termios		(struct tty_struct *tty, struct termios * old);
-static int ftdi_sio_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg);
-
-/* All of the device info needed for the FTDI SIO serial converter */
-static __u16	ftdi_vendor_id		= FTDI_VENDOR_ID;
-static __u16	ftdi_sio_product_id	= FTDI_SIO_SERIAL_CONVERTER_ID;
-static struct usb_serial_device_type ftdi_sio_device = {
-	name:			"FTDI SIO",
-	idVendor:		&ftdi_vendor_id,	/* the FTDI vendor ID */
-	idProduct:		&ftdi_sio_product_id,	/* the FTDI SIO product id */
-	needs_interrupt_in:	MUST_HAVE_NOT,		/* this device must not have an interrupt in endpoint */
-	needs_bulk_in:		MUST_HAVE,		/* this device must have a bulk in endpoint */
-	needs_bulk_out:		MUST_HAVE,		/* this device must have a bulk out endpoint */
-	num_interrupt_in:	0,
-	num_bulk_in:		1,
-	num_bulk_out:		1,
-	num_ports:		1,
-	open:			ftdi_sio_serial_open,
-	close:			ftdi_sio_serial_close,
-	write:			ftdi_sio_serial_write,
-	read_bulk_callback:	ftdi_sio_read_bulk_callback,
-	set_termios:		ftdi_sio_set_termios
-};
-#endif
-
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
-/* function prototypes for a Keyspan PDA serial converter */
-static int  keyspan_pda_serial_open	(struct tty_struct *tty, 
-					 struct file *filp);
-static void keyspan_pda_serial_close	(struct tty_struct *tty, 
-					 struct file *filp);
-static int  keyspan_pda_startup		(struct usb_serial *serial);
-static void keyspan_pda_rx_throttle	(struct tty_struct *tty);
-static void keyspan_pda_rx_unthrottle	(struct tty_struct *tty);
-static int  keyspan_pda_setbaud		(struct usb_serial *serial, int baud);
-static int  keyspan_pda_write_room	(struct tty_struct *tty);
-static int  keyspan_pda_write		(struct tty_struct *tty,
-					 int from_user,
-					 const unsigned char *buf,
-					 int count);
-static void keyspan_pda_write_bulk_callback (struct urb *urb);
-static int  keyspan_pda_chars_in_buffer (struct tty_struct *tty);
-static int  keyspan_pda_ioctl		(struct tty_struct *tty,
-					 struct file *file,
-					 unsigned int cmd,
-					 unsigned long arg);
-static void keyspan_pda_set_termios	(struct tty_struct *tty,
-					 struct termios *old);
-static void keyspan_pda_break_ctl	(struct tty_struct *tty,
-					 int break_state);
-static int  keyspan_pda_fake_startup	(struct usb_serial *serial);
-
-/* All of the device info needed for the Keyspan PDA serial converter */
-static __u16	keyspan_vendor_id		= KEYSPAN_VENDOR_ID;
-static __u16	keyspan_pda_fake_product_id	= KEYSPAN_PDA_FAKE_ID;
-static __u16	keyspan_pda_product_id		= KEYSPAN_PDA_ID;
-static struct usb_serial_device_type keyspan_pda_fake_device = {
-	name:			"Keyspan PDA - (prerenumeration)",
-	idVendor:		&keyspan_vendor_id,		/* the Keyspan PDA vendor ID */
-	idProduct:		&keyspan_pda_fake_product_id,	/* the Keyspan PDA initial product id */
-	needs_interrupt_in:	DONT_CARE,			/* don't have to have an interrupt in endpoint */
-	needs_bulk_in:		DONT_CARE,			/* don't have to have a bulk in endpoint */
-	needs_bulk_out:		DONT_CARE,			/* don't have to have a bulk out endpoint */
-	num_interrupt_in:	NUM_DONT_CARE,
-	num_bulk_in:		NUM_DONT_CARE,
-	num_bulk_out:		NUM_DONT_CARE,
-	startup:		keyspan_pda_fake_startup
-};
-static struct usb_serial_device_type keyspan_pda_device = {
-	name:			"Keyspan PDA",
-	idVendor:		&keyspan_vendor_id,		/* the Keyspan PDA vendor ID */
-	idProduct:		&keyspan_pda_product_id,	/* the Keyspan PDA product id */
-	needs_interrupt_in:	MUST_HAVE,
-	needs_bulk_in:		DONT_CARE,
-	needs_bulk_out:		MUST_HAVE,
-	num_interrupt_in:	1,
-	num_bulk_in:		0,
-	num_bulk_out:		1,
-	num_ports:		1,
-	open:			keyspan_pda_serial_open,
-	close:			keyspan_pda_serial_close,
-	write:			keyspan_pda_write,
-	write_room:		keyspan_pda_write_room,
-	write_bulk_callback: 	keyspan_pda_write_bulk_callback,
-	chars_in_buffer:	keyspan_pda_chars_in_buffer,
-	throttle:		keyspan_pda_rx_throttle,
-	unthrottle:		keyspan_pda_rx_unthrottle,
-	startup:		keyspan_pda_startup,
-	ioctl:			keyspan_pda_ioctl,
-	set_termios:		keyspan_pda_set_termios,
-	break_ctl:		keyspan_pda_break_ctl,
-};
-#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_VISOR
-	&handspring_device,
-#endif
-#ifdef CONFIG_USB_SERIAL_FTDI_SIO
-	&ftdi_sio_device,
-#endif
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
-	&keyspan_pda_fake_device,
-	&keyspan_pda_device,
-#endif
-	NULL
-};
-
-
-/* determine if we should include the EzUSB loader functions */
-#if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_WHITEHEAT)
-	#define	USES_EZUSB_FUNCTIONS
-#else
-	#undef 	USES_EZUSB_FUNCTIONS
-#endif
-
-#endif	/* ifdef __LINUX_USB_SERIAL_H */
-
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb-storage.c linux/drivers/usb/usb-storage.c
--- v2.3.50/linux/drivers/usb/usb-storage.c	Sun Feb 20 21:12:39 2000
+++ linux/drivers/usb/usb-storage.c	Fri Mar 10 16:18:34 2000
@@ -30,13 +30,13 @@
 #include <linux/malloc.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
+#include <linux/usb.h>
 
 #include <linux/blk.h>
 #include "../scsi/scsi.h"
 #include "../scsi/hosts.h"
 #include "../scsi/sd.h"
 
-#include "usb.h"
 #include "usb-storage.h"
 #include "usb-storage-debug.h"
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- v2.3.50/linux/drivers/usb/usb-uhci.c	Wed Feb 16 17:03:52 2000
+++ linux/drivers/usb/usb-uhci.c	Fri Mar 10 16:18:34 2000
@@ -28,6 +28,9 @@
 #include <linux/unistd.h>
 #include <linux/interrupt.h>	/* for in_interrupt() */
 #include <linux/init.h>
+/* This enables debug printks */
+#define DEBUG
+#include <linux/usb.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -37,16 +40,12 @@
 /* This enables more detailed sanity checks in submit_iso */
 //#define ISO_SANITY_CHECK
 
-/* This enables debug printks */
-#define DEBUG
-
 /* This enables all symbols to be exported, to ease debugging oopses */
 //#define DEBUG_SYMBOLS
 
 /* This enables an extra UHCI slab for memory debugging */
 #define DEBUG_SLAB
 
-#include "usb.h"
 #include "usb-uhci.h"
 #include "usb-uhci-debug.h"
 
@@ -2408,7 +2407,7 @@
 		unsigned int io_addr = dev->resource[i].start;
 		unsigned int io_size =
 		dev->resource[i].end - dev->resource[i].start + 1;
-		if (!(dev->resource[i].flags & 1))
+		if (!(dev->resource[i].flags & IORESOURCE_IO))
 			continue;
 #else
 		unsigned int io_addr = dev->base_address[i];
@@ -2464,7 +2463,8 @@
 			continue;
 
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,8)
-		pci_enable_device (dev);
+		if (pci_enable_device (dev) < 0)
+			continue;
 #endif
 		if(!dev->irq)
 		{
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.3.50/linux/drivers/usb/usb.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/usb/usb.c	Fri Mar 10 16:18:34 2000
@@ -24,10 +24,8 @@
 #include <linux/bitops.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>  /* for in_interrupt() */
-
 #define DEBUG
-
-#include "usb.h"
+#include <linux/usb.h>
 
 /*
  * Prototypes for the device driver probing/loading functions
@@ -475,30 +473,34 @@
  * New USB Core Functions
  * -------------------------------------------------------------------------------------*/
 
-urb_t* usb_alloc_urb(int iso_packets)
+urb_t *usb_alloc_urb(int iso_packets)
 {
 	urb_t *urb;
-	urb=(urb_t*)kmalloc(sizeof(urb_t) + iso_packets*sizeof(iso_packet_descriptor_t),
+
+	urb = (urb_t *)kmalloc(sizeof(urb_t) + iso_packets * sizeof(iso_packet_descriptor_t),
 	      in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
-	if (!urb)
-	{
+	if (!urb) {
 		err("alloc_urb: kmalloc failed");
-		return 0;
+		return NULL;
 	}
-	memset(urb,0,sizeof(urb_t));
+
+	memset(urb, 0, sizeof(*urb));
+
+	spin_lock_init(&urb->lock);
+
 	return urb;
 }
 
 /*-------------------------------------------------------------------*/
 void usb_free_urb(urb_t* urb)
 {
-	if(urb)
+	if (urb)
 		kfree(urb);
 }
 /*-------------------------------------------------------------------*/
 int usb_submit_urb(urb_t *urb)
 {
-	if(urb && urb->dev)
+	if (urb && urb->dev)
 		return urb->dev->bus->op->submit_urb(urb);
 	else
 		return -1;
@@ -507,7 +509,7 @@
 /*-------------------------------------------------------------------*/
 int usb_unlink_urb(urb_t *urb)
 {
-	if(urb && urb->dev)
+	if (urb && urb->dev)
 		return urb->dev->bus->op->unlink_urb(urb);
 	else
 		return -1;
@@ -537,10 +539,10 @@
  *-------------------------------------------------------------------*/
 static void usb_api_async_completion(urb_t *urb)
 {
-	api_wrapper_data *awd=(api_wrapper_data*)urb->context;
+	api_wrapper_data *awd = (api_wrapper_data *)urb->context;
 
 	if (awd->handler)
-		awd->handler(urb->status,urb->transfer_buffer,urb->actual_length,awd->stuff);
+		awd->handler(urb->status, urb->transfer_buffer, urb->actual_length, awd->stuff);
  }
 
 /*-------------------------------------------------------------------*
@@ -555,13 +557,13 @@
 	api_wrapper_data awd;
 	int status;
   
-	awd.wakeup=&wqh;
-	awd.handler=0;
+	awd.wakeup = &wqh;
+	awd.handler = 0;
 	init_waitqueue_head(&wqh); 	
 	current->state = TASK_INTERRUPTIBLE;
 	add_wait_queue(&wqh, &wait);
-	urb->context=&awd;
-	status=usb_submit_urb(urb);
+	urb->context = &awd;
+	status = usb_submit_urb(urb);
 	if (status) {
 		// something went wrong
 		usb_free_urb(urb);
@@ -581,13 +583,12 @@
 		// timeout
 		printk("usb_control/bulk_msg: timeout\n");
 		usb_unlink_urb(urb);  // remove urb safely
-		status=-ETIMEDOUT;
-	}
-	else
-		status=urb->status;
+		status = -ETIMEDOUT;
+	} else
+		status = urb->status;
 
 	if (actual_length)
-		*actual_length=urb->actual_length;
+		*actual_length = urb->actual_length;
 
 	usb_free_urb(urb);
   	return status;
@@ -602,20 +603,21 @@
 	int retv;
 	int length;
 
-	urb=usb_alloc_urb(0);
+	urb = usb_alloc_urb(0);
 	if (!urb)
 		return -ENOMEM;
   
 	FILL_CONTROL_URB(urb, usb_dev, pipe, (unsigned char*)cmd, data, len,    /* build urb */  
 		   (usb_complete_t)usb_api_blocking_completion,0);
 
-	retv=usb_start_wait_urb(urb,timeout, &length);
+	retv = usb_start_wait_urb(urb, timeout, &length);
 	if (retv < 0)
 		return retv;
 	else
 		return length;
 	
 }
+
 /*-------------------------------------------------------------------*/
 int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype,
 			 __u16 value, __u16 index, void *data, __u16 size, int timeout)
@@ -623,7 +625,7 @@
 	devrequest *dr = kmalloc(sizeof(devrequest), GFP_KERNEL);
 	int ret;
 	
-	if(!dr)
+	if (!dr)
 		return -ENOMEM;
 
 	dr->requesttype = requesttype;
@@ -634,7 +636,7 @@
 
 	//dbg("usb_control_msg");	
 
-	ret=usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
+	ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout);
 
 	kfree(dr);
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usb.h linux/drivers/usb/usb.h
--- v2.3.50/linux/drivers/usb/usb.h	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/usb.h	Wed Dec 31 16:00:00 1969
@@ -1,783 +0,0 @@
-#ifndef __LINUX_USB_H
-#define __LINUX_USB_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-#include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>	/* for in_interrupt() */
-
-/* USB constants */
-
-/*
- * Device and/or Interface Class codes
- */
-#define USB_CLASS_PER_INTERFACE		0	/* for DeviceClass */
-#define USB_CLASS_AUDIO			1
-#define USB_CLASS_COMM			2
-#define USB_CLASS_HID			3
-#define USB_CLASS_PRINTER		7
-#define USB_CLASS_MASS_STORAGE		8
-#define USB_CLASS_HUB			9
-#define USB_CLASS_DATA			10
-#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
-#define USB_DT_CONFIG			0x02
-#define USB_DT_STRING			0x03
-#define USB_DT_INTERFACE		0x04
-#define USB_DT_ENDPOINT			0x05
-
-#define USB_DT_HID			(USB_TYPE_CLASS | 0x01)
-#define USB_DT_REPORT			(USB_TYPE_CLASS | 0x02)
-#define USB_DT_PHYSICAL			(USB_TYPE_CLASS | 0x03)
-#define USB_DT_HUB			(USB_TYPE_CLASS | 0x09)
-
-/*
- * Descriptor sizes per descriptor type
- */
-#define USB_DT_DEVICE_SIZE		18
-#define USB_DT_CONFIG_SIZE		9
-#define USB_DT_INTERFACE_SIZE		9
-#define USB_DT_ENDPOINT_SIZE		7
-#define USB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */
-#define USB_DT_HUB_NONVAR_SIZE		7
-#define USB_DT_HID_SIZE			9
-
-/*
- * Endpoints
- */
-#define USB_ENDPOINT_NUMBER_MASK	0x0f	/* in bEndpointAddress */
-#define USB_ENDPOINT_DIR_MASK		0x80
-
-#define USB_ENDPOINT_XFERTYPE_MASK	0x03	/* in bmAttributes */
-#define USB_ENDPOINT_XFER_CONTROL	0
-#define USB_ENDPOINT_XFER_ISOC		1
-#define USB_ENDPOINT_XFER_BULK		2
-#define USB_ENDPOINT_XFER_INT		3
-
-/*
- * USB Packet IDs (PIDs)
- */
-#define USB_PID_UNDEF_0                        0xf0
-#define USB_PID_OUT                            0xe1
-#define USB_PID_ACK                            0xd2
-#define USB_PID_DATA0                          0xc3
-#define USB_PID_UNDEF_4                        0xb4
-#define USB_PID_SOF                            0xa5
-#define USB_PID_UNDEF_6                        0x96
-#define USB_PID_UNDEF_7                        0x87
-#define USB_PID_UNDEF_8                        0x78
-#define USB_PID_IN                             0x69
-#define USB_PID_NAK                            0x5a
-#define USB_PID_DATA1                          0x4b
-#define USB_PID_PREAMBLE                       0x3c
-#define USB_PID_SETUP                          0x2d
-#define USB_PID_STALL                          0x1e
-#define USB_PID_UNDEF_F                        0x0f
-
-/*
- * Standard requests
- */
-#define USB_REQ_GET_STATUS		0x00
-#define USB_REQ_CLEAR_FEATURE		0x01
-#define USB_REQ_SET_FEATURE		0x03
-#define USB_REQ_SET_ADDRESS		0x05
-#define USB_REQ_GET_DESCRIPTOR		0x06
-#define USB_REQ_SET_DESCRIPTOR		0x07
-#define USB_REQ_GET_CONFIGURATION	0x08
-#define USB_REQ_SET_CONFIGURATION	0x09
-#define USB_REQ_GET_INTERFACE		0x0A
-#define USB_REQ_SET_INTERFACE		0x0B
-#define USB_REQ_SYNCH_FRAME		0x0C
-
-/*
- * HID requests
- */
-#define USB_REQ_GET_REPORT		0x01
-#define USB_REQ_GET_IDLE		0x02
-#define USB_REQ_GET_PROTOCOL		0x03
-#define USB_REQ_SET_REPORT		0x09
-#define USB_REQ_SET_IDLE		0x0A
-#define USB_REQ_SET_PROTOCOL		0x0B
-
-
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-#include <linux/list.h>
-
-#define USB_MAJOR 180
-
-/* for 2.2-kernels */
- 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
-
-static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
-{
-	__list_add(new, head->prev, head);
-}
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-typedef struct wait_queue wait_queue_t;
-
-typedef struct wait_queue *wait_queue_head_t;
-#define DECLARE_WAITQUEUE(wait, current) \
-	struct wait_queue wait = { current, NULL }
-#define DECLARE_WAIT_QUEUE_HEAD(wait)\
-	wait_queue_head_t wait
-
-#define init_waitqueue_head(x) *x=NULL
-#define init_MUTEX(x) *(x)=MUTEX
-#define DECLARE_MUTEX(name) struct semaphore name=MUTEX
-#define DECLARE_MUTEX_LOCKED(name) struct semaphore name=MUTEX_LOCKED
-
-
-#define __set_current_state(state_value)                        \
-	do { current->state = state_value; } while (0)
-#ifdef __SMP__
-#define set_current_state(state_value)          \
-	set_mb(current->state, state_value)
-#else
-#define set_current_state(state_value)          \
-	__set_current_state(state_value)
-#endif
-
-#endif // 2.2.x
-
-
-static __inline__ void wait_ms(unsigned int ms)
-{
-	if(!in_interrupt()) {
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout(1 + ms * HZ / 1000);
-	}
-	else
-		mdelay(ms);
-}
-
-typedef struct {
-	__u8 requesttype;
-	__u8 request;
-	__u16 value;
-	__u16 index;
-	__u16 length;
-} devrequest __attribute__ ((packed));
-
-/*
- * USB-status codes:
- * USB_ST* maps to -E* and should go away in the future
- */
-
-#define USB_ST_NOERROR		0
-#define USB_ST_CRC		(-EILSEQ)
-#define USB_ST_BITSTUFF		(-EPROTO)
-#define USB_ST_NORESPONSE	(-ETIMEDOUT)			/* device not responding/handshaking */
-#define USB_ST_DATAOVERRUN	(-EOVERFLOW)
-#define USB_ST_DATAUNDERRUN	(-EREMOTEIO)
-#define USB_ST_BUFFEROVERRUN	(-ECOMM)
-#define USB_ST_BUFFERUNDERRUN	(-ENOSR)
-#define USB_ST_INTERNALERROR	(-EPROTO) 			/* unknown error */
-#define USB_ST_SHORT_PACKET    	(-EREMOTEIO)
-#define USB_ST_PARTIAL_ERROR  	(-EXDEV)			/* ISO transfer only partially completed */
-#define USB_ST_URB_KILLED     	(-ENOENT)			/* URB canceled by user */
-#define USB_ST_URB_PENDING       (-EINPROGRESS)
-#define USB_ST_REMOVED		(-ENODEV) 			/* device not existing or removed */
-#define USB_ST_TIMEOUT		(-ETIMEDOUT)			/* communication timed out, also in urb->status**/
-#define USB_ST_NOTSUPPORTED	(-ENOSYS)			
-#define USB_ST_BANDWIDTH_ERROR	(-ENOSPC)			/* too much bandwidth used */
-#define USB_ST_URB_INVALID_ERROR  (-EINVAL)			/* invalid value/transfer type */
-#define USB_ST_URB_REQUEST_ERROR  (-ENXIO)			/* invalid endpoint */
-#define USB_ST_STALL		(-EPIPE) 			/* pipe stalled, also in urb->status*/
-
-/*
- * USB device number allocation bitmap. There's one bitmap
- * per USB tree.
- */
-struct usb_devmap {
-	unsigned long devicemap[128 / (8*sizeof(unsigned long))];
-};
-
-#define USB_MAXBUS		64
-
-struct usb_busmap {
-	unsigned long busmap[USB_MAXBUS / (8*sizeof(unsigned long))];
-};
-
-/*
- * This is a USB device descriptor.
- *
- * USB device information
- */
-
-/* Everything but the endpoint maximums are aribtrary */
-#define USB_MAXCONFIG		8
-#define USB_ALTSETTINGALLOC     4
-#define USB_MAXALTSETTING	128  /* Hard limit */
-#define USB_MAXINTERFACES	32
-#define USB_MAXENDPOINTS	32
-
-/* All standard descriptors have these 2 fields in common */
-struct usb_descriptor_header {
-	__u8  bLength;
-	__u8  bDescriptorType;
-} __attribute__ ((packed));
-
-/* Device descriptor */
-struct usb_device_descriptor {
-	__u8  bLength;
-	__u8  bDescriptorType;
-	__u16 bcdUSB;
-	__u8  bDeviceClass;
-	__u8  bDeviceSubClass;
-	__u8  bDeviceProtocol;
-	__u8  bMaxPacketSize0;
-	__u16 idVendor;
-	__u16 idProduct;
-	__u16 bcdDevice;
-	__u8  iManufacturer;
-	__u8  iProduct;
-	__u8  iSerialNumber;
-	__u8  bNumConfigurations;
-} __attribute__ ((packed));
-
-/* Endpoint descriptor */
-struct usb_endpoint_descriptor {
-	__u8  bLength;
-	__u8  bDescriptorType;
-	__u8  bEndpointAddress;
-	__u8  bmAttributes;
-	__u16 wMaxPacketSize;
-	__u8  bInterval;
-	__u8  bRefresh;
-	__u8  bSynchAddress;
-
-   	unsigned char *extra;   /* Extra descriptors */
-	int extralen;
-} __attribute__ ((packed));
-
-/* Interface descriptor */
-struct usb_interface_descriptor {
-	__u8  bLength;
-	__u8  bDescriptorType;
-	__u8  bInterfaceNumber;
-	__u8  bAlternateSetting;
-	__u8  bNumEndpoints;
-	__u8  bInterfaceClass;
-	__u8  bInterfaceSubClass;
-	__u8  bInterfaceProtocol;
-	__u8  iInterface;
-
-  	struct usb_endpoint_descriptor *endpoint;
-
-	unsigned char *extra;
-	int extralen;
-} __attribute__ ((packed));
-
-struct usb_interface {
-	struct usb_interface_descriptor *altsetting;
-
-	int act_altsetting;		/* active alternate setting */
-	int num_altsetting;		/* number of alternate settings */
-	int max_altsetting;             /* total memory allocated */
- 
-	struct usb_driver *driver;	/* driver */
-	void *private_data;
-};
-
-/* Configuration descriptor information.. */
-struct usb_config_descriptor {
-	__u8  bLength;
-	__u8  bDescriptorType;
-	__u16 wTotalLength;
-	__u8  bNumInterfaces;
-	__u8  bConfigurationValue;
-	__u8  iConfiguration;
-	__u8  bmAttributes;
-	__u8  MaxPower;
-
-	struct usb_interface *interface;
-} __attribute__ ((packed));
-
-/* String descriptor */
-struct usb_string_descriptor {
-	__u8  bLength;
-	__u8  bDescriptorType;
-	__u16 wData[1];
-} __attribute__ ((packed));
-
-struct usb_device;
-
-struct usb_driver {
-	const char *name;
-
-	void * (*probe)(struct usb_device *, unsigned int);
-	void (*disconnect)(struct usb_device *, void *);
-
-	struct list_head driver_list;
-
-	struct file_operations *fops;
-	int minor;
-};
-
-/*
- * Pointer to a device endpoint interrupt function -greg
- *   Parameters:
- *     int status - This needs to be defined.  Right now each HCD
- *         passes different transfer status bits back.  Don't use it
- *         until we come up with a common meaning.
- *     void *buffer - This is a pointer to the data used in this
- *         USB transfer.
- *     int length - This is the number of bytes transferred in or out
- *         of the buffer by this transfer.  (-1 = unknown/unsupported)
- *     void *dev_id - This is a user defined pointer set when the IRQ
- *         is requested that is passed back.
- *
- *   Special Cases:
- *     if (status == USB_ST_REMOVED), don't trust buffer or len.
- */
-typedef int (*usb_device_irq)(int, void *, int, void *);
-
-/* -------------------------------------------------------------------------------------* 
- * New USB Structures                                                                   *
- * -------------------------------------------------------------------------------------*/
-
-
-#define USB_DISABLE_SPD           1
-#define USB_ISO_ASAP              2
-#define USB_URB_EARLY_COMPLETE    4
-
-typedef struct
-{
-	unsigned int offset;
-	unsigned int length;		// expected length
-	unsigned int actual_length;
-	unsigned int status;
-} iso_packet_descriptor_t, *piso_packet_descriptor_t;
-
-struct urb;
-typedef void (*usb_complete_t)(struct urb *);
-
-typedef struct urb
-{
-	void *hcpriv;			// private data for host controller
-	struct list_head urb_list;	// list pointer to all active urbs 
-	struct urb* next;		// pointer to next URB	
-	struct usb_device *dev;		// pointer to associated USB device
-	unsigned int pipe;		// pipe information
-	int status;			// returned status
-	unsigned int transfer_flags;	// USB_DISABLE_SPD | USB_ISO_ASAP | USB_URB_EARLY_COMPLETE
-	void *transfer_buffer;		// associated data buffer
-	int transfer_buffer_length;	// data buffer length
-	int actual_length;              // actual data buffer length	
-	unsigned char* setup_packet;	// setup packet (control only)
-	//
-	int start_frame;		// start frame (iso/irq only)
-	int number_of_packets;		// number of packets in this request (iso/irq only)
-	int interval;                   // polling interval (irq only)
-	int error_count;		// number of errors in this transfer (iso only)
-	//
-	void *context;			// context for completion routine
-	usb_complete_t complete;	// pointer to completion routine
-	//
-	iso_packet_descriptor_t	 iso_frame_desc[0];
-} urb_t, *purb_t;
-
-#define FILL_CONTROL_URB(a,aa,b,c,d,e,f,g) \
-    do {\
-	(a)->dev=aa;\
-	(a)->pipe=b;\
-	(a)->setup_packet=c;\
-	(a)->transfer_buffer=d;\
-	(a)->transfer_buffer_length=e;\
-	(a)->complete=f;\
-	(a)->context=g;\
-    } while (0)
-
-#define FILL_BULK_URB(a,aa,b,c,d,e,f) \
-    do {\
-	(a)->dev=aa;\
-	(a)->pipe=b;\
-	(a)->transfer_buffer=c;\
-	(a)->transfer_buffer_length=d;\
-	(a)->complete=e;\
-	(a)->context=f;\
-    } while (0)
-    
-#define FILL_INT_URB(a,aa,b,c,d,e,f,g) \
-    do {\
-	(a)->dev=aa;\
-	(a)->pipe=b;\
-	(a)->transfer_buffer=c;\
-	(a)->transfer_buffer_length=d;\
-	(a)->complete=e;\
-	(a)->context=f;\
-	(a)->interval=g;\
-	(a)->start_frame=-1;\
-    } while (0)
-
-purb_t usb_alloc_urb(int iso_packets);
-void usb_free_urb (purb_t purb);
-int usb_submit_urb(purb_t purb);
-int usb_unlink_urb(purb_t purb);
-int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd,  void *data, int len, int timeout);
-int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout);
-
-/*-------------------------------------------------------------------*
- *                         COMPATIBILITY STUFF                       *
- *-------------------------------------------------------------------*/
-typedef struct
-{
-  wait_queue_head_t *wakeup;
-
-  usb_device_irq handler;
-  void* stuff;
-  /* more to follow */
-} api_wrapper_data;
-
-struct irq_wrapper_data {
-	void *context;
-	usb_device_irq handler;
-};
-
-/* ------------------------------------------------------------------------------------- */
-
-struct usb_operations {
-	int (*allocate)(struct usb_device *);
-	int (*deallocate)(struct usb_device *);
-	int (*get_frame_number) (struct usb_device *usb_dev);
-	int (*submit_urb) (struct urb* purb);
-	int (*unlink_urb) (struct urb* purb);
-};
-
-/*
- * Allocated per bus we have
- */
-struct usb_bus {
-	int busnum;			/* Bus number (in order of reg) */
-
-	struct usb_devmap devmap;       /* Device map */
-	struct usb_operations *op;      /* Operations (specific to the HC) */
-	struct usb_device *root_hub;    /* Root hub */
-	struct list_head bus_list;
-	void *hcpriv;                   /* Host Controller private data */
-
-	unsigned int bandwidth_allocated; /* on this Host Controller; */
-					  /* applies to Int. and Isoc. pipes; */
-					  /* measured in microseconds/frame; */
-					  /* range is 0..900, where 900 = */
-					  /* 90% of a 1-millisecond frame */
-	int bandwidth_int_reqs;		/* number of Interrupt requesters */
-	int bandwidth_isoc_reqs;	/* number of Isoc. requesters */
-
-	/* usbdevfs inode list */
-        struct list_head inodes;
-};
-
-#define USB_MAXCHILDREN (8)	/* This is arbitrary */
-
-struct usb_device {
-	int devnum;			/* Device number on USB bus */
-	int slow;			/* Slow device? */
-
-	atomic_t refcnt;		/* Reference count */
-
-	int maxpacketsize;		/* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
-	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
-	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */
-					/* [0] = IN, [1] = OUT */
-	struct usb_config_descriptor *actconfig;/* the active configuration */
-	int epmaxpacketin[16];		/* INput endpoint specific maximums */
-	int epmaxpacketout[16];		/* OUTput endpoint specific maximums */
-
-	struct usb_device *parent;
-	struct usb_bus *bus;		/* Bus we're part of */
-
-	struct usb_device_descriptor descriptor;/* Descriptor */
-	struct usb_config_descriptor *config;	/* All of the configs */
-
-	int have_langid;		/* whether string_langid is valid yet */
-	int string_langid;		/* language ID for strings */
-  
-	void *hcpriv;			/* Host Controller private data */
-	
-        /* usbdevfs inode list */
-        struct list_head inodes;
-        struct list_head filelist;
-
-	/*
-	 * Child devices - these can be either new devices
-	 * (if this is a hub device), or different instances
-	 * of this same device.
-	 *
-	 * Each instance needs its own set of data structures.
-	 */
-
-	int maxchild;			/* Number of ports if hub */
-	struct usb_device *children[USB_MAXCHILDREN];
-};
-
-extern int usb_register(struct usb_driver *);
-extern void usb_deregister(struct usb_driver *);
-
-/* used these for multi-interface device registration */
-extern void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv);
-extern int usb_interface_claimed(struct usb_interface *iface);
-extern void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface);
-
-extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
-extern void usb_free_bus(struct usb_bus *);
-extern void usb_register_bus(struct usb_bus *);
-extern void usb_deregister_bus(struct usb_bus *);
-
-extern struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *);
-extern void usb_free_dev(struct usb_device *);
-extern void usb_inc_dev_use(struct usb_device *);
-#define usb_dec_dev_use usb_free_dev
-extern void usb_release_bandwidth(struct usb_device *, int);
-
-extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
-
-extern int usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *, void **);
-extern int usb_release_irq(struct usb_device *dev, void *handle, unsigned int pipe);
-
-extern void *usb_request_bulk(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *);
-extern int usb_terminate_bulk(struct usb_device *, void *);
-
-extern void usb_init_root_hub(struct usb_device *dev);
-extern void usb_connect(struct usb_device *dev);
-extern void usb_disconnect(struct usb_device **);
-
-extern void usb_destroy_configuration(struct usb_device *dev);
-
-int usb_get_current_frame_number (struct usb_device *usb_dev);
-
-/*
- * Calling this entity a "pipe" is glorifying it. A USB pipe
- * is something embarrassingly simple: it basically consists
- * of the following information:
- *  - device number (7 bits)
- *  - endpoint number (4 bits)
- *  - current Data0/1 state (1 bit)
- *  - direction (1 bit)
- *  - speed (1 bit)
- *  - max packet size (2 bits: 8, 16, 32 or 64)
- *  - pipe type (2 bits: control, interrupt, bulk, isochronous)
- *
- * That's 18 bits. Really. Nothing more. And the USB people have
- * documented these eighteen bits as some kind of glorious
- * virtual data structure.
- *
- * Let's not fall in that trap. We'll just encode it as a simple
- * unsigned int. The encoding is:
- *
- *  - max size:		bits 0-1	(00 = 8, 01 = 16, 10 = 32, 11 = 64)
- *  - direction:	bit 7		(0 = Host-to-Device [Out], 1 = Device-to-Host [In])
- *  - device:		bits 8-14
- *  - endpoint:		bits 15-18
- *  - Data0/1:		bit 19
- *  - speed:		bit 26		(0 = Full, 1 = Low Speed)
- *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk)
- *
- * Why? Because it's arbitrary, and whatever encoding we select is really
- * up to us. This one happens to share a lot of bit positions with the UHCI
- * specification, so that much of the uhci driver can just mask the bits
- * appropriately.
- */
-
-#define PIPE_ISOCHRONOUS		0
-#define PIPE_INTERRUPT			1
-#define PIPE_CONTROL			2
-#define PIPE_BULK			3
-
-#define USB_ISOCHRONOUS		0
-#define USB_INTERRUPT		1
-#define USB_CONTROL		2
-#define USB_BULK		3
-
-#define usb_maxpacket(dev, pipe, out)	(out \
-				? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \
-				: (dev)->epmaxpacketin [usb_pipeendpoint(pipe)] )
-#define usb_packetid(pipe)	(((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT)
-
-#define usb_pipeout(pipe)	((((pipe) >> 7) & 1) ^ 1)
-#define usb_pipein(pipe)	(((pipe) >> 7) & 1)
-#define usb_pipedevice(pipe)	(((pipe) >> 8) & 0x7f)
-#define usb_pipe_endpdev(pipe)	(((pipe) >> 8) & 0x7ff)
-#define usb_pipeendpoint(pipe)	(((pipe) >> 15) & 0xf)
-#define usb_pipedata(pipe)	(((pipe) >> 19) & 1)
-#define usb_pipeslow(pipe)	(((pipe) >> 26) & 1)
-#define usb_pipetype(pipe)	(((pipe) >> 30) & 3)
-#define usb_pipeisoc(pipe)	(usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
-#define usb_pipeint(pipe)	(usb_pipetype((pipe)) == PIPE_INTERRUPT)
-#define usb_pipecontrol(pipe)	(usb_pipetype((pipe)) == PIPE_CONTROL)
-#define usb_pipebulk(pipe)	(usb_pipetype((pipe)) == PIPE_BULK)
-
-#define PIPE_DEVEP_MASK		0x0007ff00
-
-/* The D0/D1 toggle bits */
-#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1)
-#define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << ep))
-#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep))
-
-/* Endpoint halt control/status */
-#define usb_endpoint_out(ep_dir)	(((ep_dir >> 7) & 1) ^ 1)
-#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
-#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
-#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
-
-static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
-{
-	return (dev->devnum << 8) | (endpoint << 15) | (dev->slow << 26) | dev->maxpacketsize;
-}
-
-static inline unsigned int __default_pipe(struct usb_device *dev)
-{
-	return (dev->slow << 26);
-}
-
-/* Create various pipes... */
-#define usb_sndctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_sndisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#define usb_sndbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
-#define usb_rcvbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
-#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)
-#define usb_snddefctrl(dev)		((PIPE_CONTROL << 30) | __default_pipe(dev))
-#define usb_rcvdefctrl(dev)		((PIPE_CONTROL << 30) | __default_pipe(dev) | USB_DIR_IN)
-
-/*
- * Send and receive control messages..
- */
-int usb_new_device(struct usb_device *dev);
-int usb_set_address(struct usb_device *dev);
-int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
-	unsigned char descindex, void *buf, int size);
-int usb_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char desctype,
-	unsigned char descindex, void *buf, int size);
-int usb_get_device_descriptor(struct usb_device *dev);
-int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr);
-int usb_get_status(struct usb_device *dev, int type, int target, void *data);
-int usb_get_protocol(struct usb_device *dev, int ifnum);
-int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
-int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
-int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id);
-int usb_set_configuration(struct usb_device *dev, int configuration);
-int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
-	unsigned char id, void *buf, int size);
-int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type,
-	unsigned char id, void *buf, int size);
-int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
-int usb_clear_halt(struct usb_device *dev, int pipe);
-
-#define usb_get_extra_descriptor(ifpoint,type,ptr)\
-	__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,type,(void**)ptr)
-
-/*
- * Some USB bandwidth allocation constants.
- */
-#define BW_HOST_DELAY	1000L		/* nanoseconds */
-#define BW_HUB_LS_SETUP	333L		/* nanoseconds */
-                        /* 4 full-speed bit times (est.) */
-
-#define FRAME_TIME_BITS         12000L		/* frame = 1 millisecond */
-#define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
-#define FRAME_TIME_USECS	1000L
-#define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
-
-#define BitTime(bytecount)  (7 * 8 * bytecount / 6)  /* with integer truncation */
-		/* Trying not to use worst-case bit-stuffing
-                   of (7/6 * 8 * bytecount) = 9.33 * bytecount */
-		/* bytecount = data payload byte count */
-
-#define NS_TO_US(ns)	((ns + 500L) / 1000L)
-			/* convert & round nanoseconds to microseconds */
-
-/*
- * Debugging helpers..
- */
-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_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)
-#else
-#define dbg(format, arg...) do {} while (0)
-#endif
-#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
-#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg)
-#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg)
-
-
-/*
- * bus and driver list
- */
-
-extern struct list_head usb_driver_list;
-extern struct list_head usb_bus_list;
-
-/*
- * USB device fs stuff
- */
-
-#ifdef CONFIG_USB_DEVICEFS
-
-/*
- * these are expected to be called from the USB core/hub thread
- * with the kernel lock held
- */
-extern void usbdevfs_add_bus(struct usb_bus *bus);
-extern void usbdevfs_remove_bus(struct usb_bus *bus);
-extern void usbdevfs_add_device(struct usb_device *dev);
-extern void usbdevfs_remove_device(struct usb_device *dev);
-
-extern int usbdevfs_init(void);
-extern void usbdevfs_cleanup(void);
-
-#else /* CONFIG_USB_DEVICEFS */
-
-extern inline void usbdevfs_add_bus(struct usb_bus *bus) {}
-extern inline void usbdevfs_remove_bus(struct usb_bus *bus) {}
-extern inline void usbdevfs_add_device(struct usb_device *dev) {}
-extern inline void usbdevfs_remove_device(struct usb_device *dev) {}
-
-extern inline int usbdevfs_init(void) { return 0; }
-extern inline void usbdevfs_cleanup(void) { }
-
-#endif /* CONFIG_USB_DEVICEFS */
-
-#endif  /* __KERNEL__ */
-
-#endif
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- v2.3.50/linux/drivers/usb/usbkbd.c	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/usbkbd.c	Fri Mar 10 16:18:34 2000
@@ -33,7 +33,7 @@
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/init.h>
-#include "usb.h"
+#include <linux/usb.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c
--- v2.3.50/linux/drivers/usb/usbmouse.c	Sat Feb 26 22:31:50 2000
+++ linux/drivers/usb/usbmouse.c	Fri Mar 10 16:18:34 2000
@@ -33,7 +33,7 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include "usb.h"
+#include <linux/usb.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c
--- v2.3.50/linux/drivers/usb/uss720.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/usb/uss720.c	Fri Mar 10 16:18:34 2000
@@ -41,8 +41,7 @@
 #include <linux/socket.h>
 #include <linux/parport.h>
 #include <linux/init.h>
-
-#include "usb.h"
+#include <linux/usb.h>
 
 /* --------------------------------------------------------------------- */
 
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c
--- v2.3.50/linux/drivers/usb/wacom.c	Thu Mar  2 14:36:23 2000
+++ linux/drivers/usb/wacom.c	Fri Mar 10 16:18:34 2000
@@ -1,9 +1,10 @@
 /*
- *  wacom.c  Version 0.3
+ *  wacom.c  Version 0.4
  *
  *  Copyright (c) 2000 Vojtech Pavlik		<vojtech@suse.cz>
  *  Copyright (c) 2000 Andreas Bach Aaen	<abach@stofanet.dk>
  *  Copyright (c) 2000 Clifford Wolf		<clifford@clifford.at>
+ *  Copyright (c) 2000 Sam Mosel		<sam.mosel@computer.org>
  *
  *  USB Wacom Graphire and Wacom Intuos tablet support
  *
@@ -13,6 +14,8 @@
  *      v0.1 (vp)  - Initial release
  *      v0.2 (aba) - Support for all buttons / combinations
  *      v0.3 (vp)  - Support for Intuos added
+ *      v0.4 (sm)  - Support for more Intuos models, menustrip,
+ *                   relative mode, proximity.
  */
 
 /*
@@ -40,7 +43,7 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include "usb.h"
+#include <linux/usb.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 
@@ -72,16 +75,16 @@
  * 
  * (0,0) is upper left corner
  *
- * Wacom Intuos packet:
+ * Wacom Intuos Status packet:
  *
  *  byte 0: report ID (2)
- *  byte 1: bit7	1 ?
- *          bit6	tilt (pressure?) data valid
- *          bit5	near
+ *  byte 1: bit7	1 (Sync Byte)
+ *          bit6	Pointer Near
+ *          bit5	0 - first proximity report
  *          bit4 	0 ?
  *          bit3	0 ?
- *          bit2	pen button
- *          bit1	first packet (contains other infos)
+ *          bit2	pen button2
+ *          bit1	pen button1
  *          bit0	0 ?
  *  byte 2: X high bits
  *  byte 3: X low bits
@@ -92,22 +95,89 @@
  *  byte 7: bits 0-5:  X tilt  (bits 1-6)
  *  byte 8: bit    7:  X tilt  (bit  0)
  *  byte 8: bits 0-6:  Y tilt  (bits 0-6)
- *  byte 9: ?
+ *  byte 9: bits 4-7:  Proximity
  */
 
 #define USB_VENDOR_ID_WACOM		0x056a
 #define USB_DEVICE_ID_WACOM_GRAPHIRE	0x0010
-#define USB_DEVICE_ID_WACOM_INTUOS	0x0021
+#define USB_DEVICE_ID_WACOM_INTUOS45	0x0020 /* Guess */
+#define USB_DEVICE_ID_WACOM_INTUOS68	0x0021
+#define USB_DEVICE_ID_WACOM_INTUOS912	0x0022 /* Guess */
+#define USB_DEVICE_ID_WACOM_INTUOS1212	0x0023
+#define USB_DEVICE_ID_WACOM_INTUOS1218	0x0024 /* Guess */
+
+#define USB_TOOL_ID_WACOM_PEN	        0x0022
+#define USB_TOOL_ID_WACOM_ERASER        0x00fa
+#define USB_TOOL_ID_WACOM_STROKE_PEN    0x0032
+#define USB_TOOL_ID_WACOM_INKING_PEN    0x0012
+#define USB_TOOL_ID_WACOM_AIRBRUSH      0x0112
+#define USB_TOOL_ID_WACOM_MOUSE4D       0x0094
+#define USB_TOOL_ID_WACOM_LENS_CURSOR   0x0096
+
+#define INTUOS_PEN_MODE_ABS             0x00
+#define INTUOS_PEN_MODE_REL             0x01
+#define INTUOS_PEN_MODE_QUICKPOINT      0x02
+
+#define INTUOS_PRESSURE_MODE_SOFT       0x00
+#define INTUOS_PRESSURE_MODE_MED        0x01
+#define INTUOS_PRESSURE_MODE_FIRM       0x02
+
+#define INTUOS_MENUSTRIP_Y_ZONE         1400
+#define INTUOS_MENUSTRIP_BTN_YMIN        270
+#define INTUOS_MENUSTRIP_BTN_YMAX       1070
+#define INTUOS_MENUSTRIP_F1_XMIN          40
+#define INTUOS_MENUSTRIP_F7_XMIN        8340
+#define INTUOS_MENUSTRIP_F12_XMIN      15300
+
+#define INTUOS_MENUSTRIP_BTN_WIDTH      1300
+
+#define INTUOS_MENUSTRIP_F7_IX_OFFSET      6 /* offset into wacom_fkeys */
+#define INTUOS_MENUSTRIP_F12_IX_OFFSET    11
 
 struct wacom {
-	signed char data[12];
+        signed char data[10];
 	struct input_dev dev;
 	struct urb irq;
+
+        int last_x, last_y;
+	unsigned int tool, device;
+	unsigned int ymax, menustrip_touch;
+	unsigned int pen_mode;
+	unsigned int pressure_mode;
 };
 
+static int wacom_fkeys[16] = { KEY_F1,  KEY_F2,  KEY_F3,  KEY_F4,
+			       KEY_F5,  KEY_F6,  KEY_F7,  KEY_F8,
+			       KEY_F9,  KEY_F10, KEY_F11, KEY_F12,
+			       KEY_F13, KEY_F14, KEY_F15, KEY_F16};
+
+#define INTUOS_EXTENTS_MAX_X              0x00
+#define INTUOS_EXTENTS_MAX_Y              0x01
+#define INTUOS_EXTENTS_HAS_F7             0x02
+#define INTUOS_EXTENTS_HAS_F12            0x03
+#define INTUOS_EXTENTS_PEN_MODE           0x04
+#define INTUOS_EXTENTS_HAS_QUICKPOINT     0x05
+#define INTUOS_EXTENTS_HAS_PRESSURE_MODE  0x06
+#define INTUOS_EXTENTS_PRESSURE_MODE      0x07
+
+#define WACOM_TRUE   1
+#define WACOM_FALSE  0
+
+static int intuos_extents[5][8] = {
+	{ 12700, 10360, WACOM_FALSE, WACOM_FALSE,  8340, WACOM_FALSE, WACOM_FALSE,     0},  /* Intuos 4x5   */
+	{ 20320, 15040,  WACOM_TRUE, WACOM_FALSE, 15300, WACOM_FALSE,  WACOM_TRUE, 18360},  /* Intuos 6x8   */
+	{ 30480, 23060,  WACOM_TRUE,  WACOM_TRUE, 22280,  WACOM_TRUE,  WACOM_TRUE, 26640},  /* Intuos 9x12  */
+	{ 30480, 30480,  WACOM_TRUE,  WACOM_TRUE, 22280,  WACOM_TRUE,  WACOM_TRUE, 26640},  /* Intuos 12x12 */
+	{ 47720, 30480,  WACOM_TRUE,  WACOM_TRUE, 29260,  WACOM_TRUE,  WACOM_TRUE, 33620}}; /* Intuos 12x18 */
+
+static char intuos_names[5][12] = {
+	{"Intuos 4x5  "}, {"Intuos 6x8  "},
+	{"Intuos 9x12 "}, {"Intuos 12x12"},
+	{"Intuos 12x18"}};
+
 static void wacom_graphire_irq(struct urb *urb)
 {
-	struct wacom *wacom = urb->context;
+        struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
 	struct input_dev *dev = &wacom->dev;
 
@@ -123,65 +193,204 @@
 
 	switch ((data[1] >> 5) & 3) {
 
-		case 0:	/* Pen */
-			input_report_btn(dev, BTN_TOOL_PEN, data[1] & 0x80);
-			input_report_btn(dev, BTN_TOUCH, data[1] & 0x01);
-			input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
-			input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
-			input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
-			break;
-
-		case 1: /* Rubber */
-	                input_report_btn(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
-			input_report_btn(dev, BTN_TOUCH, data[1] & 0x01);
-			input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
-			input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
-			input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
-			break;
-
-		case 2: /* Mouse */
-	                input_report_btn(dev, BTN_TOOL_MOUSE, data[7] > 24);
-			input_report_btn(dev, BTN_LEFT, data[1] & 0x01);
-			input_report_btn(dev, BTN_RIGHT, data[1] & 0x02);
-			input_report_btn(dev, BTN_MIDDLE, data[1] & 0x04);
-			input_report_abs(dev, ABS_DISTANCE, data[7]);
-			input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
-			break;
+	case 0:	/* Pen */
+		input_report_btn(dev, BTN_TOOL_PEN, data[1] & 0x80);
+		input_report_btn(dev, BTN_TOUCH, data[1] & 0x01);
+		input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
+		input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
+		input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+		break;
+
+	case 1: /* Rubber */
+		input_report_btn(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
+		input_report_btn(dev, BTN_TOUCH, data[1] & 0x01);
+		input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
+		input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
+		input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
+		break;
+
+	case 2: /* Mouse */
+		input_report_btn(dev, BTN_TOOL_MOUSE, data[7] > 24);
+		input_report_btn(dev, BTN_LEFT, data[1] & 0x01);
+		input_report_btn(dev, BTN_RIGHT, data[1] & 0x02);
+		input_report_btn(dev, BTN_MIDDLE, data[1] & 0x04);
+		input_report_abs(dev, ABS_DISTANCE, data[7]);
+		input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
+		break;
 	}
 }
 
+static void intuos_menustrip( unsigned int x, unsigned int y, struct wacom *wacom )
+{
+	struct input_dev *dev = &wacom->dev;
+	unsigned int local_x = x;
+	unsigned int local_y = y - ( wacom->ymax - INTUOS_MENUSTRIP_Y_ZONE );
+	unsigned int fkey_index ;
+
+	/* Ensure we are in the vertical strip for the buttons */
+	if ( (local_y > INTUOS_MENUSTRIP_BTN_YMIN) && (local_y < INTUOS_MENUSTRIP_BTN_YMAX) ) {
+
+		/* Handle Pressure Mode */
+		if ( intuos_extents[wacom->device][INTUOS_EXTENTS_HAS_PRESSURE_MODE] ) {
+			int pressure_mode = ( (local_x - intuos_extents[wacom->device][INTUOS_EXTENTS_PRESSURE_MODE])
+					      / INTUOS_MENUSTRIP_BTN_WIDTH );
+			if ( ( pressure_mode >= INTUOS_PRESSURE_MODE_SOFT ) &&
+			     ( pressure_mode <= INTUOS_PRESSURE_MODE_FIRM ) ) {
+				wacom->pressure_mode = pressure_mode;
+				return;
+			}
+		}
+
+		/* Handle Pen Mode */
+		{
+			int pen_mode = ( (local_x - intuos_extents[wacom->device][INTUOS_EXTENTS_PEN_MODE])
+					 / INTUOS_MENUSTRIP_BTN_WIDTH );
+			if ( ( pen_mode == INTUOS_PEN_MODE_ABS ) ||
+			     ( pen_mode == INTUOS_PEN_MODE_REL ) ||
+			     ( ( pen_mode == INTUOS_PEN_MODE_QUICKPOINT ) &&
+			       ( intuos_extents[wacom->device][INTUOS_EXTENTS_HAS_QUICKPOINT] ) ) ) {
+				wacom->pen_mode = pen_mode;
+				return;
+			}
+		}
+
+		/* Handle Function Keys */
+		if ( local_x > INTUOS_MENUSTRIP_F12_XMIN ) {
+			fkey_index = INTUOS_MENUSTRIP_F12_IX_OFFSET
+				+ ( (local_x - INTUOS_MENUSTRIP_F12_XMIN) / INTUOS_MENUSTRIP_BTN_WIDTH );
+			fkey_index = ( fkey_index > 16 ) ? 16 : fkey_index; /* Ensure in range */
+		}
+		else if ( local_x > INTUOS_MENUSTRIP_F7_XMIN ) {
+			fkey_index = INTUOS_MENUSTRIP_F7_IX_OFFSET
+				+ ( (local_x - INTUOS_MENUSTRIP_F7_XMIN) / INTUOS_MENUSTRIP_BTN_WIDTH );
+			fkey_index = ( fkey_index > 11 ) ? 11 : fkey_index;
+		}
+		else {
+			fkey_index = ( (local_x - INTUOS_MENUSTRIP_F1_XMIN) / INTUOS_MENUSTRIP_BTN_WIDTH );
+			fkey_index = ( fkey_index > 6 ) ? 6 : fkey_index;
+		}
+		input_report_key(dev, wacom_fkeys[fkey_index], 1);
+		input_report_key(dev, wacom_fkeys[fkey_index], 0);
+
+		return;
+	}
+}
+		
 static void wacom_intuos_irq(struct urb *urb)
 {
-	struct wacom *wacom = urb->context;
+        struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
 	struct input_dev *dev = &wacom->dev;
 	unsigned int t;
+	int x, y;
 
 	if (urb->status) return;
 
 	if (data[0] != 2)
 		dbg("received unknown report #%d", data[0]);
 
-	if (data[1] & 0x02) /* First record, weird data */
+	if ( ((data[1] >> 5) & 0x3) == 0x2 ) /* First record, feature report */
+		{
+			wacom->tool = (((char)data[2] << 4) | (char)data[3] >> 4) & 0xff ;
+			/* Report tool type */
+			switch ( wacom->tool )	{
+			case USB_TOOL_ID_WACOM_PEN: 
+				input_report_btn(dev, BTN_TOOL_PEN, 1);
+				break;
+			case USB_TOOL_ID_WACOM_ERASER: 
+				input_report_btn(dev, BTN_TOOL_RUBBER, 1);
+				break;
+			case USB_TOOL_ID_WACOM_STROKE_PEN: 
+				input_report_btn(dev, BTN_TOOL_BRUSH, 1);
+				break;
+			case USB_TOOL_ID_WACOM_INKING_PEN: 
+				input_report_btn(dev, BTN_TOOL_PENCIL, 1);
+				break;
+			case USB_TOOL_ID_WACOM_AIRBRUSH: 
+				input_report_btn(dev, BTN_TOOL_AIRBRUSH, 1);
+				break;
+			case USB_TOOL_ID_WACOM_MOUSE4D: 
+			case USB_TOOL_ID_WACOM_LENS_CURSOR: 
+				input_report_btn(dev, BTN_TOOL_MOUSE, 1);
+				break;
+			default:
+				break;
+			}			
+			return;
+		}
+
+	if ( ( data[1] | data[2] | data[3] | data[4] | data[5] | data[6]
+	       | data[7] | data[8] | data[9] ) == 0x80 ) { /* exit report */
+		switch ( wacom->tool ) {
+		case USB_TOOL_ID_WACOM_PEN: 
+			input_report_btn(dev, BTN_TOOL_PEN, 0);
+			break;
+		case USB_TOOL_ID_WACOM_ERASER: 
+			input_report_btn(dev, BTN_TOOL_RUBBER, 0);
+			break;
+		case USB_TOOL_ID_WACOM_STROKE_PEN: 
+			input_report_btn(dev, BTN_TOOL_BRUSH, 0);
+			break;
+		case USB_TOOL_ID_WACOM_INKING_PEN: 
+			input_report_btn(dev, BTN_TOOL_PENCIL, 0);
+			break;
+		case USB_TOOL_ID_WACOM_AIRBRUSH: 
+			input_report_btn(dev, BTN_TOOL_AIRBRUSH, 0);
+			break;
+		case USB_TOOL_ID_WACOM_MOUSE4D: 
+		case USB_TOOL_ID_WACOM_LENS_CURSOR: 
+			input_report_btn(dev, BTN_TOOL_MOUSE, 0);
+			break;
+		default:
+			break;
+		}			
 		return;
-	
-	if (data[1] & 0x20) { /* Near */
-		input_report_abs(dev, ABS_X, (((unsigned int) data[2]) << 8) | data[3]);
-		input_report_abs(dev, ABS_Y, 16240 - ((((unsigned int) data[4]) << 8) | data[5]));
 	}
 
-	input_report_btn(dev, BTN_TOOL_PEN, data[1] & 0x20);
-	input_report_btn(dev, BTN_STYLUS, data[1] & 0x04);
+	x = (((unsigned int) data[2]) << 8) | data[3] ;
+	y = wacom->dev.absmax[ABS_Y] - ((((unsigned int) data[4]) << 8) | data[5]);
 
 	t = (((unsigned int) data[6]) << 2) | ((data[7] & 0xC0) >> 6);
 
+	/* Handle touch near menustrip */
+	if ( y > ( wacom->dev.absmax[ABS_Y] - INTUOS_MENUSTRIP_Y_ZONE ) ) {
+		if ( t > 10 ) /* Touch */
+			wacom->menustrip_touch = 1;
+		if ( (wacom->menustrip_touch) && (t <= 10) ) { /* Pen Up */
+			intuos_menustrip( x, y, wacom );
+			wacom->menustrip_touch = 0;
+		}
+		return;
+	}
+	else
+		wacom->menustrip_touch = 0;
+
+	switch ( wacom->pen_mode ) {
+	case INTUOS_PEN_MODE_ABS:
+	        input_report_abs(dev, ABS_X, x);
+		input_report_abs(dev, ABS_Y, y);
+		break;
+	case INTUOS_PEN_MODE_REL:
+	        input_report_rel(dev, REL_X, ( x - wacom->last_x) / 8 );
+	        input_report_rel(dev, REL_Y, - ( y - wacom->last_y) / 8 );
+		break;
+	default: break;
+	}
+
+	wacom->last_x = x;
+	wacom->last_y = y;
+
+	input_report_btn(dev, BTN_STYLUS, data[1] & 0x02);
+	input_report_btn(dev, BTN_STYLUS2, data[1] & 0x04);
+
 	input_report_btn(dev, BTN_TOUCH, t > 10);
 	input_report_abs(dev, ABS_PRESSURE, t);
 
-	if (data[1] & 0x40) { /* Tilt data */
-		input_report_abs(dev, ABS_TILT_X, ((((unsigned int) data[7]) & 0x3f) << 1) | ((data[8] & 0x80) >> 7));
-		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
-	}
+	input_report_abs(dev, ABS_DISTANCE, ( data[9] & 0xf0 ) >> 4 );
+
+	input_report_abs(dev, ABS_TILT_X, ((((unsigned int) data[7]) & 0x3f) << 1) | ((data[8] & 0x80) >> 7));
+	input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
+
 }
 
 static void *wacom_probe(struct usb_device *dev, unsigned int ifnum)
@@ -191,8 +400,12 @@
 	char *name;
 
 	if (dev->descriptor.idVendor != USB_VENDOR_ID_WACOM ||
-	   (dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_GRAPHIRE &&
-	    dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS))
+	    (dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_GRAPHIRE &&
+	     dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS45 &&
+	     dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS68 &&
+	     dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS912 &&
+	     dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS1212 &&
+	     dev->descriptor.idProduct != USB_DEVICE_ID_WACOM_INTUOS1218))
 		return NULL;
 
 	endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
@@ -200,49 +413,57 @@
 	if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
 	memset(wacom, 0, sizeof(struct wacom));
 
-	switch (dev->descriptor.idProduct) {
+	if ( dev->descriptor.idProduct == USB_DEVICE_ID_WACOM_GRAPHIRE ) {
+		wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
+		wacom->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+		wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE);
+		wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
+		wacom->dev.relbit[0] |= BIT(REL_WHEEL);
+		wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
+
+		wacom->dev.absmax[ABS_X] = 10206;
+		wacom->dev.absmax[ABS_Y] = 7422;
+		wacom->dev.absmax[ABS_PRESSURE] = 511;
+		wacom->dev.absmax[ABS_DISTANCE] = 32;
 
-		case USB_DEVICE_ID_WACOM_GRAPHIRE:
+		FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+			     wacom->data, 8, wacom_graphire_irq, wacom, endpoint->bInterval);
 
-			wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
-			wacom->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
-			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE);
-			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
-			wacom->dev.relbit[0] |= BIT(REL_WHEEL);
-			wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
-
-			wacom->dev.absmax[ABS_X] = 10206;
-			wacom->dev.absmax[ABS_Y] = 7422;
-			wacom->dev.absmax[ABS_PRESSURE] = 511;
-			wacom->dev.absmax[ABS_DISTANCE] = 32;
-
-			FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-					wacom->data, 8, wacom_graphire_irq, wacom, endpoint->bInterval);
-
-			name = "Graphire";
-			break;
-
-		case USB_DEVICE_ID_WACOM_INTUOS:
-
-			wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
-			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS);
-			wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
-			wacom->dev.absbit[0] |= BIT(ABS_TILT_X) | BIT(ABS_TILT_Y);
+		name = "Graphire";
+	}
+	else { /* Intuos */
 
-			wacom->dev.absmax[ABS_X] = 20320;
-			wacom->dev.absmax[ABS_Y] = 16240;
-			wacom->dev.absmax[ABS_PRESSURE] = 1024;
-			wacom->dev.absmax[ABS_TILT_X] = 127;
-			wacom->dev.absmax[ABS_TILT_Y] = 127;
+		wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_REL);
+		wacom->dev.keybit[LONG(KEY_F1)]  |= BIT(KEY_F1)  | BIT(KEY_F2)  | BIT(KEY_F3)  | BIT(KEY_F4) | BIT(KEY_F5);
+		wacom->dev.keybit[LONG(KEY_F6)]  |= BIT(KEY_F6)  | BIT(KEY_F7)  | BIT(KEY_F8);
+		wacom->dev.keybit[LONG(KEY_F9)]  |= BIT(KEY_F9)  | BIT(KEY_F10) | BIT(KEY_F11) | BIT(KEY_F12);
+		wacom->dev.keybit[LONG(KEY_F13)] |= BIT(KEY_F13) | BIT(KEY_F14) | BIT(KEY_F15) | BIT(KEY_F16);
+		wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2);
+		wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_BRUSH);
+		wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_MOUSE);
+		wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE);
+		wacom->dev.absbit[0] |= BIT(ABS_TILT_X) | BIT(ABS_TILT_Y);
+		wacom->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
+
+		wacom->dev.absmax[ABS_PRESSURE] = 1023;
+		wacom->dev.absmax[ABS_DISTANCE] = 15;
+		wacom->dev.absmax[ABS_TILT_X] = 127;
+		wacom->dev.absmax[ABS_TILT_Y] = 127;
+
+		wacom->device = dev->descriptor.idProduct - USB_DEVICE_ID_WACOM_INTUOS45;
+
+		wacom->dev.absmax[ABS_X] = intuos_extents[wacom->device][INTUOS_EXTENTS_MAX_X];
+		wacom->dev.absmax[ABS_Y] = intuos_extents[wacom->device][INTUOS_EXTENTS_MAX_Y];
+
+		wacom->ymax = intuos_extents[wacom->device][INTUOS_EXTENTS_MAX_Y];
+		wacom->pen_mode = INTUOS_PEN_MODE_ABS;
+		wacom->pressure_mode = INTUOS_PRESSURE_MODE_SOFT;
 
-			FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
-					wacom->data, 8, wacom_intuos_irq, wacom, endpoint->bInterval);
+		name = intuos_names[wacom->device];
 
-			name = "Intuos";
-			break;
+		FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+			     wacom->data, 10, wacom_intuos_irq, wacom, endpoint->bInterval);
 
-		default:
-			return NULL;
 	}
 
 	if (usb_submit_urb(&wacom->irq)) {
diff -u --recursive --new-file v2.3.50/linux/drivers/usb/whiteheat.h linux/drivers/usb/whiteheat.h
--- v2.3.50/linux/drivers/usb/whiteheat.h	Fri Jan 21 18:19:17 2000
+++ linux/drivers/usb/whiteheat.h	Wed Dec 31 16:00:00 1969
@@ -1,1542 +0,0 @@
-/*****************************************************************************
- *
- *      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.50/linux/drivers/usb/wmforce.c linux/drivers/usb/wmforce.c
--- v2.3.50/linux/drivers/usb/wmforce.c	Sat Feb 26 22:31:50 2000
+++ linux/drivers/usb/wmforce.c	Fri Mar 10 16:18:34 2000
@@ -33,7 +33,7 @@
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include "usb.h"
+#include <linux/usb.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>");
 
diff -u --recursive --new-file v2.3.50/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.3.50/linux/drivers/video/Config.in	Tue Mar  7 14:32:26 2000
+++ linux/drivers/video/Config.in	Wed Mar  8 10:18:25 2000
@@ -40,7 +40,7 @@
       define_bool CONFIG_FB_Q40 y
    fi
    if [ "$CONFIG_AMIGA" = "y" ]; then
-      bool '  Amiga native chipset support' CONFIG_FB_AMIGA
+      tristate '  Amiga native chipset support' CONFIG_FB_AMIGA
       if [ "$CONFIG_FB_AMIGA" != "n" ]; then
 	 bool '    Amiga OCS chipset support' CONFIG_FB_AMIGA_OCS
 	 bool '    Amiga ECS chipset support' CONFIG_FB_AMIGA_ECS
diff -u --recursive --new-file v2.3.50/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.3.50/linux/drivers/video/Makefile	Tue Mar  7 14:32:26 2000
+++ linux/drivers/video/Makefile	Wed Mar  8 10:18:25 2000
@@ -16,7 +16,7 @@
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
-export-objs    := fbmem.o fbcmap.o fbcon.o fbcon-afb.o fbcon-ilbm.o \
+export-objs    := fbmem.o fbcmap.o fbcon.o fbmon.o fbcon-afb.o fbcon-ilbm.o \
 		  fbcon-vga.o fbcon-iplan2p2.o fbcon-iplan2p4.o \
 		  fbcon-iplan2p8.o fbcon-vga-planes.o fbcon-cfb16.o \
 		  fbcon-cfb2.o fbcon-cfb24.o fbcon-cfb32.o fbcon-cfb4.o \
diff -u --recursive --new-file v2.3.50/linux/drivers/video/amifb.c linux/drivers/video/amifb.c
--- v2.3.50/linux/drivers/video/amifb.c	Fri Jan 28 15:09:08 2000
+++ linux/drivers/video/amifb.c	Wed Mar  8 10:18:25 2000
@@ -53,6 +53,7 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/console.h>
+#include <linux/ioport.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -1131,6 +1132,7 @@
 	 */
 
 int amifb_init(void);
+static void amifb_deinit(void);
 static int amifbcon_switch(int con, struct fb_info *info);
 static int amifbcon_updatevar(int con, struct fb_info *info);
 static void amifbcon_blank(int blank, struct fb_info *info);
@@ -1143,6 +1145,7 @@
 static int flash_cursor(void);
 static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp);
 static u_long chipalloc(u_long size);
+static void chipfree(void);
 static char *strtoke(char *s,const char *ct);
 
 	/*
@@ -1181,13 +1184,6 @@
 static void ami_rebuild_copper(void);
 
 
-	/*
-	 * External references
-	 */
-
-extern unsigned short ami_intena_vals[];
-
-
 static struct fb_ops amifb_ops = {
 	amifb_open, amifb_release, amifb_get_fix, amifb_get_var,
 	amifb_set_var, amifb_get_cmap, amifb_set_cmap,
@@ -1599,12 +1595,35 @@
 
 
 	/*
+	 * Allocate, Clear and Align a Block of Chip Memory
+	 */
+
+static u_long unaligned_chipptr = 0;
+
+static inline u_long __init chipalloc(u_long size)
+{
+	size += PAGE_SIZE-1;
+	if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size,
+							   "amifb [RAM]")))
+		panic("No Chip RAM for frame buffer");
+	memset((void *)unaligned_chipptr, 0, size);
+	return PAGE_ALIGN(unaligned_chipptr);
+}
+
+static inline void chipfree(void)
+{
+	if (unaligned_chipptr)
+		amiga_chip_free((void *)unaligned_chipptr);
+}
+
+
+	/*
 	 * Initialisation
 	 */
 
 int __init amifb_init(void)
 {
-	int tag, i;
+	int tag, i, err = 0;
 	u_long chipptr;
 	u_int defmode;
 	struct fb_var_screeninfo var;
@@ -1625,6 +1644,13 @@
 	}
 #endif
 
+	/*
+	 * We request all registers starting from bplpt[0]
+	 */
+	if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120,
+				"amifb [Denise/Lisa]"))
+		return -EBUSY;
+
 	custom.dmacon = DMAF_ALL | DMAF_MASTER;
 
 	switch (amiga_chipset) {
@@ -1688,7 +1714,8 @@
 			strcat(amifb_name, "Unknown");
 			goto default_chipset;
 #else /* CONFIG_FB_AMIGA_OCS */
-			return -ENXIO;
+			err = -ENXIO;
+			goto amifb_error;
 #endif /* CONFIG_FB_AMIGA_OCS */
 			break;
 	}
@@ -1738,9 +1765,37 @@
 	fb_info.flags = FBINFO_FLAG_DEFAULT;
 	memset(&var, 0, sizeof(var));
 
+#ifdef MODULE
+	var.xres = ami_modedb[defmode].xres;
+	var.yres = ami_modedb[defmode].yres;
+	var.xres_virtual = ami_modedb[defmode].xres;
+	var.yres_virtual = ami_modedb[defmode].yres;
+	var.xoffset = 0;
+	var.yoffset = 0;
+	var.bits_per_pixel = 4;
+	var.activate |= FB_ACTIVATE_TEST;
+	var.pixclock = ami_modedb[defmode].pixclock;
+	var.left_margin = ami_modedb[defmode].left_margin;
+	var.right_margin = ami_modedb[defmode].right_margin;
+	var.upper_margin = ami_modedb[defmode].upper_margin;
+	var.lower_margin = ami_modedb[defmode].lower_margin;
+	var.hsync_len = ami_modedb[defmode].hsync_len;
+	var.vsync_len = ami_modedb[defmode].vsync_len;
+	var.sync = ami_modedb[defmode].sync;
+	var.vmode = ami_modedb[defmode].vmode;
+	err = fb_info.fbops->fb_set_var(&var, -1, &fb_info);
+	var.activate &= ~FB_ACTIVATE_TEST;
+	if (err) {
+		err = -EINVAL;
+		goto amifb_error;
+	}
+#else
 	if (!fb_find_mode(&var, &fb_info, mode_option, ami_modedb,
-			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4))
-	    panic("Can't find any usable video mode");
+			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
+		err = -EINVAL;
+		goto amifb_error;
+	}
+#endif
 
 	round_down_bpp = 0;
 	chipptr = chipalloc(videomemorysize+
@@ -1762,9 +1817,7 @@
 	 * access the videomem with writethrough cache
 	 */
 	videomemory_phys = (u_long)ZTWO_PADDR(videomemory);
-#if 1
 	videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize);
-#endif
 	if (!videomemory) {
 		printk("amifb: WARNING! unable to map videomem cached writethrough\n");
 		videomemory = ZTWO_VADDR(videomemory_phys);
@@ -1786,26 +1839,38 @@
 	ami_init_copper();
 
 	if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, 0,
-	                "fb vertb handler", NULL))
-		panic("Couldn't add vblank interrupt\n");
-	ami_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER;
-	ami_intena_vals[IRQ_AMIGA_COPPER] = 0;
+	                "fb vertb handler", NULL)) {
+		err = -EBUSY;
+		goto amifb_error;
+	}
+	amiga_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER;
+	amiga_intena_vals[IRQ_AMIGA_COPPER] = 0;
 	custom.intena = IF_VERTB;
 	custom.intena = IF_SETCLR | IF_COPER;
 
 	amifb_set_var(&var, -1, &fb_info);
 
-	if (register_framebuffer(&fb_info) < 0)
-		return -EINVAL;
+	if (register_framebuffer(&fb_info) < 0) {
+		err = -EINVAL;
+		goto amifb_error;
+	}
 
 	printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
 	       GET_FB_IDX(fb_info.node), fb_info.modename,
 	       videomemorysize>>10);
 
-	/* TODO: This driver cannot be unloaded yet */
-	MOD_INC_USE_COUNT;
-
 	return 0;
+	
+amifb_error:
+	amifb_deinit();
+	return err;
+}
+
+static void amifb_deinit(void)
+{
+	chipfree();    
+	release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
+	custom.dmacon = DMAF_ALL | DMAF_MASTER;
 }
 
 static int amifbcon_switch(int con, struct fb_info *info)
@@ -1931,23 +1996,6 @@
 }
 
 	/*
-	 * Allocate, Clear and Align a Block of Chip Memory
-	 */
-
-static u_long __init chipalloc(u_long size)
-{
-	u_long ptr;
-
-	size += PAGE_SIZE-1;
-	if (!(ptr = (u_long)amiga_chip_alloc(size, "amifb")))
-		panic("No Chip RAM for frame buffer");
-	memset((void *)ptr, 0, size);
-	ptr = PAGE_ALIGN(ptr);
-
-	return ptr;
-}
-
-	/*
 	 * A strtok which returns empty strings, too
 	 */
 
@@ -3373,9 +3421,7 @@
 
 void cleanup_module(void)
 {
-	/* Not reached because the usecount will never
-	   be decremented to zero */
 	unregister_framebuffer(&fb_info);
-	/* TODO: clean up ... */
+	amifb_deinit();
 }
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.50/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c
--- v2.3.50/linux/drivers/video/aty128fb.c	Thu Mar  2 14:36:23 2000
+++ linux/drivers/video/aty128fb.c	Wed Mar  8 09:18:23 2000
@@ -1358,7 +1358,7 @@
     } 
 
 #ifdef CONFIG_FB_COMPAT_XPMAC
-    if (console_fb_info == &info->fb_info) {
+    if (!console_fb_info || console_fb_info == &info->fb_info) {
 	int vmode, cmode;
 
 	display_info.width = var->xres;
@@ -1429,13 +1429,8 @@
     
     strcpy(fix->id, aty128fb_name);
 
-#ifdef CONFIG_PPC /* why?  I don't know */
-    *fix->smem_start = (long)info->frame_buffer_phys;
-    *fix->mmio_start = (long)info->regbase_phys;
-#else
     fix->smem_start = (long)info->frame_buffer_phys;
     fix->mmio_start = (long)info->regbase_phys;
-#endif
 
     fix->smem_len = (u32)info->vram_size;
     fix->mmio_len = 0x1fff;
@@ -1676,7 +1671,7 @@
     chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
 
     /* put a name with the face */
-    while (info->pdev->device != aci->device) { aci++; }
+    while (aci->name && info->pdev->device != aci->device) { aci++; }
     video_card = (char *)aci->name;
 
     printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] [card rev %x] ",
@@ -1723,7 +1718,10 @@
     if (default_cmode == CMODE_NVRAM)
         default_cmode = nvram_read_byte(NV_CMODE);
 #endif
-    }
+    } else if (_machine == _MACH_Pmac)
+ 	if (mac_vmode_to_var(default_vmode, default_cmode, &var))
+	    var = default_var;
+
 #endif
 #endif /* MODULE */
 
diff -u --recursive --new-file v2.3.50/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.3.50/linux/drivers/video/atyfb.c	Sat Feb 26 22:31:51 2000
+++ linux/drivers/video/atyfb.c	Fri Mar 10 09:43:04 2000
@@ -2689,15 +2689,6 @@
     fix->smem_start = info->frame_buffer_phys;
     fix->smem_len = (u32)info->total_vram;
 
-#ifdef __LITTLE_ENDIAN
-    /*
-     *  Last page of 8 MB little-endian aperture is MMIO
-     *  FIXME: we should use the auxiliary aperture instead so we can acces the
-     *  full 8 MB of video RAM on 8 MB boards
-     */
-    if (fix->smem_len > 0x800000-GUI_RESERVE)
-	fix->smem_len = 0x800000-GUI_RESERVE;
-#endif
     /*
      *  Reg Block 0 (CT-compatible block) is at ati_regbase_phys
      *  Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
@@ -3501,14 +3492,17 @@
     }
 #endif
 
-    if (info->bus_type == ISA)
-	if ((info->total_vram == 0x400000) || (info->total_vram == 0x800000)) {
-	    /* protect GUI-regs if complete Aperture is VRAM */
+    /*
+     *  Last page of 8 MB (4 MB on ISA) aperture is MMIO
+     *  FIXME: we should use the auxiliary aperture instead so we can acces the
+     *  full 8 MB of video RAM on 8 MB boards
+     */
+    if (info->total_vram == 0x800000 ||
+	(info->bus_type == ISA && info->total_vram == 0x400000))
 	    info->total_vram -= GUI_RESERVE;
-	}
 
     /* Clear the video memory */
-    memset_io(info->frame_buffer, 0, info->total_vram);
+    fb_memset((void *)info->frame_buffer, 0, info->total_vram);
 
     disp = &info->disp;
 
@@ -3634,14 +3628,14 @@
     struct pci_dev *pdev = NULL;
     struct fb_info_aty *info;
     unsigned long addr, res_start, res_size;
+    int i;
 #ifdef __sparc__
     extern void (*prom_palette) (int);
     extern int con_is_present(void);
     struct pcidev_cookie *pcp;
     char prop[128];
-    int node, len;
+    int node, len, j;
     u32 mem, chip_id;
-    int i, j;
 
     /* Do not attach when we have a serial console. */
     if (!con_is_present())
@@ -3654,6 +3648,12 @@
 	if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
 	    struct resource *rp;
 
+	    for (i = sizeof(aty_features)/sizeof(*aty_features)-1; i >= 0; i--)
+		if (pdev->device == aty_features[i].pci_id)
+		    break;
+	    if (i < 0)
+		continue;
+	    
 	    info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
 	    if (!info) {
 		printk("atyfb_init: can't alloc fb_info_aty\n");
diff -u --recursive --new-file v2.3.50/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.3.50/linux/drivers/video/fbcon.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/video/fbcon.c	Wed Mar  8 14:00:08 2000
@@ -111,6 +111,10 @@
 #define LOGO_W			80
 #define LOGO_LINE	(LOGO_W/8)
 
+static int first_fb_vc = 0;
+static int last_fb_vc = MAX_NR_CONSOLES-1;
+static int fbcon_is_default = 1;
+
 struct display fb_display[MAX_NR_CONSOLES];
 char con2fb_map[MAX_NR_CONSOLES];
 static int logo_lines;
@@ -128,6 +132,8 @@
 #define FNTSUM(fd)	(((int *)(fd))[-4])
 #define FONT_EXTRA_WORDS 4
 
+static char fontname[40] __initdata = { 0 };     /* default font name */
+
 #define CM_SOFTBACK	(8)
 
 #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * conp->vc_size_row)
@@ -197,7 +203,8 @@
  *  Internal routines
  */
 
-static void fbcon_setup(int con, int init, int logo);
+static int __init fbcon_setup(char *options);
+static void fbcon_set_disp(int con, int init, int logo);
 static __inline__ int real_y(struct display *p, int ypos);
 static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp);
 static __inline__ void updatescrollmode(struct display *p);
@@ -293,6 +300,8 @@
        newfb = registered_fb[newidx];
        if (newfb->fbops->fb_open(newfb,0))
            return;
+       newfb->count++;
+       oldfb->count--;		
        oldfb->fbops->fb_release(oldfb,0);
        conp = fb_display[unit].conp;
        fontdata = fb_display[unit].fontdata;
@@ -323,6 +332,57 @@
    }
 }
 
+static int __init fbcon_setup(char *options)
+{
+    int i, j;
+
+    if (!options || !*options)
+            return 0;
+
+    if (!strncmp(options, "font:", 5))
+        strcpy(fontname, options+5);
+
+    if (!strncmp(options, "scrollback:", 11)) {
+            options += 11;
+            if (*options) {
+                fbcon_softback_size = simple_strtoul(options, &options, 0);
+                if (*options == 'k' || *options == 'K') {
+                        fbcon_softback_size *= 1024;
+                        options++;
+                }
+                if (*options != ',')
+                        return 0;
+                options++;
+            } else
+                return 0;
+    }
+
+    if (!strncmp(options, "map:", 4)) {
+            options += 4;
+            if (*options)
+                    for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
+                            if (!options[j])
+                                    j = 0;
+                            con2fb_map[i] = (options[j++]-'0') % FB_MAX;
+                    }
+            return 0;
+    }
+
+    if (!strncmp(options, "vc:", 3)) {
+            options += 3;
+            if (*options)
+                first_fb_vc = simple_strtoul(options, &options, 10) - 1;
+            if (first_fb_vc < 0)
+                first_fb_vc = 0;
+            if (*options++ == '-')
+                last_fb_vc = simple_strtoul(options, &options, 10) - 1;
+            fbcon_is_default = 0;
+    }
+    return 0;
+}
+
+__setup("fbcon=", fbcon_setup);
+
 /*
  *  Low Level Operations
  */
@@ -419,15 +479,23 @@
     return display_desc;
 }
 
-
 static void fbcon_init(struct vc_data *conp, int init)
 {
-    int unit = conp->vc_num;
+    int j, unit = conp->vc_num;
     struct fb_info *info;
-
+	
     /* on which frame buffer will we open this console? */
     info = registered_fb[(int)con2fb_map[unit]];
 
+    /*
+     *  We assume initial frame buffer devices can be opened this
+     *  many times
+     */
+    for (j = 0; j < (last_fb_vc - first_fb_vc + 1); j++) {
+        info->fbops->fb_open(info,0);
+	info->count++;	
+    } 	
+
     info->changevar = &fbcon_changevar;
     fb_display[unit] = *(info->disp);	/* copy from default */
     DPRINTK("mode:   %s\n",info->modename);
@@ -443,8 +511,8 @@
     fb_display[unit].cmap.green = 0;
     fb_display[unit].cmap.blue = 0;
     fb_display[unit].cmap.transp = 0;
-    fbcon_setup(unit, init, !init);
-    /* Must be done after fbcon_setup to prevent excess updates */
+    fbcon_set_disp(unit, init, !init);
+    /* Must be done after fbcon_set_disp to prevent excess updates */
     conp->vc_display_fg = &info->display_fg;
     if (!info->display_fg)
         info->display_fg = conp;
@@ -458,6 +526,7 @@
 
     fbcon_free_font(p);
     p->dispsw = &fbcon_dummy;
+    p->fb_info->count = 0;	
     p->conp = 0;
 }
 
@@ -465,7 +534,7 @@
 static int fbcon_changevar(int con)
 {
     if (fb_display[con].conp)
-	    fbcon_setup(con, 0, 0);
+	    fbcon_set_disp(con, 0, 0);
     return 0;
 }
 
@@ -504,7 +573,7 @@
 
 #define fontwidthvalid(p,w) ((p)->dispsw->fontwidthmask & FONTWIDTH(w))
 
-static void fbcon_setup(int con, int init, int logo)
+static void fbcon_set_disp(int con, int init, int logo)
 {
     struct display *p = &fb_display[con];
     struct vc_data *conp = p->conp;
@@ -568,9 +637,8 @@
     }
 
     if (!p->fontdata) {
-        if (!p->fb_info->fontname[0] ||
-	    !(font = fbcon_find_font(p->fb_info->fontname)))
-	        font = fbcon_get_default_font(p->var.xres, p->var.yres);
+        if (!fontname[0] || !(font = fbcon_find_font(fontname)))
+	    font = fbcon_get_default_font(p->var.xres, p->var.yres);
         p->_fontwidth = font->width;
         p->_fontheight = font->height;
         p->fontdata = font->data;
@@ -586,7 +654,7 @@
 #endif
 	{
 	    /* ++Geert: changed from panic() to `correct and continue' */
-	    printk(KERN_ERR "fbcon_setup: No support for fontwidth %d\n", fontwidth(p));
+	    printk(KERN_ERR "fbcon_set_disp: No support for fontwidth %d\n", fontwidth(p));
 	    p->dispsw = &fbcon_dummy;
 	}
     }
@@ -669,7 +737,7 @@
     }
 
     if (p->dispsw == &fbcon_dummy)
-	printk(KERN_WARNING "fbcon_setup: type %d (aux %d, depth %d) not "
+	printk(KERN_WARNING "fbcon_set_disp: type %d (aux %d, depth %d) not "
 	       "supported\n", p->type, p->type_aux, p->var.bits_per_pixel);
     p->dispsw->setup(p);
 
@@ -2394,6 +2462,13 @@
     con_getxy:		fbcon_getxy,
 };
 
+void __init fbconsole_init(void)
+{
+	if (!num_registered_fb || (first_fb_vc > last_fb_vc))
+                return;
+
+	take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
+}
 
 /*
  *  Dummy Low Level Operations
diff -u --recursive --new-file v2.3.50/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.3.50/linux/drivers/video/fbmem.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/video/fbmem.c	Wed Mar  8 14:00:08 2000
@@ -239,14 +239,8 @@
 static initcall_t pref_init_funcs[FB_MAX];
 static int num_pref_init_funcs __initdata = 0;
 
-
 struct fb_info *registered_fb[FB_MAX];
 int num_registered_fb = 0;
-extern int fbcon_softback_size; 
-
-static int first_fb_vc = 0;
-static int last_fb_vc = MAX_NR_CONSOLES-1;
-static int fbcon_is_default = 1;
 
 static int fbmem_read_proc(char *buf, char **start, off_t offset,
 			   int len, int *eof, void *private)
@@ -556,6 +550,8 @@
 #endif /* CONFIG_KMOD */
 	if (!(info = registered_fb[fbidx]))
 		return -ENODEV;
+	if (info->flags & FBINFO_FLAG_OPEN) return -EBUSY; 
+	info->flags |= FBINFO_FLAG_OPEN;		
 	return info->fbops->fb_open(info,1);
 }
 
@@ -566,6 +562,7 @@
 	struct fb_info *info = registered_fb[fbidx];
 
 	info->fbops->fb_release(info,1);
+        info->flags &= ~FBINFO_FLAG_OPEN;
 	return 0;
 }
 
@@ -583,10 +580,8 @@
 int
 register_framebuffer(struct fb_info *fb_info)
 {
-	int i, j;
 	char name_buf[8];
-	static int fb_ever_opened[FB_MAX];
-	static int first = 1;
+ 	int i;
 
 	if (num_registered_fb == FB_MAX)
 		return -ENXIO;
@@ -595,22 +590,9 @@
 		if (!registered_fb[i])
 			break;
 	fb_info->node = MKDEV(FB_MAJOR, i);
+	fb_info->flags &= ~FBINFO_FLAG_OPEN;
+	fb_info->count = 0;
 	registered_fb[i] = fb_info;
-	if (!fb_ever_opened[i]) {
-		/*
-		 *  We assume initial frame buffer devices can be opened this
-		 *  many times
-		 */
-		for (j = 0; j < MAX_NR_CONSOLES; j++)
-			if (con2fb_map[j] == i)
-				fb_info->fbops->fb_open(fb_info,0);
-		fb_ever_opened[i] = 1;
-	}
-
-	if (first) {
-		first = 0;
-		take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
-	}
 	sprintf (name_buf, "%d", i);
 	fb_info->devfs_handle =
 	    devfs_register (devfs_handle, name_buf, 0, DEVFS_FL_NONE,
@@ -623,12 +605,12 @@
 int
 unregister_framebuffer(struct fb_info *fb_info)
 {
-	int i, j;
+	int i;
 
 	i = GET_FB_IDX(fb_info->node);
-	for (j = 0; j < MAX_NR_CONSOLES; j++)
-		if (con2fb_map[j] == i)
-			return -EBUSY;
+	
+	if (fb_info->count || (fb_info->flags & FBINFO_FLAG_OPEN))
+		return -EBUSY;
 	if (!registered_fb[i])
 		return -EINVAL;
 	devfs_unregister (fb_info->devfs_handle);
@@ -672,43 +654,6 @@
 
     if (!options || !*options)
 	    return 0;
-	    
-    if (!strncmp(options, "scrollback:", 11)) {
-	    options += 11;
-	    if (*options) {
-		fbcon_softback_size = simple_strtoul(options, &options, 0);
-		if (*options == 'k' || *options == 'K') {
-			fbcon_softback_size *= 1024;
-			options++;
-		}
-		if (*options != ',')
-			return 0;
-		options++;
-	    } else
-	        return 0;
-    }
-
-    if (!strncmp(options, "map:", 4)) {
-	    options += 4;
-	    if (*options)
-		    for (i = 0, j = 0; i < MAX_NR_CONSOLES; i++) {
-			    if (!options[j])
-				    j = 0;
-			    con2fb_map[i] = (options[j++]-'0') % FB_MAX;
-		    }
-	    return 0;
-    }
-    
-    if (!strncmp(options, "vc:", 3)) {
-	    options += 3;
-	    if (*options)
-		first_fb_vc = simple_strtoul(options, &options, 10) - 1;
-	    if (first_fb_vc < 0)
-		first_fb_vc = 0;
-	    if (*options++ == '-')
-		last_fb_vc = simple_strtoul(options, &options, 10) - 1;
-	    fbcon_is_default = 0;
-    }
 
     if (num_pref_init_funcs == FB_MAX)
 	    return 0;
diff -u --recursive --new-file v2.3.50/linux/drivers/video/fbmon.c linux/drivers/video/fbmon.c
--- v2.3.50/linux/drivers/video/fbmon.c	Tue Nov 23 22:42:21 1999
+++ linux/drivers/video/fbmon.c	Wed Mar  8 10:18:25 2000
@@ -41,6 +41,7 @@
  */
 #include <linux/tty.h>
 #include <linux/fb.h>
+#include <linux/module.h>
 
 int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
                         const struct fb_info *fb_info)
@@ -72,3 +73,5 @@
 {
   return fb_info->monspecs.dpms;
 }
+
+EXPORT_SYMBOL(fbmon_valid_timings);
diff -u --recursive --new-file v2.3.50/linux/drivers/video/matrox/i2c-matroxfb.c linux/drivers/video/matrox/i2c-matroxfb.c
--- v2.3.50/linux/drivers/video/matrox/i2c-matroxfb.c	Sat Feb 26 22:31:51 2000
+++ linux/drivers/video/matrox/i2c-matroxfb.c	Fri Mar 10 10:48:47 2000
@@ -287,6 +287,9 @@
 	matroxfb_DAC_unlock_irqrestore(flags);
 
 	memset(m2info, 0, sizeof(*m2info));
+	m2info->maven.minfo = m2info;
+	m2info->ddc1.minfo = m2info;
+	m2info->ddc2.minfo = m2info;
 	m2info->primary_dev = minfo;
 
 	if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGA2064W ||
diff -u --recursive --new-file v2.3.50/linux/drivers/video/matrox/matroxfb_maven.c linux/drivers/video/matrox/matroxfb_maven.c
--- v2.3.50/linux/drivers/video/matrox/matroxfb_maven.c	Sat Feb 26 22:31:51 2000
+++ linux/drivers/video/matrox/matroxfb_maven.c	Fri Mar 10 10:48:47 2000
@@ -892,11 +892,8 @@
 
 static int maven_init_client(struct i2c_client* clnt) {
 	struct i2c_adapter* a = clnt->adapter;
-	/* data are set to primary head... maybe I should change it */
-	struct matroxfb_dh_maven_info* m2info =
-		(struct matroxfb_dh_maven_info*)(((u_int8_t*)a) - offsetof(struct matroxfb_dh_maven_info, maven.adapter));
+	struct matroxfb_dh_maven_info* m2info = ((struct i2c_bit_adapter*)a)->minfo;
 	struct maven_data* md = clnt->data;
-	/* add some checks that m2info is matroxfb_dh_fb_info here... */
 	struct matrox_fb_info* minfo = m2info->primary_dev;
 
 	md->mode = MODE_MONITOR;
diff -u --recursive --new-file v2.3.50/linux/drivers/video/matrox/matroxfb_maven.h linux/drivers/video/matrox/matroxfb_maven.h
--- v2.3.50/linux/drivers/video/matrox/matroxfb_maven.h	Sat Feb 26 22:31:51 2000
+++ linux/drivers/video/matrox/matroxfb_maven.h	Fri Mar 10 10:48:47 2000
@@ -6,10 +6,13 @@
 #include <linux/i2c-algo-bit.h>
 #include "matroxfb_base.h"
 
+struct matroxfb_dh_maven_info;
+
 struct i2c_bit_adapter {
 	struct i2c_adapter		adapter;
 	int				initialized;
 	struct i2c_algo_bit_data	bac;
+	struct matroxfb_dh_maven_info  *minfo;
 };
 
 struct matroxfb_dh_maven_info {
diff -u --recursive --new-file v2.3.50/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.3.50/linux/drivers/video/offb.c	Thu Feb 10 17:11:15 2000
+++ linux/drivers/video/offb.c	Wed Mar  8 09:18:23 2000
@@ -293,9 +293,6 @@
 }
 
 
-#ifdef CONFIG_FB_ATY128
-extern void aty128fb_of_init(struct device_node *dp);
-#endif /* CONFIG_FB_ATY */
 #ifdef CONFIG_FB_S3TRIO
 extern void s3triofb_init_of(struct device_node *dp);
 #endif /* CONFIG_FB_S3TRIO */
@@ -423,12 +420,6 @@
 
 static int __init offb_init_driver(struct device_node *dp)
 {
-#ifdef CONFIG_FB_ATY128
-    if (!strncmp(dp->name, "ATY,Rage128", 11)) {
-	aty128fb_of_init(dp);
-	return 1;
-    }
-#endif
 #ifdef CONFIG_FB_S3TRIO
     if (!strncmp(dp->name, "S3Trio", 6)) {
     	s3triofb_init_of(dp);
diff -u --recursive --new-file v2.3.50/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c
--- v2.3.50/linux/drivers/video/vgacon.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/video/vgacon.c	Thu Mar  9 07:08:04 2000
@@ -94,8 +94,6 @@
 static void vgacon_invert_region(struct vc_data *c, u16 *p, int count);
 static unsigned long vgacon_uni_pagedir[2];
 
-void clear_status_line( void );
-
 
 /* Description of the hardware situation */
 static unsigned long   vga_vram_base;		/* Base of video memory */
@@ -351,7 +349,6 @@
 static inline void vga_set_mem_top(struct vc_data *c)
 {
 	write_vga(12, (c->vc_visible_origin-vga_vram_base)/2);
-	clear_status_line();
 }
 
 static void vgacon_deinit(struct vc_data *c)
@@ -1060,80 +1057,3 @@
 	vgacon_build_attr,
 	vgacon_invert_region
 };
-
-
-int inited = 0;
-
-void
-clear_status_line( void )
-{
-#if CONFIG_COMMENT_INT==3
-        u16 *org;
-        int i;
-        int currcons = fg_console;
-	struct vc_data *c = vc_cons[fg_console].d;
-	if (!inited) return;
-        if (vga_is_gfx) return;
-	if (c->vc_origin != c->vc_visible_origin) return;
-        org = screen_pos( fg_console, video_num_lines*video_num_columns, 1 );
-        for (i=0; i<video_num_columns; i++)
-                scr_writew( (0x0f << 8) + ' ', org++ );
-#endif
-}
-
-#if CONFIG_COMMENT_INT==3
-void
-paint_status_line( int timer )
-{
-	u16 *org;
-	int i,j;
-	int currcons = fg_console;
-	struct vc_data *c = vc_cons[fg_console].d;
-
-	if (!inited) return;
-	if (vga_is_gfx)		/* We don't play origin tricks in graphic modes */
-		return;
-	if (c->vc_origin != c->vc_visible_origin) return;
-
-	org = screen_pos( fg_console, video_num_lines*video_num_columns, 1 );
-
-	/* Are we busy? */
-	{
-		i = current->pid;
-		j = 0;
-		if (i)
-			j = (i>16) ? ((current->priority < DEF_PRIORITY) ? 0xA0:0xE0) : 0xC0;
-		scr_writew( (j<<8) + ' ', org++ );
-
-#if 0
-		org++;
-
-#define DISP( x ) scr_writew(  (((i&x) ? 0x90:0) << 8) + ' ', org++ );
-		DISP( 0x80 );
-		DISP( 0x40 );
-		DISP( 0x20 );
-		DISP( 0x10 );
-		DISP( 0x08 );
-		DISP( 0x04 );
-		DISP( 0x02 );
-		DISP( 0x01 );
-#endif
-	}
-
-	if (!timer) return;
-
-	org++;
-	/* Serial? */
-	{
-		j = (ledflags & 0x10) ? 0x90 : 0x00;
-		scr_writew( (j<<8) + 'S', org++ );
-	}
-
-	org++;
-	/* NE2000? */
-	{
-		j = (ledflags & 0x20) ? 0x90 : 0x00;
-		scr_writew( (j<<8) + 'N', org++ );
-	}
-}
-#endif
diff -u --recursive --new-file v2.3.50/linux/fs/adfs/super.c linux/fs/adfs/super.c
--- v2.3.50/linux/fs/adfs/super.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/adfs/super.c	Fri Mar 10 10:48:47 2000
@@ -158,7 +158,6 @@
 	for (i = 0; i < sb->u.adfs_sb.s_map_size; i++)
 		brelse(sb->u.adfs_sb.s_map[i].dm_bh);
 	kfree(sb->u.adfs_sb.s_map);
-	MOD_DEC_USE_COUNT;
 }
 
 static int parse_options(struct super_block *sb, char *options)
@@ -213,21 +212,20 @@
 	return parse_options(sb, data);
 }
 
-static int adfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int adfs_statfs(struct super_block *sb, struct statfs *buf)
 {
 	struct adfs_sb_info *asb = &sb->u.adfs_sb;
-	struct statfs tmp;
 
-	tmp.f_type    = ADFS_SUPER_MAGIC;
-	tmp.f_namelen = asb->s_namelen;
-	tmp.f_bsize   = sb->s_blocksize;
-	tmp.f_blocks  = asb->s_size;
-	tmp.f_files   = asb->s_ids_per_zone * asb->s_map_size;
-	tmp.f_bavail  =
-	tmp.f_bfree   = adfs_map_free(sb);
-	tmp.f_ffree   = tmp.f_bfree * tmp.f_files / tmp.f_blocks;
+	buf->f_type    = ADFS_SUPER_MAGIC;
+	buf->f_namelen = asb->s_namelen;
+	buf->f_bsize   = sb->s_blocksize;
+	buf->f_blocks  = asb->s_size;
+	buf->f_files   = asb->s_ids_per_zone * asb->s_map_size;
+	buf->f_bavail  =
+	buf->f_bfree   = adfs_map_free(sb);
+	buf->f_ffree   = buf->f_bfree * buf->f_files / buf->f_blocks;
 
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	return 0;
 }
 
 static struct super_operations adfs_sops = {
@@ -317,8 +315,6 @@
 	if (parse_options(sb, data))
 		goto error;
 
-	MOD_INC_USE_COUNT;
-	lock_super(sb);
 	set_blocksize(dev, BLOCK_SIZE);
 	if (!(bh = bread(dev, ADFS_DISCRECORD / BLOCK_SIZE, BLOCK_SIZE))) {
 		adfs_error(sb, "unable to read superblock");
@@ -396,7 +392,6 @@
 	 * set up enough so that we can read an inode
 	 */
 	sb->s_op = &adfs_sops;
-	unlock_super(sb);
 
 	dr = (struct adfs_discrecord *)(sb->u.adfs_sb.s_map[0].dm_bh->b_data + 4);
 
@@ -440,31 +435,24 @@
 error_free_bh:
 	brelse(bh);
 error_unlock:
-	unlock_super(sb);
 error_dec_use:
-	MOD_DEC_USE_COUNT;
 error:
-	sb->s_dev = 0;
 	return NULL;
 }
 
-static struct file_system_type adfs_fs_type = {
-	"adfs", FS_REQUIRES_DEV, adfs_read_super, NULL
-};
+static DECLARE_FSTYPE_DEV(adfs_fs_type, "adfs", adfs_read_super);
 
-int __init init_adfs_fs(void)
+static int __init init_adfs_fs(void)
 {
 	return register_filesystem(&adfs_fs_type);
 }
 
-#ifdef MODULE
-int init_module(void)
-{
-	return init_adfs_fs();
-}
-
-void cleanup_module(void)
+static void __exit exit_adfs_fs(void)
 {
 	unregister_filesystem(&adfs_fs_type);
 }
-#endif
+
+EXPORT_NO_SYMBOLS;
+
+module_init(init_adfs_fs)
+module_exit(exit_adfs_fs)
diff -u --recursive --new-file v2.3.50/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.3.50/linux/fs/affs/namei.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/affs/namei.c	Wed Mar  8 09:04:09 2000
@@ -368,7 +368,7 @@
 	if (!empty_dir(bh,AFFS_I2HSIZE(inode)))
 		goto rmdir_done;
 	retval = -EBUSY;
-	if (!list_empty(&dentry->d_hash))
+	if (!d_unhashed(dentry))
 		goto rmdir_done;
 
 	if ((retval = affs_remove_header(bh,inode)) < 0)
@@ -557,6 +557,9 @@
 	}
 	if (S_ISDIR(old_inode->i_mode)) {
 		if (new_inode) {
+			retval = -EBUSY;
+			if (!d_unhashed(new_dentry))
+				goto end_rename;
 			retval = -ENOTEMPTY;
 			if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode)))
 				goto end_rename;
diff -u --recursive --new-file v2.3.50/linux/fs/affs/super.c linux/fs/affs/super.c
--- v2.3.50/linux/fs/affs/super.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/affs/super.c	Fri Mar 10 10:48:47 2000
@@ -35,7 +35,7 @@
 
 #define MIN(a,b) (((a)<(b))?(a):(b))
 
-static int affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int affs_statfs(struct super_block *sb, struct statfs *buf);
 static int affs_remount (struct super_block *sb, int *flags, char *data);
 
 static void
@@ -65,7 +65,6 @@
 	 */
 	set_blocksize(sb->s_dev, sb->u.affs_sb.s_blksize);
 
-	MOD_DEC_USE_COUNT;
 	return;
 }
 
@@ -262,8 +261,6 @@
 
 	pr_debug("AFFS: read_super(%s)\n",data ? (const char *)data : "no options");
 
-	MOD_INC_USE_COUNT;
-	lock_super(s);
 	s->s_magic             = AFFS_SUPER_MAGIC;
 	s->s_op                = &affs_sops;
 	s->u.affs_sb.s_bitmap  = NULL;
@@ -547,7 +544,6 @@
 		goto out_no_root;
 	s->s_root->d_op = &affs_dentry_operations;
 
-	unlock_super(s);
 	/* Record date of last change if the bitmap was truncated and
 	 * create data zones if the volume is writable.
 	 */
@@ -615,9 +611,6 @@
 	if (s->u.affs_sb.s_prefix)
 		kfree(s->u.affs_sb.s_prefix);
 out_fail:
-	s->s_dev = 0;
-	unlock_super(s);
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
@@ -661,31 +654,23 @@
 }
 
 static int
-affs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+affs_statfs(struct super_block *sb, struct statfs *buf)
 {
 	int		 free;
-	struct statfs	 tmp;
 
 	pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",sb->u.affs_sb.s_partition_size,
 	     sb->u.affs_sb.s_reserved);
 
 	free          = affs_count_free_blocks(sb);
-	tmp.f_type    = AFFS_SUPER_MAGIC;
-	tmp.f_bsize   = sb->s_blocksize;
-	tmp.f_blocks  = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved;
-	tmp.f_bfree   = free;
-	tmp.f_bavail  = free;
-	tmp.f_files   = 0;
-	tmp.f_ffree   = 0;
-	return copy_to_user(buf,&tmp,bufsiz) ? -EFAULT : 0;
+	buf->f_type    = AFFS_SUPER_MAGIC;
+	buf->f_bsize   = sb->s_blocksize;
+	buf->f_blocks  = sb->u.affs_sb.s_partition_size - sb->u.affs_sb.s_reserved;
+	buf->f_bfree   = free;
+	buf->f_bavail  = free;
+	return 0;
 }
 
-static struct file_system_type affs_fs_type = {
-	"affs",
-	FS_REQUIRES_DEV,
-	affs_read_super,
-	NULL
-};
+static DECLARE_FSTYPE_DEV(affs_fs_type, "affs", affs_read_super);
 
 int __init init_affs_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/autofs/init.c linux/fs/autofs/init.c
--- v2.3.50/linux/fs/autofs/init.c	Thu Feb 10 17:11:16 2000
+++ linux/fs/autofs/init.c	Fri Mar 10 10:48:47 2000
@@ -14,12 +14,7 @@
 #include <linux/init.h>
 #include "autofs_i.h"
 
-static struct file_system_type autofs_fs_type = {
-	"autofs",
-	0,
-	autofs_read_super,
-	NULL
-};
+static DECLARE_FSTYPE(autofs_fs_type, "autofs", autofs_read_super, 0);
 
 static int __init init_autofs_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/autofs/inode.c linux/fs/autofs/inode.c
--- v2.3.50/linux/fs/autofs/inode.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/autofs/inode.c	Fri Mar 10 10:48:48 2000
@@ -49,13 +49,9 @@
 	kfree(sb->u.generic_sbp);
 
 	DPRINTK(("autofs: shutting down\n"));
-	
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif
 }
 
-static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int autofs_statfs(struct super_block *sb, struct statfs *buf);
 static void autofs_read_inode(struct inode *inode);
 static void autofs_write_inode(struct inode *inode);
 
@@ -141,9 +137,6 @@
 	struct autofs_sb_info *sbi;
 	int minproto, maxproto;
 
-	MOD_INC_USE_COUNT;
-
-	lock_super(s);
 	/* Super block already completed? */
 	if (s->s_root)
 		goto out_unlock;
@@ -167,7 +160,6 @@
 	s->s_magic = AUTOFS_SUPER_MAGIC;
 	s->s_op = &autofs_sops;
 	s->s_root = NULL;
-	unlock_super(s); /* shouldn't we keep it locked a while longer? */
 
 	/*
 	 * Get the root inode and dentry, but defer checking for errors.
@@ -224,7 +216,6 @@
 	 * Success ... somebody else completed the super block for us. 
 	 */ 
 out_unlock:
-	unlock_super(s);
 	goto out_dec;
 out_fput:
 	if (pipe)
@@ -235,7 +226,6 @@
 	else
 		iput(root_inode);
 out_dec:
-	MOD_DEC_USE_COUNT;
 	return s;
 	
 	/*
@@ -246,14 +236,12 @@
 	/*
 	 * fput() can block, so we clear the super block first.
 	 */
-	s->s_dev = 0;
 	fput(pipe);
 	/* fall through */
 fail_dput:
 	/*
 	 * dput() can block, so we clear the super block first.
 	 */
-	s->s_dev = 0;
 	dput(root);
 	goto fail_free;
 fail_iput:
@@ -261,32 +249,23 @@
 	/*
 	 * iput() can block, so we clear the super block first.
 	 */
-	s->s_dev = 0;
 	iput(root_inode);
 fail_free:
 	kfree(sbi);
-	goto fail_dec;
 fail_unlock:
-	unlock_super(s);
 fail_dec:
-	s->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-static int autofs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int autofs_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = AUTOFS_SUPER_MAGIC;
-	tmp.f_bsize = 1024;
-	tmp.f_blocks = 0;
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = AUTOFS_SUPER_MAGIC;
+	buf->f_bsize = 1024;
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_ffree = 0;
+	buf->f_namelen = NAME_MAX;
+	return 0;
 }
 
 static void autofs_read_inode(struct inode *inode)
diff -u --recursive --new-file v2.3.50/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.3.50/linux/fs/autofs/root.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/autofs/root.c	Wed Mar  8 09:04:09 2000
@@ -227,7 +227,7 @@
 	 * doesn't do the right thing for all system calls, but it should
 	 * be OK for the operations we permit from an autofs.
 	 */
-	if ( dentry->d_inode && list_empty(&dentry->d_hash) )
+	if ( dentry->d_inode && d_unhashed(dentry) )
 		return ERR_PTR(-ENOENT);
 
 	return NULL;
diff -u --recursive --new-file v2.3.50/linux/fs/autofs4/init.c linux/fs/autofs4/init.c
--- v2.3.50/linux/fs/autofs4/init.c	Fri Jan 28 15:09:08 2000
+++ linux/fs/autofs4/init.c	Fri Mar 10 10:48:48 2000
@@ -14,12 +14,7 @@
 #include <linux/init.h>
 #include "autofs_i.h"
 
-static struct file_system_type autofs_fs_type = {
-	"autofs",
-	0,
-	autofs4_read_super,
-	NULL
-};
+static DECLARE_FSTYPE(autofs_fs_type, "autofs", autofs4_read_super, 0);
 
 static int __init init_autofs4_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/autofs4/inode.c linux/fs/autofs4/inode.c
--- v2.3.50/linux/fs/autofs4/inode.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/autofs4/inode.c	Fri Mar 10 13:03:56 2000
@@ -103,10 +103,6 @@
 	kfree(sbi);
 
 	DPRINTK(("autofs: shutting down\n"));
-	
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif
 }
 
 static void autofs4_umount_begin(struct super_block *sb)
@@ -117,7 +113,7 @@
 		autofs4_catatonic_mode(sbi);
 }
 
-static int autofs4_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int autofs4_statfs(struct super_block *sb, struct statfs *buf);
 static void autofs4_read_inode(struct inode *inode);
 static void autofs4_write_inode(struct inode *inode);
 
@@ -219,9 +215,6 @@
 	struct autofs_sb_info *sbi;
 	int minproto, maxproto;
 
-	MOD_INC_USE_COUNT;
-
-	lock_super(s);
 	/* Super block already completed? */
 	if (s->s_root)
 		goto out_unlock;
@@ -248,7 +241,6 @@
 	s->s_magic = AUTOFS_SUPER_MAGIC;
 	s->s_op = &autofs4_sops;
 	s->s_root = NULL;
-	unlock_super(s); /* shouldn't we keep it locked a while longer? */
 
 	/*
 	 * Get the root inode and dentry, but defer checking for errors.
@@ -315,7 +307,6 @@
 	 * Success ... somebody else completed the super block for us. 
 	 */ 
 out_unlock:
-	unlock_super(s);
 	goto out_dec;
 out_fput:
 	if (pipe)
@@ -326,7 +317,6 @@
 	else
 		iput(root_inode);
 out_dec:
-	MOD_DEC_USE_COUNT;
 	return s;
 	
 	/*
@@ -337,14 +327,12 @@
 	/*
 	 * fput() can block, so we clear the super block first.
 	 */
-	s->s_dev = 0;
 	fput(pipe);
 	/* fall through */
 fail_dput:
 	/*
 	 * dput() can block, so we clear the super block first.
 	 */
-	s->s_dev = 0;
 	dput(root);
 	goto fail_free;
 fail_iput:
@@ -352,32 +340,22 @@
 	/*
 	 * iput() can block, so we clear the super block first.
 	 */
-	s->s_dev = 0;
 	iput(root_inode);
 fail_free:
 	kfree(sbi);
-	goto fail_dec;
 fail_unlock:
-	unlock_super(s);
-fail_dec:
-	s->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-static int autofs4_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int autofs4_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = AUTOFS_SUPER_MAGIC;
-	tmp.f_bsize = 1024;
-	tmp.f_blocks = 0;
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = AUTOFS_SUPER_MAGIC;
+	buf->f_bsize = 1024;
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_ffree = 0;
+	buf->f_namelen = NAME_MAX;
+	return 0;
 }
 
 static void autofs4_read_inode(struct inode *inode)
diff -u --recursive --new-file v2.3.50/linux/fs/autofs4/root.c linux/fs/autofs4/root.c
--- v2.3.50/linux/fs/autofs4/root.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/autofs4/root.c	Wed Mar  8 09:04:09 2000
@@ -353,7 +353,7 @@
 	 * doesn't do the right thing for all system calls, but it should
 	 * be OK for the operations we permit from an autofs.
 	 */
-	if ( dentry->d_inode && list_empty(&dentry->d_hash) )
+	if ( dentry->d_inode && d_unhashed(dentry) )
 		return ERR_PTR(-ENOENT);
 
 	return NULL;
diff -u --recursive --new-file v2.3.50/linux/fs/bfs/dir.c linux/fs/bfs/dir.c
--- v2.3.50/linux/fs/bfs/dir.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/bfs/dir.c	Fri Mar 10 10:48:53 2000
@@ -182,7 +182,7 @@
 	}
 	de->ino = 0;
 	dir->i_version = ++event;
-	mark_buffer_dirty(bh, 1);
+	mark_buffer_dirty(bh, 0);
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(dir);
 	inode->i_nlink--;
@@ -242,7 +242,7 @@
 		new_inode->i_ctime = CURRENT_TIME;
 		mark_inode_dirty(new_inode);
 	}
-	mark_buffer_dirty(old_bh, 1);
+	mark_buffer_dirty(old_bh, 0);
 	error = 0;
 
 end_rename:
@@ -294,7 +294,7 @@
 				de->ino = ino;
 				for (i=0; i<BFS_NAMELEN; i++)
 					de->name[i] = (i < namelen) ? name[i] : 0;
-				mark_buffer_dirty(bh, 1);
+				mark_buffer_dirty(bh, 0);
 				brelse(bh);
 				return 0;
 			}
diff -u --recursive --new-file v2.3.50/linux/fs/bfs/file.c linux/fs/bfs/file.c
--- v2.3.50/linux/fs/bfs/file.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/bfs/file.c	Fri Mar 10 10:48:53 2000
@@ -33,7 +33,7 @@
 		return -EIO;
 	new = getblk(dev, to, BFS_BSIZE);
 	memcpy(new->b_data, bh->b_data, bh->b_size);
-	mark_buffer_dirty(new, 1);
+	mark_buffer_dirty(new, 0);
 	bforget(bh);
 	brelse(new);
 	return 0;
diff -u --recursive --new-file v2.3.50/linux/fs/bfs/inode.c linux/fs/bfs/inode.c
--- v2.3.50/linux/fs/bfs/inode.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/bfs/inode.c	Fri Mar 10 10:48:53 2000
@@ -124,7 +124,7 @@
 	di->i_eblock = inode->iu_eblock;
 	di->i_eoffset = di->i_sblock * BFS_BSIZE + inode->i_size - 1;
 
-	mark_buffer_dirty(bh, 1);
+	mark_buffer_dirty(bh, 0);
 	brelse(bh);
 }
 
@@ -165,7 +165,7 @@
 	}
 	di->i_ino = 0;
 	di->i_sblock = 0;
-	mark_buffer_dirty(bh, 1);
+	mark_buffer_dirty(bh, 0);
 	brelse(bh);
 
 	/* if this was the last file, make the previous 
@@ -182,22 +182,19 @@
 {
 	brelse(s->su_sbh);
 	kfree(s->su_imap);
-	MOD_DEC_USE_COUNT;
 }
 
-static int bfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz)
+static int bfs_statfs(struct super_block *s, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = BFS_MAGIC;
-	tmp.f_bsize = s->s_blocksize;
-	tmp.f_blocks = s->su_blocks;
-	tmp.f_bfree = tmp.f_bavail = s->su_freeb;
-	tmp.f_files = s->su_lasti + 1 - BFS_ROOT_INO;
-	tmp.f_ffree = s->su_freei;
-	tmp.f_fsid.val[0] = s->s_dev;
-	tmp.f_namelen = BFS_NAMELEN;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = BFS_MAGIC;
+	buf->f_bsize = s->s_blocksize;
+	buf->f_blocks = s->su_blocks;
+	buf->f_bfree = buf->f_bavail = s->su_freeb;
+	buf->f_files = s->su_lasti + 1 - BFS_ROOT_INO;
+	buf->f_ffree = s->su_freei;
+	buf->f_fsid.val[0] = s->s_dev;
+	buf->f_namelen = BFS_NAMELEN;
+	return 0;
 }
 
 static void bfs_write_super(struct super_block *s)
@@ -245,8 +242,6 @@
 	struct inode * inode;
 	int i, imap_len;
 
-	MOD_INC_USE_COUNT;
-	lock_super(s);
 	dev = s->s_dev;
 	set_blocksize(dev, BFS_BSIZE);
 	s->s_blocksize = BFS_BSIZE;
@@ -318,22 +313,14 @@
 		s->s_dirt = 1;
 	} 
 	dump_imap("read_super", s);
-	unlock_super(s);
 	return s;
 
 out:
 	brelse(bh);
-	s->s_dev = 0;
-	unlock_super(s);
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-static struct file_system_type bfs_fs_type = {
-	name:		"bfs",
-	fs_flags:	FS_REQUIRES_DEV,
-	read_super:	bfs_read_super,
-};
+static DECLARE_FSTYPE_DEV( bfs_fs_type, "bfs", bfs_read_super);
 
 #ifdef MODULE
 #define init_bfs_fs init_module
diff -u --recursive --new-file v2.3.50/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.50/linux/fs/buffer.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/buffer.c	Thu Mar  9 21:12:27 2000
@@ -1754,10 +1754,10 @@
 	mark_buffer_uptodate(bh, uptodate);
 
 	kiobuf = bh->b_kiobuf;
-	if (!uptodate)
-		kiobuf->errno = -EIO;
-	if (atomic_dec_and_test(&kiobuf->io_count))
-		kiobuf->end_io(kiobuf);
+	unlock_buffer(bh);
+	
+	kiobuf = bh->b_kiobuf;
+	end_kio_request(kiobuf, uptodate);
 }
 
 
@@ -1766,8 +1766,7 @@
  * for them to complete.  Clean up the buffer_heads afterwards.  
  */
 
-static int do_kio(struct kiobuf *kiobuf,
-		  int rw, int nr, struct buffer_head *bh[], int size)
+static int do_kio(int rw, int nr, struct buffer_head *bh[], int size)
 {
 	int iosize;
 	int i;
@@ -1778,18 +1777,20 @@
 
 	if (rw == WRITE)
 		rw = WRITERAW;
-	atomic_add(nr, &kiobuf->io_count);
-	kiobuf->errno = 0;
 	ll_rw_block(rw, nr, bh);
 
-	kiobuf_wait_for_io(kiobuf);
-	
-	spin_lock(&unused_list_lock);
-	
 	iosize = 0;
+	spin_lock(&unused_list_lock);
+
 	for (i = nr; --i >= 0; ) {
 		iosize += size;
 		tmp = bh[i];
+		if (buffer_locked(tmp)) {
+			spin_unlock(&unused_list_lock);
+			wait_on_buffer(tmp);
+			spin_lock(&unused_list_lock);
+		}
+		
 		if (!buffer_uptodate(tmp)) {
 			/* We are traversing bh'es in reverse order so
                            clearing iosize on error calculates the
@@ -1801,11 +1802,7 @@
 	
 	spin_unlock(&unused_list_lock);
 
-	if (iosize)
-		return iosize;
-	if (kiobuf->errno)
-		return kiobuf->errno;
-	return -EIO;
+	return iosize;
 }
 
 /*
@@ -1847,8 +1844,6 @@
 		if ((iobuf->offset & (size-1)) ||
 		    (iobuf->length & (size-1)))
 			return -EINVAL;
-		if (!iobuf->locked)
-			panic("brw_kiovec: iobuf not locked for I/O");
 		if (!iobuf->nr_pages)
 			panic("brw_kiovec: iobuf not initialised");
 	}
@@ -1861,10 +1856,15 @@
 		iobuf = iovec[i];
 		offset = iobuf->offset;
 		length = iobuf->length;
-
+		iobuf->errno = 0;
+		
 		for (pageind = 0; pageind < iobuf->nr_pages; pageind++) {
 			map  = iobuf->maplist[pageind];
-
+			if (!map) {
+				err = -EFAULT;
+				goto error;
+			}
+			
 			while (length > 0) {
 				blocknr = b[bufind++];
 				tmp = get_unused_buffer_head(0);
@@ -1893,11 +1893,13 @@
 				length -= size;
 				offset += size;
 
+				atomic_inc(&iobuf->io_count);
+	
 				/* 
 				 * Start the IO if we have got too much 
 				 */
 				if (bhind >= KIO_MAX_SECTORS) {
-					err = do_kio(iobuf, rw, bhind, bh, size);
+					err = do_kio(rw, bhind, bh, size);
 					if (err >= 0)
 						transferred += err;
 					else
@@ -1915,7 +1917,7 @@
 
 	/* Is there any IO still left to submit? */
 	if (bhind) {
-		err = do_kio(iobuf, rw, bhind, bh, size);
+		err = do_kio(rw, bhind, bh, size);
 		if (err >= 0)
 			transferred += err;
 		else
diff -u --recursive --new-file v2.3.50/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.3.50/linux/fs/coda/dir.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/coda/dir.c	Wed Mar  8 09:04:09 2000
@@ -451,7 +451,7 @@
 
         dircnp = ITOC(dir);
 
-	if (!list_empty(&de->d_hash))
+	if (!d_unhashed(de))
 		return -EBUSY;
 	error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len);
 
diff -u --recursive --new-file v2.3.50/linux/fs/coda/inode.c linux/fs/coda/inode.c
--- v2.3.50/linux/fs/coda/inode.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/coda/inode.c	Fri Mar 10 10:48:48 2000
@@ -37,8 +37,7 @@
 static void coda_put_inode(struct inode *);
 static void coda_delete_inode(struct inode *);
 static void coda_put_super(struct super_block *);
-static int coda_statfs(struct super_block *sb, struct statfs *buf, 
-		       int bufsiz);
+static int coda_statfs(struct super_block *sb, struct statfs *buf);
 
 /* exported operations */
 struct super_operations coda_super_operations =
@@ -61,16 +60,13 @@
         int error;
 
 	ENTRY;
-        MOD_INC_USE_COUNT; 
 
         vc = &coda_upc_comm;
 	sbi = &coda_super_info;
 
         if ( sbi->sbi_sb ) {
 		printk("Already mounted\n");
-		unlock_super(sb);
 		EXIT;  
-		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 
@@ -80,7 +76,6 @@
 	INIT_LIST_HEAD(&(sbi->sbi_cchead));
 	INIT_LIST_HEAD(&(sbi->sbi_volroothead));
 
-        lock_super(sb);
         sb->u.generic_sbp = sbi;
         sb->s_blocksize = 1024;	/* XXXXX  what do we put here?? */
         sb->s_blocksize_bits = 10;
@@ -93,7 +88,6 @@
 	if ( error ) {
 	        printk("coda_read_super: coda_get_rootfid failed with %d\n",
 		       error);
-		sb->s_dev = 0;
 		goto error;
 	}	  
 	printk("coda_read_super: rootfid is %s\n", coda_f2s(&fid));
@@ -102,7 +96,6 @@
         error = coda_cnode_make(&root, &fid, sb);
         if ( error || !root ) {
 	    printk("Failure of coda_cnode_make for root: error %d\n", error);
-	    sb->s_dev = 0;
 	    goto error;
 	} 
 
@@ -110,14 +103,11 @@
 	       root->i_ino, root->i_dev);
 	sbi->sbi_root = root;
 	sb->s_root = d_alloc_root(root);
-	unlock_super(sb);
 	EXIT;  
         return sb;
 
  error:
-	unlock_super(sb);
 	EXIT;  
-	MOD_DEC_USE_COUNT;
 	if (sbi) {
 		sbi->sbi_vcomm = NULL;
 		sbi->sbi_root = NULL;
@@ -126,7 +116,6 @@
         if (root) {
                 iput(root);
         }
-        sb->s_dev = 0;
         return NULL;
 }
 
@@ -136,15 +125,12 @@
 
         ENTRY;
 
-
-        sb->s_dev = 0;
 	coda_cache_clear_all(sb);
 	sb_info = coda_sbp(sb);
 	coda_super_info.sbi_sb = NULL;
 	printk("Coda: Bye bye.\n");
 	memset(sb_info, 0, sizeof(* sb_info));
 
-        MOD_DEC_USE_COUNT;
 	EXIT;
 }
 
@@ -235,31 +221,25 @@
         return error;
 }
 
-static int coda_statfs(struct super_block *sb, struct statfs *buf, 
-		       int bufsiz)
+static int coda_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
 	int error;
 
-	memset(&tmp, 0, sizeof(struct statfs));
-
-	error = venus_statfs(sb, &tmp);
+	error = venus_statfs(sb, buf);
 
 	if (error) {
 		/* fake something like AFS does */
-		tmp.f_blocks = 9000000;
-		tmp.f_bfree  = 9000000;
-		tmp.f_bavail = 9000000;
-		tmp.f_files  = 9000000;
-		tmp.f_ffree  = 9000000;
+		buf->f_blocks = 9000000;
+		buf->f_bfree  = 9000000;
+		buf->f_bavail = 9000000;
+		buf->f_files  = 9000000;
+		buf->f_ffree  = 9000000;
 	}
 
 	/* and fill in the rest */
-	tmp.f_type = CODA_SUPER_MAGIC;
-	tmp.f_bsize = 1024;
-	tmp.f_namelen = CODA_MAXNAMLEN;
-
-	copy_to_user(buf, &tmp, bufsiz);
+	buf->f_type = CODA_SUPER_MAGIC;
+	buf->f_bsize = 1024;
+	buf->f_namelen = CODA_MAXNAMLEN;
 
 	return 0; 
 }
@@ -267,9 +247,7 @@
 
 /* init_coda: used by filesystems.c to register coda */
 
-struct file_system_type coda_fs_type = {
-   "coda", 0, coda_read_super, NULL
-};
+DECLARE_FSTYPE( coda_fs_type, "coda", coda_read_super, 0);
 
 int init_coda_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c
--- v2.3.50/linux/fs/cramfs/inode.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/cramfs/inode.c	Fri Mar 10 10:48:48 2000
@@ -153,7 +153,6 @@
 	unsigned long root_offset;
 	struct super_block * retval = NULL;
 
-	lock_super(sb);
 	set_blocksize(sb->s_dev, PAGE_CACHE_SIZE);
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -198,7 +197,6 @@
 	retval = sb;
 
 out:
-	unlock_super(sb);
 	return retval;
 }
 
@@ -208,20 +206,15 @@
 	return;
 }
 
-static int cramfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+static int cramfs_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs 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_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = 255;
-	return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
+	buf->f_type = CRAMFS_MAGIC;
+	buf->f_bsize = PAGE_CACHE_SIZE;
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_ffree = 0;
+	buf->f_namelen = 255;
+	return 0;
 }
 
 /*
@@ -372,12 +365,7 @@
 	statfs:		cramfs_statfs,
 };
 
-static struct file_system_type cramfs_fs_type = {
-	"cramfs",
-	FS_REQUIRES_DEV,
-	cramfs_read_super,
-	NULL
-};
+static DECLARE_FSTYPE_DEV(cramfs_fs_type, "cramfs", cramfs_read_super);
 
 static int __init init_cramfs_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/devfs/base.c linux/fs/devfs/base.c
--- v2.3.50/linux/fs/devfs/base.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/devfs/base.c	Fri Mar 10 10:48:48 2000
@@ -2305,27 +2305,21 @@
     if (devfs_debug & DEBUG_S_PUT)
 	printk ("%s: put_super(): devfs ptr: %p\n", DEVFS_NAME, fs_info);
 #endif
-    sb->s_dev = 0;
 #ifdef CONFIG_DEVFS_TUNNEL
     dput (fs_info->table[0]->covered);
 #endif
     delete_fs (fs_info);
-    MOD_DEC_USE_COUNT;
 }   /*  End Function devfs_put_super  */
 
-static int devfs_statfs (struct super_block *sb, struct statfs *buf,int bufsiz)
+static int devfs_statfs (struct super_block *sb, struct statfs *buf)
 {
-    struct statfs tmp;
-
-    tmp.f_type = DEVFS_SUPER_MAGIC;
-    tmp.f_bsize = PAGE_SIZE / sizeof (long);
-    tmp.f_blocks = 0;
-    tmp.f_bfree = 0;
-    tmp.f_bavail = 0;
-    tmp.f_files = 0;
-    tmp.f_ffree = 0;
-    tmp.f_namelen = NAME_MAX;
-    return copy_to_user (buf, &tmp, bufsiz) ? -EFAULT : 0;
+    buf->f_type = DEVFS_SUPER_MAGIC;
+    buf->f_bsize = PAGE_SIZE / sizeof (long);
+    buf->f_bfree = 0;
+    buf->f_bavail = 0;
+    buf->f_ffree = 0;
+    buf->f_namelen = NAME_MAX;
+    return 0;
 }   /*  End Function devfs_statfs  */
 
 static struct super_operations devfs_sops =
@@ -3152,7 +3146,6 @@
     {
 	if (strcmp (aopt, "explicit") == 0) fs_info->require_explicit = TRUE;
     }
-    lock_super (sb);
     sb->u.generic_sbp = fs_info;
     sb->s_blocksize = 1024;
     sb->s_blocksize_bits = 10;
@@ -3173,32 +3166,22 @@
 #ifdef CONFIG_DEVFS_TUNNEL
     di->covered = dget (sb->s_root->d_covered);
 #endif
-    unlock_super (sb);
 #ifdef CONFIG_DEVFS_DEBUG
     if (devfs_debug & DEBUG_DISABLED)
 	printk ("%s: read super, made devfs ptr: %p\n",
 		DEVFS_NAME, sb->u.generic_sbp);
 #endif
-    MOD_INC_USE_COUNT;
     return sb;
 
 out_no_root:
     printk ("devfs_read_super: get root inode failed\n");
     delete_fs (fs_info);
     if (root_inode) iput (root_inode);
-    sb->s_dev = 0;
-    unlock_super (sb);
     return NULL;
 }   /*  End Function devfs_read_super  */
 
 
-static struct file_system_type devfs_fs_type =
-{
-    DEVFS_NAME, 
-    0,
-    devfs_read_super, 
-    NULL,
-};
+static DECLARE_FSTYPE(devfs_fs_type, DEVFS_NAME, devfs_read_super, 0);
 
 
 /*  File operations for devfsd follow  */
diff -u --recursive --new-file v2.3.50/linux/fs/devpts/inode.c linux/fs/devpts/inode.c
--- v2.3.50/linux/fs/devpts/inode.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/devpts/inode.c	Fri Mar 10 13:41:50 2000
@@ -51,19 +51,13 @@
 
 	kfree(sbi->inodes);
 	kfree(sbi);
-
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif
 }
 
-static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int devpts_statfs(struct super_block *sb, struct statfs *buf);
 static void devpts_read_inode(struct inode *inode);
-static void devpts_write_inode(struct inode *inode);
 
 static struct super_operations devpts_sops = {
 	read_inode:	devpts_read_inode,
-	write_inode:	devpts_write_inode,
 	put_super:	devpts_put_super,
 	statfs:		devpts_statfs,
 };
@@ -125,9 +119,6 @@
 	struct dentry * root;
 	struct devpts_sb_info *sbi;
 
-	MOD_INC_USE_COUNT;
-
-	lock_super(s);
 	/* Super block already completed? */
 	if (s->s_root)
 		goto out_unlock;
@@ -151,7 +142,6 @@
 	s->s_magic = DEVPTS_SUPER_MAGIC;
 	s->s_op = &devpts_sops;
 	s->s_root = NULL;
-	unlock_super(s); /* shouldn't we keep it locked a while longer? */
 
 	/*
 	 * Get the root inode and dentry, but defer checking for errors.
@@ -183,7 +173,6 @@
 	/*
 	 * Success! Install the root dentry now to indicate completion.
 	 */
-	lock_super(s);
 	s->s_root = root;
 
 	sbi->next = mounts;
@@ -192,14 +181,12 @@
 	sbi->back = &mounts;
 	mounts = s;
 
-	unlock_super(s);
 	return s;
 
 	/*
 	 * Success ... somebody else completed the super block for us. 
 	 */ 
 out_unlock:
-	unlock_super(s);
 	goto out_dec;
 out_dput:
 	if (root)
@@ -207,7 +194,6 @@
 	else
 		iput(root_inode);
 out_dec:
-	MOD_DEC_USE_COUNT;
 	return s;
 	
 	/*
@@ -217,7 +203,6 @@
 	/*
 	 * dput() can block, so we clear the super block first.
 	 */
-	s->s_dev = 0;
 	dput(root);
 	goto fail_free;
 fail_iput:
@@ -225,32 +210,22 @@
 	/*
 	 * iput() can block, so we clear the super block first.
 	 */
-	s->s_dev = 0;
 	iput(root_inode);
 fail_free:
 	kfree(sbi);
-	goto fail_dec;
 fail_unlock:
-	unlock_super(s);
-fail_dec:
-	s->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-static int devpts_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int devpts_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = DEVPTS_SUPER_MAGIC;
-	tmp.f_bsize = 1024;
-	tmp.f_blocks = 0;
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = DEVPTS_SUPER_MAGIC;
+	buf->f_bsize = 1024;
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_ffree = 0;
+	buf->f_namelen = NAME_MAX;
+	return 0;
 }
 
 static void devpts_read_inode(struct inode *inode)
@@ -284,16 +259,7 @@
 	return;
 }
 
-static void devpts_write_inode(struct inode *inode)
-{
-}
-
-static struct file_system_type devpts_fs_type = {
-	"devpts",
-	0,
-	devpts_read_super,
-	NULL
-};
+static DECLARE_FSTYPE(devpts_fs_type, "devpts", devpts_read_super, 0);
 
 void devpts_pty_new(int number, kdev_t device)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/efs/super.c linux/fs/efs/super.c
--- v2.3.50/linux/fs/efs/super.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/efs/super.c	Fri Mar 10 10:48:48 2000
@@ -13,12 +13,7 @@
 #include <linux/efs_vh.h>
 #include <linux/efs_fs_sb.h>
 
-static struct file_system_type efs_fs_type = {
-	"efs",			/* filesystem name */
-	FS_REQUIRES_DEV,	/* fs_flags */
-	efs_read_super,		/* entry function pointer */
-	NULL 			/* next */
-};
+static DECLARE_FSTYPE_DEV(efs_fs_type, "efs", efs_read_super);
 
 static struct super_operations efs_superblock_operations = {
 	read_inode:	efs_read_inode,
@@ -145,9 +140,6 @@
 	struct efs_sb_info *sb;
 	struct buffer_head *bh;
 
-	MOD_INC_USE_COUNT;
-	lock_super(s);
-  
  	sb = SUPER_INFO(s);
 
 	set_blocksize(dev, EFS_BLOCKSIZE);
@@ -199,7 +191,6 @@
 	s->s_op   = &efs_superblock_operations;
 	s->s_dev  = dev;
 	s->s_root = d_alloc_root(iget(s, EFS_ROOTINODE));
-	unlock_super(s);
  
 	if (!(s->s_root)) {
 		printk(KERN_ERR "EFS: get root inode failed\n");
@@ -214,35 +205,30 @@
 	return(s);
 
 out_no_fs_ul:
-	unlock_super(s);
 out_no_fs:
-	s->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return(NULL);
 }
 
 void efs_put_super(struct super_block *s) {
-	MOD_DEC_USE_COUNT;
 }
 
-int efs_statfs(struct super_block *s, struct statfs *buf, int bufsiz) {
-	struct statfs ret;
+int efs_statfs(struct super_block *s, struct statfs *buf) {
 	struct efs_sb_info *sb = SUPER_INFO(s);
 
-	ret.f_type    = EFS_SUPER_MAGIC;	/* efs magic number */
-	ret.f_bsize   = EFS_BLOCKSIZE;		/* blocksize */
-	ret.f_blocks  = sb->total_groups *	/* total data blocks */
+	buf->f_type    = EFS_SUPER_MAGIC;	/* efs magic number */
+	buf->f_bsize   = EFS_BLOCKSIZE;		/* blocksize */
+	buf->f_blocks  = sb->total_groups *	/* total data blocks */
 			(sb->group_size - sb->inode_blocks);
-	ret.f_bfree   = sb->data_free;		/* free data blocks */
-	ret.f_bavail  = sb->data_free;		/* free blocks for non-root */
-	ret.f_files   = sb->total_groups *	/* total inodes */
+	buf->f_bfree   = sb->data_free;		/* free data blocks */
+	buf->f_bavail  = sb->data_free;		/* free blocks for non-root */
+	buf->f_files   = sb->total_groups *	/* total inodes */
 			sb->inode_blocks *
 			(EFS_BLOCKSIZE / sizeof(struct efs_dinode));
-	ret.f_ffree   = sb->inode_free;	/* free inodes */
-	ret.f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */
-	ret.f_fsid.val[1] =  sb->fs_magic        & 0xffff; /* fs ID */
-	ret.f_namelen = EFS_MAXNAMELEN;		/* max filename length */
+	buf->f_ffree   = sb->inode_free;	/* free inodes */
+	buf->f_fsid.val[0] = (sb->fs_magic >> 16) & 0xffff; /* fs ID */
+	buf->f_fsid.val[1] =  sb->fs_magic        & 0xffff; /* fs ID */
+	buf->f_namelen = EFS_MAXNAMELEN;	/* max filename length */
 
-	return copy_to_user(buf, &ret, bufsiz) ? -EFAULT : 0;
+	return 0;
 }
 
diff -u --recursive --new-file v2.3.50/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v2.3.50/linux/fs/ext2/balloc.c	Mon Dec 20 18:48:22 1999
+++ linux/fs/ext2/balloc.c	Fri Mar 10 14:52:42 2000
@@ -679,6 +679,7 @@
 		test_root(group, 7));
 }
 
+/* Called at mount-time, super-block is locked */
 void ext2_check_blocks_bitmap (struct super_block * sb)
 {
 	struct buffer_head * bh;
@@ -689,7 +690,6 @@
 	struct ext2_group_desc * gdp;
 	int i, j;
 
-	lock_super (sb);
 	es = sb->u.ext2_sb.s_es;
 	desc_count = 0;
 	bitmap_count = 0;
@@ -752,5 +752,4 @@
 			    "Wrong free blocks count in super block, "
 			    "stored = %lu, counted = %lu",
 			    (unsigned long) le32_to_cpu(es->s_free_blocks_count), bitmap_count);
-	unlock_super (sb);
 }
diff -u --recursive --new-file v2.3.50/linux/fs/ext2/ialloc.c linux/fs/ext2/ialloc.c
--- v2.3.50/linux/fs/ext2/ialloc.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/ext2/ialloc.c	Fri Mar 10 14:52:34 2000
@@ -527,6 +527,7 @@
 #endif
 }
 
+/* Called at mount-time, super-block is locked */
 void ext2_check_inodes_bitmap (struct super_block * sb)
 {
 	struct ext2_super_block * es;
@@ -535,7 +536,6 @@
 	struct ext2_group_desc * gdp;
 	int i;
 
-	lock_super (sb);
 	es = sb->u.ext2_sb.s_es;
 	desc_count = 0;
 	bitmap_count = 0;
@@ -564,5 +564,4 @@
 			    "stored = %lu, counted = %lu",
 			    (unsigned long) le32_to_cpu(es->s_free_inodes_count),
 			    bitmap_count);
-	unlock_super (sb);
 }
diff -u --recursive --new-file v2.3.50/linux/fs/ext2/super.c linux/fs/ext2/super.c
--- v2.3.50/linux/fs/ext2/super.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/ext2/super.c	Fri Mar 10 10:48:48 2000
@@ -116,7 +116,6 @@
 			brelse (sb->u.ext2_sb.s_block_bitmap[i]);
 	brelse (sb->u.ext2_sb.s_sbh);
 
-	MOD_DEC_USE_COUNT;
 	return;
 }
 
@@ -402,12 +401,9 @@
 	set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);
 	if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
 	    &sb->u.ext2_sb.s_mount_opt)) {
-		sb->s_dev = 0;
 		return NULL;
 	}
 
-	MOD_INC_USE_COUNT;
-	lock_super (sb);
 	set_blocksize (dev, blocksize);
 
 	/*
@@ -421,10 +417,7 @@
 	}
 
 	if (!(bh = bread (dev, logic_sb_block, blocksize))) {
-		sb->s_dev = 0;
-		unlock_super (sb);
 		printk ("EXT2-fs: unable to read superblock\n");
-		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	/*
@@ -439,11 +432,8 @@
 			printk ("VFS: Can't find an ext2 filesystem on dev "
 				"%s.\n", bdevname(dev));
 	failed_mount:
-		sb->s_dev = 0;
-		unlock_super (sb);
 		if (bh)
 			brelse(bh);
-		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) {
@@ -616,7 +606,6 @@
 	sb->u.ext2_sb.s_loaded_inode_bitmaps = 0;
 	sb->u.ext2_sb.s_loaded_block_bitmaps = 0;
 	sb->u.ext2_sb.s_db_per_group = db_count;
-	unlock_super (sb);
 	/*
 	 * set up enough so that it can read an inode
 	 */
@@ -624,7 +613,6 @@
 	sb->s_op = &ext2_sops;
 	sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO));
 	if (!sb->s_root) {
-		sb->s_dev = 0;
 		for (i = 0; i < db_count; i++)
 			if (sb->u.ext2_sb.s_group_desc[i])
 				brelse (sb->u.ext2_sb.s_group_desc[i]);
@@ -632,7 +620,6 @@
 			 db_count * sizeof (struct buffer_head *));
 		brelse (bh);
 		printk ("EXT2-fs: get root inode failed\n");
-		MOD_DEC_USE_COUNT;
 		return NULL;
 	}
 	ext2_setup_super (sb, es);
@@ -725,10 +712,9 @@
 	return 0;
 }
 
-int ext2_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
+int ext2_statfs (struct super_block * sb, struct statfs * buf)
 {
 	unsigned long overhead;
-	struct statfs tmp;
 	int	ngroups, i;
 
 	if (test_opt (sb, MINIX_DF))
@@ -768,25 +754,20 @@
 			     (2 + sb->u.ext2_sb.s_itb_per_group));
 	}
 
-	tmp.f_type = EXT2_SUPER_MAGIC;
-	tmp.f_bsize = sb->s_blocksize;
-	tmp.f_blocks = le32_to_cpu(sb->u.ext2_sb.s_es->s_blocks_count) - overhead;
-	tmp.f_bfree = ext2_count_free_blocks (sb);
-	tmp.f_bavail = tmp.f_bfree - le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count);
-	if (tmp.f_bfree < le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count))
-		tmp.f_bavail = 0;
-	tmp.f_files = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count);
-	tmp.f_ffree = ext2_count_free_inodes (sb);
-	tmp.f_namelen = EXT2_NAME_LEN;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = EXT2_SUPER_MAGIC;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = le32_to_cpu(sb->u.ext2_sb.s_es->s_blocks_count) - overhead;
+	buf->f_bfree = ext2_count_free_blocks (sb);
+	buf->f_bavail = buf->f_bfree - le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count);
+	if (buf->f_bfree < le32_to_cpu(sb->u.ext2_sb.s_es->s_r_blocks_count))
+		buf->f_bavail = 0;
+	buf->f_files = le32_to_cpu(sb->u.ext2_sb.s_es->s_inodes_count);
+	buf->f_ffree = ext2_count_free_inodes (sb);
+	buf->f_namelen = EXT2_NAME_LEN;
+	return 0;
 }
 
-static struct file_system_type ext2_fs_type = {
-	"ext2", 
-	FS_REQUIRES_DEV /* | FS_IBASKET */,	/* ibaskets have unresolved bugs */
-        ext2_read_super, 
-	NULL
-};
+static DECLARE_FSTYPE_DEV(ext2_fs_type, "ext2", ext2_read_super);
 
 static int __init init_ext2_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.3.50/linux/fs/fat/inode.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/fat/inode.c	Fri Mar 10 10:48:48 2000
@@ -194,11 +194,6 @@
 		kfree(MSDOS_SB(sb)->options.iocharset);
 		MSDOS_SB(sb)->options.iocharset = NULL;
 	}
-
-	if (MSDOS_SB(sb)->put_super_callback)
-		MSDOS_SB(sb)->put_super_callback(sb);
-	MOD_DEC_USE_COUNT;
-	return;
 }
 
 
@@ -444,9 +439,7 @@
 	sbi->cvf_format = NULL;
 	sbi->private_data = NULL;
 
-	MOD_INC_USE_COUNT;
 	sbi->dir_ops = fs_dir_inode_ops;
-	sbi->put_super_callback = NULL;
 	sb->s_op = &fat_sops;
 	if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
 		blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)];
@@ -465,7 +458,6 @@
 	memcpy(&(sbi->options), &opts, sizeof(struct fat_mount_options));
 
 	fat_cache_init();
-	lock_super(sb);
 	if( blksize > 1024 )
 	  {
 	    /* Force the superblock to a larger size here. */
@@ -479,7 +471,6 @@
 	    set_blocksize(sb->s_dev, 1024);
 	  }
 	bh = bread(sb->s_dev, 0, sb->s_blocksize);
-	unlock_super(sb);
 	if (bh == NULL || !buffer_uptodate(bh)) {
 		brelse (bh);
 		goto out_no_bread;
@@ -693,23 +684,21 @@
 		printk("VFS: freeing iocharset=%s\n", opts.iocharset);
 		kfree(opts.iocharset);
 	}
-	sb->s_dev = 0;
 	if(sbi->private_data)
 		kfree(sbi->private_data);
 	sbi->private_data=NULL;
  
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-int fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
+int fat_statfs(struct super_block *sb,struct statfs *buf)
 {
 	int free,nr;
-	struct statfs tmp;
        
 	if (MSDOS_SB(sb)->cvf_format &&
 	    MSDOS_SB(sb)->cvf_format->cvf_statfs)
-		return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,bufsiz);
+		return MSDOS_SB(sb)->cvf_format->cvf_statfs(sb,buf,
+						sizeof(struct statfs));
 	  
 	lock_fat(sb);
 	if (MSDOS_SB(sb)->free_clusters != -1)
@@ -721,15 +710,13 @@
 		MSDOS_SB(sb)->free_clusters = free;
 	}
 	unlock_fat(sb);
-	tmp.f_type = sb->s_magic;
-	tmp.f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
-	tmp.f_blocks = MSDOS_SB(sb)->clusters;
-	tmp.f_bfree = free;
-	tmp.f_bavail = free;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = sb->s_magic;
+	buf->f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
+	buf->f_blocks = MSDOS_SB(sb)->clusters;
+	buf->f_bfree = free;
+	buf->f_bavail = free;
+	buf->f_namelen = MSDOS_SB(sb)->options.isvfat ? 260 : 12;
+	return 0;
 }
 
 static int is_exec(char *extension)
diff -u --recursive --new-file v2.3.50/linux/fs/filesystems.c linux/fs/filesystems.c
--- v2.3.50/linux/fs/filesystems.c	Wed Feb 16 17:03:52 2000
+++ linux/fs/filesystems.c	Fri Mar 10 10:48:48 2000
@@ -32,7 +32,6 @@
 #include <linux/hfs_fs.h>
 #include <linux/devpts_fs.h>
 #include <linux/bfs_fs.h>
-#include <linux/adfs_fs.h>
 #include <linux/openprom_fs.h>
 #include <linux/major.h>
 #include <linux/smp.h>
@@ -89,10 +88,6 @@
 
 	init_devfs_fs();  /*  Header file may make this empty  */
 
-#ifdef CONFIG_LOCKD
-	nlmxdr_init();
-#endif
-
 #ifdef CONFIG_NFS_FS
 	init_nfs_fs();
 #endif
@@ -139,10 +134,6 @@
 
 #ifdef CONFIG_EFS_FS
 	init_efs_fs();
-#endif
-
-#ifdef CONFIG_ADFS_FS
-	init_adfs_fs();
 #endif
 
 #ifdef CONFIG_DEVPTS_FS
diff -u --recursive --new-file v2.3.50/linux/fs/hfs/dir.c linux/fs/hfs/dir.c
--- v2.3.50/linux/fs/hfs/dir.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/hfs/dir.c	Wed Mar  8 09:04:09 2000
@@ -311,7 +311,7 @@
 		goto hfs_rmdir_put;
 
 	error = -EBUSY;
-	if (!list_empty(&dentry->d_hash))
+	if (!d_unhashed(dentry))
 		goto hfs_rmdir_put;
 
 	if (/* we only have to worry about 2 and 3 for mount points */
diff -u --recursive --new-file v2.3.50/linux/fs/hfs/super.c linux/fs/hfs/super.c
--- v2.3.50/linux/fs/hfs/super.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/hfs/super.c	Fri Mar 10 10:48:48 2000
@@ -36,7 +36,7 @@
 
 static void hfs_read_inode(struct inode *);
 static void hfs_put_super(struct super_block *);
-static int hfs_statfs(struct super_block *, struct statfs *, int);
+static int hfs_statfs(struct super_block *, struct statfs *);
 static void hfs_write_super(struct super_block *);
 
 /*================ Global variables ================*/
@@ -51,11 +51,7 @@
 
 /*================ File-local variables ================*/
 
-static struct file_system_type hfs_fs = {
-        "hfs",
-	FS_REQUIRES_DEV,
-	hfs_read_super, 
-	NULL};
+static DECLARE_FSTYPE_DEV(hfs_fs, "hfs", hfs_read_super);
 
 /*================ File-local functions ================*/
 
@@ -126,8 +122,6 @@
 
 	/* restore default blocksize for the device */
 	set_blocksize(sb->s_dev, BLOCK_SIZE);
-
-	MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -139,21 +133,20 @@
  *
  * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks.
  */
-static int hfs_statfs(struct super_block *sb, struct statfs *buf, int len)
+static int hfs_statfs(struct super_block *sb, struct statfs *buf)
 {
 	struct hfs_mdb *mdb = HFS_SB(sb)->s_mdb;
-	struct statfs tmp;
 
-	tmp.f_type = HFS_SUPER_MAGIC;
-	tmp.f_bsize = HFS_SECTOR_SIZE;
-	tmp.f_blocks = mdb->alloc_blksz * mdb->fs_ablocks;
-	tmp.f_bfree = mdb->alloc_blksz * mdb->free_ablocks;
-	tmp.f_bavail = tmp.f_bfree;
-	tmp.f_files = mdb->fs_ablocks;  
-	tmp.f_ffree = mdb->free_ablocks;
-	tmp.f_namelen = HFS_NAMELEN;
+	buf->f_type = HFS_SUPER_MAGIC;
+	buf->f_bsize = HFS_SECTOR_SIZE;
+	buf->f_blocks = mdb->alloc_blksz * mdb->fs_ablocks;
+	buf->f_bfree = mdb->alloc_blksz * mdb->free_ablocks;
+	buf->f_bavail = buf->f_bfree;
+	buf->f_files = mdb->fs_ablocks;  
+	buf->f_ffree = mdb->free_ablocks;
+	buf->f_namelen = HFS_NAMELEN;
 
-	return copy_to_user(buf, &tmp, len) ? -EFAULT : 0;
+	return 0;
 }
 
 /*
@@ -407,11 +400,6 @@
 		goto bail3;
 	}
 
-	/* in case someone tries to unload the module while we wait on I/O */
-	MOD_INC_USE_COUNT;
-
-	lock_super(s);
-
 	/* set the device driver to 512-byte blocks */
 	set_blocksize(dev, HFS_SECTOR_SIZE);
 
@@ -471,7 +459,6 @@
 	s->s_root->d_op = &hfs_dentry_operations;
 
 	/* everything's okay */
-	unlock_super(s);
 	return s;
 
 bail_no_root: 
@@ -481,10 +468,7 @@
 	hfs_mdb_put(mdb, s->s_flags & MS_RDONLY);
 bail2:
 	set_blocksize(dev, BLOCK_SIZE);
-	unlock_super(s);
-	MOD_DEC_USE_COUNT;
 bail3:
-	s->s_dev = 0;
 	return NULL;	
 }
 
diff -u --recursive --new-file v2.3.50/linux/fs/hpfs/hpfs_fn.h linux/fs/hpfs/hpfs_fn.h
--- v2.3.50/linux/fs/hpfs/hpfs_fn.h	Sat Feb 26 22:31:53 2000
+++ linux/fs/hpfs/hpfs_fn.h	Wed Mar  8 13:55:08 2000
@@ -311,7 +311,7 @@
 int hpfs_remount_fs(struct super_block *, int *, char *);
 void hpfs_put_super(struct super_block *);
 unsigned hpfs_count_one_bitmap(struct super_block *, secno);
-int hpfs_statfs(struct super_block *, struct statfs *, int);
+int hpfs_statfs(struct super_block *, struct statfs *);
 struct super_block *hpfs_read_super(struct super_block *, void *, int);
 
 extern struct address_space_operations hpfs_aops;
diff -u --recursive --new-file v2.3.50/linux/fs/hpfs/namei.c linux/fs/hpfs/namei.c
--- v2.3.50/linux/fs/hpfs/namei.c	Sun Feb 13 19:29:04 2000
+++ linux/fs/hpfs/namei.c	Wed Mar  8 09:04:09 2000
@@ -375,7 +375,7 @@
 		hpfs_unlock_2inodes(dir, inode);
 		return -ENOTDIR;
 	}
-	if (!list_empty(&dentry->d_hash)) {
+	if (!d_unhashed(dentry)) {
 		hpfs_brelse4(&qbh);
 		hpfs_unlock_2inodes(dir, inode);
 		return -EBUSY;
diff -u --recursive --new-file v2.3.50/linux/fs/hpfs/super.c linux/fs/hpfs/super.c
--- v2.3.50/linux/fs/hpfs/super.c	Sat Feb 26 22:31:53 2000
+++ linux/fs/hpfs/super.c	Fri Mar 10 10:48:48 2000
@@ -102,8 +102,6 @@
 	if (s->s_hpfs_cp_table) kfree(s->s_hpfs_cp_table);
 	if (s->s_hpfs_bmp_dir) kfree(s->s_hpfs_bmp_dir);
 	unmark_dirty(s);
-	s->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 }
 
 unsigned hpfs_count_one_bitmap(struct super_block *s, secno secno)
@@ -132,22 +130,21 @@
 	return count;
 }
 
-int hpfs_statfs(struct super_block *s, struct statfs *buf, int bufsiz)
+int hpfs_statfs(struct super_block *s, struct statfs *buf)
 {
-	struct statfs tmp;
 	/*if (s->s_hpfs_n_free == -1) {*/
 		s->s_hpfs_n_free = count_bitmaps(s);
 		s->s_hpfs_n_free_dnodes = hpfs_count_one_bitmap(s, s->s_hpfs_dmap);
 	/*}*/
-	tmp.f_type = s->s_magic;
-	tmp.f_bsize = 512;
-	tmp.f_blocks = s->s_hpfs_fs_size;
-	tmp.f_bfree = s->s_hpfs_n_free;
-	tmp.f_bavail = s->s_hpfs_n_free;
-	tmp.f_files = s->s_hpfs_dirband_size / 4;
-	tmp.f_ffree = s->s_hpfs_n_free_dnodes;
-	tmp.f_namelen = 254;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = s->s_magic;
+	buf->f_bsize = 512;
+	buf->f_blocks = s->s_hpfs_fs_size;
+	buf->f_bfree = s->s_hpfs_n_free;
+	buf->f_bavail = s->s_hpfs_n_free;
+	buf->f_files = s->s_hpfs_dirband_size / 4;
+	buf->f_ffree = s->s_hpfs_n_free_dnodes;
+	buf->f_namelen = 254;
+	return 0;
 }
 
 /* Super operations */
@@ -369,8 +366,6 @@
 
 	int o;
 
-	MOD_INC_USE_COUNT;
-
 	s->s_hpfs_bmp_dir = NULL;
 	s->s_hpfs_cp_table = NULL;
 
@@ -400,7 +395,6 @@
 	}
 
 	/*s->s_hpfs_mounting = 1;*/
-	lock_super(s);
 	dev = s->s_dev;
 	set_blocksize(dev, 512);
 	s->s_hpfs_fs_size = -1;
@@ -524,7 +518,6 @@
 	hpfs_lock_iget(s, 1);
 	s->s_root = d_alloc_root(iget(s, s->s_hpfs_root));
 	hpfs_unlock_iget(s);
-	unlock_super(s);
 	if (!s->s_root || !s->s_root->d_inode) {
 		printk("HPFS: iget failed. Why???\n");
 		goto bail0;
@@ -555,17 +548,14 @@
 bail4:	brelse(bh2);
 bail3:	brelse(bh1);
 bail2:	brelse(bh0);
-bail1:	unlock_super(s);
-bail0:	s->s_dev = 0;
+bail1:
+bail0:
 	if (s->s_hpfs_bmp_dir) kfree(s->s_hpfs_bmp_dir);
 	if (s->s_hpfs_cp_table) kfree(s->s_hpfs_cp_table);
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-struct file_system_type hpfs_fs_type = {
-	"hpfs", FS_REQUIRES_DEV, hpfs_read_super, NULL
-};
+DECLARE_FSTYPE_DEV(hpfs_fs_type, "hpfs", hpfs_read_super);
 
 int init_hpfs_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/inode.c linux/fs/inode.c
--- v2.3.50/linux/fs/inode.c	Sat Feb 26 22:31:53 2000
+++ linux/fs/inode.c	Wed Mar  8 09:04:09 2000
@@ -94,6 +94,7 @@
 		INIT_LIST_HEAD(&inode->i_data.pages);
 		INIT_LIST_HEAD(&inode->i_dentry);
 		sema_init(&inode->i_sem, 1);
+		sema_init(&inode->i_zombie, 1);
 		spin_lock_init(&inode->i_data.i_shared_lock);
 	}
 }
diff -u --recursive --new-file v2.3.50/linux/fs/iobuf.c linux/fs/iobuf.c
--- v2.3.50/linux/fs/iobuf.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/iobuf.c	Thu Mar  9 21:12:27 2000
@@ -12,18 +12,21 @@
 
 static kmem_cache_t *kiobuf_cachep;
 
-/*
- * The default IO completion routine for kiobufs: just wake up
- * the kiobuf, nothing more.  
- */
 
-void simple_wakeup_kiobuf(struct kiobuf *kiobuf)
+void end_kio_request(struct kiobuf *kiobuf, int uptodate)
 {
-	wake_up(&kiobuf->wait_queue);
+	if ((!uptodate) && !kiobuf->errno)
+		kiobuf->errno = -EIO;
+
+	if (atomic_dec_and_test(&kiobuf->io_count)) {
+		if (kiobuf->end_io)
+			kiobuf->end_io(kiobuf);
+		wake_up(&kiobuf->wait_queue);
+	}
 }
 
 
-void __init kiobuf_init(void)
+void __init kiobuf_setup(void)
 {
 	kiobuf_cachep =  kmem_cache_create("kiobuf",
 					   sizeof(struct kiobuf),
@@ -33,6 +36,13 @@
 		panic("Cannot create kernel iobuf cache\n");
 }
 
+void kiobuf_init(struct kiobuf *iobuf)
+{
+	memset(iobuf, 0, sizeof(*iobuf));
+	init_waitqueue_head(&iobuf->wait_queue);
+	iobuf->array_len = KIO_STATIC_PAGES;
+	iobuf->maplist   = iobuf->map_array;
+}
 
 int alloc_kiovec(int nr, struct kiobuf **bufp)
 {
@@ -45,12 +55,7 @@
 			free_kiovec(i, bufp);
 			return -ENOMEM;
 		}
-		
-		memset(iobuf, 0, sizeof(*iobuf));
-		init_waitqueue_head(&iobuf->wait_queue);
-		iobuf->end_io = simple_wakeup_kiobuf;
-		iobuf->array_len = KIO_STATIC_PAGES;
-		iobuf->maplist   = iobuf->map_array;
+		kiobuf_init(iobuf);
 		*bufp++ = iobuf;
 	}
 	
@@ -64,6 +69,8 @@
 	
 	for (i = 0; i < nr; i++) {
 		iobuf = bufp[i];
+		if (iobuf->locked)
+			unlock_kiovec(1, &iobuf);
 		if (iobuf->array_len > KIO_STATIC_PAGES)
 			kfree (iobuf->maplist);
 		kmem_cache_free(kiobuf_cachep, bufp[i]);
@@ -103,6 +110,9 @@
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
+
+	if (atomic_read(&kiobuf->io_count) == 0)
+		return;
 
 	add_wait_queue(&kiobuf->wait_queue, &wait);
 repeat:
diff -u --recursive --new-file v2.3.50/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.3.50/linux/fs/isofs/inode.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/isofs/inode.c	Fri Mar 10 10:48:48 2000
@@ -69,12 +69,11 @@
 	       check_malloc, check_bread);
 #endif
 
-	MOD_DEC_USE_COUNT;
 	return;
 }
 
 static void isofs_read_inode(struct inode *);
-static int isofs_statfs (struct super_block *, struct statfs *, int);
+static int isofs_statfs (struct super_block *, struct statfs *);
 
 static struct super_operations isofs_sops = {
 	read_inode:	isofs_read_inode,
@@ -487,10 +486,6 @@
 	struct inode		      * inode;
 	struct iso9660_options		opt;
 
-	MOD_INC_USE_COUNT;
-	/* lock before any blocking operations */
-	lock_super(s);
-
 	if (!parse_options((char *) data, &opt))
 		goto out_unlock;
 
@@ -825,7 +820,6 @@
 	if (opt.check == 'r') table++;
 	s->s_root->d_op = &isofs_dentry_ops[table];
 
-	unlock_super(s);
 	return s;
 
 	/*
@@ -868,26 +862,21 @@
 out_freebh:
 	brelse(bh);
 out_unlock:
-	s->s_dev = 0;
-	unlock_super(s);
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-static int isofs_statfs (struct super_block *sb, struct statfs *buf, int bufsiz)
+static int isofs_statfs (struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = ISOFS_SUPER_MAGIC;
-	tmp.f_bsize = sb->s_blocksize;
-	tmp.f_blocks = (sb->u.isofs_sb.s_nzones
+	buf->f_type = ISOFS_SUPER_MAGIC;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = (sb->u.isofs_sb.s_nzones
                   << (sb->u.isofs_sb.s_log_zone_size - sb->s_blocksize_bits));
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = sb->u.isofs_sb.s_ninodes;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_files = sb->u.isofs_sb.s_ninodes;
+	buf->f_ffree = 0;
+	buf->f_namelen = NAME_MAX;
+	return 0;
 }
 
 /* Life is simpler than for other filesystem since we never
@@ -1440,12 +1429,7 @@
 
 #endif
 
-static struct file_system_type iso9660_fs_type = {
-	"iso9660",
-	FS_REQUIRES_DEV,
-	isofs_read_super, 
-	NULL
-};
+static DECLARE_FSTYPE_DEV(iso9660_fs_type, "iso9660", isofs_read_super);
 
 int __init init_iso9660_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/lockd/lockd_syms.c linux/fs/lockd/lockd_syms.c
--- v2.3.50/linux/fs/lockd/lockd_syms.c	Sun Feb 20 21:12:39 2000
+++ linux/fs/lockd/lockd_syms.c	Thu Mar  9 06:57:08 2000
@@ -39,15 +39,4 @@
 EXPORT_SYMBOL(nlmsvc_grace_period);
 EXPORT_SYMBOL(nlmsvc_timeout);
 
-#ifdef CONFIG_LOCKD_V4
-
-/* NLM4 exported symbols */ 
-EXPORT_SYMBOL(nlm4_rofs);
-EXPORT_SYMBOL(nlm4_stale_fh);
-EXPORT_SYMBOL(nlm4_deadlock);
-EXPORT_SYMBOL(nlm4_failed);
-EXPORT_SYMBOL(nlm4_fbig);
-
-#endif
-
 #endif /* CONFIG_MODULES */
diff -u --recursive --new-file v2.3.50/linux/fs/lockd/svc.c linux/fs/lockd/svc.c
--- v2.3.50/linux/fs/lockd/svc.c	Sun Feb 20 21:12:39 2000
+++ linux/fs/lockd/svc.c	Thu Mar  9 06:57:08 2000
@@ -322,7 +322,6 @@
 	init_MUTEX(&nlmsvc_sema);
 	nlmsvc_users = 0;
 	nlmsvc_pid = 0;
-	nlmxdr_init();
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.50/linux/fs/lockd/svcsubs.c linux/fs/lockd/svcsubs.c
--- v2.3.50/linux/fs/lockd/svcsubs.c	Sun Feb 20 21:12:39 2000
+++ linux/fs/lockd/svcsubs.c	Thu Mar  9 23:31:43 2000
@@ -25,15 +25,17 @@
 /*
  * Global file hash table
  */
-#define FILE_NRHASH		32
 #define FILE_HASH_BITS		5
+#define FILE_NRHASH		(1<<FILE_HASH_BITS)
 static struct nlm_file *	nlm_files[FILE_NRHASH];
 static DECLARE_MUTEX(nlm_file_sema);
 
-static unsigned int file_hash(dev_t dev, ino_t ino)
+static inline unsigned int file_hash(struct nfs_fh *f)
 {
-	unsigned long tmp = (unsigned long) ino | (unsigned long) dev;
-	tmp = tmp + (tmp >> FILE_HASH_BITS) + (tmp >> FILE_HASH_BITS*2);
+	unsigned int tmp=0;
+	int i;
+	for (i=0; i<NFS_FHSIZE;i++)
+		tmp += f->data[i];
 	return tmp & (FILE_NRHASH - 1);
 }
 
@@ -50,34 +52,35 @@
 nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
 					struct nfs_fh *f)
 {
-	struct knfs_fh	*fh = (struct knfs_fh *) f;
 	struct nlm_file	*file;
 	unsigned int	hash;
 	u32		nfserr;
+	u32		*fhp = (u32*)f->data;
 
-	dprintk("lockd: nlm_file_lookup(%s/%u)\n",
-		kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
+	dprintk("lockd: nlm_file_lookup(%08x %08x %08x %08x %08x %08x)\n",
+		fhp[0], fhp[1], fhp[2], fhp[3], fhp[4], fhp[5]);
 
-	hash = file_hash(u32_to_kdev_t(fh->fh_dev), u32_to_ino_t(fh->fh_ino));
+
+	hash = file_hash(f);
 
 	/* Lock file table */
 	down(&nlm_file_sema);
 
-	for (file = nlm_files[hash]; file; file = file->f_next) {
-		if (file->f_handle.fh_dcookie == fh->fh_dcookie &&
-		    !memcmp(&file->f_handle, fh, sizeof(*fh)))
+	for (file = nlm_files[hash]; file; file = file->f_next)
+		if (!memcmp(&file->f_handle, f, sizeof(*f)))
 			goto found;
-	}
 
-	dprintk("lockd: creating file for %s/%u\n",
-		kdevname(u32_to_kdev_t(fh->fh_dev)), fh->fh_ino);
+	dprintk("lockd: creating file for (%08x %08x %08x %08x %08x %08x)\n",
+		fhp[0], fhp[1], fhp[2], fhp[3], fhp[4], fhp[5]);
+
 	nfserr = nlm_lck_denied_nolocks;
 	file = (struct nlm_file *) kmalloc(sizeof(*file), GFP_KERNEL);
 	if (!file)
 		goto out_unlock;
 
 	memset(file, 0, sizeof(*file));
-	file->f_handle = *fh;
+	file->f_handle = *f;
+	file->f_hash = hash;
 	init_MUTEX(&file->f_sema);
 
 	/* Open the file. Note that this must not sleep for too long, else
@@ -86,7 +89,7 @@
 	 * We have to make sure we have the right credential to open
 	 * the file.
 	 */
-	if ((nfserr = nlmsvc_ops->fopen(rqstp, fh, &file->f_file)) != 0) {
+	if ((nfserr = nlmsvc_ops->fopen(rqstp, f, &file->f_file)) != 0) {
 		dprintk("lockd: open failed (nfserr %d)\n", ntohl(nfserr));
 		goto out_free;
 	}
@@ -126,7 +129,7 @@
 
 	dprintk("lockd: closing file %s/%ld\n",
 		kdevname(inode->i_dev), inode->i_ino);
-	fp = nlm_files + file_hash(inode->i_dev, inode->i_ino);
+	fp = nlm_files + file->f_hash;
 	while ((f = *fp) != NULL) {
 		if (f == file) {
 			*fp = file->f_next;
diff -u --recursive --new-file v2.3.50/linux/fs/lockd/xdr.c linux/fs/lockd/xdr.c
--- v2.3.50/linux/fs/lockd/xdr.c	Sun Feb 20 21:12:39 2000
+++ linux/fs/lockd/xdr.c	Thu Mar  9 06:57:08 2000
@@ -20,44 +20,7 @@
 #include <linux/lockd/sm_inter.h>
 
 #define NLMDBG_FACILITY		NLMDBG_XDR
-#define NLM_MAXSTRLEN		1024
 
-#define QUADLEN(len)		(((len) + 3) >> 2)
-
-
-u32	nlm_granted, nlm_lck_denied, nlm_lck_denied_nolocks,
-	nlm_lck_blocked, nlm_lck_denied_grace_period;
-
-
-typedef struct nlm_args	nlm_args;
-
-/*
- * Initialization of NFS status variables
- */
-void
-nlmxdr_init(void)
-{
-	static int	inited = 0;
-
-	if (inited)
-		return;
-
-	nlm_granted = htonl(NLM_LCK_GRANTED);
-	nlm_lck_denied = htonl(NLM_LCK_DENIED);
-	nlm_lck_denied_nolocks = htonl(NLM_LCK_DENIED_NOLOCKS);
-	nlm_lck_blocked = htonl(NLM_LCK_BLOCKED);
-	nlm_lck_denied_grace_period = htonl(NLM_LCK_DENIED_GRACE_PERIOD);
-
-#ifdef CONFIG_LOCKD_V4
-	nlm4_deadlock = htonl(NLM_DEADLCK);
-	nlm4_rofs = htonl(NLM_ROFS);
-	nlm4_stale_fh = htonl(NLM_STALE_FH);
-	nlm4_fbig = htonl(NLM_FBIG);
-	nlm4_failed = htonl(NLM_FAILED);
-#endif
-
-	inited = 1;
-}
 
 /*
  * XDR functions for basic NLM types
diff -u --recursive --new-file v2.3.50/linux/fs/lockd/xdr4.c linux/fs/lockd/xdr4.c
--- v2.3.50/linux/fs/lockd/xdr4.c	Sun Feb 20 21:12:39 2000
+++ linux/fs/lockd/xdr4.c	Thu Mar  9 06:57:08 2000
@@ -20,16 +20,8 @@
 #include <linux/lockd/sm_inter.h>
 
 #define NLMDBG_FACILITY		NLMDBG_XDR
-#define NLM_MAXSTRLEN		1024
 #define OFFSET_MAX		((off_t)LONG_MAX)
 
-#define QUADLEN(len)		(((len) + 3) >> 2)
-
-u32     nlm4_deadlock, nlm4_rofs, nlm4_stale_fh, nlm4_fbig,
-	nlm4_failed;
-
-
-typedef struct nlm_args	nlm_args;
 
 static inline off_t
 size_to_off_t(__s64 size)
diff -u --recursive --new-file v2.3.50/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.3.50/linux/fs/minix/inode.c	Sat Feb 26 22:31:53 2000
+++ linux/fs/minix/inode.c	Fri Mar 10 10:48:48 2000
@@ -23,14 +23,13 @@
 #include <linux/highuid.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
 #include <linux/minix_fs.h>
 
 static void minix_read_inode(struct inode * inode);
 static void minix_write_inode(struct inode * inode);
-static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
+static int minix_statfs(struct super_block *sb, struct statfs *buf);
 static int minix_remount (struct super_block * sb, int * flags, char * data);
 
 static void minix_delete_inode(struct inode *inode)
@@ -80,7 +79,6 @@
 	brelse (sb->u.minix_sb.s_sbh);
 	kfree(sb->u.minix_sb.s_imap);
 
-	MOD_DEC_USE_COUNT;
 	return;
 }
 
@@ -189,13 +187,10 @@
 	if (64 != sizeof(struct minix2_inode))
 		panic("bad V2 i-node size");
 
-	MOD_INC_USE_COUNT;
-
 	hblock = get_hardblocksize(dev);
 	if (hblock && hblock > BLOCK_SIZE)
 		goto out_bad_hblock;
 
-	lock_super(s);
 	set_blocksize(dev, BLOCK_SIZE);
 	if (!(bh = bread(dev,1,BLOCK_SIZE)))
 		goto out_bad_sb;
@@ -287,7 +282,6 @@
 		mark_buffer_dirty(bh, 1);
 		s->s_dirt = 1;
 	}
-	unlock_super(s);
 	if (!(s->u.minix_sb.s_mount_state & MINIX_VALID_FS))
 		printk ("MINIX-fs: mounting unchecked file system, "
 			"running fsck is recommended.\n");
@@ -329,7 +323,7 @@
 		       "%s.\n", kdevname(dev));
     out_release:
 	brelse(bh);
-	goto out_unlock;
+	goto out;
 
 out_bad_hblock:
 	printk("MINIX-fs: blocksize too small for device.\n");
@@ -337,27 +331,21 @@
 
 out_bad_sb:
 	printk("MINIX-fs: unable to read superblock\n");
-    out_unlock:
-	unlock_super(s);
  out:
-	s->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-static int minix_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int minix_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = sb->s_magic;
-	tmp.f_bsize = sb->s_blocksize;
-	tmp.f_blocks = (sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone) << sb->u.minix_sb.s_log_zone_size;
-	tmp.f_bfree = minix_count_free_blocks(sb);
-	tmp.f_bavail = tmp.f_bfree;
-	tmp.f_files = sb->u.minix_sb.s_ninodes;
-	tmp.f_ffree = minix_count_free_inodes(sb);
-	tmp.f_namelen = sb->u.minix_sb.s_namelen;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = sb->s_magic;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = (sb->u.minix_sb.s_nzones - sb->u.minix_sb.s_firstdatazone) << sb->u.minix_sb.s_log_zone_size;
+	buf->f_bfree = minix_count_free_blocks(sb);
+	buf->f_bavail = buf->f_bfree;
+	buf->f_files = sb->u.minix_sb.s_ninodes;
+	buf->f_ffree = minix_count_free_inodes(sb);
+	buf->f_namelen = sb->u.minix_sb.s_namelen;
+	return 0;
 }
 
 /*
@@ -1277,12 +1265,7 @@
 	return err;
 }
 
-static struct file_system_type minix_fs_type = {
-	"minix",
-	FS_REQUIRES_DEV,
-	minix_read_super,
-	NULL
-};
+static DECLARE_FSTYPE_DEV(minix_fs_type,"minix",minix_read_super);
 
 int __init init_minix_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.3.50/linux/fs/minix/namei.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/minix/namei.c	Wed Mar  8 09:04:09 2000
@@ -399,7 +399,7 @@
 		retval = -ENOENT;
 		goto end_rmdir;
 	}
-	if (!list_empty(&dentry->d_hash)) {
+	if (!d_unhashed(dentry)) {
 		retval = -EBUSY;
 		goto end_rmdir;
 	}
@@ -569,6 +569,9 @@
 	}
 	if (S_ISDIR(old_inode->i_mode)) {
 		if (new_inode) {
+			retval = -EBUSY;
+			if (!d_unhashed(new_dentry))
+				goto end_rename;
 			retval = -ENOTEMPTY;
 			if (!empty_dir(new_inode))
 				goto end_rename;
diff -u --recursive --new-file v2.3.50/linux/fs/msdos/msdosfs_syms.c linux/fs/msdos/msdosfs_syms.c
--- v2.3.50/linux/fs/msdos/msdosfs_syms.c	Tue Aug 31 17:29:14 1999
+++ linux/fs/msdos/msdosfs_syms.c	Fri Mar 10 10:48:48 2000
@@ -27,12 +27,7 @@
 EXPORT_SYMBOL(msdos_put_super);
 
 
-struct file_system_type msdos_fs_type = {
-	"msdos",
-	FS_REQUIRES_DEV,
-	msdos_read_super, 
-	NULL
-};
+DECLARE_FSTYPE_DEV(msdos_fs_type, "msdos", msdos_read_super);
 
 int __init init_msdos_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.3.50/linux/fs/msdos/namei.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/msdos/namei.c	Fri Mar 10 10:48:48 2000
@@ -326,7 +326,7 @@
 	 * whether it is empty.
 	 */
 	res = -EBUSY;
-	if (!list_empty(&dentry->d_hash))
+	if (!d_unhashed(dentry))
 		goto rmdir_done;
 	res = fat_dir_empty(inode);
 	if (res)
@@ -463,6 +463,9 @@
 		goto degenerate_case;
 	if (is_dir) {
 		if (new_inode) {
+			error = -EBUSY;
+			if (!d_unhashed(new_dentry))
+				goto out;
 			error = fat_dir_empty(new_inode);
 			if (error)
 				goto out;
@@ -590,28 +593,18 @@
 	setattr:	fat_notify_change,
 };
 
-static void msdos_put_super_callback(struct super_block *sb)
-{
-	MOD_DEC_USE_COUNT;
-}
-
 struct super_block *msdos_read_super(struct super_block *sb,void *data, int silent)
 {
 	struct super_block *res;
 
-	MOD_INC_USE_COUNT;
-
 	MSDOS_SB(sb)->options.isvfat = 0;
 	res = fat_read_super(sb, data, silent, &msdos_dir_inode_operations);
 	if (res == NULL)
 		goto out_fail;
-	MSDOS_SB(sb)->put_super_callback=msdos_put_super_callback;
 	sb->s_root->d_op = &msdos_dentry_operations;
 	return res;
 
 out_fail:
-	sb->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
diff -u --recursive --new-file v2.3.50/linux/fs/namei.c linux/fs/namei.c
--- v2.3.50/linux/fs/namei.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/namei.c	Wed Mar  8 09:16:24 2000
@@ -580,6 +580,7 @@
 	mode &= S_IALLUGO & ~current->fs->umask;
 	mode |= S_IFREG;
 
+	down(&dir->i_zombie);
 	error = may_create(dir, dentry);
 	if (error)
 		goto exit_lock;
@@ -591,6 +592,7 @@
 	DQUOT_INIT(dir);
 	error = dir->i_op->create(dir, dentry, mode);
 exit_lock:
+	up(&dir->i_zombie);
 	return error;
 }
 
@@ -745,7 +747,8 @@
 
 	mode &= ~current->fs->umask;
 
-	if (!S_ISFIFO(mode) && !capable(CAP_MKNOD))
+	down(&dir->i_zombie);
+	if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
 		goto exit_lock;
 
 	error = may_create(dir, dentry);
@@ -759,6 +762,7 @@
 	DQUOT_INIT(dir);
 	error = dir->i_op->mknod(dir, dentry, mode, dev);
 exit_lock:
+	up(&dir->i_zombie);
 	return error;
 }
 
@@ -836,6 +840,7 @@
 {
 	int error;
 
+	down(&dir->i_zombie);
 	error = may_create(dir, dentry);
 	if (error)
 		goto exit_lock;
@@ -849,6 +854,7 @@
 	error = dir->i_op->mkdir(dir, dentry, mode);
 
 exit_lock:
+	up(&dir->i_zombie);
 	return error;
 }
 
@@ -901,6 +907,34 @@
 	return error;
 }
 
+/*
+ * We try to drop the dentry early: we should have
+ * a usage count of 2 if we're the only user of this
+ * dentry, and if that is true (possibly after pruning
+ * the dcache), then we drop the dentry now.
+ *
+ * A low-level filesystem can, if it choses, legally
+ * do a
+ *
+ *	if (!d_unhashed(dentry))
+ *		return -EBUSY;
+ *
+ * if it cannot handle the case of removing a directory
+ * that is still in use by something else..
+ */
+static void d_unhash(struct dentry *dentry)
+{
+	dget(dentry);
+	switch (dentry->d_count) {
+	default:
+		shrink_dcache_parent(dentry);
+		if (dentry->d_count != 2)
+			break;
+	case 2:
+		d_drop(dentry);
+	}
+}
+
 int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error;
@@ -914,31 +948,11 @@
 
 	DQUOT_INIT(dir);
 
-	/*
-	 * We try to drop the dentry early: we should have
-	 * a usage count of 2 if we're the only user of this
-	 * dentry, and if that is true (possibly after pruning
-	 * the dcache), then we drop the dentry now.
-	 *
-	 * A low-level filesystem can, if it choses, legally
-	 * do a
-	 *
-	 *	if (!list_empty(&dentry->d_hash))
-	 *		return -EBUSY;
-	 *
-	 * if it cannot handle the case of removing a directory
-	 * that is still in use by something else..
-	 */
-	switch (dentry->d_count) {
-	default:
-		shrink_dcache_parent(dentry);
-		if (dentry->d_count != 2)
-			break;
-	case 2:
-		d_drop(dentry);
-	}
-
+	double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
+	d_unhash(dentry);
 	error = dir->i_op->rmdir(dir, dentry);
+	double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
+	dput(dentry);
 
 	return error;
 }
@@ -954,27 +968,11 @@
 	if (IS_ERR(dentry))
 		goto exit;
 
-	error = -ENOENT;
-	if (!dentry->d_inode)
-		goto exit_dput;
-
-	dir = dget(dentry->d_parent);
-
-	/*
-	 * The dentry->d_count stuff confuses d_delete() enough to
-	 * not kill the inode from under us while it is locked. This
-	 * wouldn't be needed, except the dentry semaphore is really
-	 * in the inode, not in the dentry..
-	 */
-	dentry->d_count++;
-	double_lock(dir, dentry);
-
+	dir = lock_parent(dentry);
 	error = -ENOENT;
 	if (check_parent(dir, dentry))
 		error = vfs_rmdir(dir->d_inode, dentry);
-
-	double_unlock(dentry, dir);
-exit_dput:
+	unlock_dir(dir);
 	dput(dentry);
 exit:
 	return error;
@@ -1001,6 +999,7 @@
 {
 	int error;
 
+	down(&dir->i_zombie);
 	error = may_delete(dir, dentry, 0);
 	if (!error) {
 		error = -EPERM;
@@ -1009,10 +1008,11 @@
 			error = dir->i_op->unlink(dir, dentry);
 		}
 	}
+	up(&dir->i_zombie);
 	return error;
 }
 
-static inline int do_unlink(const char * name)
+int do_unlink(const char * name)
 {
 	int error;
 	struct dentry *dir;
@@ -1054,6 +1054,7 @@
 {
 	int error;
 
+	down(&dir->i_zombie);
 	error = may_create(dir, dentry);
 	if (error)
 		goto exit_lock;
@@ -1066,6 +1067,7 @@
 	error = dir->i_op->symlink(dir, dentry, oldname);
 
 exit_lock:
+	up(&dir->i_zombie);
 	return error;
 }
 
@@ -1121,6 +1123,7 @@
 	struct inode *inode;
 	int error;
 
+	down(&dir->i_zombie);
 	error = -ENOENT;
 	inode = old_dentry->d_inode;
 	if (!inode)
@@ -1147,6 +1150,7 @@
 	error = dir->i_op->link(old_dentry, dir, new_dentry);
 
 exit_lock:
+	up(&dir->i_zombie);
 	return error;
 }
 
@@ -1212,11 +1216,37 @@
 	return error;
 }
 
+/*
+ * The worst of all namespace operations - renaming directory. "Perverted"
+ * doesn't even start to describe it. Somebody in UCB had a heck of a trip...
+ * Problems:
+ *	a) we can get into loop creation. Check is done in is_subdir().
+ *	b) race potential - two innocent renames can create a loop together.
+ *	   That's where 4.4 screws up. Current fix: serialization on
+ *	   sb->s_vfs_rename_sem. We might be more accurate, but that's another
+ *	   story.
+ *	c) we have to lock _three_ objects - parents and victim (if it exists).
+ *	   And that - after we got ->i_sem on parents (until then we don't know
+ *	   whether the target exists at all, let alone whether it is a directory
+ *	   or not). Solution: ->i_zombie. Taken only after ->i_sem. Always taken
+ *	   on link creation/removal of any kind. And taken (without ->i_sem) on
+ *	   directory that will be removed (both in rmdir() and here).
+ *	d) some filesystems don't support opened-but-unlinked directories,
+ *	   either because of layout or because they are not ready to deal with
+ *	   all cases correctly. The latter will be fixed (taking this sort of
+ *	   stuff into VFS), but the former is not going away. Solution: the same
+ *	   trick as in rmdir().
+ *	e) conversion from fhandle to dentry may come in the wrong moment - when
+ *	   we are removing the target. Solution: we will have to grab ->i_zombie
+ *	   in the fhandle_to_dentry code. [FIXME - current nfsfh.c relies on
+ *	   ->i_sem on parents, which works but leads to some truely excessive
+ *	   locking].
+ */
 int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
 	       struct inode *new_dir, struct dentry *new_dentry)
 {
 	int error;
-	int need_rehash = 0;
+	struct inode *target;
 
 	if (old_dentry->d_inode == new_dentry->d_inode)
 		return 0;
@@ -1254,15 +1284,26 @@
 	error = -EINVAL;
 	if (is_subdir(new_dentry, old_dentry))
 		goto out_unlock;
-	if (new_dentry->d_inode) {
-		error = -EBUSY;
-		if (d_invalidate(new_dentry)<0)
-			goto out_unlock;
-		need_rehash = 1;
-	}
+	target = new_dentry->d_inode;
+	if (target) { /* Hastur! Hastur! Hastur! */
+		triple_down(&old_dir->i_zombie,
+			    &new_dir->i_zombie,
+			    &target->i_zombie);
+		d_unhash(new_dentry);
+	} else
+		double_down(&old_dir->i_zombie,
+			    &new_dir->i_zombie);
 	error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
-	if (need_rehash)
+	if (target) {
+		triple_up(&old_dir->i_zombie,
+			  &new_dir->i_zombie,
+			  &target->i_zombie);
 		d_rehash(new_dentry);
+		dput(new_dentry);
+	} else
+		double_up(&old_dir->i_zombie,
+			  &new_dir->i_zombie);
+		
 	if (!error)
 		d_move(old_dentry,new_dentry);
 out_unlock:
@@ -1297,7 +1338,9 @@
 
 	DQUOT_INIT(old_dir);
 	DQUOT_INIT(new_dir);
+	double_down(&old_dir->i_zombie, &new_dir->i_zombie);
 	error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+	double_up(&old_dir->i_zombie, &new_dir->i_zombie);
 	if (error)
 		return error;
 	/* The following d_move() should become unconditional */
diff -u --recursive --new-file v2.3.50/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.3.50/linux/fs/ncpfs/dir.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/ncpfs/dir.c	Wed Mar  8 09:04:09 2000
@@ -929,7 +929,7 @@
 		goto out;
 
 	error = -EBUSY;
-	if (!list_empty(&dentry->d_hash))
+	if (!d_unhashed(dentry))
 		goto out;
 
 	error = ncp_io2vol(server, __name, &len, dentry->d_name.name,
@@ -1072,7 +1072,6 @@
 		case 0x00:
                	        DPRINTK("ncp renamed %s -> %s.\n",
                                 old_dentry->d_name.name,new_dentry->d_name.name);
-			/* d_move(old_dentry, new_dentry); */
 			break;
 		case 0x9E:
 			error = -ENAMETOOLONG;
diff -u --recursive --new-file v2.3.50/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.3.50/linux/fs/ncpfs/inode.c	Sat Feb 26 22:31:53 2000
+++ linux/fs/ncpfs/inode.c	Fri Mar 10 10:48:48 2000
@@ -34,7 +34,7 @@
 static void ncp_put_inode(struct inode *);
 static void ncp_delete_inode(struct inode *);
 static void ncp_put_super(struct super_block *);
-static int  ncp_statfs(struct super_block *, struct statfs *, int);
+static int  ncp_statfs(struct super_block *, struct statfs *);
 
 static struct super_operations ncp_sops =
 {
@@ -273,7 +273,6 @@
 #endif
 	struct ncp_entry_info finfo;
 
-	MOD_INC_USE_COUNT;
 	if (raw_data == NULL)
 		goto out_no_data;
 	switch (*(int*)raw_data) {
@@ -323,8 +322,6 @@
 	if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
 		goto out_bad_file2;
 
-	lock_super(sb);
-
 	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = NCP_SUPER_MAGIC;
@@ -441,7 +438,6 @@
         if (!sb->s_root)
 		goto out_no_root;
 	sb->s_root->d_op = &ncp_dentry_operations;
-	unlock_super(sb);
 	return sb;
 
 out_no_root:
@@ -473,7 +469,6 @@
 	 * it doesn't proper unlocking.
 	 */
 	fput(ncp_filp);
-	unlock_super(sb);
 	goto out;
 
 out_bad_file2:
@@ -488,8 +483,6 @@
 out_no_data:
 	printk(KERN_ERR "ncp_read_super: missing data argument\n");
 out:
-	sb->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
@@ -524,28 +517,23 @@
 		ncp_kfree_s(server->auth.object_name, server->auth.object_name_len);
 	ncp_kfree_s(server->packet, server->packet_size);
 
-	MOD_DEC_USE_COUNT;
 }
 
-static int ncp_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int ncp_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
 	/* We cannot say how much disk space is left on a mounted
 	   NetWare Server, because free space is distributed over
 	   volumes, and the current user might have disk quotas. So
 	   free space is not that simple to determine. Our decision
 	   here is to err conservatively. */
 
-	tmp.f_type = NCP_SUPER_MAGIC;
-	tmp.f_bsize = NCP_BLOCK_SIZE;
-	tmp.f_blocks = 0;
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = -1;
-	tmp.f_ffree = -1;
-	tmp.f_namelen = 12;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = NCP_SUPER_MAGIC;
+	buf->f_bsize = NCP_BLOCK_SIZE;
+	buf->f_blocks = 0;
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_namelen = 12;
+	return 0;
 }
 
 int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
@@ -708,12 +696,7 @@
 int ncp_current_malloced;
 #endif
 
-static struct file_system_type ncp_fs_type = {
-	"ncpfs",
-	0 /* FS_NO_DCACHE doesn't work correctly */,
-        ncp_read_super,
-	NULL
-};
+static DECLARE_FSTYPE(ncp_fs_type, "ncpfs", ncp_read_super, 0);
 
 int __init init_ncp_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.3.50/linux/fs/nfs/dir.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/nfs/dir.c	Wed Mar  8 09:04:09 2000
@@ -672,7 +672,7 @@
 		struct dentry * dentry = list_entry(tmp, struct dentry, d_alias);
 		const char * unhashed = "";
 
-		if (list_empty(&dentry->d_hash))
+		if (d_unhashed(dentry))
 			unhashed = "(unhashed)";
 
 		printk("show_dentry: %s/%s, d_count=%d%s\n",
@@ -1027,7 +1027,7 @@
 	/*
 	 * Unhash the dentry while we remove the file ...
 	 */
-	if (!list_empty(&dentry->d_hash)) {
+	if (!d_unhashed(dentry)) {
 		d_drop(dentry);
 		rehash = 1;
 	}
@@ -1194,11 +1194,13 @@
 	 * For files, make a copy of the dentry and then do a 
 	 * silly-rename. If the silly-rename succeeds, the
 	 * copied dentry is hashed and becomes the new target.
-	 *
-	 * With directories check is done in VFS.
 	 */
+	if (!new_inode)
+		goto go_ahead;
 	error = -EBUSY;
-	if (new_dentry->d_count > 1 && new_inode) {
+	if (S_ISDIR(new_inode->i_mode))
+		goto out;
+	else if (new_dentry->d_count > 1) {
 		int err;
 		/* copy the target dentry's name */
 		dentry = d_alloc(new_dentry->d_parent,
@@ -1227,6 +1229,7 @@
 		}
 	}
 
+go_ahead:
 	/*
 	 * ... prune child dentries and writebacks if needed.
 	 */
@@ -1235,21 +1238,11 @@
 		shrink_dcache_parent(old_dentry);
 	}
 
-	if (new_dentry->d_count > 1 && new_inode) {
-#ifdef NFS_PARANOIA
-		printk("nfs_rename: new dentry %s/%s busy, d_count=%d\n",
-		       new_dentry->d_parent->d_name.name,
-		       new_dentry->d_name.name,
-		       new_dentry->d_count);
-#endif
-		goto out;
-	}
-
 	/*
 	 * To prevent any new references to the target during the rename,
 	 * we unhash the dentry and free the inode in advance.
 	 */
-	if (!list_empty(&new_dentry->d_hash)) {
+	if (!d_unhashed(new_dentry)) {
 		d_drop(new_dentry);
 		rehash = 1;
 	}
diff -u --recursive --new-file v2.3.50/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.3.50/linux/fs/nfs/inode.c	Sat Feb 26 22:31:53 2000
+++ linux/fs/nfs/inode.c	Fri Mar 10 10:48:48 2000
@@ -46,7 +46,7 @@
 static void nfs_delete_inode(struct inode *);
 static void nfs_put_super(struct super_block *);
 static void nfs_umount_begin(struct super_block *);
-static int  nfs_statfs(struct super_block *, struct statfs *, int);
+static int  nfs_statfs(struct super_block *, struct statfs *);
 
 static struct super_operations nfs_sops = { 
 	read_inode:	nfs_read_inode,
@@ -143,8 +143,6 @@
 	rpciod_down();		/* release rpciod */
 
 	kfree(server->hostname);
-
-	MOD_DEC_USE_COUNT;
 }
 
 void
@@ -209,7 +207,6 @@
 	struct rpc_timeout	timeparms;
 	struct nfs_fattr	fattr;
 
-	MOD_INC_USE_COUNT;
 	if (!data)
 		goto out_miss_args;
 
@@ -227,8 +224,6 @@
 	if (srvaddr.sin_addr.s_addr == INADDR_ANY)
 		goto out_no_remote;
 
-	lock_super(sb);
-
 	sb->s_flags |= MS_ODD_RENAME; /* This should go away */
 
 	sb->s_magic      = NFS_SUPER_MAGIC;
@@ -312,7 +307,6 @@
 	sb->s_root->d_fsdata = root_fh;
 
 	/* We're airborne */
-	unlock_super(sb);
 
 	/* Check whether to start the lockd process */
 	if (!(server->flags & NFS_MOUNT_NONLM))
@@ -350,7 +344,6 @@
 out_free_host:
 	kfree(server->hostname);
 out_unlock:
-	unlock_super(sb);
 	goto out_fail;
 
 out_no_remote:
@@ -361,33 +354,28 @@
 	printk("nfs_read_super: missing data argument\n");
 
 out_fail:
-	sb->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
 static int
-nfs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+nfs_statfs(struct super_block *sb, struct statfs *buf)
 {
 	int error;
 	struct nfs_fsinfo res;
-	struct statfs tmp;
 
 	error = nfs_proc_statfs(&sb->u.nfs_sb.s_server, &sb->u.nfs_sb.s_root,
 		&res);
 	if (error) {
 		printk("nfs_statfs: statfs error = %d\n", -error);
-		res.bsize = res.blocks = res.bfree = res.bavail = 0;
+		res.bsize = res.blocks = res.bfree = res.bavail = -1;
 	}
-	tmp.f_type = NFS_SUPER_MAGIC;
-	tmp.f_bsize = res.bsize;
-	tmp.f_blocks = res.blocks;
-	tmp.f_bfree = res.bfree;
-	tmp.f_bavail = res.bavail;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = NFS_SUPER_MAGIC;
+	buf->f_bsize = res.bsize;
+	buf->f_blocks = res.blocks;
+	buf->f_bfree = res.bfree;
+	buf->f_bavail = res.bavail;
+	buf->f_namelen = NAME_MAX;
+	return 0;
 }
 
 /*
@@ -413,7 +401,7 @@
 		struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
 		dprintk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n",
 			dentry->d_parent->d_name.name, dentry->d_name.name,
-			dentry->d_count, !list_empty(&dentry->d_hash));
+			dentry->d_count, !d_unhashed(dentry));
 		if (!list_empty(&dentry->d_subdirs))
 			shrink_dcache_parent(dentry);
 		if (!dentry->d_count) {
@@ -422,7 +410,7 @@
 			dput(dentry);
 			goto restart;
 		}
-		if (list_empty(&dentry->d_hash))
+		if (d_unhashed(dentry))
 			unhashed++;
 	}
 	return unhashed;
@@ -934,12 +922,7 @@
 /*
  * File system information
  */
-static struct file_system_type nfs_fs_type = {
-	"nfs",
-	0 /* FS_NO_DCACHE - this doesn't work right now*/,
-	nfs_read_super,
-	NULL
-};
+static DECLARE_FSTYPE(nfs_fs_type, "nfs", nfs_read_super, 0);
 
 extern int nfs_init_fhcache(void);
 extern int nfs_init_wreqcache(void);
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/export.c linux/fs/nfsd/export.c
--- v2.3.50/linux/fs/nfsd/export.c	Thu Mar  2 14:36:23 2000
+++ linux/fs/nfsd/export.c	Thu Mar  9 23:31:43 2000
@@ -66,8 +66,6 @@
 static int			hash_count = 0;
 static DECLARE_WAIT_QUEUE_HEAD(	hash_wait );
 
-#define READLOCK		0
-#define WRITELOCK		1
 
 /*
  * Find a client's export for a device.
@@ -435,7 +433,7 @@
  */
 int
 exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
-	   char *path, struct knfs_fh *f)
+	   char *path, struct knfsd_fh *f, int maxsize)
 {
 	struct svc_export	*exp;
 	struct dentry		*dentry = NULL;
@@ -484,11 +482,11 @@
 	/*
 	 * fh must be initialized before calling fh_compose
 	 */
-	fh_init(&fh);
-	fh_compose(&fh, exp, dentry);
-	memcpy(f, &fh.fh_handle, sizeof(struct knfs_fh));
+	fh_init(&fh, maxsize);
+	err = fh_compose(&fh, exp, dentry);
+	memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
 	fh_put(&fh);
-	return 0;
+	return err;
 
 out:
 	dput(dentry);
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/lockd.c linux/fs/nfsd/lockd.c
--- v2.3.50/linux/fs/nfsd/lockd.c	Sun Feb 20 21:12:39 2000
+++ linux/fs/nfsd/lockd.c	Thu Mar  9 23:31:43 2000
@@ -20,14 +20,14 @@
  * Note: we hold the dentry use count while the file is open.
  */
 static u32
-nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp)
+nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file *filp)
 {
 	u32		nfserr;
 	struct svc_fh	fh;
 
-	/* must initialize before using! */
-	fh_init(&fh);
-	fh.fh_handle = *f;
+	/* must initialize before using! but maxsize doesn't matter */
+	fh_init(&fh,0);
+	memcpy((char*)&fh.fh_handle.fh_base, (char*)f, NFS_FHSIZE);
 	fh.fh_export = NULL;
 
 	nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
@@ -39,11 +39,14 @@
 	 *            1 = stale file handle
 	 *	      2 = other error
 	 */
-	if (nfserr == 0)
+	switch (nfserr) {
+	case nfs_ok:
 		return 0;
-	else if (nfserr == nfserr_stale)
+	case nfserr_stale:
 		return 1;
-	else return 2;
+	default:
+		return 2;
+	}
 }
 
 static void
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/nfs3proc.c linux/fs/nfsd/nfs3proc.c
--- v2.3.50/linux/fs/nfsd/nfs3proc.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/nfsd/nfs3proc.c	Thu Mar  9 23:31:43 2000
@@ -28,7 +28,7 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
-#define RETURN(st)	{ resp->status = (st); return (st); }
+#define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
 
 static int	nfs3_ftypes[] = {
 	0,			/* NF3NON */
@@ -69,13 +69,12 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: GETATTR(3)  %x/%ld\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh));
+	dprintk("nfsd: GETATTR(3)  %s\n",
+				SVCFH_fmt(&argp->fh));
 
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -87,13 +86,12 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: SETATTR(3)  %x/%ld\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh));
+	dprintk("nfsd: SETATTR(3)  %s\n",
+				SVCFH_fmt(&argp->fh));
 
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -105,17 +103,18 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: LOOKUP(3)   %x/%ld %s\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: LOOKUP(3)   %s %s\n",
+				SVCFH_fmt(&argp->fh),
 				argp->name);
 
 	fh_copy(&resp->dirfh, &argp->fh);
+	fh_init(&resp->fh, NFS3_FHSIZE);
+
 	nfserr = nfsd_lookup(rqstp, &resp->dirfh,
 				    argp->name,
 				    argp->len,
 				    &resp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -127,15 +126,14 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: ACCESS(3)   %x/%ld 0x%x\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: ACCESS(3)   %s 0x%x\n",
+				SVCFH_fmt(&argp->fh),
 				argp->access);
 
 	fh_copy(&resp->fh, &argp->fh);
 	resp->access = argp->access;
 	nfserr = nfsd_access(rqstp, &resp->fh, &resp->access);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -148,9 +146,7 @@
 	u32		*path;
 	int		dummy, nfserr;
 
-	dprintk("nfsd: READLINK(3) %x/%ld\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh));
+	dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh));
 
 	/* Reserve room for status, post_op_attr, and path length */
 	svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy,
@@ -160,7 +156,7 @@
 	fh_copy(&resp->fh, &argp->fh);
 	resp->len = NFS3_MAXPATHLEN;
 	nfserr = nfsd_readlink(rqstp, &resp->fh, (char *) path, &resp->len);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -173,9 +169,8 @@
 	u32 *	buffer;
 	int	nfserr, avail;
 
-	dprintk("nfsd: READ(3) %x/%ld %lu bytes at %lu\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: READ(3) %s %lu bytes at %lu\n",
+				SVCFH_fmt(&argp->fh),
 				(unsigned long) argp->count,
 				(unsigned long) argp->offset);
 
@@ -201,7 +196,7 @@
 		resp->eof = (argp->offset + resp->count) >= inode->i_size;
 	}
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -213,22 +208,21 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: WRITE(3)    %x/%ld %d bytes at %ld%s\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: WRITE(3)    %s %d bytes at %ld%s\n",
+				SVCFH_fmt(&argp->fh),
 				argp->len,
 				(unsigned long) argp->offset,
 				argp->stable? " stable" : "");
 
 	fh_copy(&resp->fh, &argp->fh);
+	resp->committed = argp->stable;
 	nfserr = nfsd_write(rqstp, &resp->fh,
 				   argp->offset,
 				   argp->data,
 				   argp->len,
-				   argp->stable);
-	resp->committed = argp->stable;
+				   &resp->committed);
 	resp->count = argp->count;
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -244,19 +238,18 @@
 	struct iattr	*attr;
 	u32		nfserr;
 
-	dprintk("nfsd: CREATE(3)   %x/%ld %s\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: CREATE(3)   %s %s\n",
+				SVCFH_fmt(&argp->fh),
 				argp->name);
 
 	dirfhp = fh_copy(&resp->dirfh, &argp->fh);
-	newfhp = fh_init(&resp->fh);
+	newfhp = fh_init(&resp->fh, NFS3_FHSIZE);
 	attr   = &argp->attrs;
 
 	/* Get the directory inode */
 	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_CREATE);
 	if (nfserr)
-		RETURN(nfserr);
+		RETURN_STATUS(nfserr);
 
 	/* Unfudge the mode bits */
 	attr->ia_mode &= ~S_IFMT;
@@ -272,7 +265,7 @@
 				attr, newfhp,
 				argp->createmode, argp->verf);
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -284,18 +277,17 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: MKDIR(3)    %x/%ld %s\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: MKDIR(3)    %s %s\n",
+				SVCFH_fmt(&argp->fh),
 				argp->name);
 
 	argp->attrs.ia_valid &= ~ATTR_SIZE;
 	fh_copy(&resp->dirfh, &argp->fh);
-	fh_init(&resp->fh);
+	fh_init(&resp->fh, NFS3_FHSIZE);
 	nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
 				    &argp->attrs, S_IFDIR, 0, &resp->fh);
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 static int
@@ -304,17 +296,16 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: SYMLINK(3)  %x/%ld %s -> %s\n",
-				SVCFH_DEV(&argp->ffh),
-				(long)SVCFH_INO(&argp->ffh),
+	dprintk("nfsd: SYMLINK(3)  %s %s -> %s\n",
+				SVCFH_fmt(&argp->ffh),
 				argp->fname, argp->tname);
 
 	fh_copy(&resp->dirfh, &argp->ffh);
-	fh_init(&resp->fh);
+	fh_init(&resp->fh, NFS3_FHSIZE);
 	nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen,
 						   argp->tname, argp->tlen,
 						   &resp->fh, &argp->attrs);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -327,31 +318,30 @@
 	int	nfserr, type;
 	dev_t	rdev = 0;
 
-	dprintk("nfsd: MKNOD(3)    %x/%ld %s\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: MKNOD(3)    %s %s\n",
+				SVCFH_fmt(&argp->fh),
 				argp->name);
 
 	fh_copy(&resp->dirfh, &argp->fh);
-	fh_init(&resp->fh);
+	fh_init(&resp->fh, NFS3_FHSIZE);
 
 	if (argp->ftype == 0 || argp->ftype >= NF3BAD)
-		return nfserr_inval;
+		RETURN_STATUS(nfserr_inval);
 	if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
 		if ((argp->ftype == NF3CHR && argp->major >= MAX_CHRDEV)
 		    || (argp->ftype == NF3BLK && argp->major >= MAX_BLKDEV)
 		    || argp->minor > 0xFF)
-			return nfserr_inval;
+			RETURN_STATUS(nfserr_inval);
 		rdev = ((argp->major) << 8) | (argp->minor);
 	} else
 		if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO)
-			return nfserr_inval;
+			RETURN_STATUS(nfserr_inval);
 
 	type = nfs3_ftypes[argp->ftype];
 	nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len,
 				    &argp->attrs, type, rdev, &resp->fh);
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -363,15 +353,14 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: REMOVE(3)   %x/%ld %s\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: REMOVE(3)   %s %s\n",
+				SVCFH_fmt(&argp->fh),
 				argp->name);
 
 	/* Unlink. -S_IFDIR means file must not be a directory */
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -383,14 +372,13 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: RMDIR(3)    %x/%ld %s\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: RMDIR(3)    %s %s\n",
+				SVCFH_fmt(&argp->fh),
 				argp->name);
 
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 static int
@@ -399,19 +387,18 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: RENAME(3)   %x/%ld %s -> %x/%ld %s\n",
-				SVCFH_DEV(&argp->ffh),
-				(long)SVCFH_INO(&argp->ffh),
-				argp->fname,
-				SVCFH_DEV(&argp->tfh),
-				(long)SVCFH_INO(&argp->tfh),
+	dprintk("nfsd: RENAME(3)   %s %s ->\n",
+				SVCFH_fmt(&argp->ffh),
+				argp->fname);
+	dprintk("nfsd: -> %s %s\n",
+				SVCFH_fmt(&argp->tfh),
 				argp->tname);
 
 	fh_copy(&resp->ffh, &argp->ffh);
 	fh_copy(&resp->tfh, &argp->tfh);
 	nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen,
 				    &resp->tfh, argp->tname, argp->tlen);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 static int
@@ -420,18 +407,17 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: LINK(3)     %x/%ld -> %x/%ld %s\n",
-				SVCFH_DEV(&argp->ffh),
-				(long)SVCFH_INO(&argp->ffh),
-				SVCFH_DEV(&argp->tfh),
-				(long)SVCFH_INO(&argp->tfh),
+	dprintk("nfsd: LINK(3)     %s ->\n",
+				SVCFH_fmt(&argp->ffh));
+	dprintk("nfsd:   -> %s %s\n",
+				SVCFH_fmt(&argp->tfh),
 				argp->tname);
 
 	fh_copy(&resp->fh,  &argp->ffh);
 	fh_copy(&resp->tfh, &argp->tfh);
 	nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen,
 				  &resp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -445,9 +431,8 @@
 	int		nfserr, count;
 	unsigned int	want;
 
-	dprintk("nfsd: READDIR(3)  %x/%ld %d bytes at %d\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: READDIR(3)  %s %d bytes at %d\n",
+				SVCFH_fmt(&argp->fh),
 				argp->count, (u32) argp->cookie);
 
 	/* Reserve buffer space for status, attributes and verifier */
@@ -467,7 +452,7 @@
 	memcpy(resp->verf, argp->verf, 8);
 	resp->count = count;
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -481,9 +466,8 @@
 	u32 *	buffer;
 	int	nfserr, count, want;
 
-	dprintk("nfsd: READDIR+(3) %x/%ld %d bytes at %d\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n",
+				SVCFH_fmt(&argp->fh),
 				argp->count, (u32) argp->cookie);
 
 	/* Reserve buffer space for status, attributes and verifier */
@@ -503,7 +487,7 @@
 	memcpy(resp->verf, argp->verf, 8);
 	resp->count = count;
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -515,13 +499,12 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: FSSTAT(3)   %x/%ld\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh));
+	dprintk("nfsd: FSSTAT(3)   %s\n",
+				SVCFH_fmt(&argp->fh));
 
 	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -533,9 +516,8 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: FSINFO(3)   %x/%ld\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh));
+	dprintk("nfsd: FSINFO(3)   %s\n",
+				SVCFH_fmt(&argp->fh));
 
 	resp->f_rtmax  = NFSSVC_MAXBLKSIZE;
 	resp->f_rtpref = NFSSVC_MAXBLKSIZE;
@@ -562,7 +544,7 @@
 	}
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 /*
@@ -574,9 +556,8 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: PATHCONF(3) %x/%ld\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh));
+	dprintk("nfsd: PATHCONF(3) %s\n",
+				SVCFH_fmt(&argp->fh));
 
 	/* Set default pathconf */
 	resp->p_link_max = 255;		/* at least */
@@ -605,7 +586,7 @@
 	}
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 
@@ -618,19 +599,18 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: COMMIT(3)   %x/%ld %d@%ld\n",
-				SVCFH_DEV(&argp->fh),
-				(long)SVCFH_INO(&argp->fh),
+	dprintk("nfsd: COMMIT(3)   %s %d@%ld\n",
+				SVCFH_fmt(&argp->fh),
 				argp->count,
 				(unsigned long) argp->offset);
 
 	if (argp->offset > NFS_OFFSET_MAX)
-		return nfserr_inval;
+		RETURN_STATUS(nfserr_inval);
 
 	fh_copy(&resp->fh, &argp->fh);
 	nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count);
 
-	RETURN(nfserr);
+	RETURN_STATUS(nfserr);
 }
 
 
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/nfs3xdr.c linux/fs/nfsd/nfs3xdr.c
--- v2.3.50/linux/fs/nfsd/nfs3xdr.c	Thu Mar  2 14:36:23 2000
+++ linux/fs/nfsd/nfs3xdr.c	Thu Mar  9 23:31:43 2000
@@ -21,10 +21,6 @@
 # define inline
 #endif
 
-/*
- * Size of encoded NFS3 file handle, in words
- */
-#define NFS3_FHANDLE_WORDS	(1 + XDR_QUADLEN(sizeof(struct knfs_fh)))
 
 /*
  * Mapping of S_IF* types to NFS file types
@@ -64,19 +60,36 @@
 static inline u32 *
 decode_fh(u32 *p, struct svc_fh *fhp)
 {
-	if (ntohl(*p++) != sizeof(struct knfs_fh))
+	int size;
+	fh_init(fhp, NFS3_FHSIZE);
+	size = ntohl(*p++);
+	if (size > NFS3_FHSIZE)
 		return NULL;
 
-	memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
-	return p + (sizeof(struct knfs_fh) >> 2);
+	memcpy(&fhp->fh_handle.fh_base, p, size);
+	fhp->fh_handle.fh_size = size;
+	return p + XDR_QUADLEN(size);
 }
 
 static inline u32 *
 encode_fh(u32 *p, struct svc_fh *fhp)
 {
-	*p++ = htonl(sizeof(struct knfs_fh));
-	memcpy(p, &fhp->fh_handle, sizeof(struct knfs_fh));
-	return p + (sizeof(struct knfs_fh) >> 2);
+#if 0
+	int size = fhp->fh_handle.fh_size;
+	*p++ = htonl(size);
+	if (size) p[XDR_QUADLEN(size)-1]=0;
+	memcpy(p, &fhp->fh_handle.fh_base, size);
+	return p + XDR_QUADLEN(size);
+#else
+	/* until locked knows about var-length file handles,
+	 * we always return NFS_FHSIZE handles
+	 */
+	int size = fhp->fh_handle.fh_size;
+	*p++ = htonl(NFS_FHSIZE);
+	memset(p, 0, NFS_FHSIZE);
+	memcpy(p, &fhp->fh_handle.fh_base, size);
+	return p + XDR_QUADLEN(NFS_FHSIZE);
+#endif
 }
 
 /*
@@ -698,6 +711,7 @@
 	}
 	*p++ = xdr_one;				   /* mark entry present */
 	p    = xdr_encode_hyper(p, ino);			   /* file id */
+	p[slen - 1] = 0;		/* don't leak kernel data */
 #ifdef XDR_ENCODE_STRING_TAKES_LENGTH
 	p    = xdr_encode_string(p, name, namlen); /* name length & name */
 #else
@@ -706,7 +720,6 @@
 	memcpy(p, name, namlen);
 	p += slen;
 #endif
-	p[slen - 1] = 0;		/* don't leak kernel data */
 
 	cd->offset = p;			/* remember pointer */
 	p = xdr_encode_hyper(p, NFS_OFFSET_MAX);	/* offset of next entry */
@@ -715,7 +728,7 @@
 	if (plus) {
 		struct svc_fh	fh;
 
-		fh_init(&fh);
+		fh_init(&fh, NFS3_FHSIZE);
 		/* Disabled for now because of lock-up */
 		if (0 && nfsd_lookup(cd->rqstp, cd->dirfh, name, namlen, &fh) == 0) {
 			p = encode_post_op_attr(cd->rqstp, p, fh.fh_dentry);
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.3.50/linux/fs/nfsd/nfsctl.c	Thu Feb 10 17:11:18 2000
+++ linux/fs/nfsd/nfsctl.c	Thu Mar  9 23:31:43 2000
@@ -40,8 +40,9 @@
 static int	nfsctl_delclient(struct nfsctl_client *data);
 static int	nfsctl_export(struct nfsctl_export *data);
 static int	nfsctl_unexport(struct nfsctl_export *data);
-static int	nfsctl_getfh(struct nfsctl_fhparm *, struct knfs_fh *);
-static int	nfsctl_getfd(struct nfsctl_fdparm *, struct knfs_fh *);
+static int	nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);
+static int	nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);
+static int	nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);
 /* static int	nfsctl_ugidupdate(struct nfsctl_ugidmap *data); */
 
 static int	initialized = 0;
@@ -63,7 +64,6 @@
 static void
 nfsd_init(void)
 {
-	nfsd_xdr_init();	/* XDR */
 	nfsd_stat_init();	/* Statistics */
 	nfsd_cache_init();	/* RPC reply cache */
 	nfsd_export_init();	/* Exports table */
@@ -110,12 +110,37 @@
 }
 #endif
 
+#ifdef notyet
+static inline int
+nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res)
+{
+	struct sockaddr_in	*sin;
+	struct svc_client	*clp;
+	int			err = 0;
+
+	if (data->gd_addr.sa_family != AF_INET)
+		return -EPROTONOSUPPORT;
+	sin = (struct sockaddr_in *)&data->gd_addr;
+	if (data->gd_maxlen > NFS3_FHSIZE)
+		data->gd_maxlen = NFS3_FHSIZE;
+	exp_readlock();
+	if (!(clp = exp_getclient(sin)))
+		err = -EPERM;
+	else
+		err = exp_rootfh(clp, 0, 0, data->gd_path, res, data->gd_maxlen);
+	exp_unlock();
+
+	return err;
+}
+#endif
+
 static inline int
-nfsctl_getfd(struct nfsctl_fdparm *data, struct knfs_fh *res)
+nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res)
 {
 	struct sockaddr_in	*sin;
 	struct svc_client	*clp;
 	int			err = 0;
+	struct	knfsd_fh	fh;
 
 	if (data->gd_addr.sa_family != AF_INET)
 		return -EPROTONOSUPPORT;
@@ -127,18 +152,28 @@
 	if (!(clp = exp_getclient(sin)))
 		err = -EPERM;
 	else
-		err = exp_rootfh(clp, 0, 0, data->gd_path, res);
+		err = exp_rootfh(clp, 0, 0, data->gd_path, &fh, NFS_FHSIZE);
 	exp_unlock();
 
+	if (err == 0) {
+		if (fh.fh_size > NFS_FHSIZE)
+			err = -EINVAL;
+		else {
+			memset(res,0, NFS_FHSIZE);
+			memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+		}
+	}
+
 	return err;
 }
 
 static inline int
-nfsctl_getfh(struct nfsctl_fhparm *data, struct knfs_fh *res)
+nfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res)
 {
 	struct sockaddr_in	*sin;
 	struct svc_client	*clp;
 	int			err = 0;
+	struct knfsd_fh		fh;
 
 	if (data->gf_addr.sa_family != AF_INET)
 		return -EPROTONOSUPPORT;
@@ -150,9 +185,18 @@
 	if (!(clp = exp_getclient(sin)))
 		err = -EPERM;
 	else
-		err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, res);
+		err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);
 	exp_unlock();
 
+	if (err == 0) {
+		if (fh.fh_size > NFS_FHSIZE)
+			err = -EINVAL;
+		else {
+			memset(res,0, NFS_FHSIZE);
+			memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+		}
+	}
+
 	return err;
 }
 
@@ -218,11 +262,15 @@
 		break;
 #endif
 	case NFSCTL_GETFH:
-		err = nfsctl_getfh(&arg->ca_getfh, &res->cr_getfh);
+		err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);
 		break;
 	case NFSCTL_GETFD:
-		err = nfsctl_getfd(&arg->ca_getfd, &res->cr_getfh);
+		err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);
 		break;
+#ifdef notyet
+	case NFSCTL_GETFS:
+		err = nfsctl_getfs(&arg->ca_getfs, &res->cr_getfs);
+#endif
 	default:
 		err = -EINVAL;
 	}
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- v2.3.50/linux/fs/nfsd/nfsfh.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/nfsd/nfsfh.c	Thu Mar  9 23:31:43 2000
@@ -328,7 +328,7 @@
  * connection if made.
  */
 static struct dentry *
-find_fh_dentry(struct super_block *sb, struct knfs_fh *fh, int needpath)
+find_fh_dentry(struct super_block *sb, ino_t ino, int generation, ino_t dirino, int needpath)
 {
 	struct dentry *dentry, *result = NULL;
 	struct dentry *tmp;
@@ -347,7 +347,7 @@
 	 * Attempt to find the inode.
 	 */
  retry:
-	result = nfsd_iget(sb, fh->fh_ino, fh->fh_generation);
+	result = nfsd_iget(sb, ino, generation);
 	err = PTR_ERR(result);
 	if (IS_ERR(result))
 		goto err_out;
@@ -370,10 +370,10 @@
 	/* It's a directory, or we are required to confirm the file's
 	 * location in the tree.
 	 */
-	dprintk("nfs_fh: need to look harder for %d/%d\n",sb->s_dev,fh->fh_ino);
+	dprintk("nfs_fh: need to look harder for %d/%ld\n",sb->s_dev,ino);
 	down(&sb->s_nfsd_free_path_sem);
 
-	/* claiming the semaphore might have allow things to get fixed up */
+	/* claiming the semaphore might have allowed things to get fixed up */
 	if (! (result->d_flags & DCACHE_NFSD_DISCONNECTED)) {
 		up(&sb->s_nfsd_free_path_sem);
 		return result;
@@ -383,11 +383,11 @@
 	found = 0;
 	if (!S_ISDIR(result->d_inode->i_mode)) {
 		nfsdstats.fh_nocache_nondir++;
-		if (fh->fh_dirino == 0)
+		if (dirino == 0)
 			goto err_result; /* don't know how to find parent */
 		else {
-			/* need to iget fh->fh_dirino and make sure this inode is in that directory */
-			dentry = nfsd_iget(sb, fh->fh_dirino, 0);
+			/* need to iget dirino and make sure this inode is in that directory */
+			dentry = nfsd_iget(sb, dirino, 0);
 			err = PTR_ERR(dentry);
 			if (IS_ERR(dentry))
 				goto err_result;
@@ -490,38 +490,58 @@
 u32
 fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 {
-	struct knfs_fh	*fh = &fhp->fh_handle;
+	struct knfsd_fh	*fh = &fhp->fh_handle;
 	struct svc_export *exp;
 	struct dentry	*dentry;
 	struct inode	*inode;
 	u32		error = 0;
 
-	dprintk("nfsd: fh_verify(exp %s/%u file (%s/%u dir %u)\n",
-		kdevname(fh->fh_xdev),
-		fh->fh_xino,
-		kdevname(fh->fh_dev),
-		fh->fh_ino,
-		fh->fh_dirino);
+	dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
 	if (!fhp->fh_dverified) {
-		/*
-		 * Security: Check that the fh is internally consistant (from <gam3@acm.org>)
-		 */
-		if (fh->fh_dev != fh->fh_xdev) {
-			printk("fh_verify: Security: export on other device (%s, %s).\n",
-			       kdevname(fh->fh_dev), kdevname(fh->fh_xdev));
-			error = nfserr_stale;
-			nfsdstats.fh_stale++;
-			goto out;
+		kdev_t xdev;
+		ino_t xino;
+		__u32 *datap=NULL;
+		int data_left = fh->fh_size/4;
+		int nfsdev;
+		error = nfserr_stale;
+#if CONFIG_NFSD_V3		
+		if (rqstp->rq_vers == 3)
+			error = nfserr_badhandle;
+#endif
+		if (fh->fh_version == 1) {
+			
+			datap = fh->fh_auth;
+			if (--data_left<0) goto out;
+			switch (fh->fh_auth_type) {
+			case 0: break;
+			default: goto out;
+			}
+
+			switch (fh->fh_fsid_type) {
+			case 0:
+				if ((data_left-=2)<0) goto out;
+				nfsdev = ntohl(*datap++);
+				xdev = MKDEV(nfsdev>>16, nfsdev&0xFFFF);
+				xino = *datap++;
+				break;
+			default:
+				goto out;
+			}
+		} else {
+			if (fh->fh_size != NFS_FHSIZE)
+				goto out;
+			/* assume old filehandle format */
+			xdev = u32_to_kdev_t(fh->ofh_xdev);
+			xino = u32_to_ino_t(fh->ofh_xino);
 		}
 
 		/*
 		 * Look up the export entry.
 		 */
 		error = nfserr_stale; 
-		exp = exp_get(rqstp->rq_client,
-			      u32_to_kdev_t(fh->fh_xdev),
-			      u32_to_ino_t(fh->fh_xino));
+		exp = exp_get(rqstp->rq_client, xdev, xino);
+
 		if (!exp) {
 			/* export entry revoked */
 			nfsdstats.fh_stale++;
@@ -544,13 +564,44 @@
 		/*
 		 * Look up the dentry using the NFS file handle.
 		 */
+		error = nfserr_stale;
+#if CONFIG_NFSD_V3		
+		if (rqstp->rq_vers == 3)
+			error = nfserr_badhandle;
+#endif
 
-		dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
-					fh,
-					!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+		if (fh->fh_version == 1) {
+			/* if fileid_type != 0, and super_operations provide fh_to_dentry lookup,
+			 *  then should use that */
+			switch (fh->fh_fileid_type) {
+			case 0:
+				dentry = dget(exp->ex_dentry);
+				break;
+			case 1:
+				if ((data_left-=2)<0) goto out;
+				dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+							datap[0], datap[1],
+							0,
+							!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+				break;
+			case 2:
+				if ((data_left-=3)<0) goto out;
+				dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+							datap[0], datap[1],
+							datap[2],
+							!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+				break;
+			default: goto out;
+			}
+		} else {
 
+			dentry = find_fh_dentry(exp->ex_dentry->d_inode->i_sb,
+						fh->ofh_ino, fh->ofh_generation,
+						fh->ofh_dirino,
+						!(exp->ex_flags & NFSEXP_NOSUBTREECHECK));
+		}
 		if (IS_ERR(dentry)) {
-			error = nfserrno(-PTR_ERR(dentry));
+			error = nfserrno(PTR_ERR(dentry));
 			goto out;
 		}
 #ifdef NFSD_PARANOIA
@@ -652,78 +703,106 @@
  * an inode.  In this case a call to fh_update should be made
  * before the fh goes out on the wire ...
  */
-void
+inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
+		      __u32 **datapp, int maxsize)
+{
+	__u32 *datap= *datapp;
+	if (dentry == exp->ex_dentry)
+		return 0;
+	/* if super_operations provides dentry_to_fh lookup, should use that */
+	
+	*datap++ = ino_t_to_u32(dentry->d_inode->i_ino);
+	*datap++ = dentry->d_inode->i_generation;
+	if (S_ISDIR(dentry->d_inode->i_mode) || (exp->ex_flags & NFSEXP_NOSUBTREECHECK)){
+		*datapp = datap;
+		return 1;
+	}
+	*datap++ = ino_t_to_u32(dentry->d_parent->d_inode->i_ino);
+	*datapp = datap;
+	return 2;
+}
+
+int
 fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry)
 {
 	struct inode * inode = dentry->d_inode;
 	struct dentry *parent = dentry->d_parent;
+	__u32 *datap;
 
 	dprintk("nfsd: fh_compose(exp %x/%ld %s/%s, ino=%ld)\n",
 		exp->ex_dev, (long) exp->ex_ino,
 		parent->d_name.name, dentry->d_name.name,
 		(inode ? inode->i_ino : 0));
 
-	/*
-	 * N.B. We shouldn't need to init the fh -- the call to fh_compose
-	 * may not be done on error paths, but the cleanup must call fh_put.
-	 * Fix this soon!
-	 */
 	if (fhp->fh_dverified || fhp->fh_locked || fhp->fh_dentry) {
 		printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
 			parent->d_name.name, dentry->d_name.name);
 	}
-	fh_init(fhp);
-
-	fhp->fh_handle.fh_dirino = ino_t_to_u32(parent->d_inode->i_ino);
-	fhp->fh_handle.fh_dev    = kdev_t_to_u32(parent->d_inode->i_dev);
-	fhp->fh_handle.fh_xdev   = kdev_t_to_u32(exp->ex_dev);
-	fhp->fh_handle.fh_xino   = ino_t_to_u32(exp->ex_ino);
-	fhp->fh_handle.fh_dcookie = (struct dentry *)0xfeebbaca;
-	if (inode) {
-		fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
-		fhp->fh_handle.fh_generation = inode->i_generation;
-		if (S_ISDIR(inode->i_mode) || (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
-			fhp->fh_handle.fh_dirino = 0;
-	}
+	if (fhp->fh_maxsize < NFS_FHSIZE)
+		printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
+		       fhp->fh_maxsize, parent->d_name.name, dentry->d_name.name);
 
 	fhp->fh_dentry = dentry; /* our internal copy */
 	fhp->fh_export = exp;
 
+	fhp->fh_handle.fh_version = 1;
+	fhp->fh_handle.fh_auth_type = 0;
+	fhp->fh_handle.fh_fsid_type = 0;
+	datap = fhp->fh_handle.fh_auth+0;
+	/* fsid_type 0 == 2byte major, 2byte minor, 4byte inode */
+	*datap++ = htonl((MAJOR(exp->ex_dev)<<16)| MINOR(exp->ex_dev));
+	*datap++ = ino_t_to_u32(exp->ex_ino);
+
+	if (inode)
+		fhp->fh_handle.fh_fileid_type =
+			_fh_update(dentry, exp, &datap, fhp->fh_maxsize-3);
+
+	fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
+
+
 	/* We stuck it there, we know it's good. */
 	fhp->fh_dverified = 1;
 	nfsd_nr_verified++;
+	if (fhp->fh_handle.fh_fileid_type == 255)
+		return nfserr_opnotsupp;
+	return 0;
 }
 
 /*
  * Update file handle information after changing a dentry.
- * This is only called by nfsd_create
+ * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
  */
-void
+int
 fh_update(struct svc_fh *fhp)
 {
 	struct dentry *dentry;
-	struct inode *inode;
-
+	__u32 *datap;
+	
 	if (!fhp->fh_dverified)
 		goto out_bad;
 
 	dentry = fhp->fh_dentry;
-	inode = dentry->d_inode;
-	if (!inode)
+	if (!dentry->d_inode)
 		goto out_negative;
-	fhp->fh_handle.fh_ino = ino_t_to_u32(inode->i_ino);
-	fhp->fh_handle.fh_generation = inode->i_generation;
-	if (S_ISDIR(inode->i_mode) || (fhp->fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
-		fhp->fh_handle.fh_dirino = 0;
-
+	if (fhp->fh_handle.fh_fileid_type != 0)
+		goto out_uptodate;
+	datap = fhp->fh_handle.fh_auth+
+		          fhp->fh_handle.fh_size/4 -1;
+	fhp->fh_handle.fh_fileid_type =
+		_fh_update(dentry, fhp->fh_export, &datap, fhp->fh_maxsize-fhp->fh_handle.fh_size);
+	fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
 out:
-	return;
+	return 0;
 
 out_bad:
 	printk(KERN_ERR "fh_update: fh not verified!\n");
 	goto out;
 out_negative:
 	printk(KERN_ERR "fh_update: %s/%s still negative!\n",
+		dentry->d_parent->d_name.name, dentry->d_name.name);
+	goto out;
+out_uptodate:
+	printk(KERN_ERR "fh_update: %s/%s already up-to-date!\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 	goto out;
 }
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- v2.3.50/linux/fs/nfsd/nfsproc.c	Tue Feb  1 01:35:44 2000
+++ linux/fs/nfsd/nfsproc.c	Thu Mar  9 23:31:43 2000
@@ -30,7 +30,6 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_PROC
 
-#define RETURN(st)	return st
 
 static void
 svcbuf_reserve(struct svc_buf *buf, u32 **ptr, int *len, int nr)
@@ -42,7 +41,7 @@
 static int
 nfsd_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
 {
-	RETURN(nfs_ok);
+	return nfs_ok;
 }
 
 /*
@@ -53,11 +52,10 @@
 nfsd_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle  *argp,
 					  struct nfsd_attrstat *resp)
 {
-	dprintk("nfsd: GETATTR  %d/%d\n",
-		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh));
+	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
 
 	fh_copy(&resp->fh, &argp->fh);
-	RETURN(fh_verify(rqstp, &resp->fh, 0, MAY_NOP));
+	return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
 }
 
 /*
@@ -68,12 +66,12 @@
 nfsd_proc_setattr(struct svc_rqst *rqstp, struct nfsd_sattrargs *argp,
 					  struct nfsd_attrstat  *resp)
 {
-	dprintk("nfsd: SETATTR  %d/%d, valid=%x, size=%ld\n",
-		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+	dprintk("nfsd: SETATTR  %s, valid=%x, size=%ld\n",
+		SVCFH_fmt(&argp->fh),
 		argp->attrs.ia_valid, (long) argp->attrs.ia_size);
 
 	fh_copy(&resp->fh, &argp->fh);
-	RETURN(nfsd_setattr(rqstp, &resp->fh, &argp->attrs));
+	return nfsd_setattr(rqstp, &resp->fh, &argp->attrs);
 }
 
 /*
@@ -88,14 +86,15 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: LOOKUP   %d/%d %s\n",
-		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh), argp->name);
+	dprintk("nfsd: LOOKUP   %s %s\n",
+		SVCFH_fmt(&argp->fh), argp->name);
 
+	fh_init(&resp->fh, NFS_FHSIZE);
 	nfserr = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len,
 				 &resp->fh);
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -108,7 +107,7 @@
 	u32		*path;
 	int		dummy, nfserr;
 
-	dprintk("nfsd: READLINK %p\n", SVCFH_DENTRY(&argp->fh));
+	dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh));
 
 	/* Reserve room for status and path length */
 	svcbuf_reserve(&rqstp->rq_resbuf, &path, &dummy, 2);
@@ -118,7 +117,7 @@
 	nfserr = nfsd_readlink(rqstp, &argp->fh, (char *) path, &resp->len);
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -132,8 +131,8 @@
 	u32 *	buffer;
 	int	nfserr, avail;
 
-	dprintk("nfsd: READ    %d/%d %d bytes at %d\n",
-		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+	dprintk("nfsd: READ    %s %d bytes at %d\n",
+		SVCFH_fmt(&argp->fh),
 		argp->count, argp->offset);
 
 	/* Obtain buffer pointer for payload. 19 is 1 word for
@@ -156,7 +155,7 @@
 				  (char *) buffer,
 				  &resp->count);
 
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -168,17 +167,18 @@
 					struct nfsd_attrstat  *resp)
 {
 	int	nfserr;
+	int	stable = 1;
 
-	dprintk("nfsd: WRITE    %d/%d %d bytes at %d\n",
-		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+	dprintk("nfsd: WRITE    %s %d bytes at %d\n",
+		SVCFH_fmt(&argp->fh),
 		argp->len, argp->offset);
 
 	nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
 				   argp->offset,
 				   argp->data,
 				   argp->len,
-				   0);
-	RETURN(nfserr);
+				   &stable);
+	return nfserr;
 }
 
 /*
@@ -198,8 +198,8 @@
 	int		nfserr, type, mode, rdonly = 0;
 	dev_t		rdev = NODEV;
 
-	dprintk("nfsd: CREATE   %d/%d %s\n",
-		SVCFH_DEV(dirfhp), SVCFH_INO(dirfhp), argp->name);
+	dprintk("nfsd: CREATE   %s %s\n",
+		SVCFH_fmt(dirfhp), argp->name);
 
 	/* First verify the parent file handle */
 	nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, MAY_EXEC);
@@ -217,6 +217,7 @@
 	/*
 	 * Do a lookup to verify the new file handle.
 	 */
+	fh_init(newfhp, NFS_FHSIZE);
 	nfserr = nfsd_lookup(rqstp, dirfhp, argp->name, argp->len, newfhp);
 	if (nfserr) {
 		if (nfserr != nfserr_noent)
@@ -240,9 +241,11 @@
 	if (nfserr)
 		goto done;
 	inode = newfhp->fh_dentry->d_inode;
-	if (inode && newfhp->fh_handle.fh_ino == 0)
+	if (inode && newfhp->fh_handle.fh_fileid_type == 0)
 		 /* inode might have been instantiated while we slept */
-		 fh_update(newfhp);
+		nfserr = fh_update(newfhp);
+	if (nfserr)
+		goto done;
 
 	/* Unfudge the mode bits */
 	if (attr->ia_valid & ATTR_MODE) { 
@@ -321,7 +324,7 @@
 
 done:
 	fh_put(dirfhp);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 static int
@@ -330,12 +333,12 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: REMOVE   %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+	dprintk("nfsd: REMOVE   %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
 
 	/* Unlink. -SIFDIR means file must not be a directory */
 	nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 static int
@@ -344,15 +347,16 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: RENAME   %p %s -> %p %s\n",
-		SVCFH_DENTRY(&argp->ffh), argp->fname,
-		SVCFH_DENTRY(&argp->tfh), argp->tname);
+	dprintk("nfsd: RENAME   %s %s -> \n",
+		SVCFH_fmt(&argp->ffh), argp->fname);
+	dprintk("nfsd:        ->  %s %s\n",
+		SVCFH_fmt(&argp->tfh), argp->tname);
 
 	nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen,
 				    &argp->tfh, argp->tname, argp->tlen);
 	fh_put(&argp->ffh);
 	fh_put(&argp->tfh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 static int
@@ -361,16 +365,17 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: LINK     %p -> %p %s\n",
-		SVCFH_DENTRY(&argp->ffh),
-		SVCFH_DENTRY(&argp->tfh),
+	dprintk("nfsd: LINK     %s ->\n",
+		SVCFH_fmt(&argp->ffh));
+	dprintk("nfsd:    %s %s\n",
+		SVCFH_fmt(&argp->tfh),
 		argp->tname);
 
 	nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen,
 				  &argp->ffh);
 	fh_put(&argp->ffh);
 	fh_put(&argp->tfh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 static int
@@ -380,10 +385,10 @@
 	struct svc_fh	newfh;
 	int		nfserr;
 
-	dprintk("nfsd: SYMLINK  %p %s -> %s\n",
-		SVCFH_DENTRY(&argp->ffh), argp->fname, argp->tname);
+	dprintk("nfsd: SYMLINK  %s %s -> %s\n",
+		SVCFH_fmt(&argp->ffh), argp->fname, argp->tname);
 
-	memset(&newfh, 0, sizeof(struct svc_fh));
+	fh_init(&newfh, NFS_FHSIZE);
 	/*
 	 * Create the link, look up new file and set attrs.
 	 */
@@ -394,7 +399,7 @@
 
 	fh_put(&argp->ffh);
 	fh_put(&newfh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -407,7 +412,7 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: MKDIR    %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+	dprintk("nfsd: MKDIR    %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
 
 	if (resp->fh.fh_dverified) {
 		printk(KERN_WARNING
@@ -415,10 +420,11 @@
 	}
 
 	argp->attrs.ia_valid &= ~ATTR_SIZE;
+	fh_init(&resp->fh, NFS_FHSIZE);
 	nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len,
 				    &argp->attrs, S_IFDIR, 0, &resp->fh);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -430,11 +436,11 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: RMDIR    %p %s\n", SVCFH_DENTRY(&argp->fh), argp->name);
+	dprintk("nfsd: RMDIR    %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
 
 	nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -447,8 +453,8 @@
 	u32 *		buffer;
 	int		nfserr, count;
 
-	dprintk("nfsd: READDIR  %d/%d %d bytes at %d\n",
-		SVCFH_DEV(&argp->fh), SVCFH_INO(&argp->fh),
+	dprintk("nfsd: READDIR  %s %d bytes at %d\n",
+		SVCFH_fmt(&argp->fh),		
 		argp->count, argp->cookie);
 
 	/* Reserve buffer space for status */
@@ -470,7 +476,7 @@
 	resp->count = count;
 
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -482,11 +488,11 @@
 {
 	int	nfserr;
 
-	dprintk("nfsd: STATFS   %p\n", SVCFH_DENTRY(&argp->fh));
+	dprintk("nfsd: STATFS   %s\n", SVCFH_fmt(&argp->fh));
 
 	nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats);
 	fh_put(&argp->fh);
-	RETURN(nfserr);
+	return nfserr;
 }
 
 /*
@@ -539,36 +545,36 @@
 		int	nfserr;
 		int	syserr;
 	} nfs_errtbl[] = {
-		{ NFS_OK, 0 },
-		{ NFSERR_PERM, EPERM },
-		{ NFSERR_NOENT, ENOENT },
-		{ NFSERR_IO, EIO },
-		{ NFSERR_NXIO, ENXIO },
-		{ NFSERR_ACCES, EACCES },
-		{ NFSERR_EXIST, EEXIST },
-		{ NFSERR_XDEV, EXDEV },
-		{ NFSERR_MLINK, EMLINK },
-		{ NFSERR_NODEV, ENODEV },
-		{ NFSERR_NOTDIR, ENOTDIR },
-		{ NFSERR_ISDIR, EISDIR },
-		{ NFSERR_INVAL, EINVAL },
-		{ NFSERR_FBIG, EFBIG },
-		{ NFSERR_NOSPC, ENOSPC },
-		{ NFSERR_ROFS, EROFS },
-		{ NFSERR_MLINK, EMLINK },
-		{ NFSERR_NAMETOOLONG, ENAMETOOLONG },
-		{ NFSERR_NOTEMPTY, ENOTEMPTY },
+		{ nfs_ok, 0 },
+		{ nfserr_perm, -EPERM },
+		{ nfserr_noent, -ENOENT },
+		{ nfserr_io, -EIO },
+		{ nfserr_nxio, -ENXIO },
+		{ nfserr_acces, -EACCES },
+		{ nfserr_exist, -EEXIST },
+		{ nfserr_xdev, -EXDEV },
+		{ nfserr_mlink, -EMLINK },
+		{ nfserr_nodev, -ENODEV },
+		{ nfserr_notdir, -ENOTDIR },
+		{ nfserr_isdir, -EISDIR },
+		{ nfserr_inval, -EINVAL },
+		{ nfserr_fbig, -EFBIG },
+		{ nfserr_nospc, -ENOSPC },
+		{ nfserr_rofs, -EROFS },
+		{ nfserr_mlink, -EMLINK },
+		{ nfserr_nametoolong, -ENAMETOOLONG },
+		{ nfserr_notempty, -ENOTEMPTY },
 #ifdef EDQUOT
-		{ NFSERR_DQUOT, EDQUOT },
+		{ nfserr_dquot, -EDQUOT },
 #endif
-		{ NFSERR_STALE, ESTALE },
-		{ -1, EIO }
+		{ nfserr_stale, -ESTALE },
+		{ -1, -EIO }
 	};
 	int	i;
 
 	for (i = 0; nfs_errtbl[i].nfserr != -1; i++) {
 		if (nfs_errtbl[i].syserr == errno)
-			return htonl(nfs_errtbl[i].nfserr);
+			return nfs_errtbl[i].nfserr;
 	}
 	printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno);
 	return nfserr_io;
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/nfsxdr.c linux/fs/nfsd/nfsxdr.c
--- v2.3.50/linux/fs/nfsd/nfsxdr.c	Wed Dec  8 14:11:27 1999
+++ linux/fs/nfsd/nfsxdr.c	Thu Mar  9 23:31:43 2000
@@ -17,15 +17,6 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
-u32	nfs_ok, nfserr_perm, nfserr_noent, nfserr_io, nfserr_nxio,
-	nfserr_acces, nfserr_exist, nfserr_xdev, nfserr_nodev,
-	nfserr_notdir, nfserr_isdir, nfserr_inval, nfserr_fbig,
-	nfserr_nospc, nfserr_rofs, nfserr_mlink,
-	nfserr_nametoolong, nfserr_notempty, nfserr_dquot, nfserr_stale,
-	nfserr_remote, nfserr_badhandle, nfserr_notsync,
-	nfserr_badcookie, nfserr_notsupp, nfserr_toosmall,
-	nfserr_serverfault, nfserr_badtype, nfserr_jukebox;
-
 
 #ifdef NFSD_OPTIMIZE_SPACE
 # define inline
@@ -41,51 +32,6 @@
 	NFSOCK, NFBAD,  NFLNK, NFBAD,
 };
 
-/*
- * Initialization of NFS status variables
- */
-void
-nfsd_xdr_init(void)
-{
-	static int	inited = 0;
-
-	if (inited)
-		return;
-
-	nfs_ok		= htonl(NFS_OK);
-	nfserr_perm	= htonl(NFSERR_PERM);
-	nfserr_noent	= htonl(NFSERR_NOENT);
-	nfserr_io	= htonl(NFSERR_IO);
-	nfserr_inval	= htonl(NFSERR_INVAL);
-	nfserr_nxio	= htonl(NFSERR_NXIO);
-	nfserr_acces	= htonl(NFSERR_ACCES);
-	nfserr_exist	= htonl(NFSERR_EXIST);
-	nfserr_xdev	= htonl(NFSERR_XDEV);
-	nfserr_nodev	= htonl(NFSERR_NODEV);
-	nfserr_notdir	= htonl(NFSERR_NOTDIR);
-	nfserr_isdir	= htonl(NFSERR_ISDIR);
-	nfserr_inval	= htonl(NFSERR_INVAL);
-	nfserr_fbig	= htonl(NFSERR_FBIG);
-	nfserr_nospc	= htonl(NFSERR_NOSPC);
-	nfserr_rofs	= htonl(NFSERR_ROFS);
-	nfserr_mlink	= htonl(NFSERR_MLINK);
-	nfserr_nametoolong = htonl(NFSERR_NAMETOOLONG);
-	nfserr_notempty	= htonl(NFSERR_NOTEMPTY);
-	nfserr_dquot	= htonl(NFSERR_DQUOT);
-	nfserr_stale	= htonl(NFSERR_STALE);
-	nfserr_remote	= htonl(NFSERR_REMOTE);
-	nfserr_badhandle = htonl(NFSERR_BADHANDLE);
-	nfserr_notsync	= htonl(NFSERR_NOT_SYNC);
-	nfserr_badcookie = htonl(NFSERR_BAD_COOKIE);
-	nfserr_notsupp	= htonl(NFSERR_NOTSUPP);
-	nfserr_toosmall	= htonl(NFSERR_TOOSMALL);
-	nfserr_serverfault = htonl(NFSERR_SERVERFAULT);
-	nfserr_badtype	= htonl(NFSERR_BADTYPE);
-	nfserr_jukebox	= htonl(NFSERR_JUKEBOX);
-
-
-	inited = 1;
-}
 
 /*
  * XDR functions for basic NFS types
@@ -93,19 +39,20 @@
 static inline u32 *
 decode_fh(u32 *p, struct svc_fh *fhp)
 {
-	fh_init(fhp);
-	memcpy(&fhp->fh_handle, p, sizeof(struct knfs_fh));
+	fh_init(fhp, NFS_FHSIZE);
+	memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE);
+	fhp->fh_handle.fh_size = NFS_FHSIZE;
 
 	/* FIXME: Look up export pointer here and verify
 	 * Sun Secure RPC if requested */
-	return p + (sizeof(struct knfs_fh) >> 2);
+	return p + (NFS_FHSIZE >> 2);
 }
 
 static inline u32 *
 encode_fh(u32 *p, struct svc_fh *fhp)
 {
-	memcpy(p, &fhp->fh_handle, sizeof(struct knfs_fh));
-	return p + (sizeof(struct knfs_fh) >> 2);
+	memcpy(p, &fhp->fh_handle.fh_base, NFS_FHSIZE);
+	return p + (NFS_FHSIZE>> 2);
 }
 
 /*
diff -u --recursive --new-file v2.3.50/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.3.50/linux/fs/nfsd/vfs.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/nfsd/vfs.c	Thu Mar  9 23:31:43 2000
@@ -16,6 +16,7 @@
 
 #include <linux/config.h>
 #include <linux/version.h>
+#include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
@@ -92,7 +93,7 @@
  * the check_parent in linux/fs/namei.c.
  */
 #define nfsd_check_parent(dir, dentry) \
-	((dir) == (dentry)->d_parent && !list_empty(&dentry->d_hash))
+	((dir) == (dentry)->d_parent && !d_unhashed(dentry))
 
 /*
  * Lock a parent directory following the VFS locking protocol.
@@ -137,7 +138,7 @@
 	struct dentry		*dparent, *dchild;
 	int			err;
 
-	dprintk("nfsd: nfsd_lookup(fh %p, %s)\n", SVCFH_DENTRY(fhp), name);
+	dprintk("nfsd: nfsd_lookup(fh %s, %s)\n", SVCFH_fmt(fhp), name);
 
 	/* Obtain dentry and export. */
 	err = fh_verify(rqstp, fhp, S_IFDIR, MAY_EXEC);
@@ -155,7 +156,10 @@
 	err = nfserr_acces;
 
 	/* Lookup the name, but don't follow links */
-	dchild = lookup_dentry(name, dget(dparent), 0);
+	if (strcmp(name,"..")==0 && dparent->d_covers != dparent)
+		dchild = dget(dparent);
+	else
+		dchild = lookup_dentry(name, dget(dparent), 0);
 	if (IS_ERR(dchild))
 		goto out_nfserr;
 	/*
@@ -187,15 +191,14 @@
 	 * Note: we compose the file handle now, but as the
 	 * dentry may be negative, it may need to be updated.
 	 */
-	fh_compose(resfh, exp, dchild);
-	err = nfserr_noent;
-	if (dchild->d_inode)
-		err = 0;
+	err = fh_compose(resfh, exp, dchild);
+	if (!err && !dchild->d_inode)
+		err = nfserr_noent;
 out:
 	return err;
 
 out_nfserr:
-	err = nfserrno(-PTR_ERR(dchild));
+	err = nfserrno(PTR_ERR(dchild));
 	goto out;
 }
 
@@ -261,8 +264,6 @@
 
 	/* The size case is special. It changes the file as well as the attributes.  */
 	if (iap->ia_valid & ATTR_SIZE) {
-if (!S_ISREG(inode->i_mode))
-printk("nfsd_setattr: size change??\n");
 		if (iap->ia_size < inode->i_size) {
 			err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
 			if (err)
@@ -326,7 +327,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -393,18 +394,19 @@
 		if (map->access & query) {
 			unsigned int err2;
 			err2 = nfsd_permission(export, dentry, map->how);
-			/* cannot use a "switch" as nfserr_* are variables, even though they are constant :-( */
-			if (err2 == 0)
+			switch (err2) {
+			case nfs_ok:
 				result |= map->access;
+				break;
+				
 			/* the following error codes just mean the access was not allowed,
 			 * rather than an error occurred */
-			else if (err2 == nfserr_rofs ||
-				 err2 == nfserr_acces ||
-				 err2 == nfserr_perm
-				)
+			case nfserr_rofs:
+			case nfserr_acces:
+			case nfserr_perm:
 				/* simply don't "or" in the access bit. */
-					;
-			else {
+				break;
+			default:
 				error = err2;
 				goto out;
 			}
@@ -482,7 +484,7 @@
 	}
 out_nfserr:
 	if (err)
-		err = nfserrno(-err);
+		err = nfserrno(err);
 out:
 	return err;
 }
@@ -587,7 +589,7 @@
 		goto out_close;
 
 	/* Get readahead parameters */
-	ra = nfsd_get_raparms(fhp->fh_handle.fh_dev, fhp->fh_handle.fh_ino);
+	ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino);
 	if (ra) {
 		file.f_reada = ra->p_reada;
 		file.f_ramax = ra->p_ramax;
@@ -618,7 +620,7 @@
 		*count = err;
 		err = 0;
 	} else 
-		err = nfserrno(-err);
+		err = nfserrno(err);
 out_close:
 	nfsd_close(&file);
 out:
@@ -632,7 +634,7 @@
  */
 int
 nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
-				char *buf, unsigned long cnt, int stable)
+				char *buf, unsigned long cnt, int *stablep)
 {
 	struct svc_export	*exp;
 	struct file		file;
@@ -640,6 +642,7 @@
 	struct inode		*inode;
 	mm_segment_t		oldfs;
 	int			err = 0;
+	int			stable = *stablep;
 #ifdef CONFIG_QUOTA
 	uid_t			saved_euid;
 #endif
@@ -666,10 +669,12 @@
 	 * flushing the data to disk is handled separately below.
 	 */
 #ifdef CONFIG_NFSD_V3
-	if (rqstp->rq_vers == 2)
-		stable = EX_ISSYNC(exp);
-	else if (file.f_op->fsync == 0)
-	       stable = 1;
+	if (file.f_op->fsync == 0) {/* COMMIT3 cannot work */
+	       stable = 2;
+	       *stablep = 2; /* FILE_SYNC */
+	}
+	if (!EX_ISSYNC(exp))
+		stable = 0;
 	if (stable && !EX_WGATHER(exp))
 		file.f_flags |= O_SYNC;
 #else
@@ -749,7 +754,7 @@
 	if (err >= 0)
 		err = 0;
 	else 
-		err = nfserrno(-err);
+		err = nfserrno(err);
 out_close:
 	nfsd_close(&file);
 out:
@@ -774,11 +779,12 @@
 
 	if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
 		return err;
-
-	if (file.f_op && file.f_op->fsync) {
-		nfsd_sync(&file);
-	} else {
-		err = nfserr_notsupp;
+	if (EX_ISSYNC(fhp->fh_export)) {
+		if (file.f_op && file.f_op->fsync) {
+			nfsd_sync(&file);
+		} else {
+			err = nfserr_notsupp;
+		}
 	}
 
 	nfsd_close(&file);
@@ -827,11 +833,13 @@
 		err = PTR_ERR(dchild);
 		if (IS_ERR(dchild))
 			goto out_nfserr;
-		fh_compose(resfhp, fhp->fh_export, dchild);
 		/* Lock the parent and check for errors ... */
 		err = fh_lock_parent(fhp, dchild);
 		if (err)
 			goto out;
+		err = fh_compose(resfhp, fhp->fh_export, dchild);
+		if (err)
+			goto out;
 	} else {
 		/* called from nfsd_proc_create */
 		dchild = resfhp->fh_dentry;
@@ -888,10 +896,6 @@
 		write_inode_now(dchild->d_inode);
 	}
 
-	/*
-	 * Update the file handle to get the new inode info.
-	 */
-	fh_update(resfhp);
 
 	/* Set file attributes. Mode has already been set and
 	 * setting uid/gid works only for root. Irix appears to
@@ -901,11 +905,16 @@
 	err = 0;
 	if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
 		err = nfsd_setattr(rqstp, resfhp, iap);
+	/*
+	 * Update the file handle to get the new inode info.
+	 */
+	if (!err)
+		err = fh_update(resfhp);
 out:
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -947,22 +956,20 @@
 	err = PTR_ERR(dchild);
 	if(IS_ERR(dchild))
 		goto out_nfserr;
-	fh_compose(resfhp, fhp->fh_export, dchild);
 
 	/*
 	 * We must lock the directory before we check for the inode.
 	 */
 	err = fh_lock_parent(fhp, dchild);
 	if (err)
-	    goto out;
+		goto out;
+	err = fh_compose(resfhp, fhp->fh_export, dchild);
+	if (err)
+		goto out;
 
 	if (dchild->d_inode) {
 		err = 0;
 
-		if (resfhp->fh_handle.fh_ino == 0)
-		     /* inode might have been instantiated while we slept */
-		    fh_update(resfhp);
-		
 		switch (createmode) {
 		case NFS3_CREATE_UNCHECKED:
 			if (! S_ISREG(dchild->d_inode->i_mode))
@@ -997,8 +1004,9 @@
 	/*
 	 * Update the filehandle to get the new inode info.
 	 */
-	fh_update(resfhp);
-	err = 0;
+	err = fh_update(resfhp);
+	if (err)
+		goto out;
 
 	if (createmode == NFS3_CREATE_EXCLUSIVE) {
 		/* Cram the verifier into atime/mtime */
@@ -1021,7 +1029,7 @@
  	return err;
  
  out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 #endif /* CONFIG_NFSD_V3 */
@@ -1067,7 +1075,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1083,7 +1091,7 @@
 				struct iattr *iap)
 {
 	struct dentry	*dentry, *dnew;
-	int		err;
+	int		err, cerr;
 
 	err = nfserr_noent;
 	if (!flen || !plen)
@@ -1122,17 +1130,18 @@
 		       }
 		}
 	} else
-		err = nfserrno(-err);
+		err = nfserrno(err);
 	fh_unlock(fhp);
 
 	/* Compose the fh so the dentry will be freed ... */
 out_compose:
-	fh_compose(resfhp, fhp->fh_export, dnew);
+	cerr = fh_compose(resfhp, fhp->fh_export, dnew);
+	if (err==0) err = cerr;
 out:
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1186,7 +1195,7 @@
 		if (err == -EXDEV && rqstp->rq_vers == 2)
 			err = nfserr_acces;
 		else
-			err = nfserrno(-err);
+			err = nfserrno(err);
 	}
 
 	fh_unlock(ffhp);
@@ -1196,7 +1205,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1318,7 +1327,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1356,47 +1365,21 @@
 		goto out;
 	}
 
-
-	if (type != S_IFDIR) {
-		/* It's UNLINK */
-
-		err = fh_lock_parent(fhp, rdentry);
-		if (err)
-			goto out;
-
-		err = vfs_unlink(dirp, rdentry);
-
-		fh_unlock(fhp);
-
+	err = fh_lock_parent(fhp, rdentry);
+	if (err) {
 		dput(rdentry);
+		goto out;
+	}
 
-	} else {
-		/* It's RMDIR */
-		/* See comments in fs/namei.c:do_rmdir */
-
-		rdentry->d_count++;
-		nfsd_double_down(&dirp->i_sem, &rdentry->d_inode->i_sem);
-
-#ifdef CONFIG_NFSD_V3
-		fill_pre_wcc(fhp);
-#else
-		fhp->fh_locked = 1;
-#endif /* CONFIG_NFSD_V3 */
+	if (type != S_IFDIR) { /* It's UNLINK */
+		err = vfs_unlink(dirp, rdentry);
+	} else { /* It's RMDIR */
+		err = vfs_rmdir(dirp, rdentry);
+	}
 
-		err = -ENOENT;
-		if (nfsd_check_parent(dentry, rdentry))
-			err = vfs_rmdir(dirp, rdentry);
+	fh_unlock(fhp);
 
-		rdentry->d_count--;
-#ifdef CONFIG_NFSD_V3
-		fill_post_wcc(fhp);
-#else
-		fhp->fh_locked = 0;
-#endif /* CONFIG_NFSD_V3 */
-		nfsd_double_up(&dirp->i_sem, &rdentry->d_inode->i_sem);
-
-		dput(rdentry);
-	}
+	dput(rdentry);
 
 	if (err)
 		goto out_nfserr;
@@ -1409,7 +1392,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out;
 }
 
@@ -1499,7 +1482,7 @@
 	return err;
 
 out_nfserr:
-	err = nfserrno(-err);
+	err = nfserrno(err);
 	goto out_close;
 }
 
@@ -1510,29 +1493,9 @@
 int
 nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct statfs *stat)
 {
-	struct dentry		*dentry;
-	struct inode		*inode;
-	struct super_block	*sb;
-	mm_segment_t		oldfs;
-	int			err;
-
-	err = fh_verify(rqstp, fhp, 0, MAY_NOP);
-	if (err)
-		goto out;
-	dentry = fhp->fh_dentry;
-	inode = dentry->d_inode;
-
-	err = nfserr_io;
-	if (!(sb = inode->i_sb) || !sb->s_op->statfs)
-		goto out;
-
-	oldfs = get_fs();
-	set_fs (KERNEL_DS);
-	sb->s_op->statfs(sb, stat, sizeof(*stat));
-	set_fs (oldfs);
-	err = 0;
-
-out:
+	int err = fh_verify(rqstp, fhp, 0, MAY_NOP);
+	if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat))
+		err = nfserr_io;
 	return err;
 }
 
@@ -1617,7 +1580,7 @@
 	if (current->fsuid != 0)
 		current->cap_effective = saved_cap;
 
-	return err? nfserrno(-err) : 0;
+	return err? nfserrno(err) : 0;
 }
 
 void
diff -u --recursive --new-file v2.3.50/linux/fs/ntfs/fs.c linux/fs/ntfs/fs.c
--- v2.3.50/linux/fs/ntfs/fs.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/ntfs/fs.c	Fri Mar 10 10:48:48 2000
@@ -746,13 +746,11 @@
 	ntfs_free(vol);
 #endif
 	ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");
-	MOD_DEC_USE_COUNT;
 }
 
 /* Called by the kernel when asking for stats */
-static int ntfs_statfs(struct super_block *sb, struct statfs *sf, int bufsize)
+static int ntfs_statfs(struct super_block *sb, struct statfs *sf)
 {
-	struct statfs fs;
 	struct inode *mft;
 	ntfs_volume *vol;
 	ntfs_u64 size;
@@ -760,30 +758,26 @@
 
 	ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
 	vol=NTFS_SB2VOL(sb);
-	memset(&fs,0,sizeof(fs));
-	fs.f_type=NTFS_SUPER_MAGIC;
-	fs.f_bsize=vol->clustersize;
+	sf->f_type=NTFS_SUPER_MAGIC;
+	sf->f_bsize=vol->clustersize;
 
 	error = ntfs_get_volumesize( NTFS_SB2VOL( sb ), &size );
 	if( error )
 		return -error;
-	fs.f_blocks = size;	/* volumesize is in clusters */
-	fs.f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
-	fs.f_bavail=fs.f_bfree;
+	sf->f_blocks = size;	/* volumesize is in clusters */
+	sf->f_bfree=ntfs_get_free_cluster_count(vol->bitmap);
+	sf->f_bavail=sf->f_bfree;
 
-	/* Number of files is limited by free space only, so we lie here */
-	fs.f_ffree=0;
 	mft=iget(sb,FILE_MFT);
 	if (!mft)
 		return -EIO;
 	/* So ... we lie... thus this following cast of loff_t value
 	   is ok here.. */
-	fs.f_files = (unsigned long)mft->i_size / vol->mft_recordsize;
+	sf->f_files = (unsigned long)mft->i_size / vol->mft_recordsize;
 	iput(mft);
 
 	/* should be read from volume */
-	fs.f_namelen=255;
-	copy_to_user(sf,&fs,bufsize);
+	sf->f_namelen=255;
 	return 0;
 }
 
@@ -823,14 +817,6 @@
 	struct buffer_head *bh;
 	int i;
 
-	/* When the driver is compiled as a module, kmod must know when it
-	 * can safely remove it from memory. To do this, each module owns a
-	 * reference counter.
-	 */
-	MOD_INC_USE_COUNT;
-	/* Don't put ntfs_debug() before MOD_INC_USE_COUNT, printk() can block
-	 * so this could lead to a race condition with kmod.
-	 */
 	ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");
 
 #ifdef NTFS_IN_LINUX_KERNEL
@@ -844,9 +830,6 @@
 	if(!parse_options(vol,(char*)options))
 		goto ntfs_read_super_vol;
 
-	/* Ensure that the super block won't be used until it is completed */
-	lock_super(sb);
-	ntfs_debug(DEBUG_OTHER, "lock_super\n");
 #if 0
 	/* Set to read only, user option might reset it */
 	sb->s_flags |= MS_RDONLY;
@@ -919,48 +902,24 @@
 		ntfs_error("Could not get root dir inode\n");
 		goto ntfs_read_super_mft;
 	}
-	unlock_super(sb);
-	ntfs_debug(DEBUG_OTHER, "unlock_super\n");
 	ntfs_debug(DEBUG_OTHER, "read_super: done\n");
 	return sb;
 
 ntfs_read_super_mft:
 	ntfs_free(vol->mft);
 ntfs_read_super_unl:
-	sb->s_dev = 0;
-	unlock_super(sb);
-	ntfs_debug(DEBUG_OTHER, "unlock_super\n");
 ntfs_read_super_vol:
 	#ifndef NTFS_IN_LINUX_KERNEL
 	ntfs_free(vol);
 ntfs_read_super_dec:
 	#endif
 	ntfs_debug(DEBUG_OTHER, "read_super: done\n");
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
 /* Define the filesystem
- *
- * Define SECOND if you cannot unload ntfs, and want to avoid rebooting
- * for just one more test
  */
-static struct file_system_type ntfs_fs_type = {
-/* Filesystem name, as used after mount -t */
-#ifndef SECOND
-	"ntfs",
-#else
-	"ntfs2",
-#endif
-/* This filesystem requires a device (a hard disk)
- * May want to add FS_IBASKET when it works
- */
-	FS_REQUIRES_DEV,
-/* Entry point of the filesystem */
-	ntfs_read_super,
-/* Will point to the next filesystem in the kernel table */
-	NULL
-};
+static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);
 
 /* When this code is not compiled as a module, this is the main entry point,
  * called by do_sys_setup() in fs/filesystems.c
diff -u --recursive --new-file v2.3.50/linux/fs/open.c linux/fs/open.c
--- v2.3.50/linux/fs/open.c	Sat Feb 26 22:31:53 2000
+++ linux/fs/open.c	Wed Mar  8 13:55:08 2000
@@ -4,6 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
+#include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/utime.h>
 #include <linux/file.h>
@@ -21,13 +22,10 @@
 	dentry = namei(path);
 	error = PTR_ERR(dentry);
 	if (!IS_ERR(dentry)) {
-		struct inode * inode = dentry->d_inode;
-		struct super_block * sb = inode->i_sb;
-
-		error = -ENODEV;
-		if (sb && sb->s_op && sb->s_op->statfs)
-			error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
-
+		struct statfs tmp;
+		error = vfs_statfs(dentry->d_inode->i_sb, &tmp);
+		if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
+			error = -EFAULT;
 		dput(dentry);
 	}
 	unlock_kernel();
@@ -37,18 +35,17 @@
 asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf)
 {
 	struct file * file;
-	struct super_block * sb;
+	struct statfs tmp;
 	int error;
 
 	error = -EBADF;
 	file = fget(fd);
 	if (!file)
 		goto out;
-	error = -ENODEV;
-	sb = file->f_dentry->d_inode->i_sb;
 	lock_kernel();
-	if (sb && sb->s_op && sb->s_op->statfs)
-		error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
+	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
+	if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
+		error = -EFAULT;
 	unlock_kernel();
 	fput(file);
 out:
diff -u --recursive --new-file v2.3.50/linux/fs/openpromfs/inode.c linux/fs/openpromfs/inode.c
--- v2.3.50/linux/fs/openpromfs/inode.c	Thu Mar  2 14:36:23 2000
+++ linux/fs/openpromfs/inode.c	Fri Mar 10 10:48:48 2000
@@ -1,4 +1,4 @@
-/* $Id: inode.c,v 1.6 2000/02/27 08:19:47 davem Exp $
+/* $Id: inode.c,v 1.7 2000/03/10 04:45:50 davem Exp $
  * openpromfs.c: /proc/openprom handling routines
  *
  * Copyright (C) 1996-1999 Jakub Jelinek  (jakub@redhat.com)
@@ -982,22 +982,17 @@
 
 static void openprom_put_super(struct super_block *sb)
 {
-	MOD_DEC_USE_COUNT;
 }
 
-static int openprom_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int openprom_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = OPENPROM_SUPER_MAGIC;
-	tmp.f_bsize = PAGE_SIZE/sizeof(long);	/* ??? */
-	tmp.f_blocks = 0;
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = OPENPROM_SUPER_MAGIC;
+	buf->f_bsize = PAGE_SIZE/sizeof(long);	/* ??? */
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_ffree = 0;
+	buf->f_namelen = NAME_MAX;
+	return 0;
 }
 
 static struct super_operations openprom_sops = { 
@@ -1011,8 +1006,6 @@
 {
 	struct inode * root_inode;
 
-	MOD_INC_USE_COUNT;
-	lock_super(s);
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;
 	s->s_magic = OPENPROM_SUPER_MAGIC;
@@ -1023,24 +1016,15 @@
 	s->s_root = d_alloc_root(root_inode);
 	if (!s->s_root)
 		goto out_no_root;
-	unlock_super(s);
 	return s;
 
 out_no_root:
 	printk("openprom_read_super: get root inode failed\n");
 	iput(root_inode);
-	s->s_dev = 0;
-	unlock_super(s);
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
-static struct file_system_type openprom_fs_type = {
-	"openpromfs",
-	0,
-	openprom_read_super,
-	NULL
-};
+static DECLARE_FSTYPE(openprom_fs_type, "openpromfs", openprom_read_super, 0);
 
 int init_openprom_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.3.50/linux/fs/proc/array.c	Thu Feb 10 17:11:18 2000
+++ linux/fs/proc/array.c	Thu Mar  9 07:04:49 2000
@@ -151,12 +151,13 @@
 		"State:\t%s\n"
 		"Pid:\t%d\n"
 		"PPid:\t%d\n"
+		"TracerPid:\t%d\n"
 		"Uid:\t%d\t%d\t%d\t%d\n"
 		"Gid:\t%d\t%d\t%d\t%d\n"
 		"FDSize:\t%d\n"
 		"Groups:\t",
 		get_task_state(p),
-		p->pid, p->p_pptr->pid,
+		p->pid, p->p_opptr->pid, p->p_pptr->pid != p->p_opptr->pid ? p->p_opptr->pid : 0,
 		p->uid, p->euid, p->suid, p->fsuid,
 		p->gid, p->egid, p->sgid, p->fsgid,
 		p->files ? p->files->max_fds : 0);
@@ -327,7 +328,7 @@
 		task->pid,
 		task->comm,
 		state,
-		task->p_pptr->pid,
+		task->p_opptr->pid,
 		task->pgrp,
 		task->session,
 	        task->tty ? kdev_t_to_nr(task->tty->device) : 0,
diff -u --recursive --new-file v2.3.50/linux/fs/proc/inode.c linux/fs/proc/inode.c
--- v2.3.50/linux/fs/proc/inode.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/proc/inode.c	Fri Mar 10 10:48:48 2000
@@ -100,19 +100,15 @@
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 }
 
-static int proc_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int proc_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = PROC_SUPER_MAGIC;
-	tmp.f_bsize = PAGE_SIZE/sizeof(long);
-	tmp.f_blocks = 0;
-	tmp.f_bfree = 0;
-	tmp.f_bavail = 0;
-	tmp.f_files = 0;
-	tmp.f_ffree = 0;
-	tmp.f_namelen = NAME_MAX;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = PROC_SUPER_MAGIC;
+	buf->f_bsize = PAGE_SIZE/sizeof(long);
+	buf->f_bfree = 0;
+	buf->f_bavail = 0;
+	buf->f_ffree = 0;
+	buf->f_namelen = NAME_MAX;
+	return 0;
 }
 
 static struct super_operations proc_sops = { 
@@ -209,7 +205,6 @@
 	struct inode * root_inode;
 	struct task_struct *p;
 
-	lock_super(s);
 	s->s_blocksize = 1024;
 	s->s_blocksize_bits = 10;
 	s->s_magic = PROC_SUPER_MAGIC;
@@ -229,13 +224,10 @@
 	parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
 	s->u.generic_sbp = (void*) proc_super_blocks;
 	proc_super_blocks = s;
-	unlock_super(s);
 	return s;
 
 out_no_root:
 	printk("proc_read_super: get root inode failed\n");
 	iput(root_inode);
-	s->s_dev = 0;
-	unlock_super(s);
 	return NULL;
 }
diff -u --recursive --new-file v2.3.50/linux/fs/proc/procfs_syms.c linux/fs/proc/procfs_syms.c
--- v2.3.50/linux/fs/proc/procfs_syms.c	Thu Feb 10 17:11:18 2000
+++ linux/fs/proc/procfs_syms.c	Fri Mar 10 10:48:48 2000
@@ -20,12 +20,7 @@
 EXPORT_SYMBOL(proc_bus);
 EXPORT_SYMBOL(proc_root_driver);
 
-static struct file_system_type proc_fs_type = {
-	"proc", 
-	0 /* FS_NO_DCACHE doesn't work correctly */,
-	proc_read_super, 
-	NULL
-};
+static DECLARE_FSTYPE(proc_fs_type, "proc", proc_read_super, 0);
 
 int __init init_proc_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/qnx4/inode.c linux/fs/qnx4/inode.c
--- v2.3.50/linux/fs/qnx4/inode.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/qnx4/inode.c	Fri Mar 10 10:48:48 2000
@@ -117,7 +117,7 @@
 static void qnx4_put_super(struct super_block *sb);
 static void qnx4_read_inode(struct inode *);
 static int qnx4_remount(struct super_block *sb, int *flags, char *data);
-static int qnx4_statfs(struct super_block *, struct statfs *, int);
+static int qnx4_statfs(struct super_block *, struct statfs *);
 
 static struct super_operations qnx4_sops =
 {
@@ -269,22 +269,16 @@
 	return block;
 }
 
-static int qnx4_statfs(struct super_block *sb,
-		       struct statfs *buf, int bufsize)
+static int qnx4_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
+	buf->f_type    = sb->s_magic;
+	buf->f_bsize   = sb->s_blocksize;
+	buf->f_blocks  = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8;
+	buf->f_bfree   = qnx4_count_free_blocks(sb);
+	buf->f_bavail  = buf->f_bfree;
+	buf->f_namelen = QNX4_NAME_MAX;
 
-	memset(&tmp, 0, sizeof tmp);
-	tmp.f_type    = sb->s_magic;
-	tmp.f_bsize   = sb->s_blocksize;
-	tmp.f_blocks  = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8;
-	tmp.f_bfree   = qnx4_count_free_blocks(sb);
-	tmp.f_bavail  = tmp.f_bfree;
-	tmp.f_files   = -1;	/* we don't count files */
-	tmp.f_ffree   = -1;	/* inodes are allocated dynamically */
-	tmp.f_namelen = QNX4_NAME_MAX;
-
-	return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
+	return 0;
 }
 
 /*
@@ -343,8 +337,6 @@
 	struct inode *root;
 	const char *errmsg;
 
-	MOD_INC_USE_COUNT;
-	lock_super(s);
 	set_blocksize(dev, QNX4_BLOCK_SIZE);
 	s->s_blocksize = QNX4_BLOCK_SIZE;
 	s->s_blocksize_bits = QNX4_BLOCK_SIZE_BITS;
@@ -399,7 +391,6 @@
  		goto outi;
 
 	brelse(bh);
-	unlock_super(s);
 	s->s_dirt = 1;
 
 	return s;
@@ -409,9 +400,6 @@
       out:
 	brelse(bh);
       outnobh:
-	s->s_dev = 0;
-	unlock_super(s);
-	MOD_DEC_USE_COUNT;
 
 	return NULL;
 }
@@ -419,7 +407,6 @@
 static void qnx4_put_super(struct super_block *sb)
 {
 	kfree_s( sb->u.qnx4_sb.BitMap, sizeof( struct qnx4_inode_entry ) );
-	MOD_DEC_USE_COUNT;
 	return;
 }
 
@@ -502,13 +489,7 @@
 	brelse(bh);
 }
 
-static struct file_system_type qnx4_fs_type =
-{
-	"qnx4",
-	FS_REQUIRES_DEV,
-	qnx4_read_super,
-	NULL
-};
+static DECLARE_FSTYPE_DEV(qnx4_fs_type, "qnx4", qnx4_read_super);
 
 int __init init_qnx4_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c
--- v2.3.50/linux/fs/qnx4/namei.c	Sat Feb 12 11:22:11 2000
+++ linux/fs/qnx4/namei.c	Wed Mar  8 09:04:09 2000
@@ -171,7 +171,7 @@
 		goto end_rmdir;
 	}
 #endif
-	if (!list_empty(&dentry->d_hash)) {
+	if (!d_unhashed(dentry)) {
 		retval = -EBUSY;
 		goto end_rmdir;
 	}
diff -u --recursive --new-file v2.3.50/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.3.50/linux/fs/romfs/inode.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/romfs/inode.c	Fri Mar 10 10:48:48 2000
@@ -105,11 +105,8 @@
 	struct romfs_super_block *rsb;
 	int sz;
 
-	MOD_INC_USE_COUNT;
-
 	/* I would parse the options here, but there are none.. :) */
 
-	lock_super(s);
 	set_blocksize(dev, ROMBSIZE);
 	s->s_blocksize = ROMBSIZE;
 	s->s_blocksize_bits = ROMBSBITS;
@@ -153,16 +150,11 @@
 	if (!s->s_root)
 		goto outnobh;
 
-	unlock_super(s);
-
 	/* Ehrhm; sorry.. :)  And thanks to Hans-Joachim Widmaier  :) */
 	if (0) {
 out:
 		brelse(bh);
 outnobh:
-		s->s_dev = 0;
-		unlock_super(s);
-		MOD_DEC_USE_COUNT;
 		s = NULL;
 	}
 
@@ -174,23 +166,20 @@
 static void
 romfs_put_super(struct super_block *sb)
 {
-	MOD_DEC_USE_COUNT;
 	return;
 }
 
 /* That's simple too. */
 
 static int
-romfs_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+romfs_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.f_type = ROMFS_MAGIC;
-	tmp.f_bsize = ROMBSIZE;
-	tmp.f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS;
-	tmp.f_namelen = ROMFS_MAXFN;
-	return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
+	buf->f_type = ROMFS_MAGIC;
+	buf->f_bsize = ROMBSIZE;
+	buf->f_bfree = buf->f_bavail = buf->f_ffree;
+	buf->f_blocks = (sb->u.romfs_sb.s_maxsize+ROMBSIZE-1)>>ROMBSBITS;
+	buf->f_namelen = ROMFS_MAXFN;
+	return 0;
 }
 
 /* some helper routines */
@@ -541,12 +530,7 @@
 	statfs:		romfs_statfs,
 };
 
-static struct file_system_type romfs_fs_type = {
-	"romfs",
-	FS_REQUIRES_DEV,
-	romfs_read_super,
-	NULL
-};
+static DECLARE_FSTYPE_DEV(romfs_fs_type, "romfs", romfs_read_super);
 
 int __init init_romfs_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.3.50/linux/fs/smbfs/dir.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/smbfs/dir.c	Wed Mar  8 09:04:09 2000
@@ -443,7 +443,7 @@
 	 * Check that nobody else is using the directory..
 	 */
 	error = -EBUSY;
-	if (!list_empty(&dentry->d_hash))
+	if (!d_unhashed(dentry))
 		goto out;
 
 	smb_invalid_dir_cache(dir);
diff -u --recursive --new-file v2.3.50/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.3.50/linux/fs/smbfs/inode.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/smbfs/inode.c	Fri Mar 10 10:48:48 2000
@@ -32,7 +32,7 @@
 static void smb_put_inode(struct inode *);
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
-static int  smb_statfs(struct super_block *, struct statfs *, int);
+static int  smb_statfs(struct super_block *, struct statfs *);
 static void smb_set_inode_attr(struct inode *, struct smb_fattr *);
 
 static struct super_operations smb_sops =
@@ -315,8 +315,6 @@
 	kfree(sb->u.smbfs_sb.temp_buf);
 	if (server->packet)
 		smb_vfree(server->packet);
-
-	MOD_DEC_USE_COUNT;
 }
 
 struct super_block *
@@ -326,15 +324,11 @@
 	struct inode *root_inode;
 	struct smb_fattr root;
 
-	MOD_INC_USE_COUNT;
-
 	if (!raw_data)
 		goto out_no_data;
 	if (((struct smb_mount_data *) raw_data)->version != SMB_MOUNT_VERSION)
 		goto out_wrong_data;
 
-	lock_super(sb);
-
 	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = SMB_SUPER_MAGIC;
@@ -389,7 +383,6 @@
 	if (!sb->s_root)
 		goto out_no_root;
 
-	unlock_super(sb);
 	return sb;
 
 out_no_root:
@@ -401,7 +394,6 @@
 	smb_vfree(sb->u.smbfs_sb.packet);
 out_no_mem:
 	printk(KERN_ERR "smb_read_super: allocation failure\n");
-	unlock_super(sb);
 	goto out_fail;
 out_wrong_data:
 	printk(KERN_ERR "SMBFS: need mount version %d\n", SMB_MOUNT_VERSION);
@@ -409,25 +401,17 @@
 out_no_data:
 	printk("smb_read_super: missing data argument\n");
 out_fail:
-	sb->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
 static int
-smb_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+smb_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs attr;
+	smb_proc_dskattr(sb, buf);
 
-	memset(&attr, 0, sizeof(attr));
-
-	smb_proc_dskattr(sb, &attr);
-
-	attr.f_type = SMB_SUPER_MAGIC;
-	attr.f_files = -1;
-	attr.f_ffree = -1;
-	attr.f_namelen = SMB_MAXPATHLEN;
-	return copy_to_user(buf, &attr, bufsiz) ? -EFAULT : 0;
+	buf->f_type = SMB_SUPER_MAGIC;
+	buf->f_namelen = SMB_MAXPATHLEN;
+	return 0;
 }
 
 int
@@ -550,12 +534,7 @@
 int smb_current_vmalloced;
 #endif
 
-static struct file_system_type smb_fs_type = {
-	"smbfs",
-	0 /* FS_NO_DCACHE doesn't work correctly */,
-	smb_read_super,
-	NULL
-};
+static DECLARE_FSTYPE( smb_fs_type, "smbfs", smb_read_super, 0);
 
 int __init init_smb_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/super.c linux/fs/super.c
--- v2.3.50/linux/fs/super.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/super.c	Fri Mar 10 14:54:29 2000
@@ -19,6 +19,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/string.h>
 #include <linux/malloc.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
@@ -34,9 +35,9 @@
 #include <linux/nfs_fs_sb.h>
 #include <linux/nfs_mount.h>
 
-#ifdef CONFIG_KMOD
 #include <linux/kmod.h>
-#endif
+#define __NO_VERSION__
+#include <linux/module.h>
 
 /*
  * We use a semaphore to synchronize all mount/umount
@@ -59,7 +60,194 @@
 int max_super_blocks = NR_SUPER;
 LIST_HEAD(super_blocks);
 
+/*
+ * Handling of filesystem drivers list.
+ * Rules:
+ *	Inclusion to/removals from/scanning of list are protected by spinlock.
+ *	During the unload module must call unregister_filesystem().
+ *	We can access the fields of list element if:
+ *		1) spinlock is held or
+ *		2) we hold the reference to the module.
+ *	The latter can be guaranteed by call of try_inc_mod_count(); if it
+ *	returned 0 we must skip the element, otherwise we got the reference.
+ *	Once the reference is obtained we can drop the spinlock.
+ */
+
 static struct file_system_type *file_systems = NULL;
+static spinlock_t file_systems_lock = SPIN_LOCK_UNLOCKED;
+
+static void put_filesystem(struct file_system_type *fs)
+{
+	if (fs->owner)
+		__MOD_DEC_USE_COUNT(fs->owner);
+}
+
+static struct file_system_type **find_filesystem(const char *name)
+{
+	struct file_system_type **p;
+	for (p=&file_systems; *p; p=&(*p)->next)
+		if (strcmp((*p)->name,name) == 0)
+			break;
+	return p;
+}
+
+int register_filesystem(struct file_system_type * fs)
+{
+	int res = 0;
+	struct file_system_type ** p;
+
+	if (!fs)
+		return -EINVAL;
+	if (fs->next)
+		return -EBUSY;
+	spin_lock(&file_systems_lock);
+	p = find_filesystem(fs->name);
+	if (*p)
+		res = -EBUSY;
+	else
+		*p = fs;
+	spin_unlock(&file_systems_lock);
+	return res;
+}
+
+int unregister_filesystem(struct file_system_type * fs)
+{
+	struct file_system_type ** tmp;
+
+	spin_lock(&file_systems_lock);
+	tmp = &file_systems;
+	while (*tmp) {
+		if (fs == *tmp) {
+			*tmp = fs->next;
+			fs->next = NULL;
+			spin_unlock(&file_systems_lock);
+			return 0;
+		}
+		tmp = &(*tmp)->next;
+	}
+	spin_unlock(&file_systems_lock);
+	return -EINVAL;
+}
+
+static int fs_index(const char * __name)
+{
+	struct file_system_type * tmp;
+	char * name;
+	int err, index;
+
+	name = getname(__name);
+	err = PTR_ERR(name);
+	if (IS_ERR(name))
+		return err;
+
+	err = -EINVAL;
+	spin_lock(&file_systems_lock);
+	for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
+		if (strcmp(tmp->name,name) == 0) {
+			err = index;
+			break;
+		}
+		index++;
+	}
+	spin_unlock(&file_systems_lock);
+	putname(name);
+	return err;
+}
+
+static int fs_name(unsigned int index, char * buf)
+{
+	struct file_system_type * tmp;
+	int len, res;
+
+	spin_lock(&file_systems_lock);
+	for (tmp = file_systems; tmp; tmp = tmp->next, index--)
+		if (index <= 0 && try_inc_mod_count(tmp->owner))
+				break;
+	spin_unlock(&file_systems_lock);
+	if (!tmp)
+		return -EINVAL;
+
+	/* OK, we got the reference, so we can safely block */
+	len = strlen(tmp->name) + 1;
+	res = copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
+	put_filesystem(tmp);
+	return res;
+}
+
+static int fs_maxindex(void)
+{
+	struct file_system_type * tmp;
+	int index;
+
+	spin_lock(&file_systems_lock);
+	for (tmp = file_systems, index = 0 ; tmp ; tmp = tmp->next, index++)
+		;
+	spin_unlock(&file_systems_lock);
+	return index;
+}
+
+/*
+ * Whee.. Weird sysv syscall. 
+ */
+asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
+{
+	int retval = -EINVAL;
+
+	lock_kernel();
+	switch (option) {
+		case 1:
+			retval = fs_index((const char *) arg1);
+			break;
+
+		case 2:
+			retval = fs_name(arg1, (char *) arg2);
+			break;
+
+		case 3:
+			retval = fs_maxindex();
+			break;
+	}
+	unlock_kernel();
+	return retval;
+}
+
+int get_filesystem_list(char * buf)
+{
+	int len = 0;
+	struct file_system_type * tmp;
+
+	spin_lock(&file_systems_lock);
+	tmp = file_systems;
+	while (tmp && len < PAGE_SIZE - 80) {
+		len += sprintf(buf+len, "%s\t%s\n",
+			(tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
+			tmp->name);
+		tmp = tmp->next;
+	}
+	spin_unlock(&file_systems_lock);
+	return len;
+}
+
+static struct file_system_type *get_fs_type(const char *name)
+{
+	struct file_system_type *fs;
+	
+	spin_lock(&file_systems_lock);
+	fs = *(find_filesystem(name));
+	if (fs && !try_inc_mod_count(fs->owner))
+		fs = NULL;
+	spin_unlock(&file_systems_lock);
+	if (!fs && (request_module(name) == 0)) {
+		spin_lock(&file_systems_lock);
+		fs = *(find_filesystem(name));
+		if (fs && !try_inc_mod_count(fs->owner))
+			fs = NULL;
+		spin_unlock(&file_systems_lock);
+	}
+	return fs;
+}
+
+
 struct vfsmount *vfsmntlist = NULL;
 static struct vfsmount *vfsmnttail = NULL, *mru_vfsmnt = NULL;
 
@@ -164,115 +352,6 @@
 	kfree_s(tofree, sizeof(struct vfsmount));
 }
 
-int register_filesystem(struct file_system_type * fs)
-{
-	struct file_system_type ** tmp;
-
-	if (!fs)
-		return -EINVAL;
-	if (fs->next)
-		return -EBUSY;
-	tmp = &file_systems;
-	while (*tmp) {
-		if (strcmp((*tmp)->name, fs->name) == 0)
-			return -EBUSY;
-		tmp = &(*tmp)->next;
-	}
-	*tmp = fs;
-	return 0;
-}
-
-int unregister_filesystem(struct file_system_type * fs)
-{
-	struct file_system_type ** tmp;
-
-	tmp = &file_systems;
-	while (*tmp) {
-		if (fs == *tmp) {
-			*tmp = fs->next;
-			fs->next = NULL;
-			return 0;
-		}
-		tmp = &(*tmp)->next;
-	}
-	return -EINVAL;
-}
-
-static int fs_index(const char * __name)
-{
-	struct file_system_type * tmp;
-	char * name;
-	int err, index;
-
-	name = getname(__name);
-	err = PTR_ERR(name);
-	if (IS_ERR(name))
-		return err;
-
-	index = 0;
-	for (tmp = file_systems ; tmp ; tmp = tmp->next) {
-		if (strcmp(tmp->name, name) == 0) {
-			putname(name);
-			return index;
-		}
-		index++;
-	}
-	putname(name);
-	return -EINVAL;
-}
-
-static int fs_name(unsigned int index, char * buf)
-{
-	struct file_system_type * tmp;
-	int len;
-
-	tmp = file_systems;
-	while (tmp && index > 0) {
-		tmp = tmp->next;
-		index--;
-	}
-	if (!tmp)
-		return -EINVAL;
-	len = strlen(tmp->name) + 1;
-	return copy_to_user(buf, tmp->name, len) ? -EFAULT : 0;
-}
-
-static int fs_maxindex(void)
-{
-	struct file_system_type * tmp;
-	int index;
-
-	index = 0;
-	for (tmp = file_systems ; tmp ; tmp = tmp->next)
-		index++;
-	return index;
-}
-
-/*
- * Whee.. Weird sysv syscall. 
- */
-asmlinkage long sys_sysfs(int option, unsigned long arg1, unsigned long arg2)
-{
-	int retval = -EINVAL;
-
-	lock_kernel();
-	switch (option) {
-		case 1:
-			retval = fs_index((const char *) arg1);
-			break;
-
-		case 2:
-			retval = fs_name(arg1, (char *) arg2);
-			break;
-
-		case 3:
-			retval = fs_maxindex();
-			break;
-	}
-	unlock_kernel();
-	return retval;
-}
-
 static struct proc_fs_info {
 	int flag;
 	char *str;
@@ -379,39 +458,6 @@
 	return len;
 }
 
-int get_filesystem_list(char * buf)
-{
-	int len = 0;
-	struct file_system_type * tmp;
-
-	tmp = file_systems;
-	while (tmp && len < PAGE_SIZE - 80) {
-		len += sprintf(buf+len, "%s\t%s\n",
-			(tmp->fs_flags & FS_REQUIRES_DEV) ? "" : "nodev",
-			tmp->name);
-		tmp = tmp->next;
-	}
-	return len;
-}
-
-struct file_system_type *get_fs_type(const char *name)
-{
-	struct file_system_type * fs = file_systems;
-	
-	if (!name)
-		return fs;
-	for (fs = file_systems; fs && strcmp(fs->name, name); fs = fs->next)
-		;
-#ifdef CONFIG_KMOD
-	if (!fs && (request_module(name) == 0)) {
-		for (fs = file_systems; fs && strcmp(fs->name, name); fs = fs->next)
-			;
-	}
-#endif
-
-	return fs;
-}
-
 void __wait_on_super(struct super_block * sb)
 {
 	DECLARE_WAITQUEUE(wait, current);
@@ -480,21 +526,15 @@
         struct super_block *s;
         struct ustat tmp;
         struct statfs sbuf;
-        mm_segment_t old_fs;
 	int err = -EINVAL;
 
 	lock_kernel();
         s = get_super(to_kdev_t(dev));
         if (s == NULL)
                 goto out;
-	err = -ENOSYS;
-        if (!(s->s_op->statfs))
-                goto out;
-
-        old_fs = get_fs();
-        set_fs(get_ds());
-        s->s_op->statfs(s,&sbuf,sizeof(struct statfs));
-        set_fs(old_fs);
+	err = vfs_statfs(s, &sbuf);
+	if (err)
+		goto out;
 
         memset(&tmp,0,sizeof(struct ustat));
         tmp.f_tfree = sbuf.f_bfree;
@@ -538,25 +578,10 @@
 }
 
 static struct super_block * read_super(kdev_t dev, struct block_device *bdev,
-				       const char *name, int flags,
+				       struct file_system_type *type, int flags,
 				       void *data, int silent)
 {
 	struct super_block * s;
-	struct file_system_type *type;
-
-	if (!dev)
-		goto out_null;
-	check_disk_change(dev);
-	s = get_super(dev);
-	if (s)
-		goto found;	/* ought to set ->s_bdev */
-
-	type = get_fs_type(name);
-	if (!type) {
-		printk("VFS: on device %s: get_fs_type(%s) failed\n",
-		       kdevname(dev), name);
-		goto out;
-	}
 	s = get_empty_super();
 	if (!s)
 		goto out;
@@ -566,11 +591,11 @@
 	s->s_dirt = 0;
 	sema_init(&s->s_vfs_rename_sem,1);
 	sema_init(&s->s_nfsd_free_path_sem,1);
-	/* N.B. Should lock superblock now ... */
+	s->s_type = type;
+	lock_super(s);
 	if (!type->read_super(s, data, silent))
 		goto out_fail;
-	s->s_type = type;
-bd_get:
+	unlock_super(s);
 	/* tell bdcache that we are going to keep this one */
 	if (bdev)
 		atomic_inc(&bdev->bd_count);
@@ -580,12 +605,10 @@
 out_fail:
 	s->s_dev = 0;
 	s->s_bdev = 0;
-out_null:
-	s = NULL;
-	goto out;
-found:
-	s->s_bdev = bdev;
-	goto bd_get;
+	s->s_type = NULL;
+	put_filesystem(type);
+	unlock_super(s);
+	return NULL;
 }
 
 /*
@@ -725,6 +748,8 @@
 	sb->s_dev = 0;		/* Free the superblock */
 	bdev = sb->s_bdev;
 	sb->s_bdev = NULL;
+	put_filesystem(sb->s_type);
+	sb->s_type = NULL;
 	unlock_super(sb);
 
 	remove_vfsmnt(dev);
@@ -859,6 +884,7 @@
 	struct dentry * dir_d;
 	struct super_block * sb;
 	struct vfsmount *vfsmnt;
+	struct file_system_type *fs_type;
 	int error;
 
 	if (bdev) {
@@ -896,14 +922,27 @@
 	if (dir_d->d_covers != dir_d)
 		goto dput_and_out;
 
-	/*
-	 * Note: If the superblock already exists,
-	 * read_super just does a get_super().
-	 */
 	error = -EINVAL;
-	sb = read_super(dev, bdev, type, flags, data, 0);
-	if (!sb)
+	if (!dev)
 		goto dput_and_out;
+	check_disk_change(dev);
+	sb = get_super(dev);
+	if (sb) {
+		/* Already mounted */
+		error = -EBUSY;
+		goto dput_and_out;
+	}
+
+	fs_type = get_fs_type(type);
+	if (!fs_type) {
+		printk("VFS: on device %s: get_fs_type(%s) failed\n",
+		       kdevname(dev), type);
+		goto dput_and_out;
+	}
+
+	sb = read_super(dev, bdev, fs_type, flags, data, 0);
+	if (!sb)
+		goto fsput_and_out;
 
 	/*
 	 * We may have slept while reading the super block, 
@@ -923,7 +962,12 @@
 	}
 
 bdput_and_out:
+	/* FIXME: ->put_super() is needed here */
 	sb->s_bdev = NULL;
+	sb->s_dev = 0;
+	sb->s_type = NULL;
+fsput_and_out:
+	put_filesystem(fs_type);
 	if (bdev)
 		bdput(bdev);
 dput_and_out:
@@ -956,7 +1000,9 @@
 		if (!fs_may_remount_ro(sb))
 			return -EBUSY;
 	if (sb->s_op && sb->s_op->remount_fs) {
+		lock_super(sb);
 		retval = sb->s_op->remount_fs(sb, &flags, data);
+		unlock_super(sb);
 		if (retval)
 			return retval;
 	}
@@ -1159,6 +1205,7 @@
 			}
 			put_unnamed_dev(sb->s_dev);
 			sb->s_dev = 0;
+			put_filesystem(fs_type);
 		}
 		if (!ROOT_DEV) {
 			printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
@@ -1200,6 +1247,14 @@
 	    devfs_get_maj_min (handle, &major, &minor);
 	    ROOT_DEV = MKDEV (major, minor);
 	}
+
+	/*
+	 * Probably pure paranoia, but I'm less than happy about delving into
+	 * devfs crap and checking it right now. Later.
+	 */
+	if (!ROOT_DEV)
+		panic("I have no root and I want to sream");
+
 	bdev = bdget(kdev_t_to_nr(ROOT_DEV));
 	if (!bdev)
 		panic(__FUNCTION__ ": unable to allocate root device");
@@ -1221,37 +1276,57 @@
 		printk ("VFS: Cannot open root device \"%s\" or %s\n",
 			root_device_name, kdevname (ROOT_DEV));
 		printk ("Please append a correct \"root=\" boot option\n");
+		panic("VFS: Unable to mount root fs on %s",
+			kdevname(ROOT_DEV));
 	}
-	else for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
+
+	check_disk_change(ROOT_DEV);
+
+	spin_lock(&file_systems_lock);
+	for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
   		if (!(fs_type->fs_flags & FS_REQUIRES_DEV))
   			continue;
-  		sb = read_super(ROOT_DEV,bdev,fs_type->name,root_mountflags,NULL,1);
+		if (!try_inc_mod_count(fs_type->owner))
+			continue;
+		spin_unlock(&file_systems_lock);
+		sb = get_super(ROOT_DEV);
 		if (sb) {
-			sb->s_flags = root_mountflags;
-			current->fs->root = dget(sb->s_root);
-			current->fs->pwd = dget(sb->s_root);
-			printk ("VFS: Mounted root (%s filesystem)%s.\n",
-				fs_type->name,
-				(sb->s_flags & MS_RDONLY) ? " readonly" : "");
-			if (path_start >= 0) {
-				devfs_mk_symlink (NULL,
-						  "root", 0, DEVFS_FL_DEFAULT,
-						  path + 5 + path_start, 0,
-						  NULL, NULL);
-				memcpy (path + path_start, "/dev/", 5);
-				vfsmnt = add_vfsmnt (sb, path + path_start,
-						     "/");
-			}
-			else vfsmnt = add_vfsmnt (sb, "/dev/root", "/");
-			if (vfsmnt) {
-				bdput(bdev); /* sb holds a reference */
-				return;
-			}
-			panic("VFS: add_vfsmnt failed for root fs");
+			/* Shouldn't we fail here? Oh, well... */
+			sb->s_bdev = bdev;
+			goto mount_it;
 		}
+  		sb = read_super(ROOT_DEV,bdev,fs_type,root_mountflags,NULL,1);
+		if (sb) 
+			goto mount_it;
+		spin_lock(&file_systems_lock);
+		put_filesystem(fs_type);
 	}
+	spin_unlock(&file_systems_lock);
 	panic("VFS: Unable to mount root fs on %s",
 		kdevname(ROOT_DEV));
+
+mount_it:
+	sb->s_flags = root_mountflags;
+	current->fs->root = dget(sb->s_root);
+	current->fs->pwd = dget(sb->s_root);
+	printk ("VFS: Mounted root (%s filesystem)%s.\n",
+		fs_type->name,
+		(sb->s_flags & MS_RDONLY) ? " readonly" : "");
+	if (path_start >= 0) {
+		devfs_mk_symlink (NULL,
+				  "root", 0, DEVFS_FL_DEFAULT,
+				  path + 5 + path_start, 0,
+				  NULL, NULL);
+		memcpy (path + path_start, "/dev/", 5);
+		vfsmnt = add_vfsmnt (sb, path + path_start,
+				     "/");
+	}
+	else vfsmnt = add_vfsmnt (sb, "/dev/root", "/");
+	if (vfsmnt) {
+		bdput(bdev); /* sb holds a reference */
+		return;
+	}
+	panic("VFS: add_vfsmnt failed for root fs");
 }
 
 
diff -u --recursive --new-file v2.3.50/linux/fs/sysv/inode.c linux/fs/sysv/inode.c
--- v2.3.50/linux/fs/sysv/inode.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/sysv/inode.c	Fri Mar 10 10:48:48 2000
@@ -68,7 +68,7 @@
 static void sysv_put_super(struct super_block *);
 static void sysv_write_super(struct super_block *);
 static void sysv_read_inode(struct inode *);
-static int sysv_statfs(struct super_block *, struct statfs *, int);
+static int sysv_statfs(struct super_block *, struct statfs *);
 
 static struct super_operations sysv_sops = {
 	read_inode:	sysv_read_inode,
@@ -360,8 +360,6 @@
 		panic("Coherent FS: bad super-block size");
 	if (64 != sizeof (struct sysv_inode))
 		panic("sysv fs: bad i-node size");
-	MOD_INC_USE_COUNT;
-	lock_super(sb);
 	set_blocksize(dev,BLOCK_SIZE);
 	sb->sv_block_base = 0;
 
@@ -407,13 +405,10 @@
 			}
 	}
 	bad_shift:
-	sb->s_dev = 0;
-	unlock_super(sb);
 	if (!silent)
 		printk("VFS: unable to read Xenix/SystemV/Coherent superblock on device "
 		       "%s\n", kdevname(dev));
 	failed:
-	MOD_DEC_USE_COUNT;
 	return NULL;
 
 	ok:
@@ -442,8 +437,6 @@
 		goto superblock_ok;
 		bad_superblock:
 			brelse(bh);
-			sb->s_dev = 0;
-			unlock_super(sb);
 			printk("SysV FS: cannot read superblock in %d byte mode\n", sb->sv_block_size);
 			goto failed;
 		superblock_ok:
@@ -489,8 +482,6 @@
 				brelse(bh1);
 				brelse(bh2);
 				set_blocksize(sb->s_dev,BLOCK_SIZE);
-				sb->s_dev = 0;
-				unlock_super(sb);
 				printk("SysV FS: cannot read superblock in 512 byte mode\n");
 				goto failed;
 		}
@@ -511,14 +502,11 @@
 	if (!sb->s_root) {
 		printk("SysV FS: get root inode failed\n");
 		sysv_put_super(sb);
-		sb->s_dev = 0;
-		unlock_super(sb);
 		return NULL;
 	}
 #ifndef CONFIG_SYSV_FS_WRITE
 	sb->s_flags |= MS_RDONLY;
 #endif
-	unlock_super(sb);
 	sb->s_dirt = 1;
 	/* brelse(bh);  resp.  brelse(bh1); brelse(bh2);
 	   occurs when the disk is unmounted. */
@@ -558,24 +546,20 @@
 	/* switch back to default block size */
 	if (sb->s_blocksize != BLOCK_SIZE)
 		set_blocksize(sb->s_dev,BLOCK_SIZE);
-
-	MOD_DEC_USE_COUNT;
 }
 
-static int sysv_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
+static int sysv_statfs(struct super_block *sb, struct statfs *buf)
 {
-	struct statfs tmp;
-
-	tmp.f_type = sb->s_magic;			/* type of filesystem */
-	tmp.f_bsize = sb->sv_block_size;		/* block size */
-	tmp.f_blocks = sb->sv_ndatazones;		/* total data blocks in file system */
-	tmp.f_bfree = sysv_count_free_blocks(sb);	/* free blocks in fs */
-	tmp.f_bavail = tmp.f_bfree;			/* free blocks available to non-superuser */
-	tmp.f_files = sb->sv_ninodes;			/* total file nodes in file system */
-	tmp.f_ffree = sysv_count_free_inodes(sb);	/* free file nodes in fs */
-	tmp.f_namelen = SYSV_NAMELEN;
-	/* Don't know what value to put in tmp.f_fsid */ /* file system id */
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_type = sb->s_magic;			/* type of filesystem */
+	buf->f_bsize = sb->sv_block_size;		/* block size */
+	buf->f_blocks = sb->sv_ndatazones;		/* total data blocks in file system */
+	buf->f_bfree = sysv_count_free_blocks(sb);	/* free blocks in fs */
+	buf->f_bavail = buf->f_bfree;			/* free blocks available to non-superuser */
+	buf->f_files = sb->sv_ninodes;			/* total file nodes in file system */
+	buf->f_ffree = sysv_count_free_inodes(sb);	/* free file nodes in fs */
+	buf->f_namelen = SYSV_NAMELEN;
+	/* Don't know what value to put in buf->f_fsid */ /* file system id */
+	return 0;
 }
 
 
@@ -1202,20 +1186,11 @@
 
 /* Every kernel module contains stuff like this. */
 
-static struct file_system_type sysv_fs_type[] = {
-	{"sysv",     FS_REQUIRES_DEV, sysv_read_super, NULL}
-};
+static DECLARE_FSTYPE_DEV(sysv_fs_type, "sysv", sysv_read_super);
 
 int __init init_sysv_fs(void)
 {
-	int i;
-	int ouch = 0;
-
-	for (i = 0; i < sizeof(sysv_fs_type)/sizeof(sysv_fs_type[0]); i++) {
-		if ((ouch = register_filesystem(&sysv_fs_type[i])) != 0)
-			break;
-	}
-        return ouch;
+	return register_filesystem(&sysv_fs_type);
 }
 
 #ifdef MODULE
@@ -1228,11 +1203,7 @@
 
 void cleanup_module(void)
 {
-	int i;
-
-	for (i = 0; i < sizeof(sysv_fs_type)/sizeof(sysv_fs_type[0]); i++)
-		/* No error message if this breaks... that's OK... */
-		unregister_filesystem(&sysv_fs_type[i]);
+	unregister_filesystem(&sysv_fs_type);
 }
 
 #endif
diff -u --recursive --new-file v2.3.50/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.3.50/linux/fs/sysv/namei.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/sysv/namei.c	Wed Mar  8 09:04:09 2000
@@ -389,7 +389,7 @@
 		retval = -ENOTEMPTY;
 		goto end_rmdir;
 	}
-	if (!list_empty(&dentry->d_hash)) {
+	if (!d_unhashed(dentry)) {
 		retval = -EBUSY;
 		goto end_rmdir;
 	}
@@ -552,6 +552,9 @@
 	}
 	if (S_ISDIR(old_inode->i_mode)) {
 		if (new_inode) {
+			retval = -EBUSY;
+			if (!d_unhashed(new_dentry))
+				goto end_rename;
 			retval = -ENOTEMPTY;
 			if (!empty_dir(new_inode))
 				goto end_rename;
diff -u --recursive --new-file v2.3.50/linux/fs/udf/namei.c linux/fs/udf/namei.c
--- v2.3.50/linux/fs/udf/namei.c	Thu Mar  2 14:36:23 2000
+++ linux/fs/udf/namei.c	Wed Mar  8 09:04:09 2000
@@ -1165,6 +1165,9 @@
 
 		if (new_inode)
 		{
+			retval = -EBUSY;
+			if (!d_unhashed(new_dentry))
+				goto end_rename;
 			retval = -ENOTEMPTY;
 			if (!empty_dir(new_inode))
 				goto end_rename;
diff -u --recursive --new-file v2.3.50/linux/fs/udf/super.c linux/fs/udf/super.c
--- v2.3.50/linux/fs/udf/super.c	Thu Mar  2 14:36:23 2000
+++ linux/fs/udf/super.c	Fri Mar 10 10:48:48 2000
@@ -93,25 +93,21 @@
 static void udf_open_lvid(struct super_block *);
 static void udf_close_lvid(struct super_block *);
 static unsigned int udf_count_free(struct super_block *);
-static int udf_statfs(struct super_block *, struct statfs *, int);
+static int udf_statfs(struct super_block *, struct statfs *);
 
 /* UDF filesystem type */
-static struct file_system_type udf_fstype = {
-	name:				"udf",
-	fs_flags:			FS_REQUIRES_DEV,
-	read_super:			udf_read_super,
-};
+static DECLARE_FSTYPE_DEV(udf_fstype, "udf", udf_read_super);
 
 /* Superblock operations */
 static struct super_operations udf_sb_ops = {
-	read_inode:			udf_read_inode,
+	read_inode:		udf_read_inode,
 	write_inode:		udf_write_inode,
-	put_inode:			udf_put_inode,
+	put_inode:		udf_put_inode,
 	delete_inode:		udf_delete_inode,
-	put_super:			udf_put_super,
+	put_super:		udf_put_super,
 	write_super:		udf_write_super,
-	statfs:				udf_statfs,
-	remount_fs:			udf_remount_fs,
+	statfs:			udf_statfs,
+	remount_fs:		udf_remount_fs,
 };
 
 struct udf_options
@@ -1326,10 +1322,6 @@
 	uopt.gid = -1;
 	uopt.umask = 0;
 
-	/* Lock the module in memory (if applicable) */
-	MOD_INC_USE_COUNT;
-
-	lock_super(sb);
 	memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
 
 #if CONFIG_UDF_RW != 1
@@ -1438,7 +1430,6 @@
 	}
 	if (!(sb->s_flags & MS_RDONLY))
 		udf_open_lvid(sb);
-	unlock_super(sb);
 
 	/* Assign the root inode */
 	/* assign inodes by physical block number */
@@ -1470,8 +1461,6 @@
 		udf_close_lvid(sb);
 	udf_release_data(UDF_SB_LVIDBH(sb));
 	UDF_SB_FREE(sb);
-	unlock_super(sb);
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
@@ -1530,8 +1519,6 @@
 	for (i=0; i<UDF_MAX_BLOCK_LOADED; i++)
 		udf_release_data(UDF_SB_BLOCK_BITMAP(sb, i));
 	UDF_SB_FREE(sb);
-
-	MOD_DEC_USE_COUNT;
 }
 
 /*
@@ -1548,29 +1535,21 @@
  *	Written, tested, and released.
  */
 static int
-udf_statfs(struct super_block *sb, struct statfs *buf, int bufsize)
+udf_statfs(struct super_block *sb, struct statfs *buf)
 {
-	int size;
-	struct statfs tmp;
-	int rc;
-
-	size = (bufsize < sizeof(tmp)) ? bufsize: sizeof(tmp);
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.f_type = UDF_SUPER_MAGIC;
-	tmp.f_bsize = sb->s_blocksize;
-	tmp.f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
-	tmp.f_bfree = udf_count_free(sb);
-	tmp.f_bavail = tmp.f_bfree;
-	tmp.f_files = (UDF_SB_LVIDBH(sb) ?
+	buf->f_type = UDF_SUPER_MAGIC;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
+	buf->f_bfree = udf_count_free(sb);
+	buf->f_bavail = buf->f_bfree;
+	buf->f_files = (UDF_SB_LVIDBH(sb) ?
 		(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) +
-		le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + tmp.f_bfree;
-	tmp.f_ffree = tmp.f_bfree;
+		le32_to_cpu(UDF_SB_LVIDIU(sb)->numDirs)) : 0) + buf->f_bfree;
+	buf->f_ffree = buf->f_bfree;
 	/* __kernel_fsid_t f_fsid */
-	tmp.f_namelen = UDF_NAME_LEN;
+	buf->f_namelen = UDF_NAME_LEN;
 
-	rc= copy_to_user(buf, &tmp, size) ? -EFAULT: 0;
-	return rc;
+	return 0;
 }
 
 static unsigned char udf_bitmap_lookup[16] = {
diff -u --recursive --new-file v2.3.50/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.3.50/linux/fs/ufs/super.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/ufs/super.c	Fri Mar 10 10:48:48 2000
@@ -451,9 +451,6 @@
 	
 	UFSD(("ENTER\n"))
 		
-	MOD_INC_USE_COUNT;
-	lock_super (sb);
-
 	UFSD(("flag %u\n", (int)(sb->s_flags & MS_RDONLY)))
 	
 #ifndef CONFIG_UFS_FS_WRITE
@@ -790,16 +787,12 @@
 		if (!ufs_read_cylinder_structures(sb))
 			goto failed;
 
-	unlock_super(sb);
 	UFSD(("EXIT\n"))
 	return(sb);
 
 failed:
 	if (ubh) ubh_brelse_uspi (uspi);
 	if (uspi) kfree (uspi);
-	sb->s_dev = 0;
-	unlock_super (sb);
-	MOD_DEC_USE_COUNT;
 	UFSD(("EXIT (FAILED)\n"))
 	return(NULL);
 }
@@ -843,8 +836,6 @@
 	
 	ubh_brelse_uspi (uspi);
 	kfree (sb->u.ufs_sb.s_uspi);
-	sb->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return;
 }
 
@@ -924,28 +915,27 @@
 	return 0;
 }
 
-int ufs_statfs (struct super_block * sb, struct statfs * buf, int bufsiz)
+int ufs_statfs (struct super_block * sb, struct statfs * buf)
 {
 	struct ufs_sb_private_info * uspi;
 	struct ufs_super_block_first * usb1;
-	struct statfs tmp;
 	unsigned swab;
 
 	swab = sb->u.ufs_sb.s_swab;
 	uspi = sb->u.ufs_sb.s_uspi;
 	usb1 = ubh_get_usb_first (USPI_UBH);
 	
-	tmp.f_type = UFS_MAGIC;
-	tmp.f_bsize = sb->s_blocksize;
-	tmp.f_blocks = uspi->s_dsize;
-	tmp.f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) +
+	buf->f_type = UFS_MAGIC;
+	buf->f_bsize = sb->s_blocksize;
+	buf->f_blocks = uspi->s_dsize;
+	buf->f_bfree = ufs_blkstofrags(SWAB32(usb1->fs_cstotal.cs_nbfree)) +
 		SWAB32(usb1->fs_cstotal.cs_nffree);
-	tmp.f_bavail = (tmp.f_bfree > ((tmp.f_blocks / 100) * uspi->s_minfree))
-		? (tmp.f_bfree - ((tmp.f_blocks / 100) * uspi->s_minfree)) : 0;
-	tmp.f_files = uspi->s_ncg * uspi->s_ipg;
-	tmp.f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree);
-	tmp.f_namelen = UFS_MAXNAMLEN;
-	return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
+	buf->f_bavail = (buf->f_bfree > ((buf->f_blocks / 100) * uspi->s_minfree))
+		? (buf->f_bfree - ((buf->f_blocks / 100) * uspi->s_minfree)) : 0;
+	buf->f_files = uspi->s_ncg * uspi->s_ipg;
+	buf->f_ffree = SWAB32(usb1->fs_cstotal.cs_nifree);
+	buf->f_namelen = UFS_MAXNAMLEN;
+	return 0;
 }
 
 static struct super_operations ufs_super_ops = {
@@ -959,12 +949,7 @@
 	remount_fs:	ufs_remount,
 };
 
-static struct file_system_type ufs_fs_type = {
-	"ufs", 
-	FS_REQUIRES_DEV,
-	ufs_read_super,
-	NULL
-};
+static DECLARE_FSTYPE_DEV(ufs_fs_type, "ufs", ufs_read_super);
 
 int __init init_ufs_fs(void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.3.50/linux/fs/umsdos/inode.c	Sat Feb 26 22:31:55 2000
+++ linux/fs/umsdos/inode.c	Fri Mar 10 10:48:48 2000
@@ -75,7 +75,6 @@
 		pseudo_root = NULL;
 	}
 	msdos_put_super (sb);
-	MOD_DEC_USE_COUNT;
 }
 
 
@@ -334,7 +333,6 @@
 	struct super_block *res;
 	struct dentry *new_root;
 
-	MOD_INC_USE_COUNT;
 	MSDOS_SB(sb)->options.isvfat = 0;
 	/*
 	 * Call msdos-fs to mount the disk.
@@ -381,8 +379,6 @@
 
 out_fail:
 	printk(KERN_INFO "UMSDOS: msdos_read_super failed, mount aborted.\n");
-	sb->s_dev = 0;
-	MOD_DEC_USE_COUNT;
 	return NULL;
 }
 
@@ -437,13 +433,7 @@
 }
 
 
-static struct file_system_type umsdos_fs_type =
-{
-	"umsdos",
-	FS_REQUIRES_DEV,
-	UMSDOS_read_super,
-	NULL
-};
+static DECLARE_FSTYPE_DEV(umsdos_fs_type, "umsdos", UMSDOS_read_super);
 
 int __init init_umsdos_fs (void)
 {
diff -u --recursive --new-file v2.3.50/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c
--- v2.3.50/linux/fs/umsdos/namei.c	Sun Feb 13 19:29:04 2000
+++ linux/fs/umsdos/namei.c	Wed Mar  8 09:04:09 2000
@@ -876,7 +876,7 @@
 		goto out;
 
 	ret = -EBUSY;
-	if (!list_empty(&dentry->d_hash))
+	if (!d_unhashed(dentry))
 		goto out;
 
 	/* check whether the EMD is empty */
diff -u --recursive --new-file v2.3.50/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- v2.3.50/linux/fs/umsdos/rdir.c	Sat Feb 26 22:31:55 2000
+++ linux/fs/umsdos/rdir.c	Wed Mar  8 09:04:09 2000
@@ -157,7 +157,7 @@
 		goto out;
 
 	ret = -EBUSY;
-	if (!list_empty(&dentry->d_hash))
+	if (!d_unhashed(dentry))
 		goto out;
 
 	ret = msdos_rmdir (dir, dentry);
diff -u --recursive --new-file v2.3.50/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.3.50/linux/fs/vfat/namei.c	Tue Mar  7 14:32:26 2000
+++ linux/fs/vfat/namei.c	Fri Mar 10 10:48:48 2000
@@ -78,11 +78,6 @@
 	}
 };
 
-static void vfat_put_super_callback(struct super_block *sb)
-{
-	MOD_DEC_USE_COUNT;
-}
-
 static int vfat_revalidate(struct dentry *dentry, int flags)
 {
 	PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
@@ -978,7 +973,7 @@
 		tmp = next;
 		next = tmp->next;
 		alias = list_entry(tmp, struct dentry, d_alias);
-		if (!list_empty(&alias->d_hash))
+		if (!d_unhashed(alias))
 			return dget(alias);
 	}
 	return NULL;
@@ -1085,7 +1080,7 @@
 	struct buffer_head *bh = NULL;
 	struct msdos_dir_entry *de;
 
-	if (!list_empty(&dentry->d_hash))
+	if (!d_unhashed(dentry))
 		return -EBUSY;
 
 	res = fat_dir_empty(dentry->d_inode);
@@ -1207,6 +1202,9 @@
 		}
 
 		if (is_dir) {
+			res =-EBUSY;
+			if (!d_unhashed(new_dentry))
+				goto rename_done;
 			res = fat_dir_empty(new_inode);
 			if (res)
 				goto rename_done;
@@ -1274,21 +1272,13 @@
 {
 	struct super_block *res;
   
-	MOD_INC_USE_COUNT;
-	
 	MSDOS_SB(sb)->options.isvfat = 1;
 
 	res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
-	if (res == NULL) {
-		sb->s_dev = 0;
-		MOD_DEC_USE_COUNT;
+	if (res == NULL)
 		return NULL;
-	}
 
-	if (!parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
-		MOD_DEC_USE_COUNT;
-	} else {
-		MSDOS_SB(sb)->put_super_callback=vfat_put_super_callback;
+	if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
 		MSDOS_SB(sb)->options.dotsOK = 0;
 		if (MSDOS_SB(sb)->options.posixfs) {
 			MSDOS_SB(sb)->options.name_check = 's';
diff -u --recursive --new-file v2.3.50/linux/fs/vfat/vfatfs_syms.c linux/fs/vfat/vfatfs_syms.c
--- v2.3.50/linux/fs/vfat/vfatfs_syms.c	Thu May 13 23:18:21 1999
+++ linux/fs/vfat/vfatfs_syms.c	Fri Mar 10 10:48:48 2000
@@ -12,12 +12,7 @@
 #include <linux/mm.h>
 #include <linux/msdos_fs.h>
 
-struct file_system_type vfat_fs_type = {
-	"vfat",
-	FS_REQUIRES_DEV,
-	vfat_read_super,
-	NULL
-};
+DECLARE_FSTYPE_DEV(vfat_fs_type, "vfat", vfat_read_super);
 
 EXPORT_SYMBOL(vfat_create);
 EXPORT_SYMBOL(vfat_unlink);
diff -u --recursive --new-file v2.3.50/linux/include/asm-i386/ide.h linux/include/asm-i386/ide.h
--- v2.3.50/linux/include/asm-i386/ide.h	Wed Aug 18 16:43:30 1999
+++ linux/include/asm-i386/ide.h	Fri Mar 10 14:31:31 2000
@@ -16,7 +16,11 @@
 #include <linux/config.h>
 
 #ifndef MAX_HWIFS
+# ifdef CONFIG_BLK_DEV_IDEPCI
 #define MAX_HWIFS	10
+# else
+#define MAX_HWIFS	6
+# endif
 #endif
 
 #define ide__sti()	__sti()
diff -u --recursive --new-file v2.3.50/linux/include/asm-i386/system.h linux/include/asm-i386/system.h
--- v2.3.50/linux/include/asm-i386/system.h	Wed Dec  8 14:11:28 1999
+++ linux/include/asm-i386/system.h	Fri Mar 10 14:31:30 2000
@@ -279,6 +279,8 @@
 #define __restore_flags(x) 	__asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
 #define __cli() 		__asm__ __volatile__("cli": : :"memory")
 #define __sti()			__asm__ __volatile__("sti": : :"memory")
+/* used in the idle loop; sti takes one instruction cycle to complete */
+#define safe_halt()		__asm__ __volatile__("sti; hlt": : :"memory")
 
 /* For spinlocks etc */
 #define local_irq_save(x)	__asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/atomic.h linux/include/asm-ia64/atomic.h
--- v2.3.50/linux/include/asm-ia64/atomic.h	Thu Feb 10 17:11:20 2000
+++ linux/include/asm-ia64/atomic.h	Fri Mar 10 15:24:02 2000
@@ -91,6 +91,7 @@
 
 #define atomic_sub_and_test(i,v)	(atomic_sub_return((i), (v)) == 0)
 #define atomic_dec_and_test(v)		(atomic_sub_return(1, (v)) == 0)
+#define atomic_inc_and_test(v)		(atomic_add_return(1, (v)) != 0)
 
 #define atomic_add(i,v)			atomic_add_return((i), (v))
 #define atomic_sub(i,v)			atomic_sub_return((i), (v))
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/efi.h linux/include/asm-ia64/efi.h
--- v2.3.50/linux/include/asm-ia64/efi.h	Thu Feb 10 17:11:20 2000
+++ linux/include/asm-ia64/efi.h	Fri Mar 10 15:24:02 2000
@@ -180,7 +180,7 @@
 } efi_config_table_t;
 
 #define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
-#define EFI_SYSTEM_TABLE_REVISION  ((0 << 16) | (91))
+#define EFI_SYSTEM_TABLE_REVISION  ((0 << 16) | (92))
 
 typedef struct {
 	efi_table_hdr_t hdr;
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/hardirq.h linux/include/asm-ia64/hardirq.h
--- v2.3.50/linux/include/asm-ia64/hardirq.h	Sun Feb 13 19:29:04 2000
+++ linux/include/asm-ia64/hardirq.h	Fri Mar 10 15:24:02 2000
@@ -2,77 +2,100 @@
 #define _ASM_IA64_HARDIRQ_H
 
 /*
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <linux/config.h>
+
 #include <linux/threads.h>
+#include <linux/irq.h>
+
+typedef struct {
+	unsigned int __local_irq_count;
+	unsigned int __local_bh_count;
+	atomic_t __nmi_counter;
+# if NR_CPUS > 1
+	unsigned int __pad[13];		/* this assumes 64-byte cache-lines... */
+# endif
+} ____cacheline_aligned irq_cpustat_t;
 
-extern unsigned int local_irq_count[NR_CPUS];
-extern unsigned long hardirq_no[NR_CPUS];
+extern irq_cpustat_t irq_stat[NR_CPUS];
+
+/*
+ * Simple wrappers reducing source bloat
+ */
+#define local_irq_count(cpu)	(irq_stat[(cpu)].__local_irq_count)
+#define local_bh_count(cpu)	(irq_stat[(cpu)].__local_bh_count)
+#define nmi_counter(cpu)	(irq_stat[(cpu)].__nmi_counter)
 
 /*
  * Are we in an interrupt context? Either doing bottom half
  * or hardware interrupt processing?
  */
-
-#define in_irq() (local_irq_count[smp_processor_id()] != 0)
-
 #define in_interrupt()						\
 ({								\
 	int __cpu = smp_processor_id();				\
-	(local_irq_count[__cpu] + local_bh_count[__cpu]) != 0;	\
+	(local_irq_count(__cpu) + local_bh_count(__cpu)) != 0;	\
 })
 
-
+#define in_irq() (local_irq_count(smp_processor_id()) != 0)
 
 #ifndef CONFIG_SMP
-# define hardirq_trylock(cpu)		(local_irq_count[cpu] == 0)
-# define hardirq_endlock(cpu)		((void) 0)
+# define hardirq_trylock(cpu)		(local_irq_count(cpu) == 0)
+# define hardirq_endlock(cpu)		do { } while (0)
 
-# define hardirq_enter(cpu, irq)	(local_irq_count[cpu]++)
-# define hardirq_exit(cpu, irq)		(local_irq_count[cpu]--)
+# define irq_enter(cpu, irq)		(++local_irq_count(cpu))
+# define irq_exit(cpu, irq)		(--local_irq_count(cpu))
 
 # define synchronize_irq()		barrier()
 #else
 
-#include <linux/spinlock.h>
-
 #include <asm/atomic.h>
 #include <asm/smp.h>
 
-extern int global_irq_holder;
-extern spinlock_t global_irq_lock;
-extern atomic_t global_irq_count;
+extern unsigned char global_irq_holder;
+extern unsigned volatile int global_irq_lock;
+
+static inline int irqs_running (void)
+{
+	int i;
+
+	for (i = 0; i < smp_num_cpus; i++)
+		if (local_irq_count(i))
+			return 1;
+	return 0;
+}
 
 static inline void release_irqlock(int cpu)
 {
 	/* if we didn't own the irq lock, just ignore.. */
 	if (global_irq_holder == cpu) {
 		global_irq_holder = NO_PROC_ID;
-		spin_unlock(&global_irq_lock);
+		clear_bit(0,&global_irq_lock);
         }
 }
 
-static inline void hardirq_enter(int cpu, int irq)
+static inline void irq_enter(int cpu, int irq)
 {
-	++local_irq_count[cpu];
-        atomic_inc(&global_irq_count);
+	++local_irq_count(cpu);
+
+	while (test_bit(0,&global_irq_lock)) {
+		/* nothing */;
+	}
 }
 
-static inline void hardirq_exit(int cpu, int irq)
+static inline void irq_exit(int cpu, int irq)
 {
-	atomic_dec(&global_irq_count);
-        --local_irq_count[cpu];
+	--local_irq_count(cpu);
 }
 
 static inline int hardirq_trylock(int cpu)
 {
-	return !local_irq_count[cpu] && !test_bit(0,&global_irq_lock);
+	return !local_irq_count(cpu) && !test_bit(0,&global_irq_lock);
 }
 
-#define hardirq_endlock(cpu)  ((void)0)
+#define hardirq_endlock(cpu)	do { } while (0)
 
 extern void synchronize_irq(void);
 
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/hw_irq.h linux/include/asm-ia64/hw_irq.h
--- v2.3.50/linux/include/asm-ia64/hw_irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ia64/hw_irq.h	Fri Mar 10 15:24:02 2000
@@ -0,0 +1,76 @@
+#ifndef _ASM_IA64_HW_IRQ_H
+#define _ASM_IA64_HW_IRQ_H
+
+/*
+ * Copyright (C) 2000 Hewlett-Packard Co
+ * Copyright (C) 2000 David Mosberger-Tang <davidm@hpl.hp.com>
+ */
+
+#include <linux/config.h>
+
+#include <linux/types.h>
+
+#include <asm/ptrace.h>
+
+#define NR_ISA_IRQS	 16
+
+/*
+ * 0 special
+ *
+ * 1,3-14 are reserved from firmware
+ *
+ * 16-255 (vectored external interrupts) are available
+ *
+ * 15 spurious interrupt (see IVR)
+ *
+ * 16 lowest priority, 255 highest priority
+ *
+ * 15 classes of 16 interrupts each.
+ */
+#define IA64_MIN_VECTORED_IRQ	 16
+#define IA64_MAX_VECTORED_IRQ	255
+
+#define IA64_SPURIOUS_INT	0x0f
+
+#define IA64_MIN_VECTORED_IRQ	 16
+#define IA64_MAX_VECTORED_IRQ	255
+
+#define PERFMON_IRQ		0x28	/* performanc monitor interrupt vector */
+#define TIMER_IRQ		0xef	/* use highest-prio group 15 interrupt for timer */
+#define IPI_IRQ			0xfe	/* inter-processor interrupt vector */
+#define CMC_IRQ			0xff	/* correctable machine-check interrupt vector */
+
+/* IA64 inter-cpu interrupt related definitions */
+
+/* Delivery modes for inter-cpu interrupts */
+enum {
+        IA64_IPI_DM_INT =       0x0,    /* pend an external interrupt */
+        IA64_IPI_DM_PMI =       0x2,    /* pend a PMI */
+        IA64_IPI_DM_NMI =       0x4,    /* pend an NMI (vector 2) */
+        IA64_IPI_DM_INIT =      0x5,    /* pend an INIT interrupt */
+        IA64_IPI_DM_EXTINT =    0x7,    /* pend an 8259-compatible interrupt. */
+};
+
+#define IA64_BUS_ID(cpu)        (cpu >> 8)
+#define IA64_LOCAL_ID(cpu)      (cpu & 0xff)
+
+extern __u8 isa_irq_to_vector_map[16];
+#define isa_irq_to_vector(x)	isa_irq_to_vector_map[(x)]
+
+extern struct hw_interrupt_type irq_type_ia64_internal;	/* CPU-internal interrupt controller */
+
+extern void ipi_send (int cpu, int vector, int delivery_mode);
+
+#ifdef CONFIG_SMP
+extern void handle_IPI(int irq, void *dev_id, struct pt_regs *regs);
+
+static inline void
+hw_resend_irq (struct hw_interrupt_type *h, unsigned int i)
+{
+	send_IPI_self(i);
+}
+#else
+# define hw_resend_irq(h,i)
+#endif
+
+#endif /* _ASM_IA64_HW_IRQ_H */
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/ide.h linux/include/asm-ia64/ide.h
--- v2.3.50/linux/include/asm-ia64/ide.h	Thu Feb 10 17:11:20 2000
+++ linux/include/asm-ia64/ide.h	Wed Mar  8 11:40:25 2000
@@ -16,7 +16,11 @@
 #include <linux/config.h>
 
 #ifndef MAX_HWIFS
+# ifdef CONFIG_BLK_DEV_IDEPCI
 #define MAX_HWIFS	10
+# else
+#define MAX_HWIFS	6
+# endif
 #endif
 
 #define ide__sti()	__sti()
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/irq.h linux/include/asm-ia64/irq.h
--- v2.3.50/linux/include/asm-ia64/irq.h	Thu Feb 10 17:11:20 2000
+++ linux/include/asm-ia64/irq.h	Fri Mar 10 15:24:02 2000
@@ -8,113 +8,24 @@
  *
  * 11/24/98	S.Eranian 	updated TIMER_IRQ and irq_cannonicalize
  * 01/20/99	S.Eranian	added keyboard interrupt
+ * 02/29/00     D.Mosberger	moved most things into hw_irq.h
  */
 
-#include <linux/config.h>
-#include <linux/spinlock.h>
-
-#include <asm/ptrace.h>
-
 #define NR_IRQS		256
-#define NR_ISA_IRQS	 16
-
-/*
- * 0 special
- *
- * 1,3-14 are reserved from firmware
- *
- * 16-255 (vectored external interrupts) are available
- *
- * 15 spurious interrupt (see IVR)
- *
- * 16 lowest priority, 255 highest priority
- *
- * 15 classes of 16 interrupts each.
- */
-#define IA64_MIN_VECTORED_IRQ	 16
-#define IA64_MAX_VECTORED_IRQ	255
-
-#define IA64_SPURIOUS_INT	0x0f
-#define PERFMON_IRQ		0x28	/* performanc monitor interrupt vector */
-#define TIMER_IRQ		0xef	/* use highest-prio group 15 interrupt for timer */
-#define IPI_IRQ			0xfe	/* inter-processor interrupt vector */
-#define CMC_IRQ			0xff	/* correctable machine-check interrupt vector */
-
-#define IA64_MIN_VECTORED_IRQ	 16
-#define IA64_MAX_VECTORED_IRQ	255
-
-extern __u8 irq_to_vector_map[IA64_MIN_VECTORED_IRQ];
-#define map_legacy_irq(x) (((x) < IA64_MIN_VECTORED_IRQ) ? irq_to_vector_map[(x)] : (x))
-
-#define IRQ_INPROGRESS	(1 << 0)	/* irq handler active */
-#define IRQ_ENABLED	(1 << 1)	/* irq enabled */
-#define IRQ_PENDING	(1 << 2)	/* irq pending */
-#define IRQ_REPLAY	(1 << 3)	/* irq has been replayed but not acked yet */
-#define IRQ_AUTODETECT	(1 << 4)	/* irq is being autodetected */
-#define IRQ_WAITING	(1 << 5)	/* used for autodetection: irq not yet seen yet */
-
-struct hw_interrupt_type {
-	const char *typename;
-	void (*init) (unsigned long addr);
-	void (*startup) (unsigned int irq);
-	void (*shutdown) (unsigned int irq);
-	int (*handle) (unsigned int irq, struct pt_regs *regs);
-	void (*enable) (unsigned int irq);
-	void (*disable) (unsigned int irq);
-};
-
-extern struct hw_interrupt_type irq_type_default;	/* dummy interrupt controller */
-extern struct hw_interrupt_type irq_type_ia64_internal;	/* CPU-internal interrupt controller */
-
-struct irq_desc {
-	unsigned int type;		/* type of interrupt (level vs. edge triggered) */
-	unsigned int status;		/* see above */
-	unsigned int depth;		/* disable depth for nested irq disables */
-	struct hw_interrupt_type *handler;
-	struct irqaction *action;	/* irq action list */
-};
-
-extern struct irq_desc irq_desc[NR_IRQS];
-
-extern spinlock_t irq_controller_lock;
-
-/* IA64 inter-cpu interrupt related definitions */
-
-/* Delivery modes for inter-cpu interrupts */
-enum {
-        IA64_IPI_DM_INT =       0x0,    /* pend an external interrupt */
-        IA64_IPI_DM_PMI =       0x2,    /* pend a PMI */
-        IA64_IPI_DM_NMI =       0x4,    /* pend an NMI (vector 2) */
-        IA64_IPI_DM_INIT =      0x5,    /* pend an INIT interrupt */
-        IA64_IPI_DM_EXTINT =    0x7,    /* pend an 8259-compatible interrupt. */
-};
-
-#define IA64_BUS_ID(cpu)        (cpu >> 8)
-#define IA64_LOCAL_ID(cpu)      (cpu & 0xff)
 
 static __inline__ int
 irq_cannonicalize (int irq)
 {
 	/*
 	 * We do the legacy thing here of pretending that irqs < 16
-	 * are 8259 irqs.
+	 * are 8259 irqs.  This really shouldn't be necessary at all,
+	 * but we keep it here as serial.c still uses it...
 	 */
 	return ((irq == 2) ? 9 : irq);
 }
 
-extern int invoke_irq_handlers (unsigned int irq, struct pt_regs *regs, struct irqaction *action);
 extern void disable_irq (unsigned int);
 extern void disable_irq_nosync (unsigned int);
 extern void enable_irq (unsigned int);
-extern void ipi_send (int cpu, int vector, int delivery_mode);
-
-#ifdef CONFIG_SMP
-  extern void irq_enter(int cpu, int irq);
-  extern void irq_exit(int cpu, int irq);
-  extern void handle_IPI(int irq, void *dev_id, struct pt_regs *regs);
-#else
-# define irq_enter(cpu, irq)	(++local_irq_count[cpu])
-# define irq_exit(cpu, irq)	(--local_irq_count[cpu])
-#endif
 
 #endif /* _ASM_IA64_IRQ_H */
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/keyboard.h linux/include/asm-ia64/keyboard.h
--- v2.3.50/linux/include/asm-ia64/keyboard.h	Thu Feb 10 17:11:20 2000
+++ linux/include/asm-ia64/keyboard.h	Fri Mar 10 15:24:02 2000
@@ -13,7 +13,7 @@
 
 #include <linux/config.h>
 
-#define KEYBOARD_IRQ			1
+#define KEYBOARD_IRQ			isa_irq_to_vector(1)
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
@@ -59,7 +59,7 @@
  * Machine specific bits for the PS/2 driver
  */
 
-#define AUX_IRQ 12
+#define AUX_IRQ				isa_irq_to_vector(12)
 
 #define aux_request_irq(hand, dev_id)					\
 	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/machvec.h linux/include/asm-ia64/machvec.h
--- v2.3.50/linux/include/asm-ia64/machvec.h	Thu Feb 10 17:11:20 2000
+++ linux/include/asm-ia64/machvec.h	Fri Mar 10 15:24:02 2000
@@ -23,7 +23,7 @@
 struct vm_area_struct;
 
 typedef void ia64_mv_setup_t (char **);
-typedef void ia64_mv_irq_init_t (struct irq_desc *);
+typedef void ia64_mv_irq_init_t (void);
 typedef void ia64_mv_pci_fixup_t (void);
 typedef unsigned long ia64_mv_map_nr_t (unsigned long);
 typedef void ia64_mv_mca_init_t (void);
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/pal.h linux/include/asm-ia64/pal.h
--- v2.3.50/linux/include/asm-ia64/pal.h	Thu Feb 10 17:11:20 2000
+++ linux/include/asm-ia64/pal.h	Fri Mar 10 15:24:02 2000
@@ -7,13 +7,14 @@
  * This is based on version 2.4 of the manual "Enhanced Mode Processor
  * Abstraction Layer".
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 VA Linux Systems
  * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
  * Copyright (C) 1999 Srinivasa Prasad Thirumalachar <sprasad@sprasad.engr.sgi.com>
  *
  * 99/10/01	davidm	Make sure we pass zero for reserved parameters.
+ * 00/03/07	davidm	Updated pal_cache_flush() to be in sync with PAL v2.6.
  */
 
 /*
@@ -105,8 +106,8 @@
 #define PAL_CACHE_TYPE_INSTRUCTION_DATA	3	/* Both Data & Instruction */
 
 
-#define PAL_CACHE_FLUSH_NO_INVALIDATE	0	/* Don't invalidate clean lines */
 #define PAL_CACHE_FLUSH_INVALIDATE	1	/* Invalidate clean lines */
+#define PAL_CACHE_FLUSH_CHK_INTRS	2	/* check for interrupts/mc while flushing */
 
 /* Processor cache line size in bytes  */
 typedef int				pal_cache_line_size_t;
@@ -723,12 +724,16 @@
 	return iprv.status;
 }
 
-/* Flush the processor instruction or data caches */
+/*
+ * Flush the processor instruction or data caches.  *PROGRESS must be
+ * initialized to zero before calling this for the first time..
+ */
 extern inline s64 
-ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 plat_ack) 
+ia64_pal_cache_flush (u64 cache_type, u64 invalidate, u64 *progress) 
 {	
 	struct ia64_pal_retval iprv;
-	PAL_CALL(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, plat_ack); 
+	PAL_CALL(iprv, PAL_CACHE_FLUSH, cache_type, invalidate, *progress); 
+	*progress = iprv.v1;
 	return iprv.status; 
 }
 
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/pgtable.h linux/include/asm-ia64/pgtable.h
--- v2.3.50/linux/include/asm-ia64/pgtable.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-ia64/pgtable.h	Fri Mar 10 15:24:02 2000
@@ -343,6 +343,7 @@
 
 
 extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern void paging_init (void);
 
 /*
  * IA-64 doesn't have any external MMU info: the page tables contain
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/ptrace_offsets.h linux/include/asm-ia64/ptrace_offsets.h
--- v2.3.50/linux/include/asm-ia64/ptrace_offsets.h	Thu Feb 10 17:11:20 2000
+++ linux/include/asm-ia64/ptrace_offsets.h	Fri Mar 10 15:24:02 2000
@@ -167,9 +167,9 @@
 #define PT_CR_IIP		0x0838
 #define PT_CR_IFS		0x0840
 #define PT_AR_UNAT		0x0848
-#define PT_AR_PFS		0x0858
+#define PT_AR_PFS		0x0850
 #define PT_AR_RSC		0x0858
-#define PT_AR_RNAT		0x0868
+#define PT_AR_RNAT		0x0860
 #define PT_AR_BSPSTORE		0x0868
 #define PT_PR			0x0870
 #define PT_B6			0x0878
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/smp.h linux/include/asm-ia64/smp.h
--- v2.3.50/linux/include/asm-ia64/smp.h	Sun Feb 13 19:29:04 2000
+++ linux/include/asm-ia64/smp.h	Fri Mar 10 15:24:02 2000
@@ -9,12 +9,13 @@
 
 #include <linux/config.h>
 
+#ifdef CONFIG_SMP
+
 #include <linux/init.h>
 #include <linux/threads.h>
 #include <linux/kernel.h>
 
 #include <asm/ptrace.h>
-#include <asm/spinlock.h>
 #include <asm/io.h>
 
 #define IPI_DEFAULT_BASE_ADDR	0xfee00000
@@ -99,4 +100,5 @@
 extern void __init init_smp_config (void);
 extern void smp_do_timer (struct pt_regs *regs);
 
+#endif /* CONFIG_SMP */
 #endif /* _ASM_IA64_SMP_H */
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/socket.h linux/include/asm-ia64/socket.h
--- v2.3.50/linux/include/asm-ia64/socket.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-ia64/socket.h	Fri Mar 10 15:24:02 2000
@@ -4,8 +4,8 @@
 /*
  * Socket related defines.  This mostly mirrors the Linux/x86 version.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2000 Hewlett-Packard Co
+ * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <asm/sockios.h>
@@ -40,11 +40,13 @@
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	23
 #define SO_SECURITY_ENCRYPTION_NETWORK		24
 
-#define SO_BINDTODEVICE	25
+#define SO_BINDTODEVICE		25
 
 /* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
+#define SO_ATTACH_FILTER	26
+#define SO_DETACH_FILTER	27
+
+#define SO_PEERNAME		28
 
 #define SO_PEERNAME             28
 
diff -u --recursive --new-file v2.3.50/linux/include/asm-ia64/softirq.h linux/include/asm-ia64/softirq.h
--- v2.3.50/linux/include/asm-ia64/softirq.h	Sun Feb 13 19:29:04 2000
+++ linux/include/asm-ia64/softirq.h	Fri Mar 10 15:24:02 2000
@@ -7,14 +7,12 @@
  */
 #include <asm/hardirq.h>
 
-extern unsigned int local_bh_count[NR_CPUS];
-
-#define cpu_bh_disable(cpu)	do { local_bh_count[(cpu)]++; barrier(); } while (0)
-#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count[(cpu)]--; } while (0)
+#define cpu_bh_disable(cpu)	do { local_bh_count(cpu)++; barrier(); } while (0)
+#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count(cpu)--; } while (0)
 
 #define local_bh_disable()	cpu_bh_disable(smp_processor_id())
 #define local_bh_enable()	cpu_bh_enable(smp_processor_id())
 
-#define in_softirq()		(local_bh_count[smp_processor_id()] != 0)
+#define in_softirq()		(local_bh_count(smp_processor_id()) != 0)
 
 #endif /* _ASM_IA64_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.50/linux/include/asm-mips64/ide.h linux/include/asm-mips64/ide.h
--- v2.3.50/linux/include/asm-mips64/ide.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/ide.h	Thu Mar  9 23:31:43 2000
@@ -14,6 +14,8 @@
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
+
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	6
 #endif
@@ -64,7 +66,7 @@
  */
 static inline void ide_init_default_hwifs(void)
 {
-#ifdef __DO_I_NEED_THIS
+#ifndef CONFIG_BLK_DEV_IDEPCI
 	hw_regs_t hw;
 	int index;
 
@@ -73,7 +75,7 @@
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
 	}
-#endif /* __DO_I_NEED_THIS */
+#endif /* CONFIG_BLK_DEV_IDEPCI */
 }
 
 typedef union {
diff -u --recursive --new-file v2.3.50/linux/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h
--- v2.3.50/linux/include/asm-ppc/prom.h	Thu Feb 10 17:11:21 2000
+++ linux/include/asm-ppc/prom.h	Wed Mar  8 09:18:23 2000
@@ -83,3 +83,6 @@
 extern void print_properties(struct device_node *node);
 extern int call_rtas(const char *service, int nargs, int nret,
 		     unsigned long *outputs, ...);
+extern void prom_drawstring(const char *c);
+extern void prom_drawhex(unsigned long v);
+extern void prom_drawchar(char c);
diff -u --recursive --new-file v2.3.50/linux/include/asm-sparc/ide.h linux/include/asm-sparc/ide.h
--- v2.3.50/linux/include/asm-sparc/ide.h	Fri Jan 28 15:09:09 2000
+++ linux/include/asm-sparc/ide.h	Fri Mar 10 09:43:04 2000
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.2 2000/01/21 04:56:27 zaitcev Exp $
+/* $Id: ide.h,v 1.3 2000/03/10 04:46:47 davem Exp $
  * ide.h: SPARC PCI specific IDE glue.
  *
  * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
@@ -11,6 +11,7 @@
 
 #ifdef __KERNEL__
 
+#include <linux/config.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/hdreg.h>
@@ -59,7 +60,7 @@
  */
 static __inline__ void ide_init_default_hwifs(void)
 {
-#ifdef __DO_I_NEED_THIS
+#ifndef CONFIG_BLK_DEV_IDEPCI
 	hw_regs_t hw;
 	int index;
 
@@ -68,7 +69,7 @@
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
 	}
-#endif /* __DO_I_NEED_THIS */
+#endif /* CONFIG_BLK_DEV_IDEPCI */
 }
 
 typedef union {
diff -u --recursive --new-file v2.3.50/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v2.3.50/linux/include/asm-sparc/system.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc/system.h	Thu Mar  9 06:57:17 2000
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.80 1999/12/16 12:58:31 anton Exp $ */
+/* $Id: system.h,v 1.81 2000/02/28 04:00:44 anton Exp $ */
 #include <linux/config.h>
 
 #ifndef __SPARC_SYSTEM_H
@@ -251,16 +251,10 @@
 
 #ifdef __SMP__
 
-/* This goes away after lockups have been found... */
-#ifndef DEBUG_IRQLOCK
-#define DEBUG_IRQLOCK
-#endif
-
 extern unsigned char global_irq_holder;
 
 #define save_and_cli(flags)   do { save_flags(flags); cli(); } while(0)
 
-#ifdef DEBUG_IRQLOCK
 extern void __global_cli(void);
 extern void __global_sti(void);
 extern unsigned long __global_save_flags(void);
@@ -269,42 +263,6 @@
 #define sti()			__global_sti()
 #define save_flags(flags)	((flags)=__global_save_flags())
 #define restore_flags(flags)	__global_restore_flags(flags)
-#else
-
-#error For combined sun4[md] smp, we need to get rid of the rdtbr.
-
-/* Visit arch/sparc/lib/irqlock.S for all the fun details... */
-#define cli()      __asm__ __volatile__("mov	%%o7, %%g4\n\t"			\
-					"call	___f_global_cli\n\t"		\
-					" rd	%%tbr, %%g7" : :		\
-					: "g1", "g2", "g3", "g4", "g5", "g7",	\
-					  "memory", "cc")
-
-#define sti()							\
-do {	register unsigned long bits asm("g7");			\
-	bits = 0;						\
-	__asm__ __volatile__("mov	%%o7, %%g4\n\t"		\
-			     "call	___f_global_sti\n\t"	\
-			     " rd	%%tbr, %%g2"		\
-			     : /* no outputs */			\
-			     : "r" (bits)			\
-			     : "g1", "g2", "g3", "g4", "g5",	\
-			       "memory", "cc");			\
-} while(0)
-
-#define restore_flags(flags)						\
-do {	register unsigned long bits asm("g7");				\
-	bits = flags;							\
-	__asm__ __volatile__("mov	%%o7, %%g4\n\t"			\
-			     "call	___f_global_restore_flags\n\t"	\
-			     " andcc	%%g7, 0x1, %%g0"		\
-			     : "=&r" (bits)				\
-			     : "0" (bits)				\
-			     : "g1", "g2", "g3", "g4", "g5",		\
-			       "memory", "cc");				\
-} while(0)
-
-#endif /* DEBUG_IRQLOCK */
 
 #else
 
diff -u --recursive --new-file v2.3.50/linux/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h
--- v2.3.50/linux/include/asm-sparc64/pbm.h	Sun Feb 20 21:12:39 2000
+++ linux/include/asm-sparc64/pbm.h	Fri Mar 10 09:43:04 2000
@@ -1,4 +1,4 @@
-/* $Id: pbm.h,v 1.20 2000/02/18 13:50:55 davem Exp $
+/* $Id: pbm.h,v 1.21 2000/03/10 02:42:17 davem Exp $
  * pbm.h: UltraSparc PCI controller software state.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -63,12 +63,21 @@
 	 */
 	unsigned long	write_complete_reg;
 
+	/* The lowest used consistent mapping entry.  Since
+	 * we allocate consistent maps out of cluster 0 this
+	 * is relative to the beginning of closter 0.
+	 */
+	u32		lowest_consistent_map;
+
 	/* If PBM_NCLUSTERS is ever decreased to 4 or lower,
 	 * or if largest supported page_table_sz * 8K goes above
 	 * 2GB, you must increase the size of the type of
 	 * these counters.  You have been duly warned. -DaveM
 	 */
-	u16		lowest_free[PBM_NCLUSTERS];
+	struct {
+		u16	next;
+		u16	flush;
+	} alloc_info[PBM_NCLUSTERS];
 
 	/* Here a PCI controller driver describes the areas of
 	 * PCI memory space where DMA to/from physical memory
diff -u --recursive --new-file v2.3.50/linux/include/linux/adfs_fs.h linux/include/linux/adfs_fs.h
--- v2.3.50/linux/include/linux/adfs_fs.h	Thu Feb 10 17:11:21 2000
+++ linux/include/linux/adfs_fs.h	Fri Mar 10 14:31:31 2000
@@ -61,6 +61,4 @@
 
 #endif
 
-extern int init_adfs_fs (void);
-
 #endif
diff -u --recursive --new-file v2.3.50/linux/include/linux/brlock.h linux/include/linux/brlock.h
--- v2.3.50/linux/include/linux/brlock.h	Thu Mar  2 14:36:23 2000
+++ linux/include/linux/brlock.h	Fri Mar 10 15:24:02 2000
@@ -45,7 +45,7 @@
 #include <linux/cache.h>
 #include <linux/spinlock.h>
 
-#if defined(__i386__)
+#if defined(__i386__) || defined(__ia64__)
 #define __BRLOCK_USE_ATOMICS
 #else
 #undef __BRLOCK_USE_ATOMICS
diff -u --recursive --new-file v2.3.50/linux/include/linux/dcache.h linux/include/linux/dcache.h
--- v2.3.50/linux/include/linux/dcache.h	Sun Feb 20 21:12:39 2000
+++ linux/include/linux/dcache.h	Wed Mar  8 09:04:09 2000
@@ -191,6 +191,11 @@
 	return dentry;
 }
 
+static __inline__ int d_unhashed(struct dentry *dentry)
+{
+	return list_empty(&dentry->d_hash);
+}
+
 extern void dput(struct dentry *);
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.3.50/linux/include/linux/efs_fs.h linux/include/linux/efs_fs.h
--- v2.3.50/linux/include/linux/efs_fs.h	Sat Feb 26 22:32:04 2000
+++ linux/include/linux/efs_fs.h	Fri Mar 10 14:33:59 2000
@@ -53,7 +53,7 @@
 extern void cleanup_module(void);
 extern struct super_block *efs_read_super(struct super_block *, void *, int);
 extern void efs_put_super(struct super_block *);
-extern int efs_statfs(struct super_block *, struct statfs *, int);
+extern int efs_statfs(struct super_block *, struct statfs *);
 
 extern void efs_read_inode(struct inode *);
 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
diff -u --recursive --new-file v2.3.50/linux/include/linux/ext2_fs.h linux/include/linux/ext2_fs.h
--- v2.3.50/linux/include/linux/ext2_fs.h	Sat Feb 26 22:32:05 2000
+++ linux/include/linux/ext2_fs.h	Fri Mar 10 14:31:28 2000
@@ -590,7 +590,7 @@
 extern void ext2_write_super (struct super_block *);
 extern int ext2_remount (struct super_block *, int *, char *);
 extern struct super_block * ext2_read_super (struct super_block *,void *,int);
-extern int ext2_statfs (struct super_block *, struct statfs *, int);
+extern int ext2_statfs (struct super_block *, struct statfs *);
 
 /* truncate.c */
 extern void ext2_truncate (struct inode *);
diff -u --recursive --new-file v2.3.50/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.3.50/linux/include/linux/fb.h	Sat Feb 26 22:32:06 2000
+++ linux/include/linux/fb.h	Thu Mar  9 17:22:18 2000
@@ -283,15 +283,19 @@
     int (*fb_rasterimg)(struct fb_info *info, int start);
 };
 
+/* fb_info flags */
+#define FBINFO_FLAG_MODULE      1       /* Low-level driver is a module */
+#define FBINFO_FLAG_OPEN        2       /* Has this been open already ? */ 
+
 struct fb_info {
    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 */
+   int count;                           /* How many using the hardware */
    struct fb_var_screeninfo var;        /* Current var */
    struct fb_fix_screeninfo fix;        /* Current fix */
    struct fb_monspecs monspecs;         /* Current Monitor specs */
+   struct fb_cmap cmap;                 /* Current cmap */
    struct fb_ops *fbops;
    char *screen_base;                   /* Virtual address */
    struct display *disp;		/* initial display variable */
diff -u --recursive --new-file v2.3.50/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.50/linux/include/linux/fs.h	Tue Mar  7 14:32:26 2000
+++ linux/include/linux/fs.h	Fri Mar 10 14:31:32 2000
@@ -20,6 +20,7 @@
 #include <linux/stat.h>
 #include <linux/cache.h>
 #include <linux/stddef.h>
+#include <linux/string.h>
 
 #include <asm/atomic.h>
 #include <asm/bitops.h>
@@ -181,8 +182,6 @@
 extern void file_table_init(void);
 extern void dcache_init(void);
 
-typedef char buffer_block[BLOCK_SIZE];
-
 /* bh state bits */
 #define BH_Uptodate	0	/* 1 if the buffer contains valid data */
 #define BH_Dirty	1	/* 1 if the buffer is dirty */
@@ -384,6 +383,7 @@
 	unsigned long		i_blocks;
 	unsigned long		i_version;
 	struct semaphore	i_sem;
+	struct semaphore	i_zombie;
 	struct inode_operations	*i_op;
 	struct file_operations	*i_fop;	/* former ->i_op->default_file_ops */
 	struct super_block	*i_sb;
@@ -704,7 +704,7 @@
 	void (*delete_inode) (struct inode *);
 	void (*put_super) (struct super_block *);
 	void (*write_super) (struct super_block *);
-	int (*statfs) (struct super_block *, struct statfs *, int);
+	int (*statfs) (struct super_block *, struct statfs *);
 	int (*remount_fs) (struct super_block *, int *, char *);
 	void (*clear_inode) (struct inode *);
 	void (*umount_begin) (struct super_block *);
@@ -724,12 +724,43 @@
 	const char *name;
 	int fs_flags;
 	struct super_block *(*read_super) (struct super_block *, void *, int);
+	struct module *owner;
 	struct file_system_type * next;
 };
 
+#ifdef MODULE
+#define DECLARE_FSTYPE(var,type,read,flags) \
+struct file_system_type var = { \
+	name:		type, \
+	read_super:	read, \
+	fs_flags:	flags, \
+	owner:		THIS_MODULE, \
+}
+#else
+#define DECLARE_FSTYPE(var,type,read,flags) \
+struct file_system_type var = { \
+	name:		type, \
+	read_super:	read, \
+	fs_flags:	flags, \
+}
+#endif
+
+#define DECLARE_FSTYPE_DEV(var,type,read) \
+	DECLARE_FSTYPE(var,type,read,FS_REQUIRES_DEV)
+
 extern int register_filesystem(struct file_system_type *);
 extern int unregister_filesystem(struct file_system_type *);
 
+static inline int vfs_statfs(struct super_block *sb, struct statfs *buf)
+{
+	if (!sb)
+		return -ENODEV;
+	if (!sb->s_op || !sb->s_op->statfs)
+		return -ENOSYS;
+	memset(buf, 0xff, sizeof(struct statfs));
+	return sb->s_op->statfs(sb, buf);
+}
+
 /* Return value for VFS lock functions - tells locks.c to lock conventionally
  * REALLY kosha for root NFS and nfs_lock
  */ 
@@ -830,8 +861,6 @@
 extern struct file_operations write_pipe_fops;
 extern struct file_operations rdwr_pipe_fops;
 
-extern struct file_system_type *get_fs_type(const char *);
-
 extern int fs_may_remount_ro(struct super_block *);
 extern int fs_may_mount(kdev_t);
 
@@ -907,6 +936,7 @@
 extern struct dentry * open_namei(const char *, int, int);
 extern struct dentry * do_mknod(const char *, int, dev_t);
 extern int do_pipe(int *);
+extern int do_unlink(const char * name);
 
 /* fs/dcache.c -- generic fs support functions */
 extern int is_subdir(struct dentry *, struct dentry *);
@@ -1085,7 +1115,7 @@
  * other process will be too late..
  */
 #define check_parent(dir, dentry) \
-	((dir) == (dentry)->d_parent && !list_empty(&dentry->d_hash))
+	((dir) == (dentry)->d_parent && !d_unhashed(dentry))
 
 /*
  * Locking the parent is needed to:
@@ -1122,11 +1152,8 @@
  * Whee.. Deadlock country. Happily there are only two VFS
  * operations that does this..
  */
-static inline void double_lock(struct dentry *d1, struct dentry *d2)
+static inline void double_down(struct semaphore *s1, struct semaphore *s2)
 {
-	struct semaphore *s1 = &d1->d_inode->i_sem;
-	struct semaphore *s2 = &d2->d_inode->i_sem;
-
 	if (s1 != s2) {
 		if ((unsigned long) s1 < (unsigned long) s2) {
 			struct semaphore *tmp = s2;
@@ -1137,19 +1164,76 @@
 	down(s2);
 }
 
-static inline void double_unlock(struct dentry *d1, struct dentry *d2)
+/*
+ * Ewwwwwwww... _triple_ lock. We are guaranteed that the 3rd argument is
+ * not equal to 1st and not equal to 2nd - the first case (target is parent of
+ * source) would be already caught, the second is plain impossible (target is
+ * its own parent and that case would be caught even earlier). Very messy.
+ * I _think_ that it works, but no warranties - please, look it through.
+ * Pox on bloody lusers who mandated overwriting rename() for directories...
+ */
+
+static inline void triple_down(struct semaphore *s1,
+			       struct semaphore *s2,
+			       struct semaphore *s3)
+{
+	if (s1 != s2) {
+		if ((unsigned long) s1 < (unsigned long) s2) {
+			if ((unsigned long) s1 < (unsigned long) s3) {
+				struct semaphore *tmp = s3;
+				s3 = s1; s1 = tmp;
+			}
+			if ((unsigned long) s1 < (unsigned long) s2) {
+				struct semaphore *tmp = s2;
+				s2 = s1; s1 = tmp;
+			}
+		} else {
+			if ((unsigned long) s1 < (unsigned long) s3) {
+				struct semaphore *tmp = s3;
+				s3 = s1; s1 = tmp;
+			}
+			if ((unsigned long) s2 < (unsigned long) s3) {
+				struct semaphore *tmp = s3;
+				s3 = s2; s2 = tmp;
+			}
+		}
+		down(s1);
+	} else if ((unsigned long) s2 < (unsigned long) s3) {
+		struct semaphore *tmp = s3;
+		s3 = s2; s2 = tmp;
+	}
+	down(s2);
+	down(s3);
+}
+
+static inline void double_up(struct semaphore *s1, struct semaphore *s2)
 {
-	struct semaphore *s1 = &d1->d_inode->i_sem;
-	struct semaphore *s2 = &d2->d_inode->i_sem;
+	up(s1);
+	if (s1 != s2)
+		up(s2);
+}
 
+static inline void triple_up(struct semaphore *s1,
+			     struct semaphore *s2,
+			     struct semaphore *s3)
+{
 	up(s1);
 	if (s1 != s2)
 		up(s2);
-	dput(d1);
-	dput(d2);
+	up(s3);
 }
 
+static inline void double_lock(struct dentry *d1, struct dentry *d2)
+{
+	double_down(&d1->d_inode->i_sem, &d2->d_inode->i_sem);
+}
 
+static inline void double_unlock(struct dentry *d1, struct dentry *d2)
+{
+	double_up(&d1->d_inode->i_sem,&d2->d_inode->i_sem);
+	dput(d1);
+	dput(d2);
+}
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.3.50/linux/include/linux/ide.h linux/include/linux/ide.h
--- v2.3.50/linux/include/linux/ide.h	Tue Mar  7 14:32:26 2000
+++ linux/include/linux/ide.h	Fri Mar 10 14:44:43 2000
@@ -414,6 +414,7 @@
 #if (DISK_RECOVERY_TIME > 0)
 	unsigned long	last_time;	/* time when previous rq was done */
 #endif
+	byte		straight8;	/* Alan's straight 8 check */
 } ide_hwif_t;
 
 /*
diff -u --recursive --new-file v2.3.50/linux/include/linux/if_ec.h linux/include/linux/if_ec.h
--- v2.3.50/linux/include/linux/if_ec.h	Tue Apr 28 11:10:10 1998
+++ linux/include/linux/if_ec.h	Thu Mar  9 06:57:17 2000
@@ -34,6 +34,19 @@
 
 #ifdef __KERNEL__
 
+#define EC_HLEN				6
+
+/* This is what an Econet frame looks like on the wire. */
+struct ec_framehdr 
+{
+  unsigned char dst_stn;
+  unsigned char dst_net;
+  unsigned char src_stn;
+  unsigned char src_net;
+  unsigned char cb;
+  unsigned char port;
+};
+
 struct econet_opt
 {
   unsigned char cb;
@@ -41,6 +54,14 @@
   unsigned char station;
   unsigned char net;
 };
+
+struct ec_device
+{
+  unsigned char station, net;		/* Econet protocol address */
+};
+
+extern struct sock *ec_listening_socket(unsigned char port, unsigned char
+				 station, unsigned char net);
 
 #endif
 
diff -u --recursive --new-file v2.3.50/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v2.3.50/linux/include/linux/interrupt.h	Wed Feb 16 17:03:52 2000
+++ linux/include/linux/interrupt.h	Fri Mar 10 15:24:02 2000
@@ -5,8 +5,10 @@
 #include <linux/kernel.h>
 #include <linux/smp.h>
 #include <linux/cache.h>
+
 #include <asm/bitops.h>
 #include <asm/atomic.h>
+#include <asm/ptrace.h>
 
 struct irqaction {
 	void (*handler)(int, void *, struct pt_regs *);
diff -u --recursive --new-file v2.3.50/linux/include/linux/iobuf.h linux/include/linux/iobuf.h
--- v2.3.50/linux/include/linux/iobuf.h	Fri Oct 22 13:21:55 1999
+++ linux/include/linux/iobuf.h	Fri Mar 10 14:31:56 2000
@@ -29,6 +29,8 @@
 #define KIO_STATIC_PAGES	(KIO_MAX_ATOMIC_IO / (PAGE_SIZE >> 10) + 1)
 #define KIO_MAX_SECTORS		(KIO_MAX_ATOMIC_IO * 2)
 
+/* The main kiobuf struct used for all our IO! */
+
 struct kiobuf 
 {
 	int		nr_pages;	/* Pages actually referenced */
@@ -46,7 +48,6 @@
 	unsigned int	locked : 1;	/* If set, pages has been locked */
 	
 	/* Always embed enough struct pages for 64k of IO */
-	unsigned long	page_array[KIO_STATIC_PAGES];
 	struct page *	map_array[KIO_STATIC_PAGES];
 
 	/* Dynamic state for IO completion: */
@@ -61,10 +62,14 @@
 
 int	map_user_kiobuf(int rw, struct kiobuf *, unsigned long va, size_t len);
 void	unmap_kiobuf(struct kiobuf *iobuf);
+int	lock_kiovec(int nr, struct kiobuf *iovec[], int wait);
+int	unlock_kiovec(int nr, struct kiobuf *iovec[]);
 
 /* fs/iobuf.c */
 
-void __init kiobuf_init(void);
+void __init kiobuf_setup(void);
+void	kiobuf_init(struct kiobuf *);
+void	end_kio_request(struct kiobuf *, int);
 void	simple_wakeup_kiobuf(struct kiobuf *);
 int	alloc_kiovec(int nr, struct kiobuf **);
 void	free_kiovec(int nr, struct kiobuf **);
diff -u --recursive --new-file v2.3.50/linux/include/linux/irq.h linux/include/linux/irq.h
--- v2.3.50/linux/include/linux/irq.h	Thu Mar  2 14:36:23 2000
+++ linux/include/linux/irq.h	Fri Mar 10 15:24:02 2000
@@ -1,7 +1,12 @@
 #ifndef __irq_h
 #define __irq_h
 
+#include <linux/cache.h>
+#include <linux/spinlock.h>
+
 #include <asm/irq.h>
+#include <asm/ptrace.h>
+
 /*
  * IRQ line status.
  */
diff -u --recursive --new-file v2.3.50/linux/include/linux/kmod.h linux/include/linux/kmod.h
--- v2.3.50/linux/include/linux/kmod.h	Sun Feb 13 19:29:04 2000
+++ linux/include/linux/kmod.h	Fri Mar 10 14:31:30 2000
@@ -9,7 +9,7 @@
 extern int request_module(const char * name);
 extern int exec_usermodehelper(char *program_path, char *argv[], char *envp[]);
 #else
-#define request_module(x) do {} while(0)
+static inline int request_module(const char * name) { return -ENOSYS; }
 extern inline int exec_usermodehelper(char *program_path, char *argv[], char *envp[])
 {
 	return -EACCES;
diff -u --recursive --new-file v2.3.50/linux/include/linux/lockd/bind.h linux/include/linux/lockd/bind.h
--- v2.3.50/linux/include/linux/lockd/bind.h	Mon Apr  7 11:35:31 1997
+++ linux/include/linux/lockd/bind.h	Thu Mar  9 23:31:43 2000
@@ -13,7 +13,6 @@
 
 /* Dummy declarations */
 struct svc_rqst;
-struct knfs_fh;
 struct svc_client;		/* opaque type */
 
 /*
@@ -24,7 +23,7 @@
 	void			(*exp_unlock)(void);
 	struct svc_client *	(*exp_getclient)(struct sockaddr_in *);
 	u32			(*fopen)(struct svc_rqst *,
-						struct knfs_fh *,
+						struct nfs_fh *,
 						struct file *);
 	void			(*fclose)(struct file *);
 	void			(*detach)(void);
diff -u --recursive --new-file v2.3.50/linux/include/linux/lockd/lockd.h linux/include/linux/lockd/lockd.h
--- v2.3.50/linux/include/linux/lockd/lockd.h	Sun Feb 20 21:12:40 2000
+++ linux/include/linux/lockd/lockd.h	Fri Mar 10 14:32:16 2000
@@ -75,13 +75,14 @@
  */
 struct nlm_file {
 	struct nlm_file *	f_next;		/* linked list */
-	struct knfs_fh		f_handle;	/* NFS file handle */
+	struct nfs_fh		f_handle;	/* NFS file handle */
 	struct file		f_file;		/* VFS file pointer */
 	struct nlm_share *	f_shares;	/* DOS shares */
 	struct nlm_block *	f_blocks;	/* blocked locks */
 	unsigned int		f_locks;	/* guesstimate # of locks */
 	unsigned int		f_count;	/* reference count */
 	struct semaphore	f_sema;		/* avoid concurrent access */
+	int		       	f_hash;		/* hash of f_handle */
 };
 
 /*
diff -u --recursive --new-file v2.3.50/linux/include/linux/lockd/xdr.h linux/include/linux/lockd/xdr.h
--- v2.3.50/linux/include/linux/lockd/xdr.h	Wed Aug 18 16:44:09 1999
+++ linux/include/linux/lockd/xdr.h	Fri Mar 10 14:32:13 2000
@@ -13,8 +13,15 @@
 #include <linux/nfs.h>
 #include <linux/sunrpc/xdr.h>
 
-extern u32	nlm_granted, nlm_lck_denied, nlm_lck_denied_nolocks,
-		nlm_lck_blocked, nlm_lck_denied_grace_period;
+#define NLM_MAXSTRLEN		1024
+
+#define QUADLEN(len)		(((len) + 3) >> 2)
+
+#define	nlm_granted		__constant_htonl(NLM_LCK_GRANTED)
+#define	nlm_lck_denied		__constant_htonl(NLM_LCK_DENIED)
+#define	nlm_lck_denied_nolocks	__constant_htonl(NLM_LCK_DENIED_NOLOCKS)
+#define	nlm_lck_blocked		__constant_htonl(NLM_LCK_BLOCKED)
+#define	nlm_lck_denied_grace_period	__constant_htonl(NLM_LCK_DENIED_GRACE_PERIOD)
 
 /* Lock info passed via NLM */
 struct nlm_lock {
@@ -48,6 +55,8 @@
 	u32			fsm_access;
 	u32			fsm_mode;
 };
+
+typedef struct nlm_args nlm_args;
 
 /*
  * Generic lockd result
diff -u --recursive --new-file v2.3.50/linux/include/linux/lockd/xdr4.h linux/include/linux/lockd/xdr4.h
--- v2.3.50/linux/include/linux/lockd/xdr4.h	Sun Feb 20 21:12:40 2000
+++ linux/include/linux/lockd/xdr4.h	Fri Mar 10 14:32:13 2000
@@ -15,7 +15,12 @@
 #include <linux/lockd/xdr.h>
 
 /* error codes new to NLMv4 */
-extern u32	nlm4_deadlock, nlm4_rofs, nlm4_stale_fh, nlm4_fbig, nlm4_failed;
+#define	nlm4_deadlock		__constant_htonl(NLM_DEADLCK)
+#define	nlm4_rofs		__constant_htonl(NLM_ROFS)
+#define	nlm4_stale_fh		__constant_htonl(NLM_STALE_FH)
+#define	nlm4_fbig		__constant_htonl(NLM_FBIG)
+#define	nlm4_failed		__constant_htonl(NLM_FAILED)
+
 
 
 int	nlm4svc_decode_testargs(struct svc_rqst *, u32 *, struct nlm_args *);
diff -u --recursive --new-file v2.3.50/linux/include/linux/module.h linux/include/linux/module.h
--- v2.3.50/linux/include/linux/module.h	Fri Jan 21 18:19:17 2000
+++ linux/include/linux/module.h	Fri Mar 10 14:31:30 2000
@@ -145,6 +145,8 @@
 /* Find a symbol exported by the kernel or another module */
 extern unsigned long get_module_symbol(char *, char *);
 
+extern int try_inc_mod_count(struct module *mod);
+
 #if defined(MODULE) && !defined(__GENKSYMS__)
 
 /* Embedded module documentation macros.  */
diff -u --recursive --new-file v2.3.50/linux/include/linux/msdos_fs.h linux/include/linux/msdos_fs.h
--- v2.3.50/linux/include/linux/msdos_fs.h	Sat Feb 26 22:32:06 2000
+++ linux/include/linux/msdos_fs.h	Fri Mar 10 14:33:56 2000
@@ -247,7 +247,7 @@
 extern struct inode *fat_build_inode(struct super_block*,struct msdos_dir_entry*,int,int*);
 extern struct super_block *fat_read_super(struct super_block *s, void *data, int silent, struct inode_operations *dir_ops);
 extern void msdos_put_super(struct super_block *sb);
-extern int fat_statfs(struct super_block *sb,struct statfs *buf, int);
+extern int fat_statfs(struct super_block *sb,struct statfs *buf);
 extern void fat_write_inode(struct inode *inode);
 
 /* dir.c */
diff -u --recursive --new-file v2.3.50/linux/include/linux/msdos_fs_sb.h linux/include/linux/msdos_fs_sb.h
--- v2.3.50/linux/include/linux/msdos_fs_sb.h	Sun Nov  7 16:37:34 1999
+++ linux/include/linux/msdos_fs_sb.h	Fri Mar 10 10:48:48 2000
@@ -53,7 +53,6 @@
 	struct nls_table *nls_io;    /* Charset used for input and display */
 	struct cvf_format* cvf_format;
 	void *dir_ops;		     /* Opaque; default directory operations */
-	void (*put_super_callback)(struct super_block *);
 	void *private_data;	
 };
 
diff -u --recursive --new-file v2.3.50/linux/include/linux/nbd.h linux/include/linux/nbd.h
--- v2.3.50/linux/include/linux/nbd.h	Wed Feb 16 17:03:52 2000
+++ linux/include/linux/nbd.h	Fri Mar 10 09:43:04 2000
@@ -30,22 +30,35 @@
 extern int requests_out;
 #endif
 
-static void 
+static int 
 nbd_end_request(struct request *req)
 {
 	unsigned long flags;
+	int ret = 0;
 
 #ifdef PARANOIA
 	requests_out++;
 #endif
+	/*
+	 * This is a very dirty hack that we have to do to handle
+	 * merged requests because end_request stuff is a bit
+	 * broken. The fact we have to do this only if there
+	 * aren't errors looks even more silly.
+	 */
+	if (!req->errors) {
+		req->sector += req->current_nr_sectors;
+		req->nr_sectors -= req->current_nr_sectors;
+	}
+
 	spin_lock_irqsave(&io_request_lock, flags);
 	if (end_that_request_first( req, !req->errors, "nbd" ))
 		goto out;
+	ret = 1;
 	end_that_request_last( req );
 
 out:
 	spin_unlock_irqrestore(&io_request_lock, flags);
-	return;
+	return ret;
 }
 
 #define MAX_NBD 128
@@ -56,7 +69,6 @@
 	int harderror;		/* Code of hard error			*/
 #define NBD_READ_ONLY 0x0001
 #define NBD_WRITE_NOCHK 0x0002
-#define NBD_INITIALISED 0x0004
 	struct socket * sock;
 	struct file * file; 		/* If == NULL, device is not ready, yet	*/
 	int magic;			/* FIXME: not if debugging is off	*/
diff -u --recursive --new-file v2.3.50/linux/include/linux/nfsd/export.h linux/include/linux/nfsd/export.h
--- v2.3.50/linux/include/linux/nfsd/export.h	Tue Feb  1 01:35:44 2000
+++ linux/include/linux/nfsd/export.h	Fri Mar 10 14:32:11 2000
@@ -89,7 +89,7 @@
 void			exp_putclient(struct svc_client *clp);
 struct svc_export *	exp_get(struct svc_client *clp, kdev_t dev, ino_t ino);
 int			exp_rootfh(struct svc_client *, kdev_t, ino_t,
-					char *path, struct knfs_fh *);
+					char *path, struct knfsd_fh *, int maxsize);
 int			nfserrno(int errno);
 void			exp_nlmdetach(void);
 
diff -u --recursive --new-file v2.3.50/linux/include/linux/nfsd/nfsd.h linux/include/linux/nfsd/nfsd.h
--- v2.3.50/linux/include/linux/nfsd/nfsd.h	Thu Mar  2 14:36:23 2000
+++ linux/include/linux/nfsd/nfsd.h	Fri Mar 10 14:32:13 2000
@@ -100,7 +100,7 @@
 int		nfsd_read(struct svc_rqst *, struct svc_fh *,
 				loff_t, char *, unsigned long *);
 int		nfsd_write(struct svc_rqst *, struct svc_fh *,
-				loff_t, char *, unsigned long, int);
+				loff_t, char *, unsigned long, int *);
 int		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
 				char *, int *);
 int		nfsd_symlink(struct svc_rqst *, struct svc_fh *,
@@ -129,8 +129,6 @@
 int		nfsd_notify_change(struct inode *, struct iattr *);
 int		nfsd_permission(struct svc_export *, struct dentry *, int);
 
-/* nfsd/nfsctl.c */
-void		nfsd_modcount(struct inode *, int);
 
 /*
  * lockd binding
@@ -140,43 +138,39 @@
 void		nfsd_lockd_unexport(struct svc_client *);
 
 
-#ifndef makedev
-#define makedev(maj, min)	(((maj) << 8) | (min))
-#endif
-
 /*
- * These variables contain pre-xdr'ed values for faster operation.
- * FIXME: should be replaced by macros for big-endian machines.
+ * These macros provide pre-xdr'ed values for faster operation.
  */
-extern u32	nfs_ok,
-		nfserr_perm,
-		nfserr_noent,
-		nfserr_io,
-		nfserr_nxio,
-		nfserr_acces,
-		nfserr_exist,
-		nfserr_xdev,
-		nfserr_nodev,
-		nfserr_notdir,
-		nfserr_isdir,
-		nfserr_inval,
-		nfserr_fbig,
-		nfserr_nospc,
-		nfserr_rofs,
-		nfserr_mlink,
-		nfserr_nametoolong,
-		nfserr_notempty,
-		nfserr_dquot,
-		nfserr_stale,
-		nfserr_remote,
-		nfserr_badhandle,
-		nfserr_notsync,
-		nfserr_badcookie,
-		nfserr_notsupp,
-		nfserr_toosmall,
-		nfserr_serverfault,
-		nfserr_badtype,
-		nfserr_jukebox;
+#define	nfs_ok			__constant_htonl(NFS_OK)
+#define	nfserr_perm		__constant_htonl(NFSERR_PERM)
+#define	nfserr_noent		__constant_htonl(NFSERR_NOENT)
+#define	nfserr_io		__constant_htonl(NFSERR_IO)
+#define	nfserr_nxio		__constant_htonl(NFSERR_NXIO)
+#define	nfserr_acces		__constant_htonl(NFSERR_ACCES)
+#define	nfserr_exist		__constant_htonl(NFSERR_EXIST)
+#define	nfserr_xdev		__constant_htonl(NFSERR_XDEV)
+#define	nfserr_nodev		__constant_htonl(NFSERR_NODEV)
+#define	nfserr_notdir		__constant_htonl(NFSERR_NOTDIR)
+#define	nfserr_isdir		__constant_htonl(NFSERR_ISDIR)
+#define	nfserr_inval		__constant_htonl(NFSERR_INVAL)
+#define	nfserr_fbig		__constant_htonl(NFSERR_FBIG)
+#define	nfserr_nospc		__constant_htonl(NFSERR_NOSPC)
+#define	nfserr_rofs		__constant_htonl(NFSERR_ROFS)
+#define	nfserr_mlink		__constant_htonl(NFSERR_MLINK)
+#define	nfserr_opnotsupp	__constant_htonl(NFSERR_OPNOTSUPP)
+#define	nfserr_nametoolong	__constant_htonl(NFSERR_NAMETOOLONG)
+#define	nfserr_notempty		__constant_htonl(NFSERR_NOTEMPTY)
+#define	nfserr_dquot		__constant_htonl(NFSERR_DQUOT)
+#define	nfserr_stale		__constant_htonl(NFSERR_STALE)
+#define	nfserr_remote		__constant_htonl(NFSERR_REMOTE)
+#define	nfserr_badhandle	__constant_htonl(NFSERR_BADHANDLE)
+#define	nfserr_notsync		__constant_htonl(NFSERR_NOTSYNC)
+#define	nfserr_badcookie	__constant_htonl(NFSERR_BADCOOKIE)
+#define	nfserr_notsupp		__constant_htonl(NFSERR_NOTSUPP)
+#define	nfserr_toosmall		__constant_htonl(NFSERR_TOOSMALL)
+#define	nfserr_serverfault	__constant_htonl(NFSERR_SERVERFAULT)
+#define	nfserr_badtype		__constant_htonl(NFSERR_BADTYPE)
+#define	nfserr_jukebox		__constant_htonl(NFSERR_JUKEBOX)
 
 /*
  * Time of server startup
diff -u --recursive --new-file v2.3.50/linux/include/linux/nfsd/nfsfh.h linux/include/linux/nfsd/nfsfh.h
--- v2.3.50/linux/include/linux/nfsd/nfsfh.h	Thu Mar  2 14:36:23 2000
+++ linux/include/linux/nfsd/nfsfh.h	Fri Mar 10 14:32:12 2000
@@ -25,34 +25,95 @@
 #include <linux/nfsd/debug.h>
 
 /*
- * This is the new "dentry style" Linux NFSv2 file handle.
+ * This is the old "dentry style" Linux NFSv2 file handle.
  *
  * The xino and xdev fields are currently used to transport the
  * ino/dev of the exported inode.
  */
-struct nfs_fhbase {
-	struct dentry *	fb_dentry;	/* dentry cookie */
+struct nfs_fhbase_old {
+	struct dentry *	fb_dentry;	/* dentry cookie - always 0xfeebbaca */
 	__u32		fb_ino;		/* our inode number */
-	__u32		fb_dirino;	/* dir inode number */
+	__u32		fb_dirino;	/* dir inode number, 0 for directories */
 	__u32		fb_dev;		/* our device */
 	__u32		fb_xdev;
 	__u32		fb_xino;
 	__u32		fb_generation;
 };
 
-#define NFS_FH_PADDING		(NFS_FHSIZE - sizeof(struct nfs_fhbase))
-struct knfs_fh {
-	struct nfs_fhbase	fh_base;
-	__u8			fh_cookie[NFS_FH_PADDING];
+/*
+ * This is the new flexible, extensible style NFSv2/v3 file handle.
+ * by Neil Brown <neilb@cse.unsw.edu.au> - March 2000
+ *
+ * The file handle is seens as a list of 4byte words.
+ * The first word contains a version number (1) and four descriptor bytes
+ * that tell how the remaining 3 variable length fields should be handled.
+ * These three bytes are auth_type, fsid_type and fileid_type.
+ *
+ * All 4byte values are in host-byte-order.
+ *
+ * The auth_type field specifies how the filehandle can be authenticated
+ * This might allow a file to be confirmed to be in a writable part of a
+ * filetree without checking the path from it upto the root.
+ * Current values:
+ *     0  - No authentication.  fb_auth is 0 bytes long
+ * Possible future values:
+ *     1  - 4 bytes taken from MD5 hash of the remainer of the file handle
+ *          prefixed by a secret and with the important export flags.
+ *
+ * The fsid_type identifies how the filesystem (or export point) is
+ *    encoded.
+ *  Current values:
+ *     0  - 4 byte device id (ms-2-bytes major, ls-2-bytes minor), 4byte inode number
+ *        NOTE: we cannot use the kdev_t device id value, because kdev_t.h
+ *              says we mustn't.  We must break it up and reassemble.
+ *  Possible future encodings:
+ *     1  - 4 byte user specified identifier
+ *
+ * The fileid_type identified how the file within the filesystem is encoded.
+ * This is (will be) passed to, and set by, the underlying filesystem if it supports
+ * filehandle operations.  The filesystem must not use the value '0' or '0xff' and may
+ * only use the values 1 and 2 as defined below:
+ *  Current values:
+ *    0   - The root, or export point, of the filesystem.  fb_fileid is 0 bytes.
+ *    1   - 32bit inode number, 32 bit generation number.
+ *    2   - 32bit inode number, 32 bit generation number, 32 bit parent directory inode number.
+ *
+ */
+struct nfs_fhbase_new {
+	__u8		fb_version;	/* == 1, even => nfs_fhbase_old */
+	__u8		fb_auth_type;
+	__u8		fb_fsid_type;
+	__u8		fb_fileid_type;
+	__u32		fb_auth[1];
+/*	__u32		fb_fsid[0]; floating */
+/*	__u32		fb_fileid[0]; floating */
+};
+
+struct knfsd_fh {
+	int		fh_size;	/* significant for NFSv3.
+					 * Points to the current size while building
+					 * a new file handle
+					 */
+	union {
+		struct nfs_fhbase_old	fh_old;
+		__u32			fh_pad[NFS3_FHSIZE/4];
+		struct nfs_fhbase_new	fh_new;
+	} fh_base;
 };
 
-#define fh_dcookie		fh_base.fb_dentry
-#define fh_ino			fh_base.fb_ino
-#define fh_dirino		fh_base.fb_dirino
-#define fh_dev			fh_base.fb_dev
-#define fh_xdev			fh_base.fb_xdev
-#define fh_xino			fh_base.fb_xino
-#define fh_generation		fh_base.fb_generation
+#define ofh_dcookie		fh_base.fh_old.fb_dentry
+#define ofh_ino			fh_base.fh_old.fb_ino
+#define ofh_dirino		fh_base.fh_old.fb_dirino
+#define ofh_dev			fh_base.fh_old.fb_dev
+#define ofh_xdev		fh_base.fh_old.fb_xdev
+#define ofh_xino		fh_base.fh_old.fb_xino
+#define ofh_generation		fh_base.fh_old.fb_generation
+
+#define	fh_version		fh_base.fh_new.fb_version
+#define	fh_fsid_type		fh_base.fh_new.fb_fsid_type
+#define	fh_auth_type		fh_base.fh_new.fb_auth_type
+#define	fh_fileid_type		fh_base.fh_new.fb_fileid_type
+#define	fh_auth			fh_base.fh_new.fb_auth
 
 #ifdef __KERNEL__
 
@@ -84,9 +145,10 @@
  * pre_mtime/post_version will be used to support wcc_attr's in NFSv3.
  */
 typedef struct svc_fh {
-	struct knfs_fh		fh_handle;	/* FH data */
+	struct knfsd_fh		fh_handle;	/* FH data */
 	struct dentry *		fh_dentry;	/* validated dentry */
 	struct svc_export *	fh_export;	/* export pointer */
+	int			fh_maxsize;	/* max size for fh_handle */
 #ifdef CONFIG_NFSD_V3
 	unsigned char		fh_post_saved;	/* post-op attrs saved */
 	unsigned char		fh_pre_saved;	/* pre-op attrs saved */
@@ -119,20 +181,28 @@
 /*
  * Shorthand for dprintk()'s
  */
-#define SVCFH_DENTRY(f)		((f)->fh_dentry)
-#define SVCFH_INO(f)		((f)->fh_handle.fh_ino)
-#define SVCFH_DEV(f)		((f)->fh_handle.fh_dev)
-
+inline static char * SVCFH_fmt(struct svc_fh *fhp)
+{
+	struct knfsd_fh *fh = &fhp->fh_handle;
+	
+	static char buf[80];
+	sprintf(buf, "%d: %08x %08x %08x %08x %08x %08x",
+		fh->fh_size,
+		fh->fh_base.fh_pad[0],
+		fh->fh_base.fh_pad[1],
+		fh->fh_base.fh_pad[2],
+		fh->fh_base.fh_pad[3],
+		fh->fh_base.fh_pad[4],
+		fh->fh_base.fh_pad[5]);
+	return buf;
+}
 /*
  * Function prototypes
  */
 u32	fh_verify(struct svc_rqst *, struct svc_fh *, int, int);
-void	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *);
-void	fh_update(struct svc_fh *);
+int	fh_compose(struct svc_fh *, struct svc_export *, struct dentry *);
+int	fh_update(struct svc_fh *);
 void	fh_put(struct svc_fh *);
-void	nfsd_fh_flush(kdev_t);
-void	nfsd_fh_init(void);
-void	nfsd_fh_free(void);
 
 static __inline__ struct svc_fh *
 fh_copy(struct svc_fh *dst, struct svc_fh *src)
@@ -148,9 +218,10 @@
 }
 
 static __inline__ struct svc_fh *
-fh_init(struct svc_fh *fhp)
+fh_init(struct svc_fh *fhp, int maxsize)
 {
 	memset(fhp, 0, sizeof(*fhp));
+	fhp->fh_maxsize = maxsize;
 	return fhp;
 }
 
@@ -216,8 +287,8 @@
 	struct dentry	*dentry = fhp->fh_dentry;
 	struct inode	*inode;
 
-	dfprintk(FILEOP, "nfsd: fh_lock(%x/%ld) locked = %d\n",
-			SVCFH_DEV(fhp), (long)SVCFH_INO(fhp), fhp->fh_locked);
+	dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
+			SVCFH_fmt(fhp), fhp->fh_locked);
 
 	if (!fhp->fh_dverified) {
 		printk(KERN_ERR "fh_lock: fh not verified!\n");
diff -u --recursive --new-file v2.3.50/linux/include/linux/nfsd/syscall.h linux/include/linux/nfsd/syscall.h
--- v2.3.50/linux/include/linux/nfsd/syscall.h	Wed Dec  8 14:11:28 1999
+++ linux/include/linux/nfsd/syscall.h	Fri Mar 10 14:32:15 2000
@@ -37,6 +37,7 @@
 #define NFSCTL_UGIDUPDATE	5	/* update a client's uid/gid map. */
 #define NFSCTL_GETFH		6	/* get an fh by ino (used by mountd) */
 #define NFSCTL_GETFD		7	/* get an fh by path (used by mountd) */
+#define	NFSCTL_GETFS		8	/* get an fh by path with max FH len */
 
 /* SVC */
 struct nfsctl_svc {
@@ -91,6 +92,13 @@
 	int			gd_version;
 };
 
+/* GETFS - GET Filehandle with Size */
+struct nfsctl_fsparm {
+	struct sockaddr		gd_addr;
+	char			gd_path[NFS_MAXPATHLEN+1];
+	int			gd_maxlen;
+};
+
 /*
  * This is the argument union.
  */
@@ -103,6 +111,9 @@
 		struct nfsctl_uidmap	u_umap;
 		struct nfsctl_fhparm	u_getfh;
 		struct nfsctl_fdparm	u_getfd;
+#ifdef notyet
+		struct nfsctl_fsparm	u_getfs;
+#endif
 		unsigned int		u_debug;
 	} u;
 #define ca_svc		u.u_svc
@@ -111,12 +122,16 @@
 #define ca_umap		u.u_umap
 #define ca_getfh	u.u_getfh
 #define ca_getfd	u.u_getfd
+#define	ca_getfs	u.u_getfs
 #define ca_authd	u.u_authd
 #define ca_debug	u.u_debug
 };
 
 union nfsctl_res {
-	struct knfs_fh		cr_getfh;
+	__u8			cr_getfh[NFS_FHSIZE];
+#ifdef notyet
+	struct knfsd_fh		cr_getfs;
+#endif
 	unsigned int		cr_debug;
 };
 
diff -u --recursive --new-file v2.3.50/linux/include/linux/nfsd/xdr.h linux/include/linux/nfsd/xdr.h
--- v2.3.50/linux/include/linux/nfsd/xdr.h	Mon Dec 28 14:09:59 1998
+++ linux/include/linux/nfsd/xdr.h	Fri Mar 10 14:32:11 2000
@@ -121,7 +121,6 @@
 
 #define NFSSVC_XDRSIZE		sizeof(union nfsd_xdrstore)
 
-void nfsd_xdr_init(void);
 
 int nfssvc_decode_void(struct svc_rqst *, u32 *, void *);
 int nfssvc_decode_fhandle(struct svc_rqst *, u32 *, struct svc_fh *);
diff -u --recursive --new-file v2.3.50/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.3.50/linux/include/linux/pci_ids.h	Sat Feb 26 22:32:07 2000
+++ linux/include/linux/pci_ids.h	Thu Mar  9 17:18:02 2000
@@ -669,7 +669,9 @@
 #define PCI_DEVICE_ID_TTI_HPT366	0x0004
 
 #define PCI_VENDOR_ID_VIA		0x1106
+#define PCI_DEVICE_ID_VIA_8371_0	0x0391
 #define PCI_DEVICE_ID_VIA_8501_0	0x0501
+#define PCI_DEVICE_ID_VIA_8601_0	0x0601
 #define PCI_DEVICE_ID_VIA_82C505	0x0505
 #define PCI_DEVICE_ID_VIA_82C561	0x0561
 #define PCI_DEVICE_ID_VIA_82C586_1	0x0571
@@ -693,9 +695,12 @@
 #define PCI_DEVICE_ID_VIA_82C686_5	0x3058
 #define PCI_DEVICE_ID_VIA_82C686_6	0x3068
 #define PCI_DEVICE_ID_VIA_86C100A	0x6100
+#define PCI_DEVICE_ID_VIA_8231		0x8231
+#define PCI_DEVICE_ID_VIA_8371_1	0x8391
 #define PCI_DEVICE_ID_VIA_8501_1	0x8501
 #define PCI_DEVICE_ID_VIA_82C597_1	0x8597
 #define PCI_DEVICE_ID_VIA_82C598_1	0x8598
+#define PCI_DEVICE_ID_VIA_8601_1	0x8601
 
 #define PCI_VENDOR_ID_SMC2             0x1113
 #define PCI_DEVICE_ID_SMC2_1211TX      0x1211
@@ -1050,6 +1055,9 @@
 #define PCI_VENDOR_ID_PANACOM		0x14d4
 #define PCI_DEVICE_ID_PANACOM_QUADMODEM	0x0400
 #define PCI_DEVICE_ID_PANACOM_DUALMODEM	0x0402
+
+#define PCI_VENDOR_ID_AFAVLAB		0x14db
+#define PCI_DEVICE_ID_AFAVLAB_TK9902	0x2120
 
 #define PCI_VENDOR_ID_SYMPHONY		0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101	0x0001
diff -u --recursive --new-file v2.3.50/linux/include/linux/shm.h linux/include/linux/shm.h
--- v2.3.50/linux/include/linux/shm.h	Thu Feb 10 17:11:22 2000
+++ linux/include/linux/shm.h	Fri Mar 10 14:33:04 2000
@@ -10,7 +10,7 @@
  */
 
 #define SHMMAX 0x2000000		 /* max shared seg size (bytes) */
-#define SHMMIN 1 /* really PAGE_SIZE */	 /* min shared seg size (bytes) */
+#define SHMMIN 0			 /* min shared seg size (bytes) */
 #define SHMMNI 128			 /* max num of segs system wide */
 #define SHMALL (SHMMAX/PAGE_SIZE*SHMMNI) /* max shm system wide (pages) */
 #define SHMSEG SHMMNI			 /* max shared segs per process */
diff -u --recursive --new-file v2.3.50/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.3.50/linux/include/linux/sysctl.h	Sat Feb 26 22:32:07 2000
+++ linux/include/linux/sysctl.h	Wed Mar  8 09:16:24 2000
@@ -110,7 +110,8 @@
  	KERN_SPARC_STOP_A=44,	/* int: Sparc Stop-A enable */
  	KERN_SHMMNI=45,		/* int: shm array identifiers */
 	KERN_OVERFLOWUID=46,	/* int: overflow UID */
-	KERN_OVERFLOWGID=47	/* int: overflow GID */
+	KERN_OVERFLOWGID=47,	/* int: overflow GID */
+	KERN_SHMPATH=48,	/* string: path to shm fs */
 };
 
 
diff -u --recursive --new-file v2.3.50/linux/include/linux/usb.h linux/include/linux/usb.h
--- v2.3.50/linux/include/linux/usb.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/usb.h	Fri Mar 10 16:18:34 2000
@@ -0,0 +1,786 @@
+#ifndef __LINUX_USB_H
+#define __LINUX_USB_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>	/* for in_interrupt() */
+
+/* USB constants */
+
+/*
+ * Device and/or Interface Class codes
+ */
+#define USB_CLASS_PER_INTERFACE		0	/* for DeviceClass */
+#define USB_CLASS_AUDIO			1
+#define USB_CLASS_COMM			2
+#define USB_CLASS_HID			3
+#define USB_CLASS_PRINTER		7
+#define USB_CLASS_MASS_STORAGE		8
+#define USB_CLASS_HUB			9
+#define USB_CLASS_DATA			10
+#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
+#define USB_DT_CONFIG			0x02
+#define USB_DT_STRING			0x03
+#define USB_DT_INTERFACE		0x04
+#define USB_DT_ENDPOINT			0x05
+
+#define USB_DT_HID			(USB_TYPE_CLASS | 0x01)
+#define USB_DT_REPORT			(USB_TYPE_CLASS | 0x02)
+#define USB_DT_PHYSICAL			(USB_TYPE_CLASS | 0x03)
+#define USB_DT_HUB			(USB_TYPE_CLASS | 0x09)
+
+/*
+ * Descriptor sizes per descriptor type
+ */
+#define USB_DT_DEVICE_SIZE		18
+#define USB_DT_CONFIG_SIZE		9
+#define USB_DT_INTERFACE_SIZE		9
+#define USB_DT_ENDPOINT_SIZE		7
+#define USB_DT_ENDPOINT_AUDIO_SIZE	9	/* Audio extension */
+#define USB_DT_HUB_NONVAR_SIZE		7
+#define USB_DT_HID_SIZE			9
+
+/*
+ * Endpoints
+ */
+#define USB_ENDPOINT_NUMBER_MASK	0x0f	/* in bEndpointAddress */
+#define USB_ENDPOINT_DIR_MASK		0x80
+
+#define USB_ENDPOINT_XFERTYPE_MASK	0x03	/* in bmAttributes */
+#define USB_ENDPOINT_XFER_CONTROL	0
+#define USB_ENDPOINT_XFER_ISOC		1
+#define USB_ENDPOINT_XFER_BULK		2
+#define USB_ENDPOINT_XFER_INT		3
+
+/*
+ * USB Packet IDs (PIDs)
+ */
+#define USB_PID_UNDEF_0                        0xf0
+#define USB_PID_OUT                            0xe1
+#define USB_PID_ACK                            0xd2
+#define USB_PID_DATA0                          0xc3
+#define USB_PID_UNDEF_4                        0xb4
+#define USB_PID_SOF                            0xa5
+#define USB_PID_UNDEF_6                        0x96
+#define USB_PID_UNDEF_7                        0x87
+#define USB_PID_UNDEF_8                        0x78
+#define USB_PID_IN                             0x69
+#define USB_PID_NAK                            0x5a
+#define USB_PID_DATA1                          0x4b
+#define USB_PID_PREAMBLE                       0x3c
+#define USB_PID_SETUP                          0x2d
+#define USB_PID_STALL                          0x1e
+#define USB_PID_UNDEF_F                        0x0f
+
+/*
+ * Standard requests
+ */
+#define USB_REQ_GET_STATUS		0x00
+#define USB_REQ_CLEAR_FEATURE		0x01
+#define USB_REQ_SET_FEATURE		0x03
+#define USB_REQ_SET_ADDRESS		0x05
+#define USB_REQ_GET_DESCRIPTOR		0x06
+#define USB_REQ_SET_DESCRIPTOR		0x07
+#define USB_REQ_GET_CONFIGURATION	0x08
+#define USB_REQ_SET_CONFIGURATION	0x09
+#define USB_REQ_GET_INTERFACE		0x0A
+#define USB_REQ_SET_INTERFACE		0x0B
+#define USB_REQ_SYNCH_FRAME		0x0C
+
+/*
+ * HID requests
+ */
+#define USB_REQ_GET_REPORT		0x01
+#define USB_REQ_GET_IDLE		0x02
+#define USB_REQ_GET_PROTOCOL		0x03
+#define USB_REQ_SET_REPORT		0x09
+#define USB_REQ_SET_IDLE		0x0A
+#define USB_REQ_SET_PROTOCOL		0x0B
+
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/list.h>
+
+#define USB_MAJOR 180
+
+/* for 2.2-kernels */
+ 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
+
+static __inline__ void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+typedef struct wait_queue wait_queue_t;
+
+typedef struct wait_queue *wait_queue_head_t;
+#define DECLARE_WAITQUEUE(wait, current) \
+	struct wait_queue wait = { current, NULL }
+#define DECLARE_WAIT_QUEUE_HEAD(wait)\
+	wait_queue_head_t wait
+
+#define init_waitqueue_head(x) *x=NULL
+#define init_MUTEX(x) *(x)=MUTEX
+#define DECLARE_MUTEX(name) struct semaphore name=MUTEX
+#define DECLARE_MUTEX_LOCKED(name) struct semaphore name=MUTEX_LOCKED
+
+
+#define __set_current_state(state_value)                        \
+	do { current->state = state_value; } while (0)
+#ifdef __SMP__
+#define set_current_state(state_value)          \
+	set_mb(current->state, state_value)
+#else
+#define set_current_state(state_value)          \
+	__set_current_state(state_value)
+#endif
+
+#endif // 2.2.x
+
+
+static __inline__ void wait_ms(unsigned int ms)
+{
+	if(!in_interrupt()) {
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(1 + ms * HZ / 1000);
+	}
+	else
+		mdelay(ms);
+}
+
+typedef struct {
+	__u8 requesttype;
+	__u8 request;
+	__u16 value;
+	__u16 index;
+	__u16 length;
+} devrequest __attribute__ ((packed));
+
+/*
+ * USB-status codes:
+ * USB_ST* maps to -E* and should go away in the future
+ */
+
+#define USB_ST_NOERROR		0
+#define USB_ST_CRC		(-EILSEQ)
+#define USB_ST_BITSTUFF		(-EPROTO)
+#define USB_ST_NORESPONSE	(-ETIMEDOUT)			/* device not responding/handshaking */
+#define USB_ST_DATAOVERRUN	(-EOVERFLOW)
+#define USB_ST_DATAUNDERRUN	(-EREMOTEIO)
+#define USB_ST_BUFFEROVERRUN	(-ECOMM)
+#define USB_ST_BUFFERUNDERRUN	(-ENOSR)
+#define USB_ST_INTERNALERROR	(-EPROTO) 			/* unknown error */
+#define USB_ST_SHORT_PACKET    	(-EREMOTEIO)
+#define USB_ST_PARTIAL_ERROR  	(-EXDEV)			/* ISO transfer only partially completed */
+#define USB_ST_URB_KILLED     	(-ENOENT)			/* URB canceled by user */
+#define USB_ST_URB_PENDING       (-EINPROGRESS)
+#define USB_ST_REMOVED		(-ENODEV) 			/* device not existing or removed */
+#define USB_ST_TIMEOUT		(-ETIMEDOUT)			/* communication timed out, also in urb->status**/
+#define USB_ST_NOTSUPPORTED	(-ENOSYS)			
+#define USB_ST_BANDWIDTH_ERROR	(-ENOSPC)			/* too much bandwidth used */
+#define USB_ST_URB_INVALID_ERROR  (-EINVAL)			/* invalid value/transfer type */
+#define USB_ST_URB_REQUEST_ERROR  (-ENXIO)			/* invalid endpoint */
+#define USB_ST_STALL		(-EPIPE) 			/* pipe stalled, also in urb->status*/
+
+/*
+ * USB device number allocation bitmap. There's one bitmap
+ * per USB tree.
+ */
+struct usb_devmap {
+	unsigned long devicemap[128 / (8*sizeof(unsigned long))];
+};
+
+#define USB_MAXBUS		64
+
+struct usb_busmap {
+	unsigned long busmap[USB_MAXBUS / (8*sizeof(unsigned long))];
+};
+
+/*
+ * This is a USB device descriptor.
+ *
+ * USB device information
+ */
+
+/* Everything but the endpoint maximums are aribtrary */
+#define USB_MAXCONFIG		8
+#define USB_ALTSETTINGALLOC     4
+#define USB_MAXALTSETTING	128  /* Hard limit */
+#define USB_MAXINTERFACES	32
+#define USB_MAXENDPOINTS	32
+
+/* All standard descriptors have these 2 fields in common */
+struct usb_descriptor_header {
+	__u8  bLength;
+	__u8  bDescriptorType;
+} __attribute__ ((packed));
+
+/* Device descriptor */
+struct usb_device_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u16 bcdUSB;
+	__u8  bDeviceClass;
+	__u8  bDeviceSubClass;
+	__u8  bDeviceProtocol;
+	__u8  bMaxPacketSize0;
+	__u16 idVendor;
+	__u16 idProduct;
+	__u16 bcdDevice;
+	__u8  iManufacturer;
+	__u8  iProduct;
+	__u8  iSerialNumber;
+	__u8  bNumConfigurations;
+} __attribute__ ((packed));
+
+/* Endpoint descriptor */
+struct usb_endpoint_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u8  bEndpointAddress;
+	__u8  bmAttributes;
+	__u16 wMaxPacketSize;
+	__u8  bInterval;
+	__u8  bRefresh;
+	__u8  bSynchAddress;
+
+   	unsigned char *extra;   /* Extra descriptors */
+	int extralen;
+} __attribute__ ((packed));
+
+/* Interface descriptor */
+struct usb_interface_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u8  bInterfaceNumber;
+	__u8  bAlternateSetting;
+	__u8  bNumEndpoints;
+	__u8  bInterfaceClass;
+	__u8  bInterfaceSubClass;
+	__u8  bInterfaceProtocol;
+	__u8  iInterface;
+
+  	struct usb_endpoint_descriptor *endpoint;
+
+	unsigned char *extra;
+	int extralen;
+} __attribute__ ((packed));
+
+struct usb_interface {
+	struct usb_interface_descriptor *altsetting;
+
+	int act_altsetting;		/* active alternate setting */
+	int num_altsetting;		/* number of alternate settings */
+	int max_altsetting;             /* total memory allocated */
+ 
+	struct usb_driver *driver;	/* driver */
+	void *private_data;
+};
+
+/* Configuration descriptor information.. */
+struct usb_config_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u16 wTotalLength;
+	__u8  bNumInterfaces;
+	__u8  bConfigurationValue;
+	__u8  iConfiguration;
+	__u8  bmAttributes;
+	__u8  MaxPower;
+
+	struct usb_interface *interface;
+} __attribute__ ((packed));
+
+/* String descriptor */
+struct usb_string_descriptor {
+	__u8  bLength;
+	__u8  bDescriptorType;
+	__u16 wData[1];
+} __attribute__ ((packed));
+
+struct usb_device;
+
+struct usb_driver {
+	const char *name;
+
+	void * (*probe)(struct usb_device *, unsigned int);
+	void (*disconnect)(struct usb_device *, void *);
+
+	struct list_head driver_list;
+
+	struct file_operations *fops;
+	int minor;
+};
+
+/*
+ * Pointer to a device endpoint interrupt function -greg
+ *   Parameters:
+ *     int status - This needs to be defined.  Right now each HCD
+ *         passes different transfer status bits back.  Don't use it
+ *         until we come up with a common meaning.
+ *     void *buffer - This is a pointer to the data used in this
+ *         USB transfer.
+ *     int length - This is the number of bytes transferred in or out
+ *         of the buffer by this transfer.  (-1 = unknown/unsupported)
+ *     void *dev_id - This is a user defined pointer set when the IRQ
+ *         is requested that is passed back.
+ *
+ *   Special Cases:
+ *     if (status == USB_ST_REMOVED), don't trust buffer or len.
+ */
+typedef int (*usb_device_irq)(int, void *, int, void *);
+
+/* --------------------------------------------------------------------------* 
+ * New USB Structures                                                        *
+ * --------------------------------------------------------------------------*/
+
+#define USB_DISABLE_SPD		1
+#define USB_ISO_ASAP		2
+#define USB_URB_EARLY_COMPLETE	4
+#define USB_ASYNC_UNLINK	8
+
+typedef struct {
+	unsigned int offset;
+	unsigned int length;		// expected length
+	unsigned int actual_length;
+	unsigned int status;
+} iso_packet_descriptor_t, *piso_packet_descriptor_t;
+
+struct urb;
+typedef void (*usb_complete_t)(struct urb *);
+
+typedef struct urb
+{
+	spinlock_t lock;		// lock for the URB
+	void *hcpriv;			// private data for host controller
+	struct list_head urb_list;	// list pointer to all active urbs 
+	struct urb *next;		// pointer to next URB	
+	struct usb_device *dev;		// pointer to associated USB device
+	unsigned int pipe;		// pipe information
+	int status;			// returned status
+	unsigned int transfer_flags;	// USB_DISABLE_SPD | USB_ISO_ASAP | USB_URB_EARLY_COMPLETE
+	void *transfer_buffer;		// associated data buffer
+	int transfer_buffer_length;	// data buffer length
+	int actual_length;              // actual data buffer length	
+	unsigned char *setup_packet;	// setup packet (control only)
+	//
+	int start_frame;		// start frame (iso/irq only)
+	int number_of_packets;		// number of packets in this request (iso/irq only)
+	int interval;                   // polling interval (irq only)
+	int error_count;		// number of errors in this transfer (iso only)
+	//
+	void *context;			// context for completion routine
+	usb_complete_t complete;	// pointer to completion routine
+	//
+	iso_packet_descriptor_t	 iso_frame_desc[0];
+} urb_t, *purb_t;
+
+#define FILL_CONTROL_URB(a,aa,b,c,d,e,f,g) \
+    do {\
+	spin_lock_init(&(a)->lock);\
+	(a)->dev=aa;\
+	(a)->pipe=b;\
+	(a)->setup_packet=c;\
+	(a)->transfer_buffer=d;\
+	(a)->transfer_buffer_length=e;\
+	(a)->complete=f;\
+	(a)->context=g;\
+    } while (0)
+
+#define FILL_BULK_URB(a,aa,b,c,d,e,f) \
+    do {\
+	spin_lock_init(&(a)->lock);\
+	(a)->dev=aa;\
+	(a)->pipe=b;\
+	(a)->transfer_buffer=c;\
+	(a)->transfer_buffer_length=d;\
+	(a)->complete=e;\
+	(a)->context=f;\
+    } while (0)
+    
+#define FILL_INT_URB(a,aa,b,c,d,e,f,g) \
+    do {\
+	spin_lock_init(&(a)->lock);\
+	(a)->dev=aa;\
+	(a)->pipe=b;\
+	(a)->transfer_buffer=c;\
+	(a)->transfer_buffer_length=d;\
+	(a)->complete=e;\
+	(a)->context=f;\
+	(a)->interval=g;\
+	(a)->start_frame=-1;\
+    } while (0)
+
+purb_t usb_alloc_urb(int iso_packets);
+void usb_free_urb (purb_t purb);
+int usb_submit_urb(purb_t purb);
+int usb_unlink_urb(purb_t purb);
+int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, devrequest *cmd,  void *data, int len, int timeout);
+int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout);
+
+/*-------------------------------------------------------------------*
+ *                         COMPATIBILITY STUFF                       *
+ *-------------------------------------------------------------------*/
+typedef struct
+{
+  wait_queue_head_t *wakeup;
+
+  usb_device_irq handler;
+  void* stuff;
+  /* more to follow */
+} api_wrapper_data;
+
+struct irq_wrapper_data {
+	void *context;
+	usb_device_irq handler;
+};
+
+/* ------------------------------------------------------------------------------------- */
+
+struct usb_operations {
+	int (*allocate)(struct usb_device *);
+	int (*deallocate)(struct usb_device *);
+	int (*get_frame_number) (struct usb_device *usb_dev);
+	int (*submit_urb) (struct urb* purb);
+	int (*unlink_urb) (struct urb* purb);
+};
+
+/*
+ * Allocated per bus we have
+ */
+struct usb_bus {
+	int busnum;			/* Bus number (in order of reg) */
+
+	struct usb_devmap devmap;       /* Device map */
+	struct usb_operations *op;      /* Operations (specific to the HC) */
+	struct usb_device *root_hub;    /* Root hub */
+	struct list_head bus_list;
+	void *hcpriv;                   /* Host Controller private data */
+
+	unsigned int bandwidth_allocated; /* on this Host Controller; */
+					  /* applies to Int. and Isoc. pipes; */
+					  /* measured in microseconds/frame; */
+					  /* range is 0..900, where 900 = */
+					  /* 90% of a 1-millisecond frame */
+	int bandwidth_int_reqs;		/* number of Interrupt requesters */
+	int bandwidth_isoc_reqs;	/* number of Isoc. requesters */
+
+	/* usbdevfs inode list */
+        struct list_head inodes;
+};
+
+#define USB_MAXCHILDREN (8)	/* This is arbitrary */
+
+struct usb_device {
+	int devnum;			/* Device number on USB bus */
+	int slow;			/* Slow device? */
+
+	atomic_t refcnt;		/* Reference count */
+
+	int maxpacketsize;		/* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */
+	unsigned int toggle[2];		/* one bit for each endpoint ([0] = IN, [1] = OUT) */
+	unsigned int halted[2];		/* endpoint halts; one bit per endpoint # & direction; */
+					/* [0] = IN, [1] = OUT */
+	struct usb_config_descriptor *actconfig;/* the active configuration */
+	int epmaxpacketin[16];		/* INput endpoint specific maximums */
+	int epmaxpacketout[16];		/* OUTput endpoint specific maximums */
+
+	struct usb_device *parent;
+	struct usb_bus *bus;		/* Bus we're part of */
+
+	struct usb_device_descriptor descriptor;/* Descriptor */
+	struct usb_config_descriptor *config;	/* All of the configs */
+
+	int have_langid;		/* whether string_langid is valid yet */
+	int string_langid;		/* language ID for strings */
+  
+	void *hcpriv;			/* Host Controller private data */
+	
+        /* usbdevfs inode list */
+        struct list_head inodes;
+        struct list_head filelist;
+
+	/*
+	 * Child devices - these can be either new devices
+	 * (if this is a hub device), or different instances
+	 * of this same device.
+	 *
+	 * Each instance needs its own set of data structures.
+	 */
+
+	int maxchild;			/* Number of ports if hub */
+	struct usb_device *children[USB_MAXCHILDREN];
+};
+
+extern int usb_register(struct usb_driver *);
+extern void usb_deregister(struct usb_driver *);
+
+/* used these for multi-interface device registration */
+extern void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void* priv);
+extern int usb_interface_claimed(struct usb_interface *iface);
+extern void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface);
+
+extern struct usb_bus *usb_alloc_bus(struct usb_operations *);
+extern void usb_free_bus(struct usb_bus *);
+extern void usb_register_bus(struct usb_bus *);
+extern void usb_deregister_bus(struct usb_bus *);
+
+extern struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *);
+extern void usb_free_dev(struct usb_device *);
+extern void usb_inc_dev_use(struct usb_device *);
+#define usb_dec_dev_use usb_free_dev
+extern void usb_release_bandwidth(struct usb_device *, int);
+
+extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
+
+extern int usb_request_irq(struct usb_device *, unsigned int, usb_device_irq, int, void *, void **);
+extern int usb_release_irq(struct usb_device *dev, void *handle, unsigned int pipe);
+
+extern void *usb_request_bulk(struct usb_device *, unsigned int, usb_device_irq, void *, int, void *);
+extern int usb_terminate_bulk(struct usb_device *, void *);
+
+extern void usb_init_root_hub(struct usb_device *dev);
+extern void usb_connect(struct usb_device *dev);
+extern void usb_disconnect(struct usb_device **);
+
+extern void usb_destroy_configuration(struct usb_device *dev);
+
+int usb_get_current_frame_number (struct usb_device *usb_dev);
+
+/*
+ * Calling this entity a "pipe" is glorifying it. A USB pipe
+ * is something embarrassingly simple: it basically consists
+ * of the following information:
+ *  - device number (7 bits)
+ *  - endpoint number (4 bits)
+ *  - current Data0/1 state (1 bit)
+ *  - direction (1 bit)
+ *  - speed (1 bit)
+ *  - max packet size (2 bits: 8, 16, 32 or 64)
+ *  - pipe type (2 bits: control, interrupt, bulk, isochronous)
+ *
+ * That's 18 bits. Really. Nothing more. And the USB people have
+ * documented these eighteen bits as some kind of glorious
+ * virtual data structure.
+ *
+ * Let's not fall in that trap. We'll just encode it as a simple
+ * unsigned int. The encoding is:
+ *
+ *  - max size:		bits 0-1	(00 = 8, 01 = 16, 10 = 32, 11 = 64)
+ *  - direction:	bit 7		(0 = Host-to-Device [Out], 1 = Device-to-Host [In])
+ *  - device:		bits 8-14
+ *  - endpoint:		bits 15-18
+ *  - Data0/1:		bit 19
+ *  - speed:		bit 26		(0 = Full, 1 = Low Speed)
+ *  - pipe type:	bits 30-31	(00 = isochronous, 01 = interrupt, 10 = control, 11 = bulk)
+ *
+ * Why? Because it's arbitrary, and whatever encoding we select is really
+ * up to us. This one happens to share a lot of bit positions with the UHCI
+ * specification, so that much of the uhci driver can just mask the bits
+ * appropriately.
+ */
+
+#define PIPE_ISOCHRONOUS		0
+#define PIPE_INTERRUPT			1
+#define PIPE_CONTROL			2
+#define PIPE_BULK			3
+
+#define USB_ISOCHRONOUS		0
+#define USB_INTERRUPT		1
+#define USB_CONTROL		2
+#define USB_BULK		3
+
+#define usb_maxpacket(dev, pipe, out)	(out \
+				? (dev)->epmaxpacketout[usb_pipeendpoint(pipe)] \
+				: (dev)->epmaxpacketin [usb_pipeendpoint(pipe)] )
+#define usb_packetid(pipe)	(((pipe) & USB_DIR_IN) ? USB_PID_IN : USB_PID_OUT)
+
+#define usb_pipeout(pipe)	((((pipe) >> 7) & 1) ^ 1)
+#define usb_pipein(pipe)	(((pipe) >> 7) & 1)
+#define usb_pipedevice(pipe)	(((pipe) >> 8) & 0x7f)
+#define usb_pipe_endpdev(pipe)	(((pipe) >> 8) & 0x7ff)
+#define usb_pipeendpoint(pipe)	(((pipe) >> 15) & 0xf)
+#define usb_pipedata(pipe)	(((pipe) >> 19) & 1)
+#define usb_pipeslow(pipe)	(((pipe) >> 26) & 1)
+#define usb_pipetype(pipe)	(((pipe) >> 30) & 3)
+#define usb_pipeisoc(pipe)	(usb_pipetype((pipe)) == PIPE_ISOCHRONOUS)
+#define usb_pipeint(pipe)	(usb_pipetype((pipe)) == PIPE_INTERRUPT)
+#define usb_pipecontrol(pipe)	(usb_pipetype((pipe)) == PIPE_CONTROL)
+#define usb_pipebulk(pipe)	(usb_pipetype((pipe)) == PIPE_BULK)
+
+#define PIPE_DEVEP_MASK		0x0007ff00
+
+/* The D0/D1 toggle bits */
+#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1)
+#define	usb_dotoggle(dev, ep, out)  ((dev)->toggle[out] ^= (1 << ep))
+#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << ep)) | ((bit) << ep))
+
+/* Endpoint halt control/status */
+#define usb_endpoint_out(ep_dir)	(((ep_dir >> 7) & 1) ^ 1)
+#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep)))
+#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep)))
+#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep)))
+
+static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int endpoint)
+{
+	return (dev->devnum << 8) | (endpoint << 15) | (dev->slow << 26) | dev->maxpacketsize;
+}
+
+static inline unsigned int __default_pipe(struct usb_device *dev)
+{
+	return (dev->slow << 26);
+}
+
+/* Create various pipes... */
+#define usb_sndctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvctrlpipe(dev,endpoint)	((PIPE_CONTROL << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvisocpipe(dev,endpoint)	((PIPE_ISOCHRONOUS << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#define usb_sndbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint))
+#define usb_rcvbulkpipe(dev,endpoint)	((PIPE_BULK << 30) | __create_pipe(dev,endpoint) | USB_DIR_IN)
+#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)
+#define usb_snddefctrl(dev)		((PIPE_CONTROL << 30) | __default_pipe(dev))
+#define usb_rcvdefctrl(dev)		((PIPE_CONTROL << 30) | __default_pipe(dev) | USB_DIR_IN)
+
+/*
+ * Send and receive control messages..
+ */
+int usb_new_device(struct usb_device *dev);
+int usb_set_address(struct usb_device *dev);
+int usb_get_descriptor(struct usb_device *dev, unsigned char desctype,
+	unsigned char descindex, void *buf, int size);
+int usb_get_class_descriptor(struct usb_device *dev, int ifnum, unsigned char desctype,
+	unsigned char descindex, void *buf, int size);
+int usb_get_device_descriptor(struct usb_device *dev);
+int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr);
+int usb_get_status(struct usb_device *dev, int type, int target, void *data);
+int usb_get_protocol(struct usb_device *dev, int ifnum);
+int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol);
+int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
+int usb_set_idle(struct usb_device *dev, int ifnum, int duration, int report_id);
+int usb_set_configuration(struct usb_device *dev, int configuration);
+int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type,
+	unsigned char id, void *buf, int size);
+int usb_set_report(struct usb_device *dev, int ifnum, unsigned char type,
+	unsigned char id, void *buf, int size);
+int usb_string(struct usb_device *dev, int index, char *buf, size_t size);
+int usb_clear_halt(struct usb_device *dev, int pipe);
+
+#define usb_get_extra_descriptor(ifpoint,type,ptr)\
+	__usb_get_extra_descriptor((ifpoint)->extra,(ifpoint)->extralen,type,(void**)ptr)
+
+/*
+ * Some USB bandwidth allocation constants.
+ */
+#define BW_HOST_DELAY	1000L		/* nanoseconds */
+#define BW_HUB_LS_SETUP	333L		/* nanoseconds */
+                        /* 4 full-speed bit times (est.) */
+
+#define FRAME_TIME_BITS         12000L		/* frame = 1 millisecond */
+#define FRAME_TIME_MAX_BITS_ALLOC	(90L * FRAME_TIME_BITS / 100L)
+#define FRAME_TIME_USECS	1000L
+#define FRAME_TIME_MAX_USECS_ALLOC	(90L * FRAME_TIME_USECS / 100L)
+
+#define BitTime(bytecount)  (7 * 8 * bytecount / 6)  /* with integer truncation */
+		/* Trying not to use worst-case bit-stuffing
+                   of (7/6 * 8 * bytecount) = 9.33 * bytecount */
+		/* bytecount = data payload byte count */
+
+#define NS_TO_US(ns)	((ns + 500L) / 1000L)
+			/* convert & round nanoseconds to microseconds */
+
+/*
+ * Debugging helpers..
+ */
+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_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)
+#else
+#define dbg(format, arg...) do {} while (0)
+#endif
+#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg)
+#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg)
+
+
+/*
+ * bus and driver list
+ */
+
+extern struct list_head usb_driver_list;
+extern struct list_head usb_bus_list;
+
+/*
+ * USB device fs stuff
+ */
+
+#ifdef CONFIG_USB_DEVICEFS
+
+/*
+ * these are expected to be called from the USB core/hub thread
+ * with the kernel lock held
+ */
+extern void usbdevfs_add_bus(struct usb_bus *bus);
+extern void usbdevfs_remove_bus(struct usb_bus *bus);
+extern void usbdevfs_add_device(struct usb_device *dev);
+extern void usbdevfs_remove_device(struct usb_device *dev);
+
+extern int usbdevfs_init(void);
+extern void usbdevfs_cleanup(void);
+
+#else /* CONFIG_USB_DEVICEFS */
+
+extern inline void usbdevfs_add_bus(struct usb_bus *bus) {}
+extern inline void usbdevfs_remove_bus(struct usb_bus *bus) {}
+extern inline void usbdevfs_add_device(struct usb_device *dev) {}
+extern inline void usbdevfs_remove_device(struct usb_device *dev) {}
+
+extern inline int usbdevfs_init(void) { return 0; }
+extern inline void usbdevfs_cleanup(void) { }
+
+#endif /* CONFIG_USB_DEVICEFS */
+
+#endif  /* __KERNEL__ */
+
+#endif
diff -u --recursive --new-file v2.3.50/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.3.50/linux/include/linux/videodev.h	Wed Feb 16 17:03:52 2000
+++ linux/include/linux/videodev.h	Thu Mar  9 23:31:43 2000
@@ -286,7 +286,7 @@
 #define VIDIOCGPICT		_IOR('v',6,struct video_picture)	/* Get picture properties */
 #define VIDIOCSPICT		_IOW('v',7,struct video_picture)	/* Set picture properties */
 #define VIDIOCCAPTURE		_IOW('v',8,int)				/* Start, end capture */
-#define VIDIOCGWIN		_IOR('v',9, struct video_window)	/* Set the video overlay window */
+#define VIDIOCGWIN		_IOR('v',9, struct video_window)	/* Get the video overlay window */
 #define VIDIOCSWIN		_IOW('v',10, struct video_window)	/* Set the video overlay window - passes clip list for hardware smarts , chromakey etc */
 #define VIDIOCGFBUF		_IOR('v',11, struct video_buffer)	/* Get frame buffer */
 #define VIDIOCSFBUF		_IOW('v',12, struct video_buffer)	/* Set frame buffer - root only */
diff -u --recursive --new-file v2.3.50/linux/include/net/dn_raw.h linux/include/net/dn_raw.h
--- v2.3.50/linux/include/net/dn_raw.h	Wed Jun 30 11:24:55 1999
+++ linux/include/net/dn_raw.h	Wed Dec 31 16:00:00 1969
@@ -1,19 +0,0 @@
-#ifndef _NET_DN_RAW_H
-#define _NET_DN_RAW_H
-
-#include <linux/config.h>
-
-#ifdef CONFIG_DECNET_RAW
-
-extern struct proto_ops dn_raw_proto_ops;
-
-extern void dn_raw_rx_nsp(struct sk_buff *skb);
-extern void dn_raw_rx_routing(struct sk_buff *skb);
-
-#ifdef CONFIG_DECNET_MOP
-extern void dn_raw_rx_mop(struct sk_buff *skb);
-#endif /* CONFIG_DECNET_MOP */
-
-#endif /* CONFIG_DECNET_RAW */
-
-#endif /* _NET_DN_RAW_H */
diff -u --recursive --new-file v2.3.50/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.3.50/linux/include/net/tcp.h	Sat Feb 26 22:32:07 2000
+++ linux/include/net/tcp.h	Fri Mar 10 14:33:08 2000
@@ -339,12 +339,14 @@
 
 #if HZ == 20
 # define TCP_TW_RECYCLE_TICK (5+2-TCP_TW_RECYCLE_SLOTS_LOG)
+#elif HZ == 64
+# define TCP_TW_RECYCLE_TICK (6+2-TCP_TW_RECYCLE_SLOTS_LOG)
 #elif HZ == 100 || HZ == 128
 # define TCP_TW_RECYCLE_TICK (7+2-TCP_TW_RECYCLE_SLOTS_LOG)
-#elif HZ == 1024
+#elif HZ == 1024 || HZ == 1000
 # define TCP_TW_RECYCLE_TICK (10+2-TCP_TW_RECYCLE_SLOTS_LOG)
 #else
-# error HZ != 20 &&  HZ != 100 && HZ != 1024.
+# error HZ != 20 && HZ != 64 && HZ != 100 && HZ != 1000 && HZ != 1024
 #endif
 
 /*
diff -u --recursive --new-file v2.3.50/linux/init/main.c linux/init/main.c
--- v2.3.50/linux/init/main.c	Sat Feb 26 22:32:07 2000
+++ linux/init/main.c	Thu Mar  9 21:12:27 2000
@@ -533,7 +533,7 @@
 	vma_init();
 	buffer_init(mempages);
 	page_cache_init(mempages);
-	kiobuf_init();
+	kiobuf_setup();
 	signals_init();
 	bdev_init();
 	inode_init();
diff -u --recursive --new-file v2.3.50/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.50/linux/ipc/shm.c	Tue Mar  7 14:32:26 2000
+++ linux/ipc/shm.c	Fri Mar 10 10:48:52 2000
@@ -12,6 +12,16 @@
  * avoid vmalloc and make shmmax, shmall, shmmni sysctl'able,
  *                         Christoph Rohland <hans-christoph.rohland@sap.com>
  * Shared /dev/zero support, Kanoj Sarcar <kanoj@sgi.com>
+ * make it a file system,  Christoph Rohland <hans-christoph.rohland@sap.com>
+ *
+ * The filesystem has the following restrictions/bugs:
+ * 1) It only can handle one directory.
+ * 2) Because the directory is represented by the SYSV shm array it
+ *    can only be mounted one time.
+ * 3) This again leads to SYSV shm not working properly in a chrooted
+ *    environment
+ * 4) Read and write are not implemented (should they?)
+ * 5) No special nodes are supported
  */
 
 #include <linux/config.h>
@@ -20,6 +30,9 @@
 #include <linux/swap.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/locks.h>
+#include <linux/file.h>
+#include <linux/mman.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/proc_fs.h>
@@ -30,23 +43,61 @@
 
 #include "util.h"
 
+static struct super_block *shm_read_super(struct super_block *,void *, int);
+static void	      shm_put_super  (struct super_block *);
+static int	      shm_remount_fs (struct super_block *, int *, char *);
+static void	      shm_read_inode (struct inode *);
+static void	      shm_write_inode(struct inode *);
+static int	      shm_statfs (struct super_block *, struct statfs *);
+static int	      shm_create   (struct inode *,struct dentry *,int);
+static struct dentry *shm_lookup   (struct inode *,struct dentry *);
+static int	      shm_unlink   (struct inode *,struct dentry *);
+static int	      shm_setattr  (struct dentry *dent, struct iattr *attr);
+static void	      shm_delete   (struct inode *);
+static int	      shm_mmap	   (struct file *, struct vm_area_struct *);
+static int	      shm_readdir  (struct file *, void *, filldir_t);
+
+char shm_path[256] = "/var/shm";
+
+#define SHM_NAME_LEN NAME_MAX
+#define SHM_FMT ".IPC_%08x"
+#define SHM_FMT_LEN 13
+
 struct shmid_kernel /* private to the kernel */
 {	
 	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 */
-	int                     id; /* backreference to id for shm_close */
-	struct semaphore sem;
+	pte_t			**shm_dir;  /* ptr to arr of ptrs to frames */ 
+	int			id;
+	union permap {
+		struct shmem {
+			time_t			atime;
+			time_t			dtime;
+			time_t			ctime;
+			pid_t			cpid;
+			pid_t			lpid;
+			int			nlen;
+			char			nm[0];
+		} shmem;
+		struct zero {
+			struct semaphore	sema;
+			struct list_head	list;
+		} zero;
+	} permap;
 };
 
+#define shm_atim	permap.shmem.atime
+#define shm_dtim	permap.shmem.dtime
+#define shm_ctim	permap.shmem.ctime
+#define shm_cprid	permap.shmem.cpid
+#define shm_lprid	permap.shmem.lpid
+#define shm_namelen	permap.shmem.nlen
+#define shm_name	permap.shmem.nm
+#define zsem		permap.zero.sema
+#define zero_list	permap.zero.list
+
 static struct ipc_ids shm_ids;
 
 #define shm_lock(id)	((struct shmid_kernel*)ipc_lock(&shm_ids,id))
@@ -60,9 +111,8 @@
 #define shm_buildid(id, seq) \
 	ipc_buildid(&shm_ids, id, seq)
 
-static int newseg (key_t key, int shmflg, size_t size);
-static int shm_map (struct vm_area_struct *shmd);
-static void killseg (int shmid);
+static int newseg (key_t key, const char *name, int namelen, int shmflg, size_t size);
+static void killseg_core(struct shmid_kernel *shp, int doacc);
 static void shm_open (struct vm_area_struct *shmd);
 static void shm_close (struct vm_area_struct *shmd);
 static struct page * shm_nopage(struct vm_area_struct *, unsigned long, int);
@@ -75,12 +125,57 @@
 static void zmap_unuse(swp_entry_t entry, struct page *page);
 static void shmzero_open(struct vm_area_struct *shmd);
 static void shmzero_close(struct vm_area_struct *shmd);
+static struct page *shmzero_nopage(struct vm_area_struct * shmd, unsigned long address, int no_share);
 static int zero_id;
 static struct shmid_kernel zshmid_kernel;
+static struct dentry *zdent;
+
+#define SHM_FS_MAGIC 0x02011994
+
+static struct super_block * shm_sb;
+
+static DECLARE_FSTYPE(shm_fs_type, "shm", shm_read_super, 0);
+
+static struct super_operations shm_sops = {
+	read_inode:	shm_read_inode,
+	write_inode:	shm_write_inode,
+	delete_inode:	shm_delete,
+	put_super:	shm_put_super,
+	statfs:		shm_statfs,
+	remount_fs:	shm_remount_fs,
+};
+
+static struct file_operations shm_root_operations = {
+	readdir:	shm_readdir,
+};
+
+static struct inode_operations shm_root_inode_operations = {
+	create:		shm_create,
+	lookup:		shm_lookup,
+	unlink:		shm_unlink,
+};
+
+static struct file_operations shm_file_operations = {
+	mmap:	shm_mmap,
+};
+
+static struct inode_operations shm_inode_operations = {
+	setattr:	shm_setattr,
+};
+
+static struct vm_operations_struct shm_vm_ops = {
+	open:	shm_open,	/* callback for a new vm-area open */
+	close:	shm_close,	/* callback for when the vm-area is released */
+	nopage:	shm_nopage,
+	swapout:shm_swapout,
+};
 
 size_t shm_ctlmax = SHMMAX;
-int shm_ctlall = SHMALL;
-int shm_ctlmni = SHMMNI;
+
+/* These parameters should be part of the superblock */
+static int shm_ctlall;
+static int shm_ctlmni;
+static int shm_mode;
 
 static int shm_tot = 0; /* total number of shared memory pages */
 static int shm_rss = 0; /* number of shared memory pages that are in memory */
@@ -90,7 +185,7 @@
 	pagecache_lock
 	shm_lock()/shm_lockall()
 	kernel lock
-	shp->sem
+	inode->i_sem
 	sem_ids.sem
 	mmap_sem
 
@@ -104,18 +199,318 @@
 /* some statistics */
 static ulong swap_attempts = 0;
 static ulong swap_successes = 0;
+static ulong used_segs = 0;
 
 void __init shm_init (void)
 {
-	ipc_init_ids(&shm_ids, shm_ctlmni);
+	ipc_init_ids(&shm_ids, 1);
+
+	register_filesystem (&shm_fs_type);
 #ifdef CONFIG_PROC_FS
 	create_proc_read_entry("sysvipc/shm", 0, 0, sysvipc_shm_read_proc, NULL);
 #endif
-	zero_id = ipc_addid(&shm_ids, &zshmid_kernel.shm_perm, shm_ctlmni);
+	zero_id = ipc_addid(&shm_ids, &zshmid_kernel.shm_perm, 1);
 	shm_unlock(zero_id);
+	INIT_LIST_HEAD(&zshmid_kernel.zero_list);
+	zdent = d_alloc_root(get_empty_inode());
 	return;
 }
 
+static int shm_parse_options(char *options)
+{
+	int blocks = shm_ctlall;
+	int inodes = shm_ctlmni;
+	umode_t mode = shm_mode;
+	char *this_char, *value;
+
+	this_char = NULL;
+	if ( options )
+		this_char = strtok(options,",");
+	for ( ; this_char; this_char = strtok(NULL,",")) {
+		if ((value = strchr(this_char,'=')) != NULL)
+			*value++ = 0;
+		if (!strcmp(this_char,"nr_blocks")) {
+			if (!value || !*value)
+				return 1;
+			blocks = simple_strtoul(value,&value,0);
+			if (*value)
+				return 1;
+		}
+		else if (!strcmp(this_char,"nr_inodes")) {
+			if (!value || !*value)
+				return 1;
+			inodes = simple_strtoul(value,&value,0);
+			if (*value)
+				return 1;
+		}
+		else if (!strcmp(this_char,"mode")) {
+			if (!value || !*value)
+				return 1;
+			mode = simple_strtoul(value,&value,8);
+			if (*value)
+				return 1;
+		}
+		else
+			return 1;
+	}
+	shm_ctlmni = inodes;
+	shm_ctlall = blocks;
+	shm_mode   = mode;
+
+	return 0;
+}
+
+static struct super_block *shm_read_super(struct super_block *s,void *data, 
+					  int silent)
+{
+	struct inode * root_inode;
+
+	if (shm_sb) {
+		printk ("shm fs already mounted\n");
+		return NULL;
+	}
+
+	shm_ctlall = SHMALL;
+	shm_ctlmni = SHMMNI;
+	shm_mode   = S_IRWXUGO | S_ISVTX;
+	if (shm_parse_options (data)) {
+		printk ("shm fs invalid option\n");
+		goto out_unlock;
+	}
+
+	s->s_blocksize = PAGE_SIZE;
+	s->s_blocksize_bits = PAGE_SHIFT;
+	s->s_magic = SHM_FS_MAGIC;
+	s->s_op = &shm_sops;
+	root_inode = iget (s, SEQ_MULTIPLIER);
+	if (!root_inode)
+		goto out_no_root;
+	root_inode->i_op = &shm_root_inode_operations;
+	root_inode->i_sb = s;
+	root_inode->i_nlink = 2;
+	root_inode->i_mode = S_IFDIR | shm_mode;
+	s->s_root = d_alloc_root(root_inode);
+	if (!s->s_root)
+		goto out_no_root;
+	s->u.generic_sbp = (void*) shm_sb;
+	shm_sb = s;
+	return s;
+
+out_no_root:
+	printk("proc_read_super: get root inode failed\n");
+	iput(root_inode);
+out_unlock:
+	return NULL;
+}
+
+static int shm_remount_fs (struct super_block *sb, int *flags, char *data)
+{
+	if (shm_parse_options (data))
+		return -EINVAL;
+	return 0;
+}
+
+static void shm_put_super(struct super_block *sb)
+{
+	struct super_block **p = &shm_sb;
+	int i;
+	struct shmid_kernel *shp;
+
+	while (*p != sb) {
+		if (!*p)	/* should never happen */
+			return;
+		p = (struct super_block **)&(*p)->u.generic_sbp;
+	}
+	*p = (struct super_block *)(*p)->u.generic_sbp;
+	down(&shm_ids.sem);
+	for(i = 0; i <= shm_ids.max_id; i++) {
+		if (i == zero_id)
+			continue;
+		if (!(shp = shm_lock (i)))
+			continue;
+		if (shp->shm_nattch)
+			printk ("shm_nattch = %ld\n", shp->shm_nattch);
+		shp = shm_rmid(i);
+		shm_unlock(i);
+		killseg_core(shp, 1);
+	}
+	dput (sb->s_root);
+	up(&shm_ids.sem);
+}
+
+static int shm_statfs(struct super_block *sb, struct statfs *buf)
+{
+	buf->f_type = 0;
+	buf->f_bsize = PAGE_SIZE;
+	buf->f_blocks = shm_ctlall;
+	buf->f_bavail = buf->f_bfree = shm_ctlall - shm_tot;
+	buf->f_files = shm_ctlmni;
+	buf->f_ffree = shm_ctlmni - used_segs;
+	buf->f_namelen = SHM_NAME_LEN;
+	return 0;
+}
+
+static void shm_write_inode(struct inode * inode)
+{
+}
+
+static void shm_read_inode(struct inode * inode)
+{
+	int id;
+	struct shmid_kernel *shp;
+
+	id = inode->i_ino;
+	inode->i_op = NULL;
+	inode->i_mode = 0;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+
+	if (id < SEQ_MULTIPLIER) {
+		if (!(shp = shm_lock (id)))
+			return;
+		inode->i_mode = shp->shm_perm.mode | S_IFREG;
+		inode->i_uid  = shp->shm_perm.uid;
+		inode->i_gid  = shp->shm_perm.gid;
+		inode->i_size = shp->shm_segsz;
+		shm_unlock (id);
+		inode->i_op  = &shm_inode_operations;
+		inode->i_fop = &shm_file_operations;
+		return;
+	}
+	inode->i_op    = &shm_root_inode_operations;
+	inode->i_fop   = &shm_root_operations;
+	inode->i_sb    = shm_sb;
+	inode->i_nlink = 2;
+	inode->i_mode  = S_IFDIR | shm_mode;
+	inode->i_uid   = inode->i_gid = 0;
+
+}
+
+static int shm_create (struct inode *dir, struct dentry *dent, int mode)
+{
+	int id, err;
+	struct inode * inode;
+
+	down(&shm_ids.sem);
+	err = id = newseg (IPC_PRIVATE, dent->d_name.name, dent->d_name.len, mode, 0);
+	if (err < 0)
+		goto out;
+
+	err = -ENOMEM;
+	inode = iget (shm_sb, id % SEQ_MULTIPLIER);
+	if (!inode)
+		goto out;
+
+	err = 0;
+	down (&inode->i_sem);
+	inode->i_mode = mode | S_IFREG;
+	inode->i_op   = &shm_inode_operations;
+	d_instantiate(dent, inode);
+	up (&inode->i_sem);
+
+out:
+	up(&shm_ids.sem);
+	return err;
+}
+
+static int shm_readdir (struct file *filp, void *dirent, filldir_t filldir)
+{
+	struct inode * inode = filp->f_dentry->d_inode;
+	struct shmid_kernel *shp;
+	off_t nr;
+
+	nr = filp->f_pos;
+
+	switch(nr)
+	{
+	case 0:
+		if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
+			return 0;
+		filp->f_pos = ++nr;
+		/* fall through */
+	case 1:
+		if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
+			return 0;
+		filp->f_pos = ++nr;
+		/* fall through */
+	default:
+		down(&shm_ids.sem);
+		for (; nr-2 <= shm_ids.max_id; nr++ ) {
+			if (!(shp = shm_get (nr-2))) 
+				continue;
+			if (shp->shm_perm.mode & SHM_DEST)
+				continue;
+			if (filldir(dirent, shp->shm_name, shp->shm_namelen, nr, nr) < 0 )
+				break;;
+		}
+		filp->f_pos = nr;
+		up(&shm_ids.sem);
+		break;
+	}
+
+	UPDATE_ATIME(inode);
+	return 0;
+}
+
+static struct dentry *shm_lookup (struct inode *dir, struct dentry *dent)
+{
+	int i, err = 0;
+	struct shmid_kernel* shp;
+	struct inode *inode = NULL;
+
+	if (dent->d_name.len > SHM_NAME_LEN)
+		return ERR_PTR(-ENAMETOOLONG);
+
+	down(&shm_ids.sem);
+	for(i = 0; i <= shm_ids.max_id; i++) {
+		if (!(shp = shm_lock(i)))
+		    continue;
+		if (!(shp->shm_perm.mode & SHM_DEST) &&
+		    dent->d_name.len == shp->shm_namelen &&
+		    strncmp(dent->d_name.name, shp->shm_name, shp->shm_namelen) == 0)
+			goto found;
+		shm_unlock(i);
+	}
+
+	/*
+	 * prevent the reserved names as negative dentries. 
+	 * This also prevents object creation through the filesystem
+	 */
+	if (dent->d_name.len == SHM_FMT_LEN &&
+	    memcmp (SHM_FMT, dent->d_name.name, SHM_FMT_LEN - 8) == 0)
+		err = -EINVAL;	/* EINVAL to give IPC_RMID the right error */
+
+	goto out;
+
+found:
+	shm_unlock(i);
+	inode = iget(dir->i_sb, i);
+
+	if (!inode)
+		err = -EACCES;
+out:
+	if (err == 0)
+		d_add (dent, inode);
+	up (&shm_ids.sem);
+	return ERR_PTR(err);
+}
+
+static int shm_unlink (struct inode *dir, struct dentry *dent)
+{
+	struct inode * inode = dent->d_inode;
+	struct shmid_kernel *shp;
+
+	down (&shm_ids.sem);
+	if (!(shp = shm_lock (inode->i_ino)))
+		BUG();
+	shp->shm_perm.mode |= SHM_DEST;
+	shp->shm_perm.key = IPC_PRIVATE; /* Do not find it any more */
+	shm_unlock (inode->i_ino);
+	up (&shm_ids.sem);
+	inode->i_nlink -= 1;
+	d_delete (dent);
+	return 0;
+}
+
 #define SHM_ENTRY(shp, index) (shp)->shm_dir[(index)/PTRS_PER_PTE][(index)%PTRS_PER_PTE]
 
 static pte_t **shm_alloc(unsigned long pages)
@@ -124,9 +519,12 @@
 	unsigned short last = pages % PTRS_PER_PTE;
 	pte_t **ret, **ptr;
 
+	if (pages == 0)
+		return NULL;
+
 	ret = kmalloc ((dir+1) * sizeof(pte_t *), GFP_KERNEL);
 	if (!ret)
-		goto out;
+		goto nomem;
 
 	for (ptr = ret; ptr < ret+dir ; ptr++)
 	{
@@ -143,7 +541,6 @@
 			goto free;
 		memset (*ptr, 0, last*sizeof(pte_t));
 	}
-out:	
 	return ret;
 
 free:
@@ -152,48 +549,90 @@
 		free_page ((unsigned long)*ptr);
 
 	kfree (ret);
-	return NULL;
+nomem:
+	return ERR_PTR(-ENOMEM);
 }
 
-
 static void shm_free(pte_t** dir, unsigned long pages)
 {
 	pte_t **ptr = dir+pages/PTRS_PER_PTE;
 
+	if (!dir)
+		return;
+
 	/* first the last page */
 	if (pages%PTRS_PER_PTE)
 		kfree (*ptr);
 	/* now the whole pages */
 	while (--ptr >= dir)
-		free_page ((unsigned long)*ptr);
+		if (*ptr)
+			free_page ((unsigned long)*ptr);
 
 	/* Now the indirect block */
 	kfree (dir);
 }
 
-static int shm_revalidate(struct shmid_kernel* shp, int shmid, int pagecount, int flg)
+static 	int shm_setattr (struct dentry *dentry, struct iattr *attr)
 {
-	struct shmid_kernel* new;
-	new = shm_lock(shmid);
-	if(new==NULL) {
-		return -EIDRM;
-	}
-	if(new!=shp || shm_checkid(shp, shmid) || shp->shm_npages != pagecount) {
-		shm_unlock(shmid);
-		return -EIDRM;
-	}
-	if (ipcperms(&shp->shm_perm, flg)) {
-		shm_unlock(shmid);
-		return -EACCES;
+	int error;
+	struct inode *inode = dentry->d_inode;
+	struct shmid_kernel *shp;
+	unsigned long new_pages, old_pages;
+	pte_t **new_dir, **old_dir;
+
+	if ((error = inode_change_ok(inode, attr)))
+		return error;
+	if (!(attr->ia_valid & ATTR_SIZE))
+		goto set_attr;
+	if (attr->ia_size > shm_ctlmax)
+		return -EFBIG;
+
+	/* We set old_pages and old_dir for easier cleanup */
+	old_pages = new_pages = (attr->ia_size  + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	if (shm_tot + new_pages >= shm_ctlall)
+		return -ENOSPC;
+	if (IS_ERR(old_dir = new_dir = shm_alloc(new_pages)))
+		return PTR_ERR(new_dir);
+
+	if (!(shp = shm_lock(inode->i_ino)))
+		BUG();
+	if (shp->shm_segsz == attr->ia_size)
+		goto out;
+	old_dir = shp->shm_dir;
+	old_pages = shp->shm_npages;
+	if (old_dir){
+		pte_t *swap;
+		int i,j;
+		i = old_pages < new_pages ? old_pages : new_pages;
+		j = i % PTRS_PER_PTE;
+		i /= PTRS_PER_PTE;
+		if (j)
+			memcpy (new_dir[i], old_dir[i], j * sizeof (pte_t));
+		while (i--) {
+			swap = new_dir[i];
+			new_dir[i] = old_dir[i];
+			old_dir[i] = swap;
+		}
 	}
+	shp->shm_dir = new_dir;
+	shp->shm_npages = new_pages;
+	shp->shm_segsz = attr->ia_size;
+out:
+	shm_unlock(inode->i_ino);
+	shm_lockall();
+	shm_tot += new_pages - old_pages;
+	shm_unlockall();
+	shm_free (old_dir, old_pages);
+set_attr:
+	inode_setattr(inode, attr);
 	return 0;
 }
 
-static inline struct shmid_kernel *newseg_alloc(int numpages)
+static inline struct shmid_kernel *newseg_alloc(int numpages, size_t namelen)
 {
 	struct shmid_kernel *shp;
 
-	shp = (struct shmid_kernel *) kmalloc (sizeof (*shp), GFP_KERNEL);
+	shp = (struct shmid_kernel *) kmalloc (sizeof (*shp) + namelen, GFP_KERNEL);
 	if (!shp)
 		return 0;
 
@@ -203,29 +642,29 @@
 		return 0;
 	}
 	shp->shm_npages = numpages;
-	shp->attaches = NULL;
 	shp->shm_nattch = 0;
-	init_MUTEX(&shp->sem);
+	shp->shm_namelen = namelen;
 	return(shp);
 }
 
-static int newseg (key_t key, int shmflg, size_t size)
+static int newseg (key_t key, const char *name, int namelen,
+		   int shmflg, size_t size)
 {
 	struct shmid_kernel *shp;
 	int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT;
 	int id;
 
-	if (size < SHMMIN)
-		return -EINVAL;
+	if (namelen > SHM_NAME_LEN)
+		return -ENAMETOOLONG;
 
 	if (size > shm_ctlmax)
 		return -EINVAL;
 	if (shm_tot + numpages >= shm_ctlall)
 		return -ENOSPC;
 
-	if (!(shp = newseg_alloc(numpages)))
+	if (!(shp = newseg_alloc(numpages, namelen ? namelen : SHM_FMT_LEN + 1)))
 		return -ENOMEM;
-	id = ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni);
+	id = ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni+1);
 	if(id == -1) {
 		shm_free(shp->shm_dir,numpages);
 		kfree(shp);
@@ -234,16 +673,23 @@
 	shp->shm_perm.key = key;
 	shp->shm_perm.mode = (shmflg & S_IRWXUGO);
 	shp->shm_segsz = size;
-	shp->shm_cpid = current->pid;
-	shp->shm_lpid = 0;
-	shp->shm_atime = shp->shm_dtime = 0;
-	shp->shm_ctime = CURRENT_TIME;
+	shp->shm_cprid = current->pid;
+	shp->shm_lprid = 0;
+	shp->shm_atim = shp->shm_dtim = 0;
+	shp->shm_ctim = CURRENT_TIME;
 	shp->id = shm_buildid(id,shp->shm_perm.seq);
+	if (namelen != 0) {
+		shp->shm_namelen = namelen;
+		memcpy (shp->shm_name, name, namelen);		  
+	} else {
+		shp->shm_namelen = sprintf (shp->shm_name, SHM_FMT, shp->id);
+	}
 
 	shm_tot += numpages;
+	used_segs++;
 	shm_unlock(id);
-
-	return shm_buildid(id,shp->shm_perm.seq);
+	
+	return shp->id;
 }
 
 asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
@@ -251,21 +697,31 @@
 	struct shmid_kernel *shp;
 	int err, id = 0;
 
+	if (!shm_sb) {
+		printk ("shmget: shm filesystem not mounted\n");
+		return -EINVAL;
+	}
+
+	if (size < SHMMIN)
+		return -EINVAL;
+
 	down(&shm_ids.sem);
 	if (key == IPC_PRIVATE) {
-		err = newseg(key, shmflg, size);
+		err = newseg(key, NULL, 0, shmflg, size);
 	} else if ((id = ipc_findkey(&shm_ids,key)) == -1) {
 		if (!(shmflg & IPC_CREAT))
 			err = -ENOENT;
 		else
-			err = newseg(key, shmflg, size);
+			err = newseg(key, NULL, 0, shmflg, size);
 	} else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) {
 		err = -EEXIST;
 	} else {
 		shp = shm_lock(id);
 		if(shp==NULL)
 			BUG();
-		if (ipcperms(&shp->shm_perm, shmflg))
+		if (shp->shm_segsz < size)
+			err = -EINVAL;
+		else if (ipcperms(&shp->shm_perm, shmflg))
 			err = -EACCES;
 		else
 			err = shm_buildid(id, shp->shm_perm.seq);
@@ -300,40 +756,26 @@
 		shm_rss -= rss;
 		shm_swp -= swp;
 		shm_tot -= numpages;
+		used_segs--;
 		shm_unlockall();
 	}
 }
 
-/*
- * Only called after testing nattch and SHM_DEST.
- * Here pages, pgtable and shmid_kernel are freed.
- */
-static void killseg (int shmid)
+static void shm_delete (struct inode *ino)
 {
+	int shmid = ino->i_ino;
 	struct shmid_kernel *shp;
 
 	down(&shm_ids.sem);
 	shp = shm_lock(shmid);
 	if(shp==NULL) {
-out_up:
-		up(&shm_ids.sem);
-		return;
-	}
-	if(shm_checkid(shp,shmid) || shp->shm_nattch > 0 ||
-	    !(shp->shm_perm.mode & SHM_DEST)) {
-		shm_unlock(shmid);
-		goto out_up;
+		BUG();
 	}
 	shp = shm_rmid(shmid);
-	if(shp==NULL)
-		BUG();
-	if (!shp->shm_dir)
-		BUG();
 	shm_unlock(shmid);
 	up(&shm_ids.sem);
 	killseg_core(shp, 1);
-
-	return;
+	clear_inode(ino);
 }
 
 static inline unsigned long copy_shmid_to_user(void *buf, struct shmid64_ds *in, int version)
@@ -427,12 +869,29 @@
 	}
 }
 
+char * shm_getname(int id)
+{
+	char *result;
+
+	result = __getname ();
+	if (IS_ERR(result))
+		return result;
+
+	sprintf (result, "%s/" SHM_FMT, shm_path, id); 
+	return result;
+}
+
 asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
 {
 	struct shm_setbuf setbuf;
 	struct shmid_kernel *shp;
 	int err, version;
 
+	if (!shm_sb) {
+		printk ("shmctl: shm filesystem not mounted\n");
+		return -EINVAL;
+	}
+
 	if (cmd < 0 || shmid < 0)
 		return -EINVAL;
 
@@ -481,14 +940,12 @@
 	{
 		struct shmid64_ds tbuf;
 		int result;
+		if ((shmid % SEQ_MULTIPLIER) == zero_id)
+			return -EINVAL;
 		memset(&tbuf, 0, sizeof(tbuf));
 		shp = shm_lock(shmid);
 		if(shp==NULL)
 			return -EINVAL;
-		if (shp == &zshmid_kernel) {
-			shm_unlock(shmid);
-			return -EINVAL;
-		}
 		if(cmd==SHM_STAT) {
 			err = -EINVAL;
 			if (shmid > shm_ids.max_id)
@@ -505,11 +962,11 @@
 			goto out_unlock;
 		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_atime	= shp->shm_atim;
+		tbuf.shm_dtime	= shp->shm_dtim;
+		tbuf.shm_ctime	= shp->shm_ctim;
+		tbuf.shm_cpid	= shp->shm_cprid;
+		tbuf.shm_lpid	= shp->shm_lprid;
 		tbuf.shm_nattch	= shp->shm_nattch;
 		shm_unlock(shmid);
 		if(copy_shmid_to_user (buf, &tbuf, version))
@@ -523,16 +980,14 @@
 /* Should the pages be faulted in here or leave it to user? */
 /* need to determine interaction with current->swappable */
 		struct kern_ipc_perm *ipcp;
+		if ((shmid % SEQ_MULTIPLIER)== zero_id)
+			return -EINVAL;
 		if (!capable(CAP_IPC_LOCK))
 			return -EPERM;
 
 		shp = shm_lock(shmid);
 		if(shp==NULL)
 			return -EINVAL;
-		if (shp == &zshmid_kernel) {
-			shm_unlock(shmid);
-			return -EINVAL;
-		}
 		err=-EIDRM;
 		if(shm_checkid(shp,shmid))
 			goto out_unlock;
@@ -552,50 +1007,56 @@
 		return err;
 	}
 	case IPC_RMID:
-	case IPC_SET:
-		break;
-	default:
-		return -EINVAL;
+	{
+		char *name;
+		if ((shmid % SEQ_MULTIPLIER)== zero_id)
+			return -EINVAL;
+		name = shm_getname(shmid);
+		if (IS_ERR(name))
+			return PTR_ERR(name);
+		lock_kernel();
+		err = do_unlink (name);
+		unlock_kernel();
+		putname (name);
+		if (err == -ENOENT)
+			err = -EINVAL;
+		return err;
 	}
 
-	if (cmd == IPC_SET) {
+	case IPC_SET:
+	{
+		if ((shmid % SEQ_MULTIPLIER)== zero_id)
+			return -EINVAL;
+
 		if(copy_shmid_from_user (&setbuf, buf, version))
 			return -EFAULT;
-	}
-	down(&shm_ids.sem);
-	shp = shm_lock(shmid);
-	err=-EINVAL;
-	if(shp==NULL)
-		goto out_up;
-	if (shp == &zshmid_kernel)
-		goto out_unlock_up;
-	err=-EIDRM;
-	if(shm_checkid(shp,shmid))
-		goto out_unlock_up;
-	err=-EPERM;
-	if (current->euid != shp->shm_perm.uid &&
-	    current->euid != shp->shm_perm.cuid && 
-	    !capable(CAP_SYS_ADMIN)) {
-		goto out_unlock_up;
-	}
+		down(&shm_ids.sem);
+		shp = shm_lock(shmid);
+		err=-EINVAL;
+		if(shp==NULL)
+			goto out_up;
+		err=-EIDRM;
+		if(shm_checkid(shp,shmid))
+			goto out_unlock_up;
+		err=-EPERM;
+		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->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->shm_ctime = CURRENT_TIME;
+		shp->shm_ctim = CURRENT_TIME;
 		break;
-	case IPC_RMID:
-		shp->shm_perm.mode |= SHM_DEST;
-		if (shp->shm_nattch <= 0) {
-			shm_unlock(shmid);
-			up(&shm_ids.sem);
-			killseg (shmid);
-			return 0;
-		}
 	}
+
+	default:
+		return -EINVAL;
+	}
+
 	err = 0;
 out_unlock_up:
 	shm_unlock(shmid);
@@ -607,65 +1068,24 @@
 	return err;
 }
 
-/*
- * The per process internal structure for managing segments is
- * `struct vm_area_struct'.
- * A shmat will add to and shmdt will remove from the list.
- * shmd->vm_mm		the attacher
- * shmd->vm_start	virt addr of attach, multiple of SHMLBA
- * shmd->vm_end		multiple of SHMLBA
- * shmd->vm_next	next attach for task
- * shmd->vm_next_share	next attach for segment
- * shmd->vm_pgoff	offset into segment (in pages)
- * shmd->vm_private_data		signature for this attach
- */
-
-static struct vm_operations_struct shm_vm_ops = {
-	open:		shm_open,	/* open - callback for a new vm-area open */
-	close:		shm_close,	/* close - callback for when the vm-area is released */
-	nopage:		shm_nopage,
-	swapout:	shm_swapout,
-};
-
-/* Insert shmd into the list shp->attaches */
-static inline void insert_attach (struct shmid_kernel * shp, struct vm_area_struct * shmd)
-{
-	if((shmd->vm_next_share = shp->attaches) != NULL)
-		shp->attaches->vm_pprev_share = &shmd->vm_next_share;
-	shp->attaches = shmd;
-	shmd->vm_pprev_share = &shp->attaches;
-}
+static inline void shm_inc (int id) {
+	struct shmid_kernel *shp;
 
-/* Remove shmd from list shp->attaches */
-static inline void remove_attach (struct shmid_kernel * shp, struct vm_area_struct * shmd)
-{
-	if(shmd->vm_next_share)
-		shmd->vm_next_share->vm_pprev_share = shmd->vm_pprev_share;
-	*shmd->vm_pprev_share = shmd->vm_next_share;
+	if(!(shp = shm_lock(id)))
+		BUG();
+	shp->shm_atim = CURRENT_TIME;
+	shp->shm_lprid = current->pid;
+	shp->shm_nattch++;
+	shm_unlock(id);
 }
 
-/*
- * ensure page tables exist
- * mark page table entries with shm_sgn.
- */
-static int shm_map (struct vm_area_struct *shmd)
+static int shm_mmap(struct file * file, struct vm_area_struct * vma)
 {
-	unsigned long tmp;
-
-	/* clear old mappings */
-	do_munmap(shmd->vm_start, shmd->vm_end - shmd->vm_start);
-
-	/* add new mapping */
-	tmp = shmd->vm_end - shmd->vm_start;
-	if((current->mm->total_vm << PAGE_SHIFT) + tmp
-	   > (unsigned long) current->rlim[RLIMIT_AS].rlim_cur)
-		return -ENOMEM;
-	current->mm->total_vm += tmp >> PAGE_SHIFT;
-	vmlist_modify_lock(current->mm);
-	insert_vm_struct(current->mm, shmd);
-	merge_segments(current->mm, shmd->vm_start, shmd->vm_end);
-	vmlist_modify_unlock(current->mm);
-
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL; /* we cannot do private mappings */
+	UPDATE_ATIME(file->f_dentry->d_inode);
+	vma->vm_ops = &shm_vm_ops;
+	shm_inc(file->f_dentry->d_inode->i_ino);
 	return 0;
 }
 
@@ -674,137 +1094,57 @@
  */
 asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
 {
-	struct shmid_kernel *shp;
-	struct vm_area_struct *shmd;
-	int err;
 	unsigned long addr;
-	unsigned long len;
-	short flg = shmflg & SHM_RDONLY ? S_IRUGO : S_IRUGO|S_IWUGO;
-
+	struct file * file;
+	int    err;
+	int    flags;
+	char   *name;
 
-	if (shmid < 0)
+	if (!shm_sb || (shmid % SEQ_MULTIPLIER) == zero_id)
 		return -EINVAL;
 
-	down(&current->mm->mmap_sem);
-	err = -EINVAL;
-	shp = shm_lock(shmid);
-	if (!shp)
-		goto out_up;
-	if (shp == &zshmid_kernel)
-		goto out_unlock_up;
-
-	err = -EACCES;
-	if (ipcperms(&shp->shm_perm, flg))
-		goto out_unlock_up;
-
-	err = -EIDRM;
-	if (shm_checkid(shp,shmid))
-		goto out_unlock_up;
-
-	if (!(addr = (ulong) shmaddr)) {
-		if (shmflg & SHM_REMAP)
-			goto out_unlock_up;
-		err = -ENOMEM;
-		addr = 0;
-	again:
-		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);
-			goto again;
+	if ((addr = (ulong)shmaddr))
+	{
+		if(addr & (SHMLBA-1)) {
+			if (shmflg & SHM_RND)
+				addr &= ~(SHMLBA-1);	   /* round down */
+			else
+				return -EINVAL;
 		}
-	} else if (addr & (SHMLBA-1)) {
-		err=-EINVAL;
-		if (shmflg & SHM_RND)
-			addr &= ~(SHMLBA-1);       /* round down */
-		else
-			goto out_unlock_up;
-	}
-	/*
-	 * Check if addr exceeds TASK_SIZE (from do_mmap)
-	 */
-	len = PAGE_SIZE*shp->shm_npages;
-	err = -EINVAL;
-	if (addr >= TASK_SIZE || len > TASK_SIZE  || addr > TASK_SIZE - len)
-		goto out_unlock_up;
-	/*
-	 * If shm segment goes below stack, make sure there is some
-	 * space left for the stack to grow (presently 4 pages).
-	 */
-	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->shm_segsz))
-		goto out_unlock_up;
-
-	shm_unlock(shmid);
-	err = -ENOMEM;
-	shmd = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
-	err = shm_revalidate(shp, shmid, len/PAGE_SIZE,flg);
-	if(err)	{
-		kmem_cache_free(vm_area_cachep, shmd);
-		goto out_up;
-	}
-
-	shmd->vm_private_data = shp;
-	shmd->vm_start = addr;
-	shmd->vm_end = addr + shp->shm_npages * PAGE_SIZE;
-	shmd->vm_mm = current->mm;
-	shmd->vm_page_prot = (shmflg & SHM_RDONLY) ? PAGE_READONLY : PAGE_SHARED;
-	shmd->vm_flags = VM_SHM | VM_MAYSHARE | VM_SHARED
-			 | VM_MAYREAD | VM_MAYEXEC | VM_READ | VM_EXEC
-			 | ((shmflg & SHM_RDONLY) ? 0 : VM_MAYWRITE | VM_WRITE);
-	shmd->vm_file = NULL;
-	shmd->vm_pgoff = 0;
-	shmd->vm_ops = &shm_vm_ops;
-
-	shp->shm_nattch++;	    /* prevent destruction */
-	shm_unlock(shp->id);
-	err = shm_map (shmd);
-	shm_lock(shmid); /* cannot fail */
-	if (err)
-		goto failed_shm_map;
-
-	insert_attach(shp,shmd);  /* insert shmd into shp->attaches */
-
-	shp->shm_lpid = current->pid;
-	shp->shm_atime = CURRENT_TIME;
+		flags = MAP_SHARED | MAP_FIXED;
+	} else
+		flags = MAP_SHARED;
 
-	*raddr = addr;
-	err = 0;
-out_unlock_up:
-	shm_unlock(shmid);
-out_up:
-	up(&current->mm->mmap_sem);
+	name = shm_getname(shmid);
+	if (IS_ERR (name))
+		return PTR_ERR (name);
+
+	file = filp_open (name, O_RDWR, 0);
+	putname (name);
+	if (IS_ERR (file))
+		goto bad_file;
+	lock_kernel();
+	*raddr = do_mmap (file, addr, file->f_dentry->d_inode->i_size,
+			  (shmflg & SHM_RDONLY ? PROT_READ :
+			   PROT_READ | PROT_WRITE), flags, 0);
+	unlock_kernel();
+	if (IS_ERR(*raddr))
+		err = PTR_ERR(*raddr);
+	else
+		err = 0;
+	fput (file);
 	return err;
 
-failed_shm_map:
-	{
-		int delete = 0;
-		if (--shp->shm_nattch <= 0 && shp->shm_perm.mode & SHM_DEST)
-			delete = 1;
-		shm_unlock(shmid);
-		up(&current->mm->mmap_sem);
-		kmem_cache_free(vm_area_cachep, shmd);
-		if(delete)
-			killseg(shmid);
-		return err;
-	}
+bad_file:
+	if ((err = PTR_ERR(file)) == -ENOENT)
+		return -EINVAL;
+	return err;
 }
 
 /* This is called by fork, once for every shm attach. */
 static void shm_open (struct vm_area_struct *shmd)
 {
-	struct shmid_kernel *shp;
-
-	shp = (struct shmid_kernel *) shmd->vm_private_data;
-	if(shp != shm_lock(shp->id))
-		BUG();
-	insert_attach(shp,shmd);  /* insert shmd into shp->attaches */
-	shp->shm_nattch++;
-	shp->shm_atime = CURRENT_TIME;
-	shp->shm_lpid = current->pid;
-	shm_unlock(shp->id);
+	shm_inc (shmd->vm_file->f_dentry->d_inode->i_ino);
 }
 
 /*
@@ -815,22 +1155,16 @@
  */
 static void shm_close (struct vm_area_struct *shmd)
 {
+	int id = shmd->vm_file->f_dentry->d_inode->i_ino;
 	struct shmid_kernel *shp;
-	int id;
 
 	/* remove from the list of attaches of the shm segment */
-	shp = (struct shmid_kernel *) shmd->vm_private_data;
-	if(shp != shm_lock(shp->id))
+	if(!(shp = shm_lock(id)))
 		BUG();
-	remove_attach(shp,shmd);  /* remove from shp->attaches */
-  	shp->shm_lpid = current->pid;
-	shp->shm_dtime = CURRENT_TIME;
-	id=-1;
-	if (--shp->shm_nattch <= 0 && shp->shm_perm.mode & SHM_DEST)
-		id=shp->id;
-	shm_unlock(shp->id);
-	if(id!=-1)
-		killseg(id);
+	shp->shm_lprid = current->pid;
+	shp->shm_dtim = CURRENT_TIME;
+	shp->shm_nattch--;
+	shm_unlock(id);
 }
 
 /*
@@ -868,31 +1202,13 @@
 /*
  * page not present ... go through shm_dir
  */
-static struct page * shm_nopage(struct vm_area_struct * shmd, unsigned long address, int no_share)
+static struct page * shm_nopage_core(struct shmid_kernel *shp, unsigned int idx, int *swp, int *rss)
 {
 	pte_t pte;
-	struct shmid_kernel *shp;
-	unsigned int idx;
 	struct page * page;
-	int is_shmzero;
 
-	shp = (struct shmid_kernel *) shmd->vm_private_data;
-	idx = (address - shmd->vm_start) >> PAGE_SHIFT;
-	idx += shmd->vm_pgoff;
-	is_shmzero = (shp->id == zero_id);
-
-	/*
-	 * A shared mapping past the last page of the file is an error
-	 * and results in a SIGBUS, so logically a shared mapping past 
-	 * the end of a shared memory segment should result in SIGBUS
-	 * as well.
-	 */
-	if (idx >= shp->shm_npages) { 
-		return NULL;
-	}
-	down(&shp->sem);
-	if ((shp != shm_lock(shp->id)) && (is_shmzero == 0))
-		BUG();
+	if (idx >= shp->shm_npages)
+		goto sigbus;
 
 	pte = SHM_ENTRY(shp,idx);
 	if (!pte_present(pte)) {
@@ -905,7 +1221,7 @@
 			if (!page)
 				goto oom;
 			clear_highpage(page);
-			if ((shp != shm_lock(shp->id)) && (is_shmzero == 0))
+			if ((shp != shm_lock(shp->id)) && (shp->id != zero_id))
 				BUG();
 		} else {
 			swp_entry_t entry = pte_to_swp_entry(pte);
@@ -923,11 +1239,11 @@
 			delete_from_swap_cache(page);
 			page = replace_with_highmem(page);
 			swap_free(entry);
-			if ((shp != shm_lock(shp->id)) && (is_shmzero == 0))
+			if ((shp != shm_lock(shp->id)) && (shp->id != zero_id))
 				BUG();
-			if (is_shmzero == 0) shm_swp--;
+			(*swp)--;
 		}
-		if (is_shmzero == 0) shm_rss++;
+		(*rss)++;
 		pte = pte_mkdirty(mk_pte(page, PAGE_SHARED));
 		SHM_ENTRY(shp, idx) = pte;
 	} else
@@ -935,14 +1251,32 @@
 
 	/* pte_val(pte) == SHM_ENTRY (shp, idx) */
 	get_page(pte_page(pte));
-	shm_unlock(shp->id);
-	up(&shp->sem);
 	current->min_flt++;
 	return pte_page(pte);
 
 oom:
-	up(&shp->sem);
 	return NOPAGE_OOM;
+sigbus:
+	return NOPAGE_SIGBUS;
+}
+
+static struct page * shm_nopage(struct vm_area_struct * shmd, unsigned long address, int no_share)
+{
+	struct page * page;
+	struct shmid_kernel *shp;
+	unsigned int idx;
+	struct inode * inode = shmd->vm_file->f_dentry->d_inode;
+
+	idx = (address - shmd->vm_start) >> PAGE_SHIFT;
+	idx += shmd->vm_pgoff;
+
+	down(&inode->i_sem);
+	if(!(shp = shm_lock(inode->i_ino)))
+		BUG();
+	page = shm_nopage_core(shp, idx, &shm_swp, &shm_rss);
+	shm_unlock(inode->i_ino);
+	up(&inode->i_sem);
+	return(page);
 }
 
 #define OKAY	0
@@ -1127,38 +1461,40 @@
 	int i, len = 0;
 
 	down(&shm_ids.sem);
-	len += sprintf(buffer, "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime\n");
+	len += sprintf(buffer, "       key      shmid perms       size  cpid  lpid nattch   uid   gid  cuid  cgid      atime      dtime      ctime name\n");
 
-    	for(i = 0; i <= shm_ids.max_id; i++) {
-		struct shmid_kernel* shp = shm_lock(i);
-		if (shp == &zshmid_kernel) {
-			shm_unlock(i);
+	for(i = 0; i <= shm_ids.max_id; i++) {
+		struct shmid_kernel* shp;
+
+		if (i == zero_id)
 			continue;
-		}
+		shp = shm_lock(i);
 		if(shp!=NULL) {
-#define SMALL_STRING "%10d %10d  %4o %10u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
-#define BIG_STRING   "%10d %10d  %4o %21u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu\n"
+#define SMALL_STRING "%10d %10d  %4o %10u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu %.*s\n"
+#define BIG_STRING   "%10d %10d  %4o %21u %5u %5u  %5d %5u %5u %5u %5u %10lu %10lu %10lu %.*s\n"
 			char *format;
 
 			if (sizeof(size_t) <= sizeof(int))
 				format = SMALL_STRING;
 			else
 				format = BIG_STRING;
-	    		len += sprintf(buffer + len, format,
+			len += sprintf(buffer + len, format,
 				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_cprid,
+				shp->shm_lprid,
 				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);
+				shp->shm_atim,
+				shp->shm_dtim,
+				shp->shm_ctim,
+				shp->shm_namelen,
+				shp->shm_name);
 			shm_unlock(i);
 
 			pos += len;
@@ -1183,31 +1519,84 @@
 }
 #endif
 
-static struct shmid_kernel *zmap_list = 0;
+#define VMA_TO_SHP(vma)		((vma)->vm_file->private_data)
+
 static spinlock_t zmap_list_lock = SPIN_LOCK_UNLOCKED;
 static unsigned long zswap_idx = 0; /* next to swap */
-static struct shmid_kernel *zswap_shp = 0;
+static struct shmid_kernel *zswap_shp = &zshmid_kernel;
+static int zshm_rss;
 
 static struct vm_operations_struct shmzero_vm_ops = {
 	open:		shmzero_open,
 	close:		shmzero_close,
-	nopage:		shm_nopage,
+	nopage:		shmzero_nopage,
 	swapout:	shm_swapout,
 };
 
+/*
+ * In this implementation, the "unuse" and "swapout" interfaces are
+ * interlocked out via the kernel_lock, as well as shm_lock(zero_id).
+ * "unuse" and "nopage/swapin", as well as "swapout" and "nopage/swapin"
+ * interlock via shm_lock(zero_id). All these interlocks can be based
+ * on a per mapping lock instead of being a global lock.
+ */
+/*
+ * Reference (existance) counting on the file/dentry/inode is done
+ * by generic vm_file code. The zero code does not hold any reference 
+ * on the pseudo-file. This is possible because the open/close calls
+ * are bracketed by the file count update calls.
+ */
+static struct file *file_setup(struct file *fzero, struct shmid_kernel *shp)
+{
+	struct file *filp;
+	struct inode *inp;
+
+	if ((filp = get_empty_filp()) == 0)
+		return(filp);
+	if ((inp = get_empty_inode()) == 0) {
+		put_filp(filp);
+		return(0);
+	}
+	if ((filp->f_dentry = d_alloc(zdent, &(const struct qstr) { "dev/zero", 
+				8, 0 })) == 0) {
+		iput(inp);
+		put_filp(filp);
+		return(0);
+	}
+	d_instantiate(filp->f_dentry, inp);
+
+	/*
+	 * Copy over /dev/zero dev/ino for benefit of procfs. Use
+	 * ino to indicate seperate mappings.
+	 */
+	filp->f_dentry->d_inode->i_dev = fzero->f_dentry->d_inode->i_dev;
+	filp->f_dentry->d_inode->i_ino = (unsigned long)shp;
+	fput(fzero);	/* release /dev/zero file */
+	return(filp);
+}
+
 int map_zero_setup(struct vm_area_struct *vma)
 {
+	extern int vm_enough_memory(long pages);
 	struct shmid_kernel *shp;
+	struct file *filp;
 
-	if (!(shp = newseg_alloc((vma->vm_end - vma->vm_start) / PAGE_SIZE)))
+	if (!vm_enough_memory((vma->vm_end - vma->vm_start) >> PAGE_SHIFT))
+		return -ENOMEM;
+	if (!(shp = newseg_alloc((vma->vm_end - vma->vm_start) / PAGE_SIZE, 0)))
+		return -ENOMEM;
+	if ((filp = file_setup(vma->vm_file, shp)) == 0) {
+		killseg_core(shp, 0);
 		return -ENOMEM;
-	shp->id = zero_id;	/* hack for shm_lock et al */
-	vma->vm_private_data = shp;
+	}
+	vma->vm_file = filp;
+	VMA_TO_SHP(vma) = (void *)shp;
+	shp->id = zero_id;
+	init_MUTEX(&shp->zsem);
 	vma->vm_ops = &shmzero_vm_ops;
 	shmzero_open(vma);
 	spin_lock(&zmap_list_lock);
-	shp->attaches = (struct vm_area_struct *)zmap_list;
-	zmap_list = shp;
+	list_add(&shp->zero_list, &zshmid_kernel.zero_list);
 	spin_unlock(&zmap_list_lock);
 	return 0;
 }
@@ -1216,53 +1605,66 @@
 {
 	struct shmid_kernel *shp;
 
-	shp = (struct shmid_kernel *) shmd->vm_private_data;
-	down(&shp->sem);
+	shp = VMA_TO_SHP(shmd);
+	down(&shp->zsem);
 	shp->shm_nattch++;
-	up(&shp->sem);
+	up(&shp->zsem);
 }
 
 static void shmzero_close(struct vm_area_struct *shmd)
 {
 	int done = 0;
-	struct shmid_kernel *shp, *prev, *cur;
+	struct shmid_kernel *shp;
 
-	shp = (struct shmid_kernel *) shmd->vm_private_data;
-	down(&shp->sem);
+	shp = VMA_TO_SHP(shmd);
+	down(&shp->zsem);
 	if (--shp->shm_nattch == 0)
 		done = 1;
-	up(&shp->sem);
+	up(&shp->zsem);
 	if (done) {
 		spin_lock(&zmap_list_lock);
 		if (shp == zswap_shp)
-			zswap_shp = (struct shmid_kernel *)(shp->attaches);
-		if (shp == zmap_list)
-			zmap_list = (struct shmid_kernel *)(shp->attaches);
-		else {
-			prev = zmap_list;
-			cur = (struct shmid_kernel *)(prev->attaches);
-			while (cur != shp) {
-				prev = cur;
-				cur = (struct shmid_kernel *)(prev->attaches);
-			}
-			prev->attaches = (struct vm_area_struct *)(shp->attaches);
-		}
+			zswap_shp = list_entry(zswap_shp->zero_list.next, 
+						struct shmid_kernel, zero_list);
+		list_del(&shp->zero_list);
 		spin_unlock(&zmap_list_lock);
 		killseg_core(shp, 0);
 	}
 }
 
+static struct page * shmzero_nopage(struct vm_area_struct * shmd, unsigned long address, int no_share)
+{
+	struct page *page;
+	struct shmid_kernel *shp;
+	unsigned int idx;
+	int dummy;
+
+	idx = (address - shmd->vm_start) >> PAGE_SHIFT;
+	idx += shmd->vm_pgoff;
+
+	shp = VMA_TO_SHP(shmd);
+	down(&shp->zsem);
+	shm_lock(zero_id);
+	page = shm_nopage_core(shp, idx, &dummy, &zshm_rss);
+	shm_unlock(zero_id);
+	up(&shp->zsem);
+	return(page);
+}
+
 static void zmap_unuse(swp_entry_t entry, struct page *page)
 {
 	struct shmid_kernel *shp;
 
 	spin_lock(&zmap_list_lock);
-	shp = zmap_list;
-	while (shp) {
+	shm_lock(zero_id);
+	for (shp = list_entry(zshmid_kernel.zero_list.next, struct shmid_kernel, 
+			zero_list); shp != &zshmid_kernel;
+			shp = list_entry(shp->zero_list.next, struct shmid_kernel,
+								zero_list)) {
 		if (shm_unuse_core(shp, entry, page))
 			break;
-		shp = (struct shmid_kernel *)shp->attaches;
 	}
+	shm_unlock(zero_id);
 	spin_unlock(&zmap_list_lock);
 }
 
@@ -1275,7 +1677,7 @@
 	int counter;
 	struct page * page_map;
 
-	counter = 10;	/* maybe we should use zshm_rss */
+	counter = zshm_rss >> prio;
 	if (!counter)
 		return;
 next:
@@ -1283,25 +1685,30 @@
 		return;
 
 	spin_lock(&zmap_list_lock);
-	if (zmap_list == 0)
+	shm_lock(zero_id);
+	if (zshmid_kernel.zero_list.next == 0)
 		goto failed;
 next_id:
-	if ((shp = zswap_shp) == 0) {
+	if (zswap_shp == &zshmid_kernel) {
 		if (loop) {
 failed:
+			shm_unlock(zero_id);
 			spin_unlock(&zmap_list_lock);
 			__swap_free(swap_entry, 2);
 			return;
 		}
-		zswap_shp = shp = zmap_list;
+		zswap_shp = list_entry(zshmid_kernel.zero_list.next, 
+					struct shmid_kernel, zero_list);
 		zswap_idx = 0;
 		loop = 1;
 	}
+	shp = zswap_shp;
 
 check_table:
 	idx = zswap_idx++;
 	if (idx >= shp->shm_npages) {
-		zswap_shp = (struct shmid_kernel *)(zswap_shp->attaches);
+		zswap_shp = list_entry(zswap_shp->zero_list.next, 
+					struct shmid_kernel, zero_list);
 		zswap_idx = 0;
 		goto next_id;
 	}
@@ -1310,6 +1717,7 @@
 		case RETRY: goto check_table;
 		case FAILED: goto failed;
 	}
+	shm_unlock(zero_id);
 	spin_unlock(&zmap_list_lock);
 
 	shm_swap_postop(page_map);
@@ -1317,3 +1725,4 @@
 		goto next;
 	return;
 }
+
diff -u --recursive --new-file v2.3.50/linux/ipc/util.c linux/ipc/util.c
--- v2.3.50/linux/ipc/util.c	Sat Feb 26 22:32:07 2000
+++ linux/ipc/util.c	Wed Mar  8 09:16:24 2000
@@ -40,9 +40,6 @@
 	if(size > IPCMNI)
 		size = IPCMNI;
 	ids->size = size;
-	if(size == 0)
-		return;
-
 	ids->in_use = 0;
 	ids->max_id = -1;
 	ids->seq = 0;
diff -u --recursive --new-file v2.3.50/linux/kernel/acct.c linux/kernel/acct.c
--- v2.3.50/linux/kernel/acct.c	Wed Dec  8 14:11:28 1999
+++ linux/kernel/acct.c	Wed Mar  8 13:55:09 2000
@@ -88,24 +88,16 @@
  */
 static int check_free_space(struct file *file)
 {
-	mm_segment_t fs;
 	struct statfs sbuf;
-	struct super_block *sb;
 	int res = acct_active;
 	int act;
 
 	if (!file || !acct_needcheck)
 		return res;
 
-	sb = file->f_dentry->d_inode->i_sb;
-	if (!sb->s_op || !sb->s_op->statfs)
-		return res;
-
-	fs = get_fs();
-	set_fs(KERNEL_DS);
 	/* May block */
-	sb->s_op->statfs(sb, &sbuf, sizeof(struct statfs));
-	set_fs(fs);
+	if (vfs_statfs(file->f_dentry->d_inode->i_sb, &sbuf))
+		return res;
 
 	if (sbuf.f_bavail <= SUSPEND * sbuf.f_blocks / 100)
 		act = -1;
diff -u --recursive --new-file v2.3.50/linux/kernel/exit.c linux/kernel/exit.c
--- v2.3.50/linux/kernel/exit.c	Sat Feb 26 22:32:07 2000
+++ linux/kernel/exit.c	Fri Mar 10 15:33:42 2000
@@ -45,6 +45,18 @@
 		current->cmin_flt += p->min_flt + p->cmin_flt;
 		current->cmaj_flt += p->maj_flt + p->cmaj_flt;
 		current->cnswap += p->nswap + p->cnswap;
+		/*
+		 * Potentially available timeslices are retrieved
+		 * here - this way the parent does not get penalized
+		 * for creating too many processes.
+		 *
+		 * (this cannot be used to artificially 'generate'
+		 * timeslices, because any timeslice recovered here
+		 * was given away by the parent in the first place.)
+		 */
+		current->counter += p->counter;
+		if (current->counter > current->priority)
+			current->counter = current->priority;
 		free_task_struct(p);
 	} else {
 		printk("task releasing itself\n");
diff -u --recursive --new-file v2.3.50/linux/kernel/fork.c linux/kernel/fork.c
--- v2.3.50/linux/kernel/fork.c	Sun Feb 13 19:29:04 2000
+++ linux/kernel/fork.c	Fri Mar 10 15:31:29 2000
@@ -713,8 +713,10 @@
 	 * more scheduling fairness. This is only important in the first
 	 * timeslice, on the long run the scheduling behaviour is unchanged.
 	 */
+	p->counter = (current->counter + 1) >> 1;
 	current->counter >>= 1;
-	p->counter = current->counter;
+	if (!current->counter)
+		current->need_resched = 1;
 
 	/*
 	 * Ok, add it to the run-queues and make it
diff -u --recursive --new-file v2.3.50/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.50/linux/kernel/ksyms.c	Tue Mar  7 14:32:26 2000
+++ linux/kernel/ksyms.c	Fri Mar 10 10:48:52 2000
@@ -131,7 +131,6 @@
 EXPORT_SYMBOL(in_group_p);
 EXPORT_SYMBOL(update_atime);
 EXPORT_SYMBOL(get_super);
-EXPORT_SYMBOL(get_fs_type);
 EXPORT_SYMBOL(get_empty_super);
 EXPORT_SYMBOL(remove_vfsmnt);
 EXPORT_SYMBOL(getname);
@@ -157,11 +156,6 @@
 EXPORT_SYMBOL(mark_buffer_dirty);
 EXPORT_SYMBOL(__mark_buffer_dirty);
 EXPORT_SYMBOL(__mark_inode_dirty);
-EXPORT_SYMBOL(free_kiovec);
-EXPORT_SYMBOL(brw_kiovec);
-EXPORT_SYMBOL(alloc_kiovec);
-EXPORT_SYMBOL(expand_kiobuf);
-EXPORT_SYMBOL(unmap_kiobuf);
 EXPORT_SYMBOL(get_empty_filp);
 EXPORT_SYMBOL(init_private_file);
 EXPORT_SYMBOL(filp_open);
@@ -358,6 +352,18 @@
 EXPORT_SYMBOL(__br_write_unlock);
 #endif
 
+/* Kiobufs */
+EXPORT_SYMBOL(kiobuf_init);
+
+EXPORT_SYMBOL(alloc_kiovec);
+EXPORT_SYMBOL(free_kiovec);
+EXPORT_SYMBOL(expand_kiobuf);
+
+EXPORT_SYMBOL(map_user_kiobuf);
+EXPORT_SYMBOL(lock_kiovec);
+EXPORT_SYMBOL(unlock_kiovec);
+EXPORT_SYMBOL(brw_kiovec);
+
 /* autoirq from  drivers/net/auto_irq.c */
 EXPORT_SYMBOL(autoirq_setup);
 EXPORT_SYMBOL(autoirq_report);
@@ -393,6 +399,7 @@
 EXPORT_SYMBOL(jiffies);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
+EXPORT_SYMBOL(do_settimeofday);
 #ifndef __ia64__
 EXPORT_SYMBOL(loops_per_sec);
 #endif
diff -u --recursive --new-file v2.3.50/linux/kernel/module.c linux/kernel/module.c
--- v2.3.50/linux/kernel/module.c	Tue Dec 14 01:27:24 1999
+++ linux/kernel/module.c	Fri Mar 10 10:48:52 2000
@@ -350,6 +350,21 @@
 	return error;
 }
 
+static spinlock_t unload_lock = SPIN_LOCK_UNLOCKED;
+int try_inc_mod_count(struct module *mod)
+{
+	int res = 1;
+	if (mod) {
+		spin_lock(&unload_lock);
+		if (mod->flags & MOD_DELETED)
+			res = 0;
+		else
+			__MOD_INC_USE_COUNT(mod);
+		spin_unlock(&unload_lock);
+	}
+	return res;
+}
+
 asmlinkage long
 sys_delete_module(const char *name_user)
 {
@@ -377,11 +392,18 @@
 		}
 		put_mod_name(name);
 		error = -EBUSY;
- 		if (mod->refs != NULL || __MOD_IN_USE(mod))
+ 		if (mod->refs != NULL)
 			goto out;
 
-		free_module(mod, 0);
-		error = 0;
+		spin_lock(&unload_lock);
+ 		if (!__MOD_IN_USE(mod)) {
+			mod->flags |= MOD_DELETED;
+			spin_unlock(&unload_lock);
+			free_module(mod, 0);
+			error = 0;
+		} else {
+			spin_unlock(&unload_lock);
+		}
 		goto out;
 	}
 
@@ -390,6 +412,7 @@
 	something_changed = 0;
 	for (mod = module_list; mod != &kernel_module; mod = next) {
 		next = mod->next;
+		spin_lock(&unload_lock);
 		if (mod->refs == NULL
 		    && (mod->flags & MOD_AUTOCLEAN)
 		    && (mod->flags & MOD_RUNNING)
@@ -398,11 +421,16 @@
 		    && !__MOD_IN_USE(mod)) {
 			if ((mod->flags & MOD_VISITED)
 			    && !(mod->flags & MOD_JUST_FREED)) {
+				spin_unlock(&unload_lock);
 				mod->flags &= ~MOD_VISITED;
 			} else {
+				mod->flags |= MOD_DELETED;
+				spin_unlock(&unload_lock);
 				free_module(mod, 1);
 				something_changed = 1;
 			}
+		} else {
+			spin_unlock(&unload_lock);
 		}
 	}
 	if (something_changed)
@@ -775,7 +803,6 @@
 
 	/* Let the module clean up.  */
 
-	mod->flags |= MOD_DELETED;
 	if (mod->flags & MOD_RUNNING) 
 	{
 		if(mod->cleanup)
diff -u --recursive --new-file v2.3.50/linux/kernel/signal.c linux/kernel/signal.c
--- v2.3.50/linux/kernel/signal.c	Fri Jan 28 15:09:09 2000
+++ linux/kernel/signal.c	Fri Mar 10 10:48:53 2000
@@ -39,6 +39,8 @@
 				  sizeof(struct signal_queue),
 				  __alignof__(struct signal_queue),
 				  SIG_SLAB_DEBUG, NULL, NULL);
+	if (!signal_queue_cachep)
+		panic("signals_init(): cannot create signal_queue SLAB cache");
 }
 
 
diff -u --recursive --new-file v2.3.50/linux/kernel/sys.c linux/kernel/sys.c
--- v2.3.50/linux/kernel/sys.c	Sat Feb 26 22:32:07 2000
+++ linux/kernel/sys.c	Fri Mar 10 11:01:19 2000
@@ -801,23 +801,39 @@
 	return 0;
 }
 
-int in_group_p(gid_t grp)
+static int supplemental_group_member(gid_t grp)
 {
-	if (grp != current->fsgid) {
-		int i = current->ngroups;
-		if (i) {
-			gid_t *groups = current->groups;
-			do {
-				if (*groups == grp)
-					goto out;
-				groups++;
-				i--;
-			} while (i);
-		}
-		return 0;
+	int i = current->ngroups;
+
+	if (i) {
+		gid_t *groups = current->groups;
+		do {
+			if (*groups == grp)
+				return 1;
+			groups++;
+			i--;
+		} while (i);
 	}
-out:
-	return 1;
+	return 0;
+}
+
+/*
+ * Check whether we're fsgid/egid or in the supplemental group..
+ */
+int in_group_p(gid_t grp)
+{
+	int retval = 1;
+	if (grp != current->fsgid)
+		retval = supplemental_group_member(grp);
+	return retval;
+}
+
+int in_egroup_p(gid_t grp)
+{
+	int retval = 1;
+	if (grp != current->egid)
+		retval = supplemental_group_member(grp);
+	return retval;
 }
 
 DECLARE_RWSEM(uts_sem);
diff -u --recursive --new-file v2.3.50/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.3.50/linux/kernel/sysctl.c	Sat Feb 26 22:32:07 2000
+++ linux/kernel/sysctl.c	Fri Mar 10 10:56:48 2000
@@ -57,8 +57,7 @@
 #endif
 #ifdef CONFIG_SYSVIPC
 extern size_t shm_ctlmax;
-extern int shm_ctlall;
-extern int shm_ctlmni;
+extern char shm_path[];
 extern int msg_ctlmax;
 extern int msg_ctlmnb;
 extern int msg_ctlmni;
@@ -200,12 +199,10 @@
 	{KERN_RTSIGMAX, "rtsig-max", &max_queued_signals, sizeof(int),
 	 0644, NULL, &proc_dointvec},
 #ifdef CONFIG_SYSVIPC
+	{KERN_SHMPATH, "shmpath", &shm_path, 256,
+	 0644, NULL, &proc_dostring, &sysctl_string },
 	{KERN_SHMMAX, "shmmax", &shm_ctlmax, sizeof (size_t),
 	 0644, NULL, &proc_doulongvec_minmax},
-	{KERN_SHMALL, "shmall", &shm_ctlall, sizeof (int),
-	 0644, NULL, &proc_dointvec},
-	{KERN_SHMMNI, "shmmni", &shm_ctlmni, sizeof (int),
-	 0644, NULL, &proc_dointvec},
 	{KERN_MSGMAX, "msgmax", &msg_ctlmax, sizeof (int),
 	 0644, NULL, &proc_dointvec},
 	{KERN_MSGMNI, "msgmni", &msg_ctlmni, sizeof (int),
@@ -351,25 +348,6 @@
 	return error;
 }
 
-/* Like in_group_p, but testing against egid, not fsgid */
-int in_egroup_p(gid_t grp)
-{
-	if (grp != current->egid) {
-		int i = current->ngroups;
-		if (i) {
-			gid_t *groups = current->groups;
-			do {
-				if (*groups == grp)
-					goto out;
-				groups++;
-				i--;
-			} while (i);
-		}
-		return 0;
-	}
-out:
-	return 1;
-}
 
 /* ctl_perm does NOT grant the superuser all rights automatically, because
    some sysctl variables are readonly even to root. */
diff -u --recursive --new-file v2.3.50/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.50/linux/mm/filemap.c	Sat Feb 26 22:32:07 2000
+++ linux/mm/filemap.c	Fri Mar 10 10:48:53 2000
@@ -954,8 +954,7 @@
  */
 void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor)
 {
-	struct dentry *dentry = filp->f_dentry;
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode = filp->f_dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
 	unsigned long index, offset;
 	struct page *cached_page;
@@ -1307,8 +1306,7 @@
 {
 	int error;
 	struct file *file = area->vm_file;
-	struct dentry *dentry = file->f_dentry;
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
 	struct page *page, **hash, *old_page;
 	unsigned long size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
diff -u --recursive --new-file v2.3.50/linux/mm/memory.c linux/mm/memory.c
--- v2.3.50/linux/mm/memory.c	Thu Mar  2 14:36:23 2000
+++ linux/mm/memory.c	Thu Mar  9 21:12:27 2000
@@ -398,28 +398,25 @@
 			return pte_page(*pte);
 	}
 	
-	printk(KERN_ERR "Missing page in follow_page\n");
 	return NULL;
 }
 
 /* 
- * Given a physical address, is there a useful struct page pointing to it?
+ * Given a physical address, is there a useful struct page pointing to
+ * it?  This may become more complex in the future if we start dealing
+ * with IO-aperture pages in kiobufs.
  */
 
-struct page * get_page_map(struct page *page, unsigned long vaddr)
+static inline struct page * get_page_map(struct page *page)
 {
-	if (MAP_NR(vaddr) >= max_mapnr)
-		return 0;
-	if (page == ZERO_PAGE(vaddr))
-		return 0;
-	if (PageReserved(page))
+	if (page > (mem_map + max_mapnr))
 		return 0;
 	return page;
 }
 
 /*
  * Force in an entire range of pages from the current process's user VA,
- * and pin and lock the pages for IO.  
+ * and pin them in physical memory.  
  */
 
 #define dprintk(x...)
@@ -430,8 +427,6 @@
 	struct mm_struct *	mm;
 	struct vm_area_struct *	vma = 0;
 	struct page *		map;
-	int			doublepage = 0;
-	int			repeat = 0;
 	int			i;
 	
 	/* Make sure the iobuf is not already mapped somewhere. */
@@ -447,11 +442,10 @@
 	if (err)
 		return err;
 
- repeat:
 	down(&mm->mmap_sem);
 
 	err = -EFAULT;
-	iobuf->locked = 1;
+	iobuf->locked = 0;
 	iobuf->offset = va & ~PAGE_MASK;
 	iobuf->length = len;
 	
@@ -471,16 +465,15 @@
 		spin_lock(&mm->page_table_lock);
 		map = follow_page(ptr);
 		if (!map) {
+			spin_unlock(&mm->page_table_lock);
 			dprintk (KERN_ERR "Missing page in map_user_kiobuf\n");
-			goto retry;
+			goto out_unlock;
 		}
-		map = get_page_map(map, ptr);
-		if (map) {
-			if (TryLockPage(map)) {
-				goto retry;
-			}
+		map = get_page_map(map);
+		if (map)
 			atomic_inc(&map->count);
-		}
+		else
+			printk (KERN_INFO "Mapped page missing [%d]\n", i);
 		spin_unlock(&mm->page_table_lock);
 		iobuf->maplist[i] = map;
 		iobuf->nr_pages = ++i;
@@ -497,42 +490,6 @@
 	unmap_kiobuf(iobuf);
 	dprintk ("map_user_kiobuf: end %d\n", err);
 	return err;
-
- retry:
-
-	/* 
-	 * Undo the locking so far, wait on the page we got to, and try again.
-	 */
-	spin_unlock(&mm->page_table_lock);
-	unmap_kiobuf(iobuf);
-	up(&mm->mmap_sem);
-
-	/* 
-	 * Did the release also unlock the page we got stuck on?
-	 */
-	if (map) {
-		if (!PageLocked(map)) {
-			/* If so, we may well have the page mapped twice
-			 * in the IO address range.  Bad news.  Of
-			 * course, it _might_ * just be a coincidence,
-			 * but if it happens more than * once, chances
-			 * are we have a double-mapped page. */
-			if (++doublepage >= 3) {
-				return -EINVAL;
-			}
-		}
-	
-		/*
-		 * Try again...
-		 */
-		wait_on_page(map);
-	}
-	
-	if (++repeat < 16) {
-		ptr = va & PAGE_MASK;
-		goto repeat;
-	}
-	return -EAGAIN;
 }
 
 
@@ -548,15 +505,118 @@
 	
 	for (i = 0; i < iobuf->nr_pages; i++) {
 		map = iobuf->maplist[i];
-		
-		if (map && iobuf->locked) {
-			UnlockPage(map);
+		if (map) {
+			if (iobuf->locked)
+				UnlockPage(map);
 			__free_page(map);
 		}
 	}
 	
 	iobuf->nr_pages = 0;
 	iobuf->locked = 0;
+}
+
+
+/*
+ * Lock down all of the pages of a kiovec for IO.
+ *
+ * If any page is mapped twice in the kiovec, we return the error -EINVAL.
+ *
+ * The optional wait parameter causes the lock call to block until all
+ * pages can be locked if set.  If wait==0, the lock operation is
+ * aborted if any locked pages are found and -EAGAIN is returned.
+ */
+
+int lock_kiovec(int nr, struct kiobuf *iovec[], int wait)
+{
+	struct kiobuf *iobuf;
+	int i, j;
+	struct page *page, **ppage;
+	int doublepage = 0;
+	int repeat = 0;
+	
+ repeat:
+	
+	for (i = 0; i < nr; i++) {
+		iobuf = iovec[i];
+
+		if (iobuf->locked)
+			continue;
+		iobuf->locked = 1;
+
+		ppage = iobuf->maplist;
+		for (j = 0; j < iobuf->nr_pages; ppage++, j++) {
+			page = *ppage;
+			if (!page)
+				continue;
+			
+			if (TryLockPage(page))
+				goto retry;
+		}
+	}
+
+	return 0;
+	
+ retry:
+	
+	/* 
+	 * We couldn't lock one of the pages.  Undo the locking so far,
+	 * wait on the page we got to, and try again.  
+	 */
+	
+	unlock_kiovec(nr, iovec);
+	if (!wait)
+		return -EAGAIN;
+	
+	/* 
+	 * Did the release also unlock the page we got stuck on?
+	 */
+	if (!PageLocked(page)) {
+		/* 
+		 * If so, we may well have the page mapped twice
+		 * in the IO address range.  Bad news.  Of
+		 * course, it _might_ just be a coincidence,
+		 * but if it happens more than once, chances
+		 * are we have a double-mapped page. 
+		 */
+		if (++doublepage >= 3) 
+			return -EINVAL;
+		
+		/* Try again...  */
+		wait_on_page(page);
+	}
+	
+	if (++repeat < 16)
+		goto repeat;
+	return -EAGAIN;
+}
+
+/*
+ * Unlock all of the pages of a kiovec after IO.
+ */
+
+int unlock_kiovec(int nr, struct kiobuf *iovec[])
+{
+	struct kiobuf *iobuf;
+	int i, j;
+	struct page *page, **ppage;
+	
+	for (i = 0; i < nr; i++) {
+		iobuf = iovec[i];
+
+		if (!iobuf->locked)
+			continue;
+		iobuf->locked = 0;
+		
+		ppage = iobuf->maplist;
+		for (j = 0; j < iobuf->nr_pages; ppage++, j++) {
+			page = *ppage;
+			if (!page)
+				continue;
+			UnlockPage(page);
+		}
+	}
+	return 0;
 }
 
 static inline void zeromap_pte_range(pte_t * pte, unsigned long address,
diff -u --recursive --new-file v2.3.50/linux/mm/mmap.c linux/mm/mmap.c
--- v2.3.50/linux/mm/mmap.c	Thu Mar  2 14:36:23 2000
+++ linux/mm/mmap.c	Wed Mar  8 09:16:24 2000
@@ -305,14 +305,14 @@
 			atomic_dec(&file->f_dentry->d_inode->i_writecount);
 			correct_wcount = 1;
 		}
+		vma->vm_file = file;
+		get_file(file);
 		error = file->f_op->mmap(file, vma);
 		/* Fix up the count if necessary, then check for an error */
 		if (correct_wcount)
 			atomic_inc(&file->f_dentry->d_inode->i_writecount);
 		if (error)
 			goto unmap_and_free_vma;
-		vma->vm_file = file;
-		get_file(file);
 	}
 
 	/*
@@ -334,6 +334,8 @@
 	return addr;
 
 unmap_and_free_vma:
+	vma->vm_file = NULL;
+	fput(file);
 	/* Undo any partial mapping done by a device driver. */
 	flush_cache_range(mm, vma->vm_start, vma->vm_end);
 	zap_page_range(mm, vma->vm_start, vma->vm_end - vma->vm_start);
diff -u --recursive --new-file v2.3.50/linux/net/Config.in linux/net/Config.in
--- v2.3.50/linux/net/Config.in	Tue Mar  7 14:32:26 2000
+++ linux/net/Config.in	Thu Mar  9 06:57:17 2000
@@ -54,11 +54,11 @@
    source net/ipx/Config.in
 fi
 tristate 'Appletalk protocol support' CONFIG_ATALK
+tristate 'DECnet Support' CONFIG_DECNET
+if [ "$CONFIG_DECNET" != "n" ]; then
+   source net/decnet/Config.in
+fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   tristate 'DECnet Support (EXPERIMENTAL)' CONFIG_DECNET
-   if [ "$CONFIG_DECNET" != "n" ]; then
-      source net/decnet/Config.in
-   fi
    tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25
    tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB
    tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE
diff -u --recursive --new-file v2.3.50/linux/net/appletalk/aarp.c linux/net/appletalk/aarp.c
--- v2.3.50/linux/net/appletalk/aarp.c	Tue Nov 23 22:42:21 1999
+++ linux/net/appletalk/aarp.c	Fri Mar 10 09:43:04 2000
@@ -50,6 +50,7 @@
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
+#include <linux/spinlock.h>
 #include <net/sock.h>
 #include <net/datalink.h>
 #include <net/psnap.h>
@@ -67,8 +68,7 @@
  *	Lists of aarp entries
  */
  
-struct aarp_entry
-{
+struct aarp_entry {
 	/* These first two are only used for unresolved entries */
 	unsigned long last_sent;		/* Last time we xmitted the aarp request */
 	struct sk_buff_head packet_queue;	/* Queue of frames wait for resolution */
@@ -85,8 +85,13 @@
  *	Hashed list of resolved, unresolved and proxy entries
  */
 
-static struct aarp_entry *resolved[AARP_HASH_SIZE], *unresolved[AARP_HASH_SIZE], *proxies[AARP_HASH_SIZE];
-static int unresolved_count=0;
+static struct aarp_entry *resolved[AARP_HASH_SIZE];
+static struct aarp_entry *unresolved[AARP_HASH_SIZE];
+static struct aarp_entry *proxies[AARP_HASH_SIZE];
+static int unresolved_count = 0;
+
+/* One lock protects it all. */
+static spinlock_t aarp_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  *	Used to walk the list and purge/kick entries.
@@ -96,38 +101,49 @@
 
 /*
  *	Delete an aarp queue
+ *
+ *	Must run under aarp_lock.
  */
-static void aarp_expire(struct aarp_entry *a)
+static void __aarp_expire(struct aarp_entry *a)
 {
 	struct sk_buff *skb;
 	
-	while((skb=skb_dequeue(&a->packet_queue))!=NULL)
+	while ((skb=skb_dequeue(&a->packet_queue)) != NULL)
 		kfree_skb(skb);
-	kfree_s(a,sizeof(*a));
+
+	kfree_s(a, sizeof(*a));
 }
 
 /*
  *	Send an aarp queue entry request
+ *
+ *	Must run under aarp_lock.
  */
  
-static void aarp_send_query(struct aarp_entry *a)
+static void __aarp_send_query(struct aarp_entry *a)
 {
-	static char aarp_eth_multicast[ETH_ALEN]={ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
-	struct net_device *dev=a->dev;
-	int len=dev->hard_header_len+sizeof(struct elapaarp)+aarp_dl->header_length;
-	struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
+	static char aarp_eth_multicast[ETH_ALEN] =
+		{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
+	struct net_device *dev = a->dev;
+	int len = dev->hard_header_len + sizeof(struct elapaarp) + aarp_dl->header_length;
+	struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
 	struct elapaarp *eah;
-	struct at_addr *sat=atalk_find_dev_addr(dev);
+	struct at_addr *sat = atalk_find_dev_addr(dev);
 	
-	if(skb==NULL || sat==NULL)
+	if (skb == NULL)
+		return;
+
+	if (sat == NULL) {
+		kfree_skb(skb);
 		return;
+	}
 	
 	/*
 	 *	Set up the buffer.
 	 */		
 
-	skb_reserve(skb,dev->hard_header_len+aarp_dl->header_length);
-	eah		=	(struct elapaarp *)skb_put(skb,sizeof(struct elapaarp));
+	skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
+	eah		=	(struct elapaarp *)skb_put(skb, sizeof(struct elapaarp));
 	skb->protocol   =       htons(ETH_P_ATALK);
 	skb->nh.raw     =       skb->h.raw = (void *) eah;
 	skb->dev	=	dev;
@@ -173,21 +189,25 @@
 	a->xmit_count++;
 }
 
-static void aarp_send_reply(struct net_device *dev, struct at_addr *us, struct at_addr *them, unsigned char *sha)
+/* This runs under aarp_lock and in softint context, so only
+ * atomic memory allocations can be used.
+ */
+static void aarp_send_reply(struct net_device *dev, struct at_addr *us,
+			    struct at_addr *them, unsigned char *sha)
 {
-	int len=dev->hard_header_len+sizeof(struct elapaarp)+aarp_dl->header_length;
-	struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
+	int len = dev->hard_header_len + sizeof(struct elapaarp) + aarp_dl->header_length;
+	struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
 	struct elapaarp *eah;
 	
-	if(skb==NULL)
+	if (skb == NULL)
 		return;
 	
 	/*
 	 *	Set up the buffer.
 	 */		
 
-	skb_reserve(skb,dev->hard_header_len+aarp_dl->header_length);
-	eah		=	(struct elapaarp *)skb_put(skb,sizeof(struct elapaarp));	 
+	skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
+	eah		=	(struct elapaarp *)skb_put(skb, sizeof(struct elapaarp));	 
 	skb->protocol   =       htons(ETH_P_ATALK);
 	skb->nh.raw     =       skb->h.raw = (void *) eah;
 	skb->dev	=	dev;
@@ -208,7 +228,7 @@
 	eah->pa_src_net	=	us->s_net;
 	eah->pa_src_node=	us->s_node;
 	
-	if(sha==NULL)
+	if (sha == NULL)
 		memset(eah->hw_dst, '\0', ETH_ALEN);
 	else
 		memcpy(eah->hw_dst, sha, ETH_ALEN);
@@ -227,110 +247,110 @@
 	 *	Send it.
 	 */	
 	dev_queue_xmit(skb);
-	
 }
 
 /*
  *	Send probe frames. Called from aarp_probe_network and aarp_proxy_probe_network.
  */
- 
+
 void aarp_send_probe(struct net_device *dev, struct at_addr *us)
 {
-	int len=dev->hard_header_len+sizeof(struct elapaarp)+aarp_dl->header_length;
-	struct sk_buff *skb=alloc_skb(len, GFP_ATOMIC);
+	int len = dev->hard_header_len + sizeof(struct elapaarp) + aarp_dl->header_length;
+	struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC);
 	struct elapaarp *eah;
-	static char aarp_eth_multicast[ETH_ALEN]={ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
-	
-	if(skb==NULL)
+	static char aarp_eth_multicast[ETH_ALEN] =
+		{ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
+
+	if (skb == NULL)
 		return;
-	
+
 	/*
 	 *	Set up the buffer.
-	 */		
+	 */
 
-	skb_reserve(skb,dev->hard_header_len+aarp_dl->header_length);
-	eah		=	(struct elapaarp *)skb_put(skb,sizeof(struct elapaarp));
+	skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length);
+	eah		=	(struct elapaarp *)skb_put(skb, sizeof(struct elapaarp));
 	skb->protocol   =       htons(ETH_P_ATALK);
 	skb->nh.raw     =       skb->h.raw = (void *) eah;
 	skb->dev	=	dev;
-	
+
 	/*
 	 *	Set up the ARP.
 	 */
-	 
+
 	eah->hw_type	=	htons(AARP_HW_TYPE_ETHERNET);
 	eah->pa_type	=	htons(ETH_P_ATALK);
-	eah->hw_len	=	ETH_ALEN;	
+	eah->hw_len	=	ETH_ALEN;
 	eah->pa_len	=	AARP_PA_ALEN;
 	eah->function	=	htons(AARP_PROBE);
-	
+
 	memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN);
-	
+
 	eah->pa_src_zero=	0;
 	eah->pa_src_net	=	us->s_net;
 	eah->pa_src_node=	us->s_node;
-	
+
 	memset(eah->hw_dst, '\0', ETH_ALEN);
-	
+
 	eah->pa_dst_zero=	0;
 	eah->pa_dst_net	=	us->s_net;
 	eah->pa_dst_node=	us->s_node;
-	
+
 	/*
 	 *	Add ELAP headers and set target to the AARP multicast.
 	 */
-	 
-	aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);	
+
+	aarp_dl->datalink_header(aarp_dl, skb, aarp_eth_multicast);
 
 	/*
 	 *	Send it.
-	 */	
+	 */
 	dev_queue_xmit(skb);
-	
 }
 	
 /*
  *	Handle an aarp timer expire
+ *
+ *	Must run under the aarp_lock.
  */
 
-static void aarp_expire_timer(struct aarp_entry **n)
+static void __aarp_expire_timer(struct aarp_entry **n)
 {
 	struct aarp_entry *t;
-	while((*n)!=NULL)
-	{
+
+	while ((*n) != NULL) {
 		/* Expired ? */
-		if(time_after(jiffies, (*n)->expires_at))
-		{
-			t= *n;
-			*n=(*n)->next;
-			aarp_expire(t);
+		if(time_after(jiffies, (*n)->expires_at)) {
+			t = *n;
+			*n = (*n)->next;
+			__aarp_expire(t);
+		} else {
+			n = &((*n)->next);
 		}
-		else
-			n=&((*n)->next);
 	}
 }
 
 /*
  *	Kick all pending requests 5 times a second.
+ *
+ *	Must run under the aarp_lock.
  */
  
-static void aarp_kick(struct aarp_entry **n)
+static void __aarp_kick(struct aarp_entry **n)
 {
 	struct aarp_entry *t;
-	while((*n)!=NULL)
-	{
+
+	while ((*n) != NULL) {
 		/* Expired - if this will be the 11th transmit, we delete
-		   instead */
-		if((*n)->xmit_count>=sysctl_aarp_retransmit_limit)
-		{
-			t= *n;
-			*n=(*n)->next;
-			aarp_expire(t);
-		}
-		else
-		{
-			aarp_send_query(*n);
-			n=&((*n)->next);
+		 * instead.
+		 */
+		if ((*n)->xmit_count >= sysctl_aarp_retransmit_limit) {
+			t = *n;
+			*n = (*n)->next;
+			__aarp_expire(t);
+		} else {
+			__aarp_send_query(*n);
+			n = &((*n)->next);
 		}
 	}
 }
@@ -338,21 +358,22 @@
 /*
  *	A device has gone down. Take all entries referring to the device
  *	and remove them.
+ *
+ *	Must run under the aarp_lock.
  */
  
-static void aarp_expire_device(struct aarp_entry **n, struct net_device *dev)
+static void __aarp_expire_device(struct aarp_entry **n, struct net_device *dev)
 {
 	struct aarp_entry *t;
-	while((*n)!=NULL)
-	{
-		if((*n)->dev==dev)
-		{
-			t= *n;
-			*n=(*n)->next;
-			aarp_expire(t);
+
+	while ((*n) != NULL) {
+		if ((*n)->dev == dev) {
+			t = *n;
+			*n = (*n)->next;
+			__aarp_expire(t);
+		} else {
+			n = &((*n)->next);
 		}
-		else
-			n=&((*n)->next);
 	}
 }
 		
@@ -362,15 +383,19 @@
  
 static void aarp_expire_timeout(unsigned long unused)
 {
-	int ct=0;
-	for(ct=0;ct<AARP_HASH_SIZE;ct++)
-	{
-		aarp_expire_timer(&resolved[ct]);
-		aarp_kick(&unresolved[ct]);
-		aarp_expire_timer(&unresolved[ct]);
-		aarp_expire_timer(&proxies[ct]);
+	int ct;
+
+	spin_lock_bh(&aarp_lock);
+
+	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
+		__aarp_expire_timer(&resolved[ct]);
+		__aarp_kick(&unresolved[ct]);
+		__aarp_expire_timer(&unresolved[ct]);
+		__aarp_expire_timer(&proxies[ct]);
 	}
 
+	spin_unlock_bh(&aarp_lock);
+
 	mod_timer(&aarp_timer, jiffies + 
 		  (unresolved_count ? sysctl_aarp_tick_time:
 		   sysctl_aarp_expiry_time));
@@ -382,77 +407,92 @@
  
 static int aarp_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	int ct=0;
-	if(event==NETDEV_DOWN)
-	{
-		for(ct=0;ct<AARP_HASH_SIZE;ct++)
-		{
-			aarp_expire_device(&resolved[ct],ptr);
-			aarp_expire_device(&unresolved[ct],ptr);
-			aarp_expire_device(&proxies[ct],ptr);
+	int ct;
+
+	if (event == NETDEV_DOWN) {
+		spin_lock_bh(&aarp_lock);
+
+		for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
+			__aarp_expire_device(&resolved[ct], ptr);
+			__aarp_expire_device(&unresolved[ct], ptr);
+			__aarp_expire_device(&proxies[ct], ptr);
 		}
+
+		spin_unlock_bh(&aarp_lock);
 	}
 	return NOTIFY_DONE;
 }
 
 /*
- *	Create a new aarp entry.
+ *	Create a new aarp entry.  This must use GFP_ATOMIC because it
+ *	runs while holding spinlocks.
  */
  
 static struct aarp_entry *aarp_alloc(void)
 {
-	struct aarp_entry *a=kmalloc(sizeof(struct aarp_entry), GFP_ATOMIC);
-	if(a==NULL)
+	struct aarp_entry *a = kmalloc(sizeof(struct aarp_entry), GFP_ATOMIC);
+
+	if (a == NULL)
 		return NULL;
+
 	skb_queue_head_init(&a->packet_queue);
+
 	return a;
 }
 
 /*
  * Find an entry. We might return an expired but not yet purged entry. We
  * don't care as it will do no harm.
+ *
+ * This must run under the aarp_lock.
  */
-static struct aarp_entry *aarp_find_entry(struct aarp_entry *list, struct net_device *dev, struct at_addr *sat)
-{
-	unsigned long flags;
-	save_flags(flags);
-	cli();
-	while(list)
-	{
-		if(list->target_addr.s_net==sat->s_net &&
-		   list->target_addr.s_node==sat->s_node && list->dev==dev)
+static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list,
+					    struct net_device *dev,
+					    struct at_addr *sat)
+{
+	while (list) {
+		if (list->target_addr.s_net == sat->s_net &&
+		    list->target_addr.s_node == sat->s_node &&
+		    list->dev == dev)
 			break;
-		list=list->next;
+		list = list->next;
 	}
-	restore_flags(flags);
+
 	return list;
 }
 
+/* Called from the DDP code, and thus must be exported. */
 void aarp_proxy_remove(struct net_device *dev, struct at_addr *sa)
 {
 	struct aarp_entry *a;
 	int hash;
 	
 	hash = 	sa->s_node % (AARP_HASH_SIZE-1);
-	a = aarp_find_entry(proxies[hash], dev, sa);
+
+	spin_lock_bh(&aarp_lock);
+
+	a = __aarp_find_entry(proxies[hash], dev, sa);
 	if (a)
-	{
-		a->expires_at = 0;
-		
-	}
+		a->expires_at = jiffies - 1;
+
+	spin_unlock_bh(&aarp_lock);
 }
 
-struct at_addr* aarp_proxy_find(struct net_device *dev, struct at_addr *sa)
+/* This must run under aarp_lock. */
+static struct at_addr *__aarp_proxy_find(struct net_device *dev, struct at_addr *sa)
 {
+	struct at_addr *retval;
 	struct aarp_entry *a;
 	int hash;
 
 	hash = 	sa->s_node % (AARP_HASH_SIZE-1);
-	a = aarp_find_entry(proxies[hash], dev, sa);
+
+	retval = NULL;
+	a = __aarp_find_entry(proxies[hash], dev, sa);
 	if (a != NULL)
-		return sa;
-	
-	return NULL;
+		retval = sa;
+
+	return retval;
 }
 
 	
@@ -468,31 +508,27 @@
     sa->sat_addr.s_node = iface->address.s_node;
     sa->sat_addr.s_net  = ntohs(iface->address.s_net);
 
-	/* We pass the Net:Node to the drivers/cards by a Device ioctl. */
-	if(!(iface->dev->do_ioctl(iface->dev, &atreq, SIOCSIFADDR)))
-    {
-    	(void)iface->dev->do_ioctl(iface->dev, &atreq, SIOCGIFADDR);
-    	if((iface->address.s_net != htons(sa->sat_addr.s_net))
-				|| (iface->address.s_node != sa->sat_addr.s_node))
-			iface->status |= ATIF_PROBE_FAIL;
-
-		iface->address.s_net  = htons(sa->sat_addr.s_net);
-		iface->address.s_node = sa->sat_addr.s_node;
-	}
-
-	return;
+    /* We pass the Net:Node to the drivers/cards by a Device ioctl. */
+    if (!(iface->dev->do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) {
+	    (void)iface->dev->do_ioctl(iface->dev, &atreq, SIOCGIFADDR);
+	    if ((iface->address.s_net != htons(sa->sat_addr.s_net)) ||
+		(iface->address.s_node != sa->sat_addr.s_node))
+		    iface->status |= ATIF_PROBE_FAIL;
+
+	    iface->address.s_net  = htons(sa->sat_addr.s_net);
+	    iface->address.s_node = sa->sat_addr.s_node;
+    }
 }
 
 
 void aarp_probe_network(struct atalk_iface *atif)
 {
-	if(atif->dev->type == ARPHRD_LOCALTLK || atif->dev->type == ARPHRD_PPP)
+	if(atif->dev->type == ARPHRD_LOCALTLK || atif->dev->type == ARPHRD_PPP) {
 		aarp_send_probe_phase1(atif);
-	else
-	{
+	} else {
 		unsigned int count;
-		for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++)
-		{
+
+		for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) {
 			aarp_send_probe(atif->dev, &atif->address);
 
 			/*
@@ -511,17 +547,17 @@
 {
 	struct	aarp_entry	*entry;
 	unsigned int count;
-	int	hash;
+	int	hash, retval;
 	
 	/*
 	 * we don't currently support LocalTalk or PPP for proxy AARP;
 	 * if someone wants to try and add it, have fun
 	 */
 	if (atif->dev->type == ARPHRD_LOCALTLK)
-		return (-EPROTONOSUPPORT);
+		return -EPROTONOSUPPORT;
 		
 	if (atif->dev->type == ARPHRD_PPP)
-		return (-EPROTONOSUPPORT);
+		return -EPROTONOSUPPORT;
 		
 	/* 
 	 * create a new AARP entry with the flags set to be published -- 
@@ -529,7 +565,7 @@
 	 */
 	entry = aarp_alloc();
 	if (entry == NULL)
-		return (-ENOMEM);
+		return -ENOMEM;
 	
 	entry->expires_at = -1;
 	entry->status = ATIF_PROBE;
@@ -537,44 +573,46 @@
 	entry->target_addr.s_net = sa->s_net;
 	entry->dev = atif->dev;
 
-	hash = sa->s_node % (AARP_HASH_SIZE-1);
+	spin_lock_bh(&aarp_lock);
+
+	hash = sa->s_node % (AARP_HASH_SIZE - 1);
 	entry->next = proxies[hash];
 	proxies[hash] = entry;
 	
-	for(count = 0; count < AARP_RETRANSMIT_LIMIT; count++)
-	{
+	for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) {
 		aarp_send_probe(atif->dev, sa);
 
 		/*
 		 * Defer 1/10th
 		 */
 		current->state = TASK_INTERRUPTIBLE;
+
+		spin_unlock_bh(&aarp_lock);
+
 		schedule_timeout(HZ/10);
 						
+		spin_lock_bh(&aarp_lock);
+
 		if (entry->status & ATIF_PROBE_FAIL)
 			break;
 	}
 	
-	/*
-	 * FIX ME: I think we need exclusive access to the status flags,
-	 * 		in case some one fails the probe while we're removing
-	 *		the probe flag.
-	 */
-	if (entry->status & ATIF_PROBE_FAIL)
-	{
+	retval = 1;
+
+	if (entry->status & ATIF_PROBE_FAIL) {
 		/* free the entry */
-		entry->expires_at = 0;
+		entry->expires_at = jiffies - 1;
 		
 		/* return network full */
-		return (-EADDRINUSE);
-	}
-	else
-	{
+		retval = -EADDRINUSE;
+	} else {
 		/* clear the probing flag */
 		entry->status &= ~ATIF_PROBE;
 	}
 
-	return 1;	
+	spin_unlock_bh(&aarp_lock);
+
+	return retval;
 }
 
 
@@ -583,23 +621,21 @@
  */
 int aarp_send_ddp(struct net_device *dev,struct sk_buff *skb, struct at_addr *sa, void *hwaddr)
 {
-	static char ddp_eth_multicast[ETH_ALEN]={ 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
+	static char ddp_eth_multicast[ETH_ALEN] = { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF };
 	int hash;
 	struct aarp_entry *a;
-	unsigned long flags;
 	
-	skb->nh.raw=skb->data;
+	skb->nh.raw = skb->data;
 	
 	/*
 	 *	Check for LocalTalk first
 	 */
 	 
 	 
-	if(dev->type==ARPHRD_LOCALTLK)
-	{
-		struct at_addr *at=atalk_find_dev_addr(dev);
-		struct ddpehdr *ddp=(struct ddpehdr *)skb->data;
-		int ft=2;
+	if (dev->type == ARPHRD_LOCALTLK) {
+		struct at_addr *at = atalk_find_dev_addr(dev);
+		struct ddpehdr *ddp = (struct ddpehdr *)skb->data;
+		int ft = 2;
 		
 		/*
 		 *	Compressible ?
@@ -608,29 +644,29 @@
 		 *	(zero matches anything)
 		 */
 		 
-		if( ( ddp->deh_snet==0 || at->s_net==ddp->deh_snet)
-		  &&( ddp->deh_dnet==0 || at->s_net==ddp->deh_dnet) )
-		{
-			skb_pull(skb,sizeof(struct ddpehdr)-4);
+		if( ( ddp->deh_snet==0 || at->s_net==ddp->deh_snet) &&
+		    ( ddp->deh_dnet==0 || at->s_net==ddp->deh_dnet) ) {
+			skb_pull(skb, sizeof(struct ddpehdr) - 4);
+
 			/*
 			 *	The upper two remaining bytes are the port 
 			 *	numbers	we just happen to need. Now put the 
 			 *	length in the lower two.
 			 */
-			*((__u16 *)skb->data)=htons(skb->len);
-			ft=1;
+			*((__u16 *)skb->data) = htons(skb->len);
+			ft = 1;
 		}
 		/*
 		 *	Nice and easy. No AARP type protocols occur here
 		 *	so we can just shovel it out with a 3 byte LLAP header
 		 */
 		 
-		skb_push(skb,3);
-		skb->data[0]=sa->s_node;
-		skb->data[1]=at->s_node;
-		skb->data[2]=ft;
+		skb_push(skb, 3);
+		skb->data[0] = sa->s_node;
+		skb->data[1] = at->s_node;
+		skb->data[2] = ft;
 		 
-		if(skb->sk)
+		if (skb->sk)
 			skb->priority = skb->sk->priority;
 		skb->dev = dev;
 		dev_queue_xmit(skb);
@@ -640,10 +676,9 @@
 	/*
 	 *	On a PPP link we neither compress nor aarp.
 	 */
-	if(dev->type==ARPHRD_PPP)
-	{
+	if (dev->type == ARPHRD_PPP) {
 		skb->protocol = htons(ETH_P_PPPTALK);
-		if(skb->sk)
+		if (skb->sk)
 			skb->priority = skb->sk->priority;
 		skb->dev = dev;
 		dev_queue_xmit(skb);
@@ -654,44 +689,43 @@
 	 *	Non ELAP we cannot do.
 	 */
 
-	if(dev->type!=ARPHRD_ETHER)
-	{
+	if (dev->type != ARPHRD_ETHER)
 		return -1;
-	}
 
 	skb->dev = dev;
 	skb->protocol = htons(ETH_P_ATALK);
 			
-	hash=sa->s_node%(AARP_HASH_SIZE-1);
-	save_flags(flags);
-	cli();
+	hash = sa->s_node % (AARP_HASH_SIZE - 1);
 	
 	/*
 	 *	Do we have a resolved entry ?
 	 */
 	 
-	if(sa->s_node==ATADDR_BCAST)
-	{
+	if (sa->s_node == ATADDR_BCAST) {
 		ddp_dl->datalink_header(ddp_dl, skb, ddp_eth_multicast);
-		if(skb->sk)
+
+		if (skb->sk)
 			skb->priority = skb->sk->priority;
 		dev_queue_xmit(skb);
-		restore_flags(flags);
 		return 1;
 	}
-	a=aarp_find_entry(resolved[hash],dev,sa);
-	if(a!=NULL)
-	{
+
+	spin_lock_bh(&aarp_lock);
+
+	a = __aarp_find_entry(resolved[hash], dev, sa);
+
+	if (a != NULL) {
 		/*
 		 *	Return 1 and fill in the address
 		 */
 
-		a->expires_at=jiffies+sysctl_aarp_expiry_time*10;
+		a->expires_at = jiffies + (sysctl_aarp_expiry_time * 10);
 		ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr);
 		if(skb->sk)
 			skb->priority = skb->sk->priority;
 		dev_queue_xmit(skb);
-		restore_flags(flags);
+
+		spin_unlock_bh(&aarp_lock);
 		return 1;
 	}
 
@@ -699,15 +733,15 @@
 	 *	Do we have an unresolved entry: This is the less common path
 	 */
 
-	a=aarp_find_entry(unresolved[hash],dev,sa);
-	if(a!=NULL)
-	{
+	a = __aarp_find_entry(unresolved[hash], dev, sa);
+	if (a != NULL) {
 		/*
 		 *	Queue onto the unresolved queue
 		 */
 
 		skb_queue_tail(&a->packet_queue, skb);
-		restore_flags(flags);
+
+		spin_unlock_bh(&aarp_lock);
 		return 0;
 	}
 
@@ -715,14 +749,13 @@
 	 *	Allocate a new entry
 	 */
 
-	a=aarp_alloc();
-	if(a==NULL)
-	{
+	a = aarp_alloc();
+	if (a == NULL) {
 		/*
 		 *	Whoops slipped... good job it's an unreliable 
 		 *	protocol 8)	
 		 */
-		restore_flags(flags);
+		spin_unlock_bh(&aarp_lock);
 		return -1;
 	}
 
@@ -731,30 +764,34 @@
 	 */
 
 	skb_queue_tail(&a->packet_queue, skb);
-	a->expires_at=jiffies+sysctl_aarp_resolve_time;
-	a->dev=dev;
-	a->next=unresolved[hash];
-	a->target_addr= *sa;
-	a->xmit_count=0;
-	unresolved[hash]=a;
+	a->expires_at = jiffies + sysctl_aarp_resolve_time;
+	a->dev = dev;
+	a->next = unresolved[hash];
+	a->target_addr = *sa;
+	a->xmit_count = 0;
+	unresolved[hash] = a;
 	unresolved_count++;
-	restore_flags(flags);
 
 	/*
 	 *	Send an initial request for the address
 	 */
 
-	aarp_send_query(a);
+	__aarp_send_query(a);
 
 	/*
 	 *	Switch to fast timer if needed (That is if this is the
 	 *	first unresolved entry to get added)
 	 */
 
-	if(unresolved_count==1)
-	{
+	if (unresolved_count == 1)
 		mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time);
-	}
+
+
+	/*
+	 *	Now finally, it is safe to drop the lock.
+	 */
+
+	spin_unlock_bh(&aarp_lock);
 
 	/*
 	 *	Tell the ddp layer we have taken over for this frame.
@@ -766,39 +803,40 @@
 /*
  *	An entry in the aarp unresolved queue has become resolved. Send
  *	all the frames queued under it.
+ *
+ *	Must run under aarp_lock.
  */
-static void aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, int hash)
+static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, int hash)
 {
 	struct sk_buff *skb;
-	while(*list!=NULL)
-	{
-		if(*list==a)
-		{
+
+	while (*list != NULL) {
+		if (*list == a) {
 			unresolved_count--;
-			*list=a->next;
-			
+
+			*list = a->next;
+
 			/* 
 			 *	Move into the resolved list 
 			 */
-			 
-			a->next=resolved[hash];
-			resolved[hash]=a;
-			
+
+			a->next = resolved[hash];
+			resolved[hash] = a;
+
 			/*
 			 *	Kick frames off 
 			 */
-			 
-			while((skb=skb_dequeue(&a->packet_queue))!=NULL)
-			{
-				a->expires_at=jiffies+sysctl_aarp_expiry_time*10;
-				ddp_dl->datalink_header(ddp_dl,skb,a->hwaddr);
-				if(skb->sk)
+
+			while ((skb = skb_dequeue(&a->packet_queue)) != NULL) {
+				a->expires_at = jiffies + (sysctl_aarp_expiry_time*10);
+				ddp_dl->datalink_header(ddp_dl, skb, a->hwaddr);
+				if (skb->sk)
 					skb->priority = skb->sk->priority;
 				dev_queue_xmit(skb);
 			}
+		} else {
+			list = &((*list)->next);
 		}
-		else
-			list=&((*list)->next);
 	}
 }
 
@@ -811,138 +849,129 @@
 	struct elapaarp *ea=(struct elapaarp *)skb->h.raw;
 	struct aarp_entry *a;
 	struct at_addr sa, *ma, da;
-	unsigned long flags;
 	int hash;
 	struct atalk_iface *ifa;
-	
-	
+
 	/*
-	 *	We only do Ethernet SNAP AARP
+	 *	We only do Ethernet SNAP AARP.
 	 */
-	 
-	if(dev->type!=ARPHRD_ETHER)
-	{
+
+	if (dev->type != ARPHRD_ETHER) {
 		kfree_skb(skb);
 		return 0;
 	}
-	
+
 	/*
 	 *	Frame size ok ?
 	 */
-	 
-	if(!skb_pull(skb,sizeof(*ea)))
-	{
+
+	if (!skb_pull(skb, sizeof(*ea))) {
 		kfree_skb(skb);
 		return 0;
 	}
 
-	ea->function=ntohs(ea->function);
-	
+	ea->function = ntohs(ea->function);
+
 	/*
 	 *	Sanity check fields.
 	 */
-	 
-	if(ea->function<AARP_REQUEST || ea->function > AARP_PROBE || ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN ||
-		ea->pa_src_zero != 0 || ea->pa_dst_zero != 0)
-	{
+
+	if (ea->function < AARP_REQUEST ||
+	    ea->function > AARP_PROBE ||
+	    ea->hw_len != ETH_ALEN ||
+	    ea->pa_len != AARP_PA_ALEN ||
+	    ea->pa_src_zero != 0 ||
+	    ea->pa_dst_zero != 0) {
 		kfree_skb(skb);
 		return 0;
 	}
-	
-	/*
-	 *	Looks good
-	 */
-	
-	hash=ea->pa_src_node%(AARP_HASH_SIZE-1);
 
 	/*
-	 *	Build an address
+	 *	Looks good.
 	 */
-	 
-	sa.s_node=ea->pa_src_node;
-	sa.s_net=ea->pa_src_net;
-	
+
+	hash = ea->pa_src_node % (AARP_HASH_SIZE - 1);
+
 	/*
-	 *	Process the packet
+	 *	Build an address.
 	 */
-	 
-	save_flags(flags);
+
+	sa.s_node = ea->pa_src_node;
+	sa.s_net = ea->pa_src_net;
 
 	/*
-	 *	Check for replies of me
+	 *	Process the packet.
+	 *	Check for replies of me.
 	 */
-			
-	ifa=atalk_find_dev(dev);
-	if(ifa==NULL)
-	{
-		restore_flags(flags);
+
+	ifa = atalk_find_dev(dev);
+	if (ifa == NULL) {
 		kfree_skb(skb);
-		return 1;		
+		return 1;
 	}
-	if(ifa->status&ATIF_PROBE)
-	{			
-		if(ifa->address.s_node==ea->pa_dst_node && ifa->address.s_net==ea->pa_dst_net)
-		{
+
+	if (ifa->status & ATIF_PROBE) {
+		if (ifa->address.s_node == ea->pa_dst_node &&
+		    ifa->address.s_net == ea->pa_dst_net) {
 			/*
 			 *	Fail the probe (in use)
 			 */
-			 
-			ifa->status|=ATIF_PROBE_FAIL;
-			restore_flags(flags);
+
+			ifa->status |= ATIF_PROBE_FAIL;
 			kfree_skb(skb);
-			return 1;		
+			return 1;
 		}
 	}
-	
+
 	/*
 	 * Check for replies of proxy AARP entries
 	 */
 
-	/*
-	 * FIX ME: do we need a cli() here? 
-	 * aarp_find_entry does one on its own, between saving and restoring flags, so
-	 * I don't think it is necessary, but I could be wrong -- it's happened before
-	 */
 	da.s_node = ea->pa_dst_node;
 	da.s_net = ea->pa_dst_net;
-	a = aarp_find_entry(proxies[hash], dev, &da);
-	if (a != NULL)
-		if (a->status & ATIF_PROBE)
-		{
+
+	spin_lock_bh(&aarp_lock);
+
+	a = __aarp_find_entry(proxies[hash], dev, &da);
+
+	if (a != NULL) {
+		if (a->status & ATIF_PROBE) {
 			a->status |= ATIF_PROBE_FAIL;
-			
+
+			spin_unlock_bh(&aarp_lock);
+
 			/*
-			 * we do not respond to probe or request packets for 
+			 * we do not respond to probe or request packets for
 			 * this address while we are probing this address
 			 */
-			restore_flags(flags);
 			kfree_skb(skb);
+
 			return 1;
 		}
+	}
 
-	switch(ea->function)
-	{
+	switch (ea->function) {
 		case AARP_REPLY:	
-			if(unresolved_count==0)	/* Speed up */
+			if (unresolved_count == 0)	/* Speed up */
 				break;
+
 			/*
-			 *	Find the entry	
+			 *	Find the entry.
 			 */
 			 
-			cli();	/* FIX ME: is this cli() necessary? aarp_find_entry does one on its own... */
-			if((a=aarp_find_entry(unresolved[hash],dev,&sa))==NULL || dev != a->dev)
+			if ((a = __aarp_find_entry(unresolved[hash],dev,&sa)) == NULL ||
+			    (dev != a->dev))
 				break;
+
 			/*
-			 *	We can fill one in - this is good
+			 *	We can fill one in - this is good.
 			 */
 			 
 			memcpy(a->hwaddr,ea->hw_src,ETH_ALEN);
-			aarp_resolved(&unresolved[hash],a,hash);
-			if(unresolved_count==0)
-			{
-				mod_timer(&aarp_timer, jiffies +
-					  sysctl_aarp_expiry_time);
-			}
+			__aarp_resolved(&unresolved[hash],a,hash);
+			if (unresolved_count == 0)
+				mod_timer(&aarp_timer,
+					  jiffies + sysctl_aarp_expiry_time);
 			break;
 			
 		case AARP_REQUEST:
@@ -956,100 +985,101 @@
 			 *	of our proxies before we toss the packet out.
 			 */
 			 
-			sa.s_node=ea->pa_dst_node;
-			sa.s_net=ea->pa_dst_net;
+			sa.s_node = ea->pa_dst_node;
+			sa.s_net = ea->pa_dst_net;
 
 			/*
-			 * see if we have a matching proxy
+			 * See if we have a matching proxy.
 			 */
-			ma = aarp_proxy_find(dev, &sa);
-			if (!ma)
-			{
-				ma=&ifa->address;
-			}
-			else
-			{
+			ma = __aarp_proxy_find(dev, &sa);
+			if (!ma) {
+				ma = &ifa->address;
+			} else {
 				/*
-				 * we need to make a copy of the entry
+				 * We need to make a copy of the entry.
 				 */
 				da.s_node = sa.s_node;
 				da.s_net = da.s_net;
 				ma = &da;
 			}
 
-			if(ea->function==AARP_PROBE)
-			{
+			if (ea->function == AARP_PROBE) {
 				/* A probe implies someone trying to get an
-				   address. So as a precaution flush any
-				   entries we have for this address */
-				struct aarp_entry *a=aarp_find_entry(
+				 * address. So as a precaution flush any
+				 * entries we have for this address.
+				 */
+				struct aarp_entry *a = __aarp_find_entry(
 						resolved[sa.s_node%(AARP_HASH_SIZE-1)],
 						skb->dev,
 						&sa);
 				/* Make it expire next tick - that avoids us
-				   getting into a probe/flush/learn/probe/flush/learn
-				   cycle during probing of a slow to respond host addr */
-				if(a!=NULL)
-					a->expires_at=jiffies-1;
+				 * getting into a probe/flush/learn/probe/flush/learn
+				 * cycle during probing of a slow to respond host addr.
+				 */
+				if (a != NULL)
+					a->expires_at = jiffies - 1;
 			}
-			if(sa.s_node!=ma->s_node)
+
+			if (sa.s_node != ma->s_node)
 				break;
-			if(sa.s_net && ma->s_net && sa.s_net!=ma->s_net)
+
+			if (sa.s_net && ma->s_net && sa.s_net != ma->s_net)
 				break;
 
-			sa.s_node=ea->pa_src_node;
-			sa.s_net=ea->pa_src_net;
+			sa.s_node = ea->pa_src_node;
+			sa.s_net = ea->pa_src_net;
 			
 			/*
 			 *	aarp_my_address has found the address to use for us.
 			 */
 			 
-			aarp_send_reply(dev,ma,&sa,ea->hw_src);
+			aarp_send_reply(dev, ma, &sa, ea->hw_src);
 			break;
-	}
-	restore_flags(flags);
+	};
+
+	spin_unlock_bh(&aarp_lock);
+
 	kfree_skb(skb);
-	return 1;		
+	return 1;
 }
 
-static struct notifier_block aarp_notifier={
+static struct notifier_block aarp_notifier = {
 	aarp_device_event,
 	NULL,
 	0
 };
 
-static char aarp_snap_id[]={0x00,0x00,0x00,0x80,0xF3};
+static char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 };
 
 
 void __init aarp_proto_init(void)
 {
-	if((aarp_dl=register_snap_client(aarp_snap_id, aarp_rcv))==NULL)
+	if ((aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv)) == NULL)
 		printk(KERN_CRIT "Unable to register AARP with SNAP.\n");
 	init_timer(&aarp_timer);
-	aarp_timer.function=aarp_expire_timeout;
-	aarp_timer.data=0;
-	aarp_timer.expires=jiffies+sysctl_aarp_expiry_time;
+	aarp_timer.function = aarp_expire_timeout;
+	aarp_timer.data = 0;
+	aarp_timer.expires = jiffies + sysctl_aarp_expiry_time;
 	add_timer(&aarp_timer);
 	register_netdevice_notifier(&aarp_notifier);
 }
 
-
-
 /*
  * Remove the AARP entries associated with a device.
  */
 void aarp_device_down(struct net_device *dev)
 {
-	int ct = 0;
+	int ct;
+
+	spin_lock_bh(&aarp_lock);
 
-	for(ct = 0; ct < AARP_HASH_SIZE; ct++)
-	{
-		aarp_expire_device(&resolved[ct], dev);
-		aarp_expire_device(&unresolved[ct], dev);
-		aarp_expire_device(&proxies[ct], dev);
+	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
+		__aarp_expire_device(&resolved[ct], dev);
+		__aarp_expire_device(&unresolved[ct], dev);
+		__aarp_expire_device(&proxies[ct], dev);
 	}
 
-	return;
+	spin_unlock_bh(&aarp_lock);
 }
 
 /*
@@ -1064,10 +1094,11 @@
 	len = sprintf(buffer,
 		"%-10.10s  ""%-10.10s""%-18.18s""%12.12s""%12.12s"" xmit_count  status\n",
 		"address","device","hw addr","last_sent", "expires");
-	for (ct = 0; ct < AARP_HASH_SIZE; ct++)
-	{
-		for (entry = resolved[ct]; entry; entry = entry->next)
-		{
+
+	spin_lock_bh(&aarp_lock);
+
+	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
+		for (entry = resolved[ct]; entry; entry = entry->next) {
 			len+= sprintf(buffer+len,"%6u:%-3u  ",
 				(unsigned int)ntohs(entry->target_addr.s_net),
 				(unsigned int)(entry->target_addr.s_node));
@@ -1090,10 +1121,8 @@
 		}
 	}
 
-	for (ct = 0; ct < AARP_HASH_SIZE; ct++)
-	{
-		for (entry = unresolved[ct]; entry; entry = entry->next)
-		{
+	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
+		for (entry = unresolved[ct]; entry; entry = entry->next) {
 			len+= sprintf(buffer+len,"%6u:%-3u  ",
 				(unsigned int)ntohs(entry->target_addr.s_net),
 				(unsigned int)(entry->target_addr.s_node));
@@ -1115,10 +1144,8 @@
 		}
 	}
 
-	for (ct = 0; ct < AARP_HASH_SIZE; ct++)
-	{
-		for (entry = proxies[ct]; entry; entry = entry->next)
-		{
+	for (ct = 0; ct < AARP_HASH_SIZE; ct++) {
+		for (entry = proxies[ct]; entry; entry = entry->next) {
 			len+= sprintf(buffer+len,"%6u:%-3u  ",
 				(unsigned int)ntohs(entry->target_addr.s_net),
 				(unsigned int)(entry->target_addr.s_node));
@@ -1140,6 +1167,7 @@
 		}
 	}
 
+	spin_unlock_bh(&aarp_lock);
 
 	return len;
 }
diff -u --recursive --new-file v2.3.50/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.3.50/linux/net/appletalk/ddp.c	Tue Nov 23 22:42:21 1999
+++ linux/net/appletalk/ddp.c	Fri Mar 10 09:43:04 2000
@@ -71,6 +71,7 @@
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
+#include <linux/spinlock.h>
 #include <linux/termios.h>	/* For TIOCOUTQ/INQ */
 #include <net/datalink.h>
 #include <net/p8022.h>
@@ -118,49 +119,50 @@
 *                                                                          *
 \**************************************************************************/
 
-static struct sock *atalk_socket_list = NULL;
+static struct sock *atalk_sockets = NULL;
+static spinlock_t atalk_sockets_lock = SPIN_LOCK_UNLOCKED;
 
-/*
- * Note: Sockets may not be removed _during_ an interrupt or inet_bh
- * handler using this technique. They can be added although we do not
- * use this facility.
- */
-
-extern inline void atalk_remove_socket(struct sock *sk)
+extern inline void atalk_insert_socket(struct sock *sk)
 {
-	sklist_remove_socket(&atalk_socket_list,sk);
+	spin_lock_bh(&atalk_sockets_lock);
+	if ((sk->next = atalk_sockets) != NULL)
+		atalk_sockets->pprev = &sk->next;
+	atalk_sockets = sk;
+	sk->pprev = &atalk_sockets;
+	spin_unlock_bh(&atalk_sockets_lock);
 }
 
-extern inline void atalk_insert_socket(struct sock *sk)
+extern inline void atalk_remove_socket(struct sock *sk)
 {
-	sklist_insert_socket(&atalk_socket_list,sk);
+	spin_lock_bh(&atalk_sockets_lock);
+	if (sk->pprev != NULL) {
+		if (sk->next)
+			sk->next->pprev = sk->pprev;
+		*sk->pprev = sk->next;
+		sk->pprev = NULL;
+	}
+	spin_unlock_bh(&atalk_sockets_lock);
 }
 
 static struct sock *atalk_search_socket(struct sockaddr_at *to, struct atalk_iface *atif)
 {
 	struct sock *s;
 
-	for(s = atalk_socket_list; s != NULL; s = s->next)
-	{
-		if(to->sat_port != s->protinfo.af_at.src_port)
-		{
+	spin_lock_bh(&atalk_sockets_lock);
+	for (s = atalk_sockets; s != NULL; s = s->next) {
+		if (to->sat_port != s->protinfo.af_at.src_port)
 			continue;
-	   	}
 
-	    	if(to->sat_addr.s_net == ATADDR_ANYNET
-			&& to->sat_addr.s_node == ATADDR_BCAST
-			&& s->protinfo.af_at.src_net == atif->address.s_net)
-		{
+	    	if (to->sat_addr.s_net == ATADDR_ANYNET &&
+		    to->sat_addr.s_node == ATADDR_BCAST &&
+		    s->protinfo.af_at.src_net == atif->address.s_net)
 			break;
-	    	}
 
-	    	if(to->sat_addr.s_net == s->protinfo.af_at.src_net
-			&& (to->sat_addr.s_node == s->protinfo.af_at.src_node
-		     	|| to->sat_addr.s_node == ATADDR_BCAST
-			|| to->sat_addr.s_node == ATADDR_ANYNODE))
-		{
+	    	if (to->sat_addr.s_net == s->protinfo.af_at.src_net &&
+		    (to->sat_addr.s_node == s->protinfo.af_at.src_node ||
+		     to->sat_addr.s_node == ATADDR_BCAST ||
+		     to->sat_addr.s_node == ATADDR_ANYNODE))
 			break;
-	   	}
 
 	    	/* XXXX.0 -- we got a request for this router. make sure
 		 * that the node is appropriately set. */
@@ -171,44 +173,80 @@
 			break; 
 		}
 	}
+	spin_unlock_bh(&atalk_sockets_lock);
 
-	return (s);
+	return s;
 }
 
 /*
- * Find a socket in the list.
+ * Try to find a socket matching ADDR in the socket list,
+ * if found then return it.  If not, insert SK into the
+ * socket list.
+ *
+ * This entire operation must execute atomically.
  */
-static struct sock *atalk_find_socket(struct sockaddr_at *sat)
+static struct sock *atalk_find_or_insert_socket(struct sock *sk, struct sockaddr_at *sat)
 {
 	struct sock *s;
 
-	for(s = atalk_socket_list; s != NULL; s = s->next)
-	{
-		if(s->protinfo.af_at.src_net != sat->sat_addr.s_net)
-		{
-			continue;
-		}
+	spin_lock_bh(&atalk_sockets_lock);
 
-		if(s->protinfo.af_at.src_node != sat->sat_addr.s_node)
-		{
-			continue;
-		}
-
-		if(s->protinfo.af_at.src_port != sat->sat_port)
-		{
-			continue;
-		}
+	for (s = atalk_sockets; s != NULL; s = s->next) {
+		if (s->protinfo.af_at.src_net == sat->sat_addr.s_net &&
+		    s->protinfo.af_at.src_node == sat->sat_addr.s_node &&
+		    s->protinfo.af_at.src_port == sat->sat_port)
+			break;
+	}
 
-		break;
+	if (!s) {
+		/* Wheee, it's free, assign and insert. */
+		if ((sk->next = atalk_sockets) != NULL)
+			atalk_sockets->pprev = &sk->next;
+		atalk_sockets = sk;
+		sk->pprev = &atalk_sockets;
 	}
 
-	return (s);
+	spin_unlock_bh(&atalk_sockets_lock);
+
+	return s;
+}
+
+static void atalk_destroy_timer(unsigned long data)
+{
+	struct sock *sk = (struct sock *) data;
+
+	if (atomic_read(&sk->wmem_alloc) == 0 &&
+	    atomic_read(&sk->rmem_alloc) == 0 &&
+	    sk->dead) {
+		sock_put(sk);
+		MOD_DEC_USE_COUNT;
+	} else {
+		sk->timer.expires = jiffies + SOCK_DESTROY_TIME;
+		add_timer(&sk->timer);
+	}
 }
 
 extern inline void atalk_destroy_socket(struct sock *sk)
 {
-	sklist_destroy_socket(&atalk_socket_list, sk);
-	MOD_DEC_USE_COUNT;
+	struct sk_buff *skb;
+
+	atalk_remove_socket(sk);
+
+	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL)
+		kfree_skb(skb);
+
+	if (atomic_read(&sk->wmem_alloc) == 0 &&
+	    atomic_read(&sk->rmem_alloc) == 0 &&
+	    sk->dead) {
+		sock_put(sk);
+		MOD_DEC_USE_COUNT;
+	} else {
+		init_timer(&sk->timer);
+		sk->timer.expires = jiffies + SOCK_DESTROY_TIME;
+		sk->timer.function = atalk_destroy_timer;
+		sk->timer.data = (unsigned long) sk;
+		add_timer(&sk->timer);
+	}
 }
 
 /*
@@ -217,51 +255,52 @@
 static int atalk_get_info(char *buffer, char **start, off_t offset, int length)
 {
 	struct sock *s;
-	int len=0;
-	off_t pos=0;
-	off_t begin=0;
+	int len = 0;
+	off_t pos = 0;
+	off_t begin = 0;
 
 	/*
 	 * Output the AppleTalk data for the /proc filesystem.
 	 */
 
 	len += sprintf(buffer,"Type local_addr  remote_addr tx_queue rx_queue st uid\n");
-	for(s = atalk_socket_list; s != NULL; s = s->next)
-	{
+
+	spin_lock_bh(&atalk_sockets_lock);
+	for (s = atalk_sockets; s != NULL; s = s->next) {
 		len += sprintf(buffer+len,"%02X   ", s->type);
 		len += sprintf(buffer+len,"%04X:%02X:%02X  ",
-			ntohs(s->protinfo.af_at.src_net),
-			s->protinfo.af_at.src_node,
-			s->protinfo.af_at.src_port);
+			       ntohs(s->protinfo.af_at.src_net),
+			       s->protinfo.af_at.src_node,
+			       s->protinfo.af_at.src_port);
 		len += sprintf(buffer+len,"%04X:%02X:%02X  ",
-			ntohs(s->protinfo.af_at.dest_net),
-			s->protinfo.af_at.dest_node,
-			s->protinfo.af_at.dest_port);
+			       ntohs(s->protinfo.af_at.dest_net),
+			       s->protinfo.af_at.dest_node,
+			       s->protinfo.af_at.dest_port);
 		len += sprintf(buffer+len,"%08X:%08X ",
-			atomic_read(&s->wmem_alloc),
-			atomic_read(&s->rmem_alloc));
+			       atomic_read(&s->wmem_alloc),
+			       atomic_read(&s->rmem_alloc));
 		len += sprintf(buffer+len,"%02X %d\n", s->state, 
-			SOCK_INODE(s->socket)->i_uid);
+			       SOCK_INODE(s->socket)->i_uid);
 
 		/* Are we still dumping unwanted data then discard the record */
 		pos = begin + len;
 
-		if(pos < offset)
-		{
+		if (pos < offset) {
 			len = 0;	/* Keep dumping into the buffer start */
 			begin = pos;
 		}
-		if(pos > offset + length)	/* We have dumped enough */
+		if (pos > offset + length)	/* We have dumped enough */
 			break;
 	}
+	spin_lock_bh(&atalk_sockets_lock);
 
 	/* The data in question runs from begin to begin+len */
 	*start = buffer + (offset - begin);	/* Start of wanted data */
 	len -= (offset - begin);   /* Remove unwanted header data from length */
-	if(len > length)
+	if (len > length)
 		len = length;	   /* Remove unwanted tail data from length */
 
-	return (len);
+	return len;
 }
 
 /**************************************************************************\
@@ -270,8 +309,13 @@
 *                                                                          *
 \**************************************************************************/
 
+/* Anti-deadlock ordering is router_lock --> iface_lock -DaveM */
 static struct atalk_route *atalk_router_list = NULL;
+static rwlock_t atalk_router_lock = RW_LOCK_UNLOCKED;
+
 static struct atalk_iface *atalk_iface_list  = NULL;
+static spinlock_t atalk_iface_lock = SPIN_LOCK_UNLOCKED;
+
 static struct atalk_route atrtr_default; /* For probing devices or in a routerless network */
 
 /*
@@ -287,43 +331,40 @@
 	struct atalk_iface **iface = &atalk_iface_list;
 	struct atalk_iface *tmp;
 
-	while((tmp = *iface) != NULL)
-	{
-		if(tmp->dev == dev)
-		{
+	spin_lock_bh(&atalk_iface_lock);
+	while ((tmp = *iface) != NULL) {
+		if (tmp->dev == dev) {
 			*iface = tmp->next;
 			kfree_s(tmp, sizeof(struct atalk_iface));
-			dev->atalk_ptr=NULL;
+			dev->atalk_ptr = NULL;
 			MOD_DEC_USE_COUNT;
-		}
-		else
+		} else
 			iface = &tmp->next;
 	}
-
+	spin_unlock_bh(&atalk_iface_lock);
 }
 
 static struct atalk_iface *atif_add_device(struct net_device *dev, struct at_addr *sa)
 {
 	struct atalk_iface *iface = (struct atalk_iface *)
 		kmalloc(sizeof(*iface), GFP_KERNEL);
-	unsigned long flags;
 
-	if(iface==NULL)
-		return (NULL);
+	if (iface == NULL)
+		return NULL;
 
-	iface->dev=dev;
-	dev->atalk_ptr=iface;
-	iface->address= *sa;
-	iface->status=0;
-	save_flags(flags);
-	cli();
-	iface->next=atalk_iface_list;
-	atalk_iface_list=iface;
-	restore_flags(flags);
+	iface->dev = dev;
+	dev->atalk_ptr = iface;
+	iface->address = *sa;
+	iface->status = 0;
+
+	spin_lock_bh(&atalk_iface_lock);
+	iface->next = atalk_iface_list;
+	atalk_iface_list = iface;
+	spin_unlock_bh(&atalk_iface_lock);
 
 	MOD_INC_USE_COUNT;
 
-	return (iface);
+	return iface;
 }
 
 
@@ -332,60 +373,57 @@
  */
 static int atif_probe_device(struct atalk_iface *atif)
 {
-	int netrange=ntohs(atif->nets.nr_lastnet)-ntohs(atif->nets.nr_firstnet)+1;
-	int probe_net=ntohs(atif->address.s_net);
-	int probe_node=atif->address.s_node;
+	int netrange = ntohs(atif->nets.nr_lastnet) - ntohs(atif->nets.nr_firstnet) + 1;
+	int probe_net = ntohs(atif->address.s_net);
+	int probe_node = atif->address.s_node;
 	int netct, nodect;
 
 	/*
 	 * Offset the network we start probing with.
 	 */
 
-	if(probe_net == ATADDR_ANYNET)
-	{
-		if(!netrange)
+	if (probe_net == ATADDR_ANYNET) {
+		if (!netrange)
 			probe_net = ntohs(atif->nets.nr_firstnet);
 		else
-			probe_net = ntohs(atif->nets.nr_firstnet) + (jiffies%netrange);
+			probe_net = ntohs(atif->nets.nr_firstnet) + (jiffies % netrange);
 	}
 
-	if(probe_node == ATADDR_ANYNODE)
-		probe_node = jiffies&0xFF;
+	if (probe_node == ATADDR_ANYNODE)
+		probe_node = jiffies & 0xFF;
 
 	/*
 	 * Scan the networks.
 	 */
 	atif->status |= ATIF_PROBE;
-	for(netct = 0; netct <= netrange; netct++)
-	{
+	for (netct = 0; netct <= netrange; netct++) {
 		/*
 		 * Sweep the available nodes from a given start.
 		 */
 
 		atif->address.s_net = htons(probe_net);
-		for(nodect = 0; nodect < 256; nodect++)
-		{
+		for (nodect = 0; nodect < 256; nodect++) {
 			atif->address.s_node = ((nodect+probe_node) & 0xFF);
-			if(atif->address.s_node > 0 && atif->address.s_node<254)
-			{
+			if (atif->address.s_node > 0 && atif->address.s_node < 254) {
 				/*
 				 * Probe a proposed address.
 				 */
 				aarp_probe_network(atif);
 
-				if(!(atif->status & ATIF_PROBE_FAIL)) {
+				if (!(atif->status & ATIF_PROBE_FAIL)) {
 					atif->status &= ~ATIF_PROBE;
-					return (0);
+					return 0;
 				}
 			}
 			atif->status &= ~ATIF_PROBE_FAIL;
 		}
 		probe_net++;
-		if(probe_net > ntohs(atif->nets.nr_lastnet))
+		if (probe_net > ntohs(atif->nets.nr_lastnet))
 			probe_net = ntohs(atif->nets.nr_firstnet);
 	}
 	atif->status &= ~ATIF_PROBE;
-	return (-EADDRINUSE);	/* Network is full... */
+
+	return -EADDRINUSE;	/* Network is full... */
 }
 
 
@@ -394,46 +432,43 @@
  */
 static int atif_proxy_probe_device(struct atalk_iface *atif, struct at_addr* proxy_addr)
 {
-	int netrange=ntohs(atif->nets.nr_lastnet)-ntohs(atif->nets.nr_firstnet)+1;
-	int probe_net=ntohs(atif->address.s_net);	// we probe the interface's network
-	int probe_node=ATADDR_ANYNODE;				// we'll take anything
+	int netrange = ntohs(atif->nets.nr_lastnet) - ntohs(atif->nets.nr_firstnet) + 1;
+	int probe_net = ntohs(atif->address.s_net); /* we probe the interface's network */
+	int probe_node = ATADDR_ANYNODE;	    /* we'll take anything */
 	int netct, nodect;
 
 	/*
 	 * Offset the network we start probing with.
 	 */
 
-	if(probe_net == ATADDR_ANYNET)
-	{
-		if(!netrange)
+	if (probe_net == ATADDR_ANYNET) {
+		if (!netrange)
 			probe_net = ntohs(atif->nets.nr_firstnet);
 		else
-			probe_net = ntohs(atif->nets.nr_firstnet) + (jiffies%netrange);
+			probe_net = ntohs(atif->nets.nr_firstnet) + (jiffies % netrange);
 	}
 
-	if(probe_node == ATADDR_ANYNODE)
-		probe_node = jiffies&0xFF;
+	if (probe_node == ATADDR_ANYNODE)
+		probe_node = jiffies & 0xFF;
 		
 	/*
 	 * Scan the networks.
 	 */
 
-	for(netct = 0; netct <= netrange; netct++)
-	{
+	for (netct = 0; netct <= netrange; netct++) {
 		/*
 		 * Sweep the available nodes from a given start.
 		 */
 
 		proxy_addr->s_net = htons(probe_net);
-		for(nodect = 0; nodect < 256; nodect++)
-		{
-			proxy_addr->s_node = ((nodect+probe_node) & 0xFF);
-			if((proxy_addr->s_node>0) && (proxy_addr->s_node<254))
-			{
+		for (nodect = 0; nodect < 256; nodect++) {
+			proxy_addr->s_node = ((nodect + probe_node) & 0xFF);
+			if ((proxy_addr->s_node > 0) && (proxy_addr->s_node < 254)) {
 				/*
 				 * Tell AARP to probe a proposed address.
 				 */
-				int probe_result = aarp_proxy_probe_network(atif, proxy_addr);
+				int probe_result = aarp_proxy_probe_network(atif,
+									    proxy_addr);
 
 				if (probe_result == 0)
 					return 0;
@@ -447,22 +482,23 @@
 			probe_net = ntohs(atif->nets.nr_firstnet);
 	}
 
-	return (-EADDRINUSE);	/* Network is full... */
+	return -EADDRINUSE;	/* Network is full... */
 }
 
 
 struct at_addr *atalk_find_dev_addr(struct net_device *dev)
 {
-	struct atalk_iface *iface=dev->atalk_ptr;
+	struct atalk_iface *iface = dev->atalk_ptr;
 
 	if(iface)
-		return (&iface->address);
+		return &iface->address;
 
-	return (NULL);
+	return NULL;
 }
 
 static struct at_addr *atalk_find_primary(void)
 {
+	struct at_addr *retval;
 	struct atalk_iface *iface;
 	struct atalk_iface *fiface = NULL;
 
@@ -470,20 +506,27 @@
 	 * Return a point-to-point interface only if
 	 * there is no non-ptp interface available.
 	 */
-	for(iface=atalk_iface_list; iface != NULL; iface=iface->next)
-	{
-		if(!fiface && !(iface->dev->flags & IFF_LOOPBACK))
-			fiface=iface;
-		if(!(iface->dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
-			return (&iface->address);
+	spin_lock_bh(&atalk_iface_lock);
+	for (iface = atalk_iface_list; iface != NULL; iface = iface->next) {
+		if (!fiface && !(iface->dev->flags & IFF_LOOPBACK))
+			fiface = iface;
+		if (!(iface->dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
+			retval = &iface->address;
+			goto out;
+		}
 	}
 
-	if(fiface)
-		return (&fiface->address);
-	if(atalk_iface_list != NULL)
-		return (&atalk_iface_list->address);
-	else
-		return (NULL);
+	if (fiface) {
+		retval = &fiface->address;
+	} else if (atalk_iface_list != NULL) {
+		retval = &atalk_iface_list->address;
+	} else {
+		retval = NULL;
+	}
+out:
+	spin_unlock_bh(&atalk_iface_lock);
+
+	return retval;
 }
 
 /*
@@ -494,13 +537,15 @@
 {
 	struct atalk_iface *iface=dev->atalk_ptr;
 
-	if(iface==NULL || (iface->status & ATIF_PROBE))
-		return (NULL);
-	if(node == ATADDR_BCAST || iface->address.s_node == node
-		|| node == ATADDR_ANYNODE)
-		return (iface);
+	if (iface==NULL || (iface->status & ATIF_PROBE))
+		return NULL;
 
-	return (NULL);
+	if (node == ATADDR_BCAST ||
+	    iface->address.s_node == node ||
+	    node == ATADDR_ANYNODE)
+		return iface;
+
+	return NULL;
 }
 
 /*
@@ -510,22 +555,24 @@
 {
 	struct atalk_iface *iface;
 
-	for(iface=atalk_iface_list; iface != NULL; iface=iface->next)
-	{
-		if((node==ATADDR_BCAST || node==ATADDR_ANYNODE 
-			|| iface->address.s_node==node)
-			&& iface->address.s_net==net 
-			&& !(iface->status & ATIF_PROBE))
-			return (iface);
+	spin_lock_bh(&atalk_iface_lock);
+	for (iface = atalk_iface_list; iface != NULL; iface = iface->next) {
+		if ((node == ATADDR_BCAST ||
+		     node == ATADDR_ANYNODE ||
+		     iface->address.s_node == node) &&
+		    iface->address.s_net == net &&
+		    !(iface->status & ATIF_PROBE))
+			break;
 
 		/* XXXX.0 -- net.0 returns the iface associated with net */
-		if ((node==ATADDR_ANYNODE) && (net != ATADDR_ANYNET) &&
+		if ((node == ATADDR_ANYNODE) && (net != ATADDR_ANYNET) &&
 		    (ntohs(iface->nets.nr_firstnet) <= ntohs(net)) &&
 		    (ntohs(net) <= ntohs(iface->nets.nr_lastnet)))
-		        return (iface);
+		        break;
 	}
+	spin_unlock_bh(&atalk_iface_lock);
 
-	return (NULL);
+	return iface;
 }
 
 
@@ -544,23 +591,20 @@
 	struct atalk_route *r;
 	struct atalk_route *net_route = NULL;
 	
-	for(r=atalk_router_list; r != NULL; r=r->next)
-	{
-		if(!(r->flags & RTF_UP))
+	read_lock_bh(&atalk_router_lock);
+	for (r = atalk_router_list; r != NULL; r = r->next) {
+		if (!(r->flags & RTF_UP))
 			continue;
-		if(r->target.s_net == target->s_net)
-		{
-			if (r->flags & RTF_HOST)
-			{
+
+		if (r->target.s_net == target->s_net) {
+			if (r->flags & RTF_HOST) {
 				/*
 				 * if this host route is for the target,
 				 * the we're done
 				 */
 				if (r->target.s_node == target->s_node)
-					return (r);
-			}
-			else
-			{
+					goto out;
+			} else {
 				/*
 				 * this route will work if there isn't a
 				 * direct host route, so cache it
@@ -574,13 +618,20 @@
 	 * if we found a network route but not a direct host
 	 * route, then return it
 	 */
-	if (net_route != NULL)
-		return (net_route);
-
-	if(atrtr_default.dev)
-		return (&atrtr_default);
+	if (net_route != NULL) {
+		r = net_route;
+	} else if (atrtr_default.dev) {
+		r = &atrtr_default;
+	} else {
+		/*
+		 * No route can be found.
+		 */
+		r = NULL;
+	}
 
-	return (NULL);
+out:
+	read_unlock_bh(&atalk_router_lock);
+	return r;
 }
 
 
@@ -590,12 +641,12 @@
  */
 struct net_device *atrtr_get_dev(struct at_addr *sa)
 {
-	struct atalk_route *atr=atrtr_find(sa);
+	struct atalk_route *atr = atrtr_find(sa);
 
-	if(atr == NULL)
-		return (NULL);
+	if (atr == NULL)
+		return NULL;
 	else
-		return (atr->dev);
+		return atr->dev;
 }
 
 /*
@@ -616,13 +667,11 @@
  */
 static int atrtr_create(struct rtentry *r, struct net_device *devhint)
 {
-	struct sockaddr_at *ta=(struct sockaddr_at *)&r->rt_dst;
-	struct sockaddr_at *ga=(struct sockaddr_at *)&r->rt_gateway;
+	struct sockaddr_at *ta = (struct sockaddr_at *)&r->rt_dst;
+	struct sockaddr_at *ga = (struct sockaddr_at *)&r->rt_gateway;
 	struct atalk_route *rt;
 	struct atalk_iface *iface, *riface;
-	unsigned long flags;
-
-	save_flags(flags);
+	int retval;
 
 	/*
 	 * Fixme: Raise/Lower a routing change semaphore for these
@@ -632,53 +681,59 @@
 	/*
 	 * Validate the request
 	 */
-	if(ta->sat_family != AF_APPLETALK)
-		return (-EINVAL);
-	if(devhint == NULL && ga->sat_family != AF_APPLETALK)
-		return (-EINVAL);
+	if (ta->sat_family != AF_APPLETALK)
+		return -EINVAL;
+
+	if (devhint == NULL && ga->sat_family != AF_APPLETALK)
+		return -EINVAL;
 
 	/*
 	 * Now walk the routing table and make our decisions.
 	 */
-	for(rt=atalk_router_list; rt!=NULL; rt=rt->next)
-	{
-		if(r->rt_flags != rt->flags)
+	write_lock_bh(&atalk_router_lock);
+	for (rt = atalk_router_list; rt != NULL; rt = rt->next) {
+		if (r->rt_flags != rt->flags)
 			continue;
 
-		if(ta->sat_addr.s_net == rt->target.s_net)
-		{
-			if(!(rt->flags & RTF_HOST))
+		if (ta->sat_addr.s_net == rt->target.s_net) {
+			if (!(rt->flags & RTF_HOST))
 				break;
-			if(ta->sat_addr.s_node == rt->target.s_node)
+			if (ta->sat_addr.s_node == rt->target.s_node)
 				break;
 		}
 	}
 
-	if(devhint == NULL)
-	{
-		for(riface = NULL, iface = atalk_iface_list; iface; iface = iface->next)
-		{
-			if(riface == NULL && ntohs(ga->sat_addr.s_net) >= ntohs(iface->nets.nr_firstnet) &&
-				ntohs(ga->sat_addr.s_net) <= ntohs(iface->nets.nr_lastnet))
-			{
+	if(devhint == NULL) {
+		riface = NULL;
+
+		spin_lock_bh(&atalk_iface_lock);
+		for (iface = atalk_iface_list; iface; iface = iface->next) {
+			if (riface == NULL &&
+			    ntohs(ga->sat_addr.s_net) >= ntohs(iface->nets.nr_firstnet) &&
+			    ntohs(ga->sat_addr.s_net) <= ntohs(iface->nets.nr_lastnet))
 				riface = iface;
-			}
-			if(ga->sat_addr.s_net == iface->address.s_net 
-				&& ga->sat_addr.s_node == iface->address.s_node)
+
+			if (ga->sat_addr.s_net == iface->address.s_net  &&
+			    ga->sat_addr.s_node == iface->address.s_node)
 				riface = iface;
-		}
+		}		
+		spin_unlock_bh(&atalk_iface_lock);
+
+		retval = -ENETUNREACH;
+		if (riface == NULL)
+			goto out;
 
-		if(riface == NULL)
-			return (-ENETUNREACH);
 		devhint = riface->dev;
 	}
 
-	if(rt == NULL)
-	{
-		rt = (struct atalk_route *)kmalloc(sizeof(struct atalk_route), GFP_KERNEL);
-		if(rt == NULL)
-			return (-ENOBUFS);
-		cli();
+	if (rt == NULL) {
+		rt = (struct atalk_route *)
+			kmalloc(sizeof(struct atalk_route), GFP_ATOMIC);
+
+		retval = -ENOBUFS;
+		if (rt == NULL)
+			goto out;
+
 		rt->next = atalk_router_list;
 		atalk_router_list = rt;
 	}
@@ -691,33 +746,38 @@
 	rt->flags   = r->rt_flags;
 	rt->gateway = ga->sat_addr;
 
-	restore_flags(flags);
+	retval = 0;
 
-	return (0);
+out:
+	write_unlock_bh(&atalk_router_lock);
+
+	return retval;
 }
 
 /*
  * Delete a route. Find it and discard it.
  */
-static int atrtr_delete( struct at_addr *addr )
+static int atrtr_delete(struct at_addr * addr)
 {
 	struct atalk_route **r = &atalk_router_list;
 	struct atalk_route *tmp;
+	int retval = 0;
 
-	while((tmp = *r) != NULL)
-	{
-		if(tmp->target.s_net == addr->s_net
-			&& (!(tmp->flags&RTF_GATEWAY)
-			|| tmp->target.s_node == addr->s_node))
-		{
+	write_lock_bh(&atalk_router_lock);
+	while ((tmp = *r) != NULL) {
+		if (tmp->target.s_net == addr->s_net &&
+		    (!(tmp->flags&RTF_GATEWAY) ||
+		     tmp->target.s_node == addr->s_node)) {
 			*r = tmp->next;
 			kfree_s(tmp, sizeof(struct atalk_route));
-			return (0);
+			goto out;
 		}
 		r = &tmp->next;
 	}
-
-	return (-ENOENT);
+	retval = -ENOENT;
+out:
+	write_unlock_bh(&atalk_router_lock);
+	return retval;
 }
 
 /*
@@ -729,18 +789,18 @@
 	struct atalk_route **r = &atalk_router_list;
 	struct atalk_route *tmp;
 
-	while((tmp = *r) != NULL)
-	{
-		if(tmp->dev == dev)
-		{
+	write_lock_bh(&atalk_router_lock);
+	while ((tmp = *r) != NULL) {
+		if (tmp->dev == dev) {
 			*r = tmp->next;
 			kfree_s(tmp, sizeof(struct atalk_route));
-		}
-		else
+		} else {
 			r = &tmp->next;
+		}
 	}
+	write_unlock_bh(&atalk_router_lock);
 
-	if(atrtr_default.dev == dev)
+	if (atrtr_default.dev == dev)
 		atrtr_set_default(NULL);
 }
 
@@ -760,13 +820,12 @@
  */
 static int ddp_device_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-	if(event == NETDEV_DOWN)
-	{
+	if (event == NETDEV_DOWN) {
 		/* Discard any use of this */
 	        atalk_dev_down((struct net_device *) ptr);
 	}
 
-	return (NOTIFY_DONE);
+	return NOTIFY_DONE;
 }
 
 /*
@@ -789,29 +848,28 @@
 	struct rtentry rtdef;
 	int	add_route;
 
-	if(copy_from_user(&atreq,arg,sizeof(atreq)))
-		return (-EFAULT);
+	if (copy_from_user(&atreq, arg, sizeof(atreq)))
+		return -EFAULT;
 
-	if((dev = __dev_get_by_name(atreq.ifr_name)) == NULL)
-		return (-ENODEV);
+	if ((dev = __dev_get_by_name(atreq.ifr_name)) == NULL)
+		return -ENODEV;
 
-	sa=(struct sockaddr_at*)&atreq.ifr_addr;
-	atif=atalk_find_dev(dev);
+	sa = (struct sockaddr_at*) &atreq.ifr_addr;
+	atif = atalk_find_dev(dev);
 
-	switch(cmd)
-	{
+	switch (cmd) {
 		case SIOCSIFADDR:
-			if(!capable(CAP_NET_ADMIN))
-				return (-EPERM);
-			if(sa->sat_family != AF_APPLETALK)
-				return (-EINVAL);
-			if(dev->type != ARPHRD_ETHER
-				&& dev->type != ARPHRD_LOOPBACK
-				&& dev->type != ARPHRD_LOCALTLK
-				&& dev->type != ARPHRD_PPP)
-				return (-EPROTONOSUPPORT);
+			if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+			if (sa->sat_family != AF_APPLETALK)
+				return -EINVAL;
+			if (dev->type != ARPHRD_ETHER &&
+			    dev->type != ARPHRD_LOOPBACK &&
+			    dev->type != ARPHRD_LOCALTLK &&
+			    dev->type != ARPHRD_PPP)
+				return -EPROTONOSUPPORT;
 
-			nr=(struct netrange *)&sa->sat_zero[0];
+			nr = (struct netrange *) &sa->sat_zero[0];
 
 			add_route = 1;
 
@@ -819,8 +877,8 @@
 			 * if this is a point-to-point iface, and we already have an 
 			 * iface for this AppleTalk address, then we should not add a route
 			 */
-			if (dev->flags & IFF_POINTOPOINT && atalk_find_interface(sa->sat_addr.s_net, sa->sat_addr.s_node))
-			{
+			if ((dev->flags & IFF_POINTOPOINT) &&
+			    atalk_find_interface(sa->sat_addr.s_net, sa->sat_addr.s_node)) {
 				printk(KERN_DEBUG "AppleTalk: point-to-point interface added with existing address\n");
 				add_route = 0;
 			}
@@ -829,123 +887,123 @@
 			 * Phase 1 is fine on LocalTalk but we don't do
 			 * EtherTalk phase 1. Anyone wanting to add it go ahead.
 			 */
-			if(dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
-				return (-EPROTONOSUPPORT);
-			if(sa->sat_addr.s_node == ATADDR_BCAST 
-				|| sa->sat_addr.s_node == 254)
-				return (-EINVAL);
-			if(atif)
-			{
+			if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+				return -EPROTONOSUPPORT;
+			if (sa->sat_addr.s_node == ATADDR_BCAST  ||
+			    sa->sat_addr.s_node == 254)
+				return -EINVAL;
+			if (atif) {
 				/*
 				 * Already setting address.
 				 */
-				if(atif->status&ATIF_PROBE)
-					return (-EBUSY);
+				if (atif->status & ATIF_PROBE)
+					return -EBUSY;
 
 				atif->address.s_net  = sa->sat_addr.s_net;
 				atif->address.s_node = sa->sat_addr.s_node;
 				atrtr_device_down(dev);	/* Flush old routes */
-			}
-			else
-			{
-				atif=atif_add_device(dev, &sa->sat_addr);
+			} else {
+				atif = atif_add_device(dev, &sa->sat_addr);
 				if (atif == NULL)
-					return (-ENOMEM);
+					return -ENOMEM;
 			}
-			atif->nets= *nr;
+			atif->nets = *nr;
 
 			/*
 			 * Check if the chosen address is used. If so we
 			 * error and atalkd will try another.
 			 */
 
-			if(!(dev->flags & IFF_LOOPBACK) && !(dev->flags & IFF_POINTOPOINT) && atif_probe_device(atif) < 0)
-			{
+			if (!(dev->flags & IFF_LOOPBACK) &&
+			    !(dev->flags & IFF_POINTOPOINT) &&
+			    atif_probe_device(atif) < 0) {
 				atif_drop_device(dev);
-				return (-EADDRINUSE);
+				return -EADDRINUSE;
 			}
 
 			/*
 			 * Hey it worked - add the direct routes.
 			 */
 
-			sa = (struct sockaddr_at *)&rtdef.rt_gateway;
+			sa = (struct sockaddr_at *) &rtdef.rt_gateway;
 			sa->sat_family = AF_APPLETALK;
 			sa->sat_addr.s_net  = atif->address.s_net;
 			sa->sat_addr.s_node = atif->address.s_node;
-			sa = (struct sockaddr_at *)&rtdef.rt_dst;
+			sa = (struct sockaddr_at *) &rtdef.rt_dst;
 			rtdef.rt_flags = RTF_UP;
 			sa->sat_family = AF_APPLETALK;
 			sa->sat_addr.s_node = ATADDR_ANYNODE;
-			if((dev->flags & IFF_LOOPBACK) || (dev->flags & IFF_POINTOPOINT))
+			if ((dev->flags & IFF_LOOPBACK) ||
+			    (dev->flags & IFF_POINTOPOINT))
 				rtdef.rt_flags |= RTF_HOST;
 
 			/*
 			 * Routerless initial state.
 			 */
-			if(nr->nr_firstnet == htons(0)
-				&& nr->nr_lastnet == htons(0xFFFE))
-			{
+			if (nr->nr_firstnet == htons(0) &&
+			    nr->nr_lastnet == htons(0xFFFE)) {
 				sa->sat_addr.s_net = atif->address.s_net;
 				atrtr_create(&rtdef, dev);
 				atrtr_set_default(dev);
-			}
-			else
-			{
+			} else {
 				limit = ntohs(nr->nr_lastnet);
-				if(limit - ntohs(nr->nr_firstnet) > 4096)
-				{
+				if (limit - ntohs(nr->nr_firstnet) > 4096) {
 					printk(KERN_WARNING "Too many routes/iface.\n");
-					return (-EINVAL);
+					return -EINVAL;
 				}
-				if (add_route)
-					for(ct=ntohs(nr->nr_firstnet);ct<=limit;ct++)
-					{
+				if (add_route) {
+					for(ct = ntohs(nr->nr_firstnet);ct <= limit; ct++) {
 						sa->sat_addr.s_net = htons(ct);
 						atrtr_create(&rtdef, dev);
 					}
+				}
 			}
 			dev_mc_add(dev, aarp_mcast, 6, 1);
-			return (0);
+			return 0;
 
 		case SIOCGIFADDR:
-			if(atif == NULL)
-				return (-EADDRNOTAVAIL);
-			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_family=AF_APPLETALK;
-			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr=atif->address;
+			if (atif == NULL)
+				return -EADDRNOTAVAIL;
+			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_family =
+				AF_APPLETALK;
+			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr =
+				atif->address;
 			break;
 
 		case SIOCGIFBRDADDR:
-			if(atif == NULL)
-				return (-EADDRNOTAVAIL);
-			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_family=AF_APPLETALK;
-			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr.s_net=atif->address.s_net;
-			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr.s_node=ATADDR_BCAST;
+			if (atif == NULL)
+				return -EADDRNOTAVAIL;
+			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_family =
+				AF_APPLETALK;
+			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr.s_net =
+				atif->address.s_net;
+			((struct sockaddr_at *)(&atreq.ifr_addr))->sat_addr.s_node =
+				ATADDR_BCAST;
 			break;
 
 	        case SIOCATALKDIFADDR:
 	        case SIOCDIFADDR:
-			if(!capable(CAP_NET_ADMIN))
-				return (-EPERM);
-			if(sa->sat_family != AF_APPLETALK)
-				return (-EINVAL);
+			if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+			if (sa->sat_family != AF_APPLETALK)
+				return -EINVAL;
 			atalk_dev_down(dev);
 			break;			
 
 		case SIOCSARP:
-			if(!capable(CAP_NET_ADMIN))
-                                return (-EPERM);
-                        if(sa->sat_family != AF_APPLETALK)
-                                return (-EINVAL);
+			if (!capable(CAP_NET_ADMIN))
+                                return -EPERM;
+                        if (sa->sat_family != AF_APPLETALK)
+                                return -EINVAL;
                         if (atif == NULL)
-                                return (-EADDRNOTAVAIL);
+                                return -EADDRNOTAVAIL;
 
                         /*
                          * for now, we only support proxy AARP on ELAP;
                          * we should be able to do it for LocalTalk, too.
                          */
-                        if(dev->type != ARPHRD_ETHER)
-                                return (-EPROTONOSUPPORT);
+                        if (dev->type != ARPHRD_ETHER)
+                                return -EPROTONOSUPPORT;
 
                         /*
                          * atif points to the current interface on this network;
@@ -954,28 +1012,28 @@
                          * to probe.  consequently, it must exist.
                          */
                         if (!atif)
-                                return (-EADDRNOTAVAIL);
+                                return -EADDRNOTAVAIL;
 
-                        nr=(struct netrange *)&(atif->nets);
+                        nr = (struct netrange *) &(atif->nets);
                         /*
                          * Phase 1 is fine on Localtalk but we don't do
                          * Ethertalk phase 1. Anyone wanting to add it go ahead.
                          */
-                        if(dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
-                                return (-EPROTONOSUPPORT);
+                        if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2)
+                                return -EPROTONOSUPPORT;
 
-                        if(sa->sat_addr.s_node == ATADDR_BCAST
-                                || sa->sat_addr.s_node == 254)
-                                return (-EINVAL);
+                        if (sa->sat_addr.s_node == ATADDR_BCAST ||
+			    sa->sat_addr.s_node == 254)
+                                return -EINVAL;
 
                         /*
                          * Check if the chosen address is used. If so we
                          * error and ATCP will try another.
                          */
                       	if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0)
-                      		return (-EADDRINUSE);
+                      		return -EADDRINUSE;
                       	
-                       /*
+			/*
                          * We now have an address on the local network, and the AARP
                          * code will defend it for us until we take it down.
                          * We don't set up any routes right now, because ATCP will
@@ -984,25 +1042,25 @@
                         break;
 
                 case SIOCDARP:
-                        if(!capable(CAP_NET_ADMIN))
-                                return (-EPERM);
-                        if(sa->sat_family != AF_APPLETALK)
-                                return (-EINVAL);
+                        if (!capable(CAP_NET_ADMIN))
+                                return -EPERM;
+                        if (sa->sat_family != AF_APPLETALK)
+                                return -EINVAL;
                         if (atif == NULL)
-                                return (-EADDRNOTAVAIL);
+                                return -EADDRNOTAVAIL;
 
                         /*
                          * give to aarp module to remove proxy entry
                          */
                         aarp_proxy_remove(atif->dev, &(sa->sat_addr));
 
-                        return (0);
-	}
+                        return 0;
+	};
 
-	if(copy_to_user(arg, &atreq, sizeof(atreq)))
-		return (-EFAULT);
+	if (copy_to_user(arg, &atreq, sizeof(atreq)))
+		return -EFAULT;
 
-	return (0);
+	return 0;
 }
 
 /*
@@ -1013,27 +1071,26 @@
 	struct rtentry rt;
 	struct net_device *dev = NULL;
 
-	if(copy_from_user(&rt, arg, sizeof(rt)))
-		return (-EFAULT);
+	if (copy_from_user(&rt, arg, sizeof(rt)))
+		return -EFAULT;
 
-	switch(cmd)
-	{
+	switch (cmd) {
 		case SIOCDELRT:
-			if(rt.rt_dst.sa_family != AF_APPLETALK)
-				return (-EINVAL);
-			return (atrtr_delete(&((struct sockaddr_at *)&rt.rt_dst)->sat_addr));
+			if (rt.rt_dst.sa_family != AF_APPLETALK)
+				return -EINVAL;
+			return atrtr_delete(&((struct sockaddr_at *)&rt.rt_dst)->sat_addr);
 
 		case SIOCADDRT:
 			/* FIX ME: the name of the device is still in user space, isn't it? */
-			if (rt.rt_dev != NULL)
+			if (rt.rt_dev != NULL) {
 				if ((dev = __dev_get_by_name(rt.rt_dev)) == NULL)
-					return -(ENODEV);
-			
-			return (atrtr_create(&rt, dev));
+					return -ENODEV;
+			}			
+			return atrtr_create(&rt, dev);
 
 		default:
-			return (-EINVAL);
-	}
+			return -EINVAL;
+	};
 }
 
 /* Called from proc fs - just make it print the ifaces neatly */
@@ -1041,29 +1098,31 @@
 static int atalk_if_get_info(char *buffer, char **start, off_t offset, int length)
 {
 	struct atalk_iface *iface;
-	int len=0;
-	off_t pos=0;
-	off_t begin=0;
+	int len = 0;
+	off_t pos = 0;
+	off_t begin = 0;
 
 	len += sprintf(buffer,"Interface	  Address   Networks   Status\n");
-	for(iface = atalk_iface_list; iface != NULL; iface = iface->next)
-	{
+
+	spin_lock_bh(&atalk_iface_lock);
+	for (iface = atalk_iface_list; iface != NULL; iface = iface->next) {
 		len += sprintf(buffer+len,"%-16s %04X:%02X  %04X-%04X  %d\n",
-			iface->dev->name, ntohs(iface->address.s_net),
-			iface->address.s_node, ntohs(iface->nets.nr_firstnet),
-			ntohs(iface->nets.nr_lastnet), iface->status);
+			       iface->dev->name, ntohs(iface->address.s_net),
+			       iface->address.s_node, ntohs(iface->nets.nr_firstnet),
+			       ntohs(iface->nets.nr_lastnet), iface->status);
 		pos = begin + len;
-		if(pos < offset)
-		{
+		if (pos < offset) {
 			len   = 0;
 			begin = pos;
 		}
-		if(pos > offset + length)
+		if (pos > offset + length)
 			break;
 	}
+	spin_unlock_bh(&atalk_iface_lock);
+
 	*start = buffer + (offset - begin);
 	len -= (offset - begin);
-	if(len > length)
+	if (len > length)
 		len = length;
 
 	return (len);
@@ -1074,41 +1133,40 @@
 static int atalk_rt_get_info(char *buffer, char **start, off_t offset, int length)
 {
 	struct atalk_route *rt;
-	int len=0;
-	off_t pos=0;
-	off_t begin=0;
+	int len = 0;
+	off_t pos = 0;
+	off_t begin = 0;
 
 	len += sprintf(buffer,"Target        Router  Flags Dev\n");
-	if(atrtr_default.dev)
-	{
+	if (atrtr_default.dev) {
 		rt = &atrtr_default;
 		len += sprintf(buffer+len,"Default     %04X:%02X  %-4d  %s\n",
-			ntohs(rt->gateway.s_net), rt->gateway.s_node, rt->flags,
-			rt->dev->name);
+			       ntohs(rt->gateway.s_net), rt->gateway.s_node,
+			       rt->flags, rt->dev->name);
 	}
 
-	for(rt = atalk_router_list; rt != NULL; rt = rt->next)
-	{
+	read_lock_bh(&atalk_router_lock);
+	for (rt = atalk_router_list; rt != NULL; rt = rt->next) {
 		len += sprintf(buffer+len,"%04X:%02X     %04X:%02X  %-4d  %s\n",
-			ntohs(rt->target.s_net),rt->target.s_node,
-			ntohs(rt->gateway.s_net), rt->gateway.s_node, rt->flags,
-			rt->dev->name);
+			       ntohs(rt->target.s_net), rt->target.s_node,
+			       ntohs(rt->gateway.s_net), rt->gateway.s_node, rt->flags,
+			       rt->dev->name);
 		pos = begin + len;
-		if(pos < offset)
-		{
+		if (pos < offset) {
 			len = 0;
 			begin = pos;
 		}
-		if(pos > offset + length)
+		if (pos > offset + length)
 			break;
 	}
+	read_unlock_bh(&atalk_router_lock);
 
 	*start = buffer + (offset - begin);
 	len -= (offset - begin);
-	if(len > length)
+	if (len > length)
 		len = length;
 
-	return (len);
+	return len;
 }
 
 /**************************************************************************\
@@ -1124,27 +1182,25 @@
  */
 unsigned short atalk_checksum(struct ddpehdr *ddp, int len)
 {
-	unsigned long sum=0;	/* Assume unsigned long is >16 bits */
-	unsigned char *data=(unsigned char *)ddp;
+	unsigned long sum = 0;	/* Assume unsigned long is >16 bits */
+	unsigned char *data = (unsigned char *) ddp;
 
 	len  -= 4;		/* skip header 4 bytes */
 	data += 4;
 
 	/* This ought to be unwrapped neatly. I'll trust gcc for now */
-	while(len--)
-	{
+	while (len--) {
 		sum += *data;
 		sum <<= 1;
-		if(sum & 0x10000)
-		{
+		if (sum & 0x10000) {
 			sum++;
 			sum &= 0xFFFF;
 		}
 		data++;
 	}
 
-	if(sum)
-		return htons((unsigned short)sum);
+	if (sum)
+		return htons((unsigned short) sum);
 
 	return 0xFFFF;		/* Use 0xFFFF for 0. 0 itself means none */
 }
@@ -1158,11 +1214,10 @@
 	struct sock *sk;
 
 	sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1);
-	if(sk == NULL)
-		return (-ENOMEM);
+	if (sk == NULL)
+		return -ENOMEM;
 
-	switch(sock->type)
-	{
+	switch (sock->type) {
 		/*
 		 * We permit SOCK_DGRAM and RAW is an extension. It is
 		 * trivial to do and gives you the full ELAP frame.
@@ -1182,19 +1237,19 @@
 			break;
 			*/
 		default:
-			sk_free((void *)sk);
-			return (-ESOCKTNOSUPPORT);
-	}
+			sk_free((void *) sk);
+			return -ESOCKTNOSUPPORT;
+	};
 
 	MOD_INC_USE_COUNT;
 
-	sock_init_data(sock,sk);
+	sock_init_data(sock, sk);
 
 	sk->destruct = NULL;
 	/* Checksums on by default */
 	sk->zapped = 1;
 
-	return (0);
+	return 0;
 }
 
 /*
@@ -1204,32 +1259,63 @@
 {
 	struct sock *sk=sock->sk;
 
-	if(sk == NULL)
-		return (0);
+	if (sk == NULL)
+		return 0;
 
-	if(!sk->dead)
+	if (!sk->dead)
 		sk->state_change(sk);
 
 	sk->dead = 1;
 	sock->sk = NULL;
 	atalk_destroy_socket(sk);
 
-	return (0);
+	return 0;
 }
 
 /*
- * Pick a source address if one is not given. Just return
- * an error if not supportable.
+ * Pick a source port when one is not given. If we can
+ * find a suitable free one, we insert the socket into
+ * the tables using it.
+ *
+ * This whole operation must be atomic.
  */
-static int atalk_pick_port(struct sockaddr_at *sat)
+static int atalk_pick_and_bind_port(struct sock *sk, struct sockaddr_at *sat)
 {
-	for(sat->sat_port = ATPORT_RESERVED; sat->sat_port < ATPORT_LAST; sat->sat_port++)
-	{
-		if(atalk_find_socket(sat) == NULL)
-			return sat->sat_port;
+	struct sock *s;
+	int retval;
+
+	spin_lock_bh(&atalk_sockets_lock);
+
+	for (sat->sat_port = ATPORT_RESERVED;
+	     sat->sat_port < ATPORT_LAST;
+	     sat->sat_port++) {
+		for (s = atalk_sockets; s != NULL; s = s->next) {
+			if (s->protinfo.af_at.src_net == sat->sat_addr.s_net &&
+			    s->protinfo.af_at.src_node == sat->sat_addr.s_node &&
+			    s->protinfo.af_at.src_port == sat->sat_port)
+				goto try_next_port;
+		}
+
+		/* Wheee, it's free, assign and insert. */
+		if ((sk->next = atalk_sockets) != NULL)
+			atalk_sockets->pprev = &sk->next;
+		atalk_sockets = sk;
+		sk->pprev = &atalk_sockets;
+
+		sk->protinfo.af_at.src_port = sat->sat_port;
+
+		retval = 0;
+		goto out;
+
+	try_next_port:
+		;
 	}
 
-	return (-EBUSY);
+	retval = -EBUSY;
+out:
+	spin_unlock_bh(&atalk_sockets_lock);
+
+	return retval;
 }
 
 static int atalk_autobind(struct sock *sk)
@@ -1238,20 +1324,18 @@
 	struct sockaddr_at sat;
 	int n;
 
-	if(ap == NULL || ap->s_net == htons(ATADDR_ANYNET))
-		return (-EADDRNOTAVAIL);
+	if (ap == NULL || ap->s_net == htons(ATADDR_ANYNET))
+		return -EADDRNOTAVAIL;
 
 	sk->protinfo.af_at.src_net  = sat.sat_addr.s_net  = ap->s_net;
 	sk->protinfo.af_at.src_node = sat.sat_addr.s_node = ap->s_node;
 
-	if((n = atalk_pick_port(&sat)) < 0)
-		return (n);
+	if ((n = atalk_pick_and_bind_port(sk, &sat)) < 0)
+		return n;
 
-	sk->protinfo.af_at.src_port = n;
-	atalk_insert_socket(sk);
 	sk->zapped = 0;
 
-	return (0);
+	return 0;
 }
 
 /*
@@ -1260,95 +1344,87 @@
 static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
 	struct sock *sk;
-	struct sockaddr_at *addr=(struct sockaddr_at *)uaddr;
+	struct sockaddr_at *addr = (struct sockaddr_at *)uaddr;
 
 	sk = sock->sk;
 
 	if(sk->zapped == 0)
-		return (-EINVAL);
+		return -EINVAL;
 
 	if(addr_len != sizeof(struct sockaddr_at))
-		return (-EINVAL);
+		return -EINVAL;
 
 	if(addr->sat_family != AF_APPLETALK)
-		return (-EAFNOSUPPORT);
+		return -EAFNOSUPPORT;
 
-	if(addr->sat_addr.s_net == htons(ATADDR_ANYNET))
-	{
-		struct at_addr *ap=atalk_find_primary();
+	if(addr->sat_addr.s_net == htons(ATADDR_ANYNET)) {
+		struct at_addr *ap = atalk_find_primary();
 
 		if(ap == NULL)
-			return (-EADDRNOTAVAIL);
+			return -EADDRNOTAVAIL;
 
 		sk->protinfo.af_at.src_net  = addr->sat_addr.s_net = ap->s_net;
 		sk->protinfo.af_at.src_node = addr->sat_addr.s_node= ap->s_node;
-	}
-	else
-	{
-		if(atalk_find_interface(addr->sat_addr.s_net, addr->sat_addr.s_node) == NULL)
-			return (-EADDRNOTAVAIL);
+	} else {
+		if (atalk_find_interface(addr->sat_addr.s_net, addr->sat_addr.s_node) == NULL)
+			return -EADDRNOTAVAIL;
 
 		sk->protinfo.af_at.src_net  = addr->sat_addr.s_net;
 		sk->protinfo.af_at.src_node = addr->sat_addr.s_node;
 	}
 
-	if(addr->sat_port == ATADDR_ANYPORT)
-	{
-		int n = atalk_pick_port(addr);
-		if(n < 0)
-			return (n);
+	if (addr->sat_port == ATADDR_ANYPORT) {
+		int n = atalk_pick_and_bind_port(sk, addr);
 
-		sk->protinfo.af_at.src_port = addr->sat_port = n;
-	}
-	else
+		if (n < 0)
+			return n;
+	} else
 		sk->protinfo.af_at.src_port = addr->sat_port;
 
-	if(atalk_find_socket(addr) != NULL)
-		return (-EADDRINUSE);
+	if (atalk_find_or_insert_socket(sk, addr) != NULL)
+		return -EADDRINUSE;
 
-	atalk_insert_socket(sk);
 	sk->zapped = 0;
 
-	return (0);
+	return 0;
 }
 
 /*
  * Set the address we talk to.
  */
 static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
-	int addr_len, int flags)
+			 int addr_len, int flags)
 {
-	struct sock *sk=sock->sk;
+	struct sock *sk = sock->sk;
 	struct sockaddr_at *addr;
 
 	sk->state   = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
-	if(addr_len != sizeof(*addr))
-		return (-EINVAL);
+	if (addr_len != sizeof(*addr))
+		return -EINVAL;
+
 	addr = (struct sockaddr_at *)uaddr;
 
-	if(addr->sat_family != AF_APPLETALK)
-		return (-EAFNOSUPPORT);
+	if (addr->sat_family != AF_APPLETALK)
+		return -EAFNOSUPPORT;
 
-	if(addr->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast)
-	{
+	if (addr->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) {
 #if 1	
 		printk(KERN_WARNING "%s is broken and did not set SO_BROADCAST. It will break when 2.2 is released.\n",
 			current->comm);
 #else
-		return (-EACCES);
+		return -EACCES;
 #endif			
 	}
 
-	if(sk->zapped)
-	{
-		if(atalk_autobind(sk) < 0)
-			return (-EBUSY);
+	if (sk->zapped) {
+		if (atalk_autobind(sk) < 0)
+			return -EBUSY;
 	}
 
-	if(atrtr_get_dev(&addr->sat_addr) == NULL)
-		return (-ENETUNREACH);
+	if (atrtr_get_dev(&addr->sat_addr) == NULL)
+		return -ENETUNREACH;
 
 	sk->protinfo.af_at.dest_port = addr->sat_port;
 	sk->protinfo.af_at.dest_net  = addr->sat_addr.s_net;
@@ -1357,7 +1433,7 @@
 	sock->state = SS_CONNECTED;
 	sk->state   = TCP_ESTABLISHED;
 
-	return (0);
+	return 0;
 }
 
 
@@ -1366,30 +1442,27 @@
  * fields into the sockaddr.
  */
 static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
-	int *uaddr_len, int peer)
+			 int *uaddr_len, int peer)
 {
 	struct sockaddr_at sat;
 	struct sock *sk;
 
 	sk = sock->sk;
-	if(sk->zapped)
-	{
-		if(atalk_autobind(sk) < 0)
-			return (-ENOBUFS);
+	if (sk->zapped) {
+		if (atalk_autobind(sk) < 0)
+			return -ENOBUFS;
 	}
 
 	*uaddr_len = sizeof(struct sockaddr_at);
 
-	if(peer)
-	{
-		if(sk->state != TCP_ESTABLISHED)
-			return (-ENOTCONN);
+	if (peer) {
+		if (sk->state != TCP_ESTABLISHED)
+			return -ENOTCONN;
+
 		sat.sat_addr.s_net  = sk->protinfo.af_at.dest_net;
 		sat.sat_addr.s_node = sk->protinfo.af_at.dest_node;
 		sat.sat_port = sk->protinfo.af_at.dest_port;
-	}
-	else
-	{
+	} else {
 		sat.sat_addr.s_net  = sk->protinfo.af_at.src_net;
 		sat.sat_addr.s_node = sk->protinfo.af_at.src_node;
 		sat.sat_port = sk->protinfo.af_at.src_port;
@@ -1398,7 +1471,7 @@
 	sat.sat_family = AF_APPLETALK;
 	memcpy(uaddr, &sat, sizeof(sat));
 
-	return (0);
+	return 0;
 }
 
 /*
@@ -1411,17 +1484,16 @@
 static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
 {
 	struct sock *sock;
-	struct ddpehdr *ddp=(void *)skb->h.raw;
+	struct ddpehdr *ddp = (void *) skb->h.raw;
 	struct atalk_iface *atif;
 	struct sockaddr_at tosat;
         int origlen;
         struct ddpebits ddphv;
 
 	/* Size check */
-	if(skb->len < sizeof(*ddp))
-	{
+	if (skb->len < sizeof(*ddp)) {
 		kfree_skb(skb);
-		return (0);
+		return 0;
 	}
 
 	/*
@@ -1449,26 +1521,24 @@
 	 * (Otherwise we'll detonate most spectacularly
 	 * in the middle of recvmsg()).
 	 */
-	if(skb->len < sizeof(*ddp))
-	{
+	if (skb->len < sizeof(*ddp)) {
 		kfree_skb(skb);
-		return (0);
+		return 0;
 	}
 
 	/*
 	 * Any checksums. Note we don't do htons() on this == is assumed to be
 	 * valid for net byte orders all over the networking code...
 	 */
-	if(ddp->deh_sum && atalk_checksum(ddp, ddphv.deh_len) != ddp->deh_sum)
-	{
+	if (ddp->deh_sum && atalk_checksum(ddp, ddphv.deh_len) != ddp->deh_sum) {
 		/* Not a valid AppleTalk frame - dustbin time */
 		kfree_skb(skb);
-		return (0);
+		return 0;
 	}
 
 	/* Check the packet is aimed at us */
 
-	if(ddp->deh_dnet == 0)	/* Net 0 is 'this network' */
+	if (ddp->deh_dnet == 0)	/* Net 0 is 'this network' */
 		atif = atalk_find_anynet(ddp->deh_dnode, dev);
 	else
 		atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode);
@@ -1476,8 +1546,7 @@
 	/* 
 	 * Not ours, so we route the packet via the correct AppleTalk interface.
 	 */
-	if(atif == NULL)
-	{
+	if (atif == NULL) {
 		struct atalk_route *rt;
 		struct at_addr ta;
 
@@ -1485,8 +1554,7 @@
 		 * Don't route multicast, etc., packets, or packets
 		 * sent to "this network" 
 		 */
-		if (skb->pkt_type != PACKET_HOST || ddp->deh_dnet == 0)
-		{
+		if (skb->pkt_type != PACKET_HOST || ddp->deh_dnet == 0) {
 			/*
 			 * FIX ME:
 			 * Can it ever happen that a packet is from a PPP iface and needs to be broadcast onto the default network?
@@ -1495,7 +1563,7 @@
 				printk(KERN_DEBUG "AppleTalk: didn't forward broadcast packet received from PPP iface\n");
 			
 			kfree_skb(skb);
-			return (0);
+			return 0;
 		}
 
 		ta.s_net  = ddp->deh_dnet;
@@ -1503,10 +1571,9 @@
 
 		/* Route the packet */
 		rt = atrtr_find(&ta);
-		if(rt == NULL || ddphv.deh_hops == DDP_MAXHOPS)
-		{
+		if (rt == NULL || ddphv.deh_hops == DDP_MAXHOPS) {
 			kfree_skb(skb);
-			return (0);
+			return 0;
 		}
 		ddphv.deh_hops++;
 
@@ -1514,8 +1581,7 @@
 		 * Route goes through another gateway, so
 		 * set the target to the gateway instead.
 		 */
-		if(rt->flags & RTF_GATEWAY)
-		{
+		if (rt->flags & RTF_GATEWAY) {
 			ta.s_net  = rt->gateway.s_net;
 			ta.s_node = rt->gateway.s_node;
 		}
@@ -1539,7 +1605,7 @@
 		 *
 		 * Note. ddp-> becomes invalid at the realloc.
 		 */
-		if(skb_headroom(skb) < 22)
+		if (skb_headroom(skb) < 22)
 			/* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */
 			skb = skb_realloc_headroom(skb, 32);
 		else
@@ -1549,26 +1615,24 @@
 		 * If the buffer didn't vanish into the lack of
 		 * space bitbucket we can send it.
 		 */
-		if(skb)
-		{
-			if(aarp_send_ddp(rt->dev, skb, &ta, NULL) == -1)
+		if (skb) {
+			if (aarp_send_ddp(rt->dev, skb, &ta, NULL) == -1)
 				kfree_skb(skb);
 		}
 
-		return (0);
+		return 0;
 	}
 
 #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE)
         /*
          *      Check if IP-over-DDP
          */
-        if(skb->data[12] == 22)
-        {
+        if (skb->data[12] == 22) {
                 struct net_device *dev;
 
 		/* This needs to be able to handle ipddp"N" devices */
-                if((dev = __dev_get_by_name("ipddp0")) == NULL)
-                        return (-ENODEV);
+                if ((dev = __dev_get_by_name("ipddp0")) == NULL)
+                        return -ENODEV;
 
                 skb->protocol = htons(ETH_P_IP);
                 skb_pull(skb, 13);
@@ -1576,10 +1640,10 @@
                 skb->h.raw = skb->data;
 
                 ((struct net_device_stats *)dev->priv)->rx_packets++;
-                ((struct net_device_stats *)dev->priv)->rx_bytes += skb->len+13;
+                ((struct net_device_stats *)dev->priv)->rx_bytes += skb->len + 13;
                 netif_rx(skb);  /* Send the SKB up to a higher place. */
 
-                return (0);
+                return 0;
         }
 #endif
 
@@ -1593,10 +1657,10 @@
 
 	sock = atalk_search_socket(&tosat, atif);
 	
-	if(sock == NULL)	/* But not one of our sockets */
-	{
+	if (sock == NULL) {
+		/* But not one of our sockets */
 		kfree_skb(skb);
-		return (0);
+		return 0;
 	}
 
 	/*
@@ -1605,10 +1669,10 @@
 	 
 	skb->sk = sock;
 
-	if(sock_queue_rcv_skb(sock, skb) < 0)
+	if (sock_queue_rcv_skb(sock, skb) < 0)
 		kfree_skb(skb);
 
-	return (0);
+	return 0;
 }
 
 /*
@@ -1624,17 +1688,15 @@
 	/*
 	 * Expand any short form frames.
 	 */
-	if(skb->mac.raw[2] == 1)
-	{
+	if (skb->mac.raw[2] == 1) {
 		/*
 		 * Find our address.
 		 */
 
 		ap = atalk_find_dev_addr(dev);
-		if(ap == NULL || skb->len < sizeof(struct ddpshdr))
-		{
+		if (ap == NULL || skb->len < sizeof(struct ddpshdr)) {
 			kfree_skb(skb);
-			return (0);
+			return 0;
 		}
 
 		/*
@@ -1673,57 +1735,51 @@
 	}
 	skb->h.raw = skb->data;
 
-	return (atalk_rcv(skb, dev, pt));
+	return atalk_rcv(skb, dev, pt);
 }
 
-static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len,
-	struct scm_cookie *scm)
+static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct scm_cookie *scm)
 {
-	struct sock *sk=sock->sk;
-	struct sockaddr_at *usat=(struct sockaddr_at *)msg->msg_name;
+	struct sock *sk = sock->sk;
+	struct sockaddr_at *usat = (struct sockaddr_at *)msg->msg_name;
 	struct sockaddr_at local_satalk, gsat;
 	struct sk_buff *skb;
 	struct net_device *dev;
 	struct ddpehdr *ddp;
 	int size;
 	struct atalk_route *rt;
-	int loopback=0;
+	int loopback = 0;
 	int err;
 	int flags = msg->msg_flags;
 
-	if(flags & ~MSG_DONTWAIT)
-		return (-EINVAL);
+	if (flags & ~MSG_DONTWAIT)
+		return -EINVAL;
 
-	if(len > DDP_MAXSZ)
-		return (-EMSGSIZE);
+	if (len > DDP_MAXSZ)
+		return -EMSGSIZE;
 
-	if(usat)
-	{
-		if(sk->zapped)
-		{
-			if(atalk_autobind(sk) < 0)
-				return (-EBUSY);
-		}
-
-		if(msg->msg_namelen < sizeof(*usat))
-			return (-EINVAL);
-		if(usat->sat_family != AF_APPLETALK)
-			return (-EINVAL);
+	if (usat) {
+		if(sk->zapped) {
+			if (atalk_autobind(sk) < 0)
+				return -EBUSY;
+		}
+
+		if (msg->msg_namelen < sizeof(*usat))
+			return -EINVAL;
+		if (usat->sat_family != AF_APPLETALK)
+			return -EINVAL;
 
 		/* netatalk doesn't implement this check */
-		if(usat->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast)
-		{
+		if (usat->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) {
 			printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as it will break before 2.2\n");
 #if 0
-			return (-EPERM);
+			return -EPERM;
 #endif
 		}
-	}
-	else
-	{
-		if(sk->state != TCP_ESTABLISHED)
-			return (-ENOTCONN);
-		usat =& local_satalk;
+	} else {
+		if (sk->state != TCP_ESTABLISHED)
+			return -ENOTCONN;
+		usat = &local_satalk;
 		usat->sat_family = AF_APPLETALK;
 		usat->sat_port   = sk->protinfo.af_at.dest_port;
 		usat->sat_addr.s_node = sk->protinfo.af_at.dest_node;
@@ -1732,26 +1788,27 @@
 
 	/* Build a packet */
 
-	SOCK_DEBUG(sk, "SK %p: Got address.\n",sk);
+	SOCK_DEBUG(sk, "SK %p: Got address.\n", sk);
 
 	/* For headers */
 	size = sizeof(struct ddpehdr) + len + ddp_dl->header_length;
 
-	if(usat->sat_addr.s_net != 0 || usat->sat_addr.s_node == ATADDR_ANYNODE)
-	{
+	if (usat->sat_addr.s_net != 0 || usat->sat_addr.s_node == ATADDR_ANYNODE) {
 		rt = atrtr_find(&usat->sat_addr);
-		if(rt == NULL)
-			return (-ENETUNREACH);
+		if (rt == NULL)
+			return -ENETUNREACH;
+
 		dev = rt->dev;
-	}
-	else
-	{
+	} else {
 		struct at_addr at_hint;
+
 		at_hint.s_node = 0;
 		at_hint.s_net  = sk->protinfo.af_at.src_net;
+
 		rt = atrtr_find(&at_hint);
-		if(rt == NULL)
-			return (-ENETUNREACH);
+		if (rt == NULL)
+			return -ENETUNREACH;
+
 		dev = rt->dev;
 	}
 
@@ -1759,9 +1816,9 @@
 
 	size += dev->hard_header_len;
 
-	skb = sock_alloc_send_skb(sk, size, 0, flags&MSG_DONTWAIT, &err);
-	if(skb == NULL)
-		return (err);
+	skb = sock_alloc_send_skb(sk, size, 0, (flags & MSG_DONTWAIT), &err);
+	if (skb == NULL)
+		return err;
 	
 	skb->sk = sk;
 	skb_reserve(skb, ddp_dl->header_length);
@@ -1771,7 +1828,7 @@
 
 	SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);
 
-	ddp = (struct ddpehdr *)skb_put(skb,sizeof(struct ddpehdr));
+	ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr));
 	ddp->deh_pad  = 0;
 	ddp->deh_hops = 0;
 	ddp->deh_len  = len + sizeof(*ddp);
@@ -1791,14 +1848,13 @@
 
 	SOCK_DEBUG(sk, "SK %p: Copy user data (%d bytes).\n", sk, len);
 
-	err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
-	if(err)
-	{
+	err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+	if (err) {
 		kfree_skb(skb);
-		return (-EFAULT);
+		return -EFAULT;
 	}
 
-	if(sk->no_check == 1)
+	if (sk->no_check == 1)
 		ddp->deh_sum = 0;
 	else
 		ddp->deh_sum = atalk_checksum(ddp, len + sizeof(*ddp));
@@ -1807,24 +1863,20 @@
 	 * Loopback broadcast packets to non gateway targets (ie routes
 	 * to group we are in)
 	 */
-	if(ddp->deh_dnode == ATADDR_BCAST)
-	{
-		if((!(rt->flags&RTF_GATEWAY)) && (!(dev->flags&IFF_LOOPBACK)))
-		{
+	if (ddp->deh_dnode == ATADDR_BCAST) {
+		if ((!(rt->flags&RTF_GATEWAY)) && (!(dev->flags&IFF_LOOPBACK))) {
 			struct sk_buff *skb2 = skb_copy(skb, GFP_KERNEL);
-			if(skb2)
-			{
+			if (skb2) {
 				loopback = 1;
 				SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk);
-				if(aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL) == -1)
+				if (aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL) == -1)
 					kfree_skb(skb2);
 				/* else queued/sent above in the aarp queue */
 			}
 		}
 	}
 
-	if((dev->flags & IFF_LOOPBACK) || loopback)
-	{
+	if ((dev->flags & IFF_LOOPBACK) || loopback) {
 		SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk);
 		/* loop back */
 		skb_orphan(skb);
@@ -1834,70 +1886,60 @@
 		skb_pull(skb,dev->hard_header_len);
 		skb_pull(skb,ddp_dl->header_length);
 		atalk_rcv(skb, dev, NULL);
-	}
-	else
-	{
+	} else {
 		SOCK_DEBUG(sk, "SK %p: send out.\n", sk);
-		if (rt->flags & RTF_GATEWAY)
-		{
+		if (rt->flags & RTF_GATEWAY) {
 		    gsat.sat_addr = rt->gateway;
 		    usat = &gsat;
 		}
 
-		if(aarp_send_ddp(dev, skb, &usat->sat_addr, NULL) == -1)
+		if (aarp_send_ddp(dev, skb, &usat->sat_addr, NULL) == -1)
 			kfree_skb(skb);
 		/* else queued/sent above in the aarp queue */
 	}
 	SOCK_DEBUG(sk, "SK %p: Done write (%d).\n", sk, len);
 
-	return (len);
+	return len;
 }
 
 static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size,
-		int flags, struct scm_cookie *scm)
+			 int flags, struct scm_cookie *scm)
 {
-	struct sock *sk=sock->sk;
-	struct sockaddr_at *sat=(struct sockaddr_at *)msg->msg_name;
+	struct sock *sk = sock->sk;
+	struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
 	struct ddpehdr	*ddp = NULL;
         struct ddpebits ddphv;
 	int copied = 0;
 	struct sk_buff *skb;
 	int err = 0;
 
-
-	skb = skb_recv_datagram(sk,flags&~MSG_DONTWAIT,flags&MSG_DONTWAIT,&err);
-	if(skb == NULL)
-		return (err);
+	skb = skb_recv_datagram(sk, (flags & ~MSG_DONTWAIT),
+				(flags & MSG_DONTWAIT), &err);
+	if (skb == NULL)
+		return err;
 
 	ddp = (struct ddpehdr *)(skb->h.raw);
 	*((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
 
-	if(sk->type == SOCK_RAW)
-	{
+	if (sk->type == SOCK_RAW) {
 		copied = ddphv.deh_len;
-		if(copied > size)
-		{
+		if (copied > size) {
 			copied = size;
 			msg->msg_flags |= MSG_TRUNC;
 		}
 
 		err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-	}
-	else
-	{
+	} else {
 		copied = ddphv.deh_len - sizeof(*ddp);
-		if(copied > size)
-		{
+		if (copied > size) {
 			copied = size;
 			msg->msg_flags |= MSG_TRUNC;
 		}
-		err = skb_copy_datagram_iovec(skb,sizeof(*ddp),msg->msg_iov,copied);
+		err = skb_copy_datagram_iovec(skb, sizeof(*ddp), msg->msg_iov, copied);
 	}
 
-	if(!err)
-	{
-		if(sat)
-		{
+	if (!err) {
+		if (sat) {
 			sat->sat_family      = AF_APPLETALK;
 			sat->sat_port        = ddp->deh_sport;
 			sat->sat_addr.s_node = ddp->deh_snode;
@@ -1908,7 +1950,7 @@
 
 	skb_free_datagram(sk, skb);	/* Free the datagram. */
 
-	return (err ? err : (copied));
+	return err ? err : copied;
 }
 
 
diff -u --recursive --new-file v2.3.50/linux/net/decnet/Config.in linux/net/decnet/Config.in
--- v2.3.50/linux/net/decnet/Config.in	Tue Jan 11 22:31:46 2000
+++ linux/net/decnet/Config.in	Thu Mar  9 06:57:17 2000
@@ -5,7 +5,6 @@
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool '  DECnet: router support (EXPERIMENTAL)' CONFIG_DECNET_ROUTER
    if [ "$CONFIG_DECNET_ROUTER"  = "y" ]; then
-      bool '    DECnet: use FWMARK value as routing key' CONFIG_DECNET_ROUTE_FWMARK
+      bool '    DECnet: use FWMARK value as routing key (EXPERIMENTAL)' CONFIG_DECNET_ROUTE_FWMARK
    fi
 fi
-bool '  DECnet: raw socket support' CONFIG_DECNET_RAW
diff -u --recursive --new-file v2.3.50/linux/net/decnet/Makefile linux/net/decnet/Makefile
--- v2.3.50/linux/net/decnet/Makefile	Tue Jan 11 22:31:46 2000
+++ linux/net/decnet/Makefile	Thu Mar  9 06:57:17 2000
@@ -8,10 +8,6 @@
 O_OBJS += dn_fib.o dn_rules.o dn_table.o
 endif
 
-ifeq ($(CONFIG_DECNET_RAW),y)
-O_OBJS += dn_raw.o
-endif
-
 ifeq ($(CONFIG_DECNET_FW),y)
 O_OBJS += dn_fw.o
 endif
diff -u --recursive --new-file v2.3.50/linux/net/decnet/TODO linux/net/decnet/TODO
--- v2.3.50/linux/net/decnet/TODO	Thu Mar  2 14:36:23 2000
+++ linux/net/decnet/TODO	Thu Mar  9 06:57:17 2000
@@ -4,8 +4,6 @@
  o Proper timeouts on each neighbour (in routing mode) rather than
    just the 60 second On-Ethernet cache value.
 
- o Misc. get/set_sockopt() functions [done for the time being, more later]
-
  o Support for X.25 linklayer
 
  o Support for DDCMP link layer
@@ -13,10 +11,6 @@
  o The DDCMP device itself
 
  o PPP support (rfc1762)
-
- o sendmsg() in the raw socket layer (yes, its for sending routing messages)
-
- o Fix /proc for raw sockets
 
  o Lots of testing with real applications
 
diff -u --recursive --new-file v2.3.50/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- v2.3.50/linux/net/decnet/af_decnet.c	Thu Mar  2 14:36:23 2000
+++ linux/net/decnet/af_decnet.c	Thu Mar  9 06:57:17 2000
@@ -123,7 +123,6 @@
 #include <net/dn_dev.h>
 #include <net/dn_route.h>
 #include <net/dn_fib.h>
-#include <net/dn_raw.h>
 #include <net/dn_neigh.h>
 
 #define MAX(a,b) ((a)>(b)?(a):(b))
@@ -401,11 +400,6 @@
 		goto no_sock;
 
 	if (sock) {
-#ifdef CONFIG_DECNET_RAW
-		if (sock->type == SOCK_RAW)
-			sock->ops = &dn_raw_proto_ops;
-		else
-#endif /* CONFIG_DECNET_RAW */
 			sock->ops = &dn_proto_ops;
 	}
 	sock_init_data(sock,sk);
@@ -647,13 +641,6 @@
 			break;
 		case SOCK_STREAM:
 			break;
-#ifdef CONFIG_DECNET_RAW
-		case SOCK_RAW:
-			if ((protocol != DNPROTO_NSP) &&
-					(protocol != DNPROTO_ROU))
-				return -EPROTONOSUPPORT;
-			break;
-#endif /* CONFIG_DECNET_RAW */
 		default:
 			return -ESOCKTNOSUPPORT;
 	}
@@ -1095,6 +1082,7 @@
 static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
+	struct dn_scp *scp = &sk->protinfo.dn;
 	int err = -EOPNOTSUPP;
 	unsigned long amount = 0;
 	struct sk_buff *skb;
@@ -1221,8 +1209,17 @@
 
 	case TIOCINQ:
 		lock_sock(sk);
-		if ((skb = skb_peek(&sk->receive_queue)) != NULL)
+		if ((skb = skb_peek(&scp->other_receive_queue)) != NULL) {
 			amount = skb->len;
+		} else {
+			struct sk_buff *skb = sk->receive_queue.next;
+			for(;;) {
+				if (skb == (struct sk_buff *)&sk->receive_queue)
+					break;
+				amount += skb->len;
+				skb = skb->next;
+			}
+		}
 		release_sock(sk);
 		err = put_user(amount, (int *)arg);
 		break;
@@ -2028,11 +2025,7 @@
 	return len;
 }
 
-#ifdef CONFIG_DECNET_RAW
-
-extern int dn_raw_get_info(char *, char **, off_t, int);
 
-#endif /* CONFIG_DECNET_RAW */
 static struct net_proto_family	dn_family_ops = {
 	AF_DECnet,
 	dn_create
@@ -2066,16 +2059,14 @@
 
 void __init decnet_proto_init(struct net_proto *pro)
 {
-        printk(KERN_INFO "NET4: DECnet for Linux: V.2.3.38s (C) 1995-1999 Linux DECnet Project Team\n");
+        printk(KERN_INFO "NET4: DECnet for Linux: V.2.3.49s (C) 1995-2000 Linux DECnet Project Team\n");
 
 	sock_register(&dn_family_ops);
 	dev_add_pack(&dn_dix_packet_type);
 	register_netdevice_notifier(&dn_dev_notifier);
 
 	proc_net_create("decnet", 0, dn_get_info);
-#ifdef CONFIG_DECNET_RAW
-	proc_net_create("decnet_raw", 0, dn_raw_get_info);
-#endif
+
 	dn_neigh_init();
 	dn_dev_init();
 	dn_route_init();
@@ -2153,9 +2144,6 @@
 #endif /* CONFIG_DECNET_ROUTER */
 
 	proc_net_remove("decnet");
-#ifdef CONFIG_DECNET_RAW
-	proc_net_remove("decnet_raw");
-#endif
 
 	dev_remove_pack(&dn_dix_packet_type);
 	sock_unregister(AF_DECnet);
diff -u --recursive --new-file v2.3.50/linux/net/decnet/dn_nsp_in.c linux/net/decnet/dn_nsp_in.c
--- v2.3.50/linux/net/decnet/dn_nsp_in.c	Thu Mar  2 14:36:23 2000
+++ linux/net/decnet/dn_nsp_in.c	Thu Mar  9 06:57:17 2000
@@ -70,7 +70,6 @@
 #include <net/dn_nsp.h>
 #include <net/dn_dev.h>
 #include <net/dn_route.h>
-#include <net/dn_raw.h>
 
 
 /*
@@ -320,7 +319,7 @@
 	struct dn_scp *scp = &sk->protinfo.dn;
 	unsigned short reason;
 
-	if (skb->len < 2)
+	if (skb->len != 2)
 		goto out;
 
 	reason = dn_ntohs(*(__u16 *)skb->data);
@@ -551,10 +550,6 @@
 
 	if (decnet_debug_level & 2)
 		printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags);
-
-#ifdef CONFIG_DECNET_RAW
-	dn_raw_rx_nsp(skb);
-#endif /* CONFIG_DECNET_RAW */
 
 	if (skb->len < 2) 
 		goto free_out;
diff -u --recursive --new-file v2.3.50/linux/net/decnet/dn_nsp_out.c linux/net/decnet/dn_nsp_out.c
--- v2.3.50/linux/net/decnet/dn_nsp_out.c	Thu Mar  2 14:36:23 2000
+++ linux/net/decnet/dn_nsp_out.c	Thu Mar  9 06:57:17 2000
@@ -511,7 +511,7 @@
 			int ddl, unsigned char *dd, __u16 rem, __u16 loc)
 {
 	struct sk_buff *skb = NULL;
-	int size = 8 + ddl;
+	int size = 7 + ddl + ((msgflg == NSP_DISCINIT) ? 1 : 0);
 	unsigned char *msg;
 
 	if ((dst == NULL) || (rem == 0)) {
@@ -531,7 +531,8 @@
 	msg += 2;
 	*(__u16 *)msg = dn_htons(reason);
 	msg += 2;
-	*msg++ = ddl;
+	if (msgflg == NSP_DISCINIT)
+		*msg++ = ddl;
 
 	if (ddl) {
 		memcpy(msg, dd, ddl);
diff -u --recursive --new-file v2.3.50/linux/net/decnet/dn_raw.c linux/net/decnet/dn_raw.c
--- v2.3.50/linux/net/decnet/dn_raw.c	Tue Nov 23 22:42:21 1999
+++ linux/net/decnet/dn_raw.c	Wed Dec 31 16:00:00 1969
@@ -1,367 +0,0 @@
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Raw Sockets Interface
- *
- * Author:      Steve Whitehouse <SteveW@ACM.org>
- *
- *
- * Changes:
- *           Steve Whitehouse - connect() function.
- *           Steve Whitehouse - SMP changes, removed MOP stubs. MOP will
- *                              be userland only.
- */
-
-#include <linux/config.h>
-#include <linux/net.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <net/sock.h>
-#include <net/dst.h>
-#include <net/dn.h>
-#include <net/dn_raw.h>
-#include <net/dn_route.h>
-
-static rwlock_t dn_raw_hash_lock = RW_LOCK_UNLOCKED;
-static struct sock *dn_raw_nsp_sklist = NULL;
-static struct sock *dn_raw_routing_sklist = NULL;
-
-static void dn_raw_hash(struct sock *sk)
-{
-	struct sock **skp;
-
-	switch(sk->protocol) {
-		case DNPROTO_NSP:
-			skp = &dn_raw_nsp_sklist;
-			break;
-		case DNPROTO_ROU:
-			skp = &dn_raw_routing_sklist;
-			break;
-		default:
-			printk(KERN_DEBUG "dn_raw_hash: Unknown protocol\n");
-			return;
-	}
-
-	write_lock_bh(&dn_raw_hash_lock);
-	sk->next = *skp;
-	sk->pprev = skp;
-	*skp = sk;
-	write_unlock_bh(&dn_raw_hash_lock);
-}
-
-static void dn_raw_unhash(struct sock *sk)
-{
-	struct sock **skp = sk->pprev;
-
-	if (skp == NULL)
-		return;
-
-	write_lock_bh(&dn_raw_hash_lock);
-	while(*skp != sk)
-		skp = &((*skp)->next);
-	*skp = sk->next;
-	write_unlock_bh(&dn_raw_hash_lock);
-
-	sk->next = NULL;
-	sk->pprev = NULL;
-}
-
-static void dn_raw_autobind(struct sock *sk)
-{
-	dn_raw_hash(sk);
-	sk->zapped = 0;
-}
-
-static int dn_raw_release(struct socket *sock)
-{
-	struct sock *sk = sock->sk;
-
-	if (sk == NULL)
-		return 0;
-
-	if (!sk->dead) sk->state_change(sk);
-
-	sk->dead = 1;
-	sk->socket = NULL;
-	sock->sk = NULL;
-
-	dn_raw_unhash(sk);
-	sock_put(sk);
-
-	return 0;
-}
-
-/*
- * Bind does odd things with raw sockets. Its basically used to filter
- * the incoming packets, but this differs with the different layers
- * at which you extract packets.
- *
- * For Routing layer sockets, the object name is a host ordered unsigned
- * short which is a mask for the 16 different types of possible routing
- * packet. I'd like to also select by destination address of the packets
- * but alas, this is rather too difficult to do at the moment.
- */
-static int dn_raw_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
-{
-	struct sock *sk = sock->sk;
-	struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;
-
-	if (addr_len != sizeof(struct sockaddr_dn))
-		return -EINVAL;
-
-	if (sk->zapped == 0)
-		return -EINVAL;
-
-	switch(sk->protocol) {
-		case DNPROTO_ROU:
-			if (dn_ntohs(addr->sdn_objnamel) && (dn_ntohs(addr->sdn_objnamel) != 2))
-				return -EINVAL;
-			/* Fall through here */
-		case DNPROTO_NSP:
-			if (dn_ntohs(addr->sdn_add.a_len) && (dn_ntohs(addr->sdn_add.a_len) != 2))
-				return -EINVAL;
-			break;
-		default:
-			return -EPROTONOSUPPORT;
-	}
-
-	if (dn_ntohs(addr->sdn_objnamel) > (DN_MAXOBJL-1))
-		return -EINVAL;
-
-	if (dn_ntohs(addr->sdn_add.a_len) > DN_MAXADDL)
-		return -EINVAL;
-
-	memcpy(&sk->protinfo.dn.addr, addr, sizeof(struct sockaddr_dn));
-
-	dn_raw_autobind(sk);
-
-	return 0;
-}
-
-/*
- * This is to allow send() and write() to work. You set the destination address
- * with this function.
- */
-static int dn_raw_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
-{
-	struct sock *sk = sock->sk;
-	struct dn_scp *scp = &sk->protinfo.dn;
-	struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
-	int err;
-
-	lock_sock(sk);
-
-	err = -EINVAL;
-	if (addr_len != sizeof(struct sockaddr_dn))
-		goto out;
-
-	if (saddr->sdn_family != AF_DECnet)
-		goto out;
-
-	if (dn_ntohs(saddr->sdn_objnamel) > (DN_MAXOBJL-1))
-		goto out;
-
-	if (dn_ntohs(saddr->sdn_add.a_len) > DN_MAXADDL)
-		goto out;
-
-	if (sk->zapped)
-		dn_raw_autobind(sk);
-
-	if ((err = dn_route_output(&sk->dst_cache, dn_saddr2dn(saddr), dn_saddr2dn(&scp->addr), 0)) < 0)
-		goto out;
-
-	memcpy(&scp->peer, saddr, sizeof(struct sockaddr_dn));
-out:
-	release_sock(sk);
-
-	return err;
-}
-
-/*
- * TBD.
- */
-static int dn_raw_sendmsg(struct socket *sock, struct msghdr *hdr, int size,
-			struct scm_cookie *scm)
-{
-	struct sock *sk = sock->sk;
-
-	if (sk->zapped)
-		dn_raw_autobind(sk);
-
-	if (sk->protocol != DNPROTO_NSP)
-		return -EOPNOTSUPP;
-
-	return 0;
-}
-
-/*
- * This works fine, execpt that it doesn't report the originating address
- * or anything at the moment.
- */
-static int dn_raw_recvmsg(struct socket *sock, struct msghdr *msg, int size,
-			int flags, struct scm_cookie *scm)
-{
-	struct sock *sk = sock->sk;
-	struct sk_buff *skb;
-	int err = 0;
-	int copied = 0;
-
-	lock_sock(sk);
-
-	if (sk->zapped)
-		dn_raw_autobind(sk);
-
-	if ((skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err)) == NULL)
-		goto out;
-
-	copied = skb->len;
-
-	if (copied > size) {
-		copied = size;
-		msg->msg_flags |= MSG_TRUNC;
-	}
-
-	if ((err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied)) != 0) {
-		if (flags & MSG_PEEK)
-			atomic_dec(&skb->users);
-		else
-			skb_queue_head(&sk->receive_queue, skb);
-
-		goto out;
-	}
-
-	skb_free_datagram(sk, skb);
-
-out:
-	release_sock(sk);
-
-	return copied ? copied : err;
-}
-
-struct proto_ops dn_raw_proto_ops = {
-	AF_DECnet,
-
-	dn_raw_release,
-	dn_raw_bind,
-	dn_raw_connect,
-	sock_no_socketpair,
-	sock_no_accept,
-	sock_no_getname,
-	datagram_poll,
-	sock_no_ioctl,
-	sock_no_listen,
-	sock_no_shutdown,
-	sock_no_setsockopt,
-	sock_no_getsockopt,
-	sock_no_fcntl,
-	dn_raw_sendmsg,
-	dn_raw_recvmsg,
-	sock_no_mmap
-};
-
-#ifdef CONFIG_PROC_FS
-int dn_raw_get_info(char *buffer, char **start, off_t offset, int length)
-{
-	int len = 0;
-	off_t pos = 0;
-	off_t begin = 0;
-	struct sock *sk;
-
-	read_lock_bh(&dn_raw_hash_lock);
-	for(sk = dn_raw_nsp_sklist; sk; sk = sk->next) {	
-		len += sprintf(buffer+len, "NSP\n");
-
-		pos = begin + len;
-
-		if (pos < offset) {
-			len = 0;
-			begin = pos;
-		}
-
-		if (pos > offset + length)
-			goto all_done;
-
-	}
-
-	for(sk = dn_raw_routing_sklist; sk; sk = sk->next) {
-		len += sprintf(buffer+len, "ROU\n");
-
-		pos = begin + len;
-
-		if (pos < offset) {
-			len = 0;
-			begin = pos;
-		}
-
-		if (pos > offset + length)
-			goto all_done;
-	}
-
-all_done:
-	read_unlock_bh(&dn_raw_hash_lock);
-
-	*start = buffer + (offset - begin);
-	len -= (offset - begin);
-
-	if (len > length) len = length;
-
-	return(len);
-}
-#endif /* CONFIG_PROC_FS */
-
-void dn_raw_rx_nsp(struct sk_buff *skb)
-{
-	struct sock *sk;
-	struct sk_buff *skb2;
-
-	read_lock(&dn_raw_hash_lock);
-	for(sk = dn_raw_nsp_sklist; sk != NULL; sk = sk->next) {
-		if (skb->len > sock_rspace(sk))
-			continue;
-		if (sk->dead)
-			continue;
-		if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
-			skb_set_owner_r(skb2, sk);
-			skb_queue_tail(&sk->receive_queue, skb2);
-			sk->data_ready(sk, skb->len);	
-		}
-	}
-	read_unlock(&dn_raw_hash_lock);
-}
-
-void dn_raw_rx_routing(struct sk_buff *skb)
-{
-	struct sock *sk;
-	struct sk_buff *skb2;
-	struct dn_skb_cb *cb = (struct dn_skb_cb *)skb->cb;
-	unsigned short rt_flagmask;
-	unsigned short objnamel;
-	struct dn_scp *scp;
-
-	read_lock(&dn_raw_hash_lock);
-	for(sk = dn_raw_routing_sklist; sk != NULL; sk = sk->next) {
-		if (skb->len > sock_rspace(sk))
-			continue;
-		if (sk->dead)
-			continue;
-		scp = &sk->protinfo.dn;
-
-		rt_flagmask = dn_ntohs(*(unsigned short *)scp->addr.sdn_objname);
-		objnamel = dn_ntohs(scp->addr.sdn_objnamel);
-
-		if ((objnamel == 2) && (!((1 << (cb->rt_flags & 0x0f)) & rt_flagmask)))
-			continue;
-
-		if ((skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
-			skb_set_owner_r(skb2, sk);
-			skb_queue_tail(&sk->receive_queue, skb2);
-			sk->data_ready(sk, skb->len);
-		}
-	}
-	read_unlock(&dn_raw_hash_lock);
-}
-
diff -u --recursive --new-file v2.3.50/linux/net/decnet/dn_route.c linux/net/decnet/dn_route.c
--- v2.3.50/linux/net/decnet/dn_route.c	Thu Mar  2 14:36:23 2000
+++ linux/net/decnet/dn_route.c	Thu Mar  9 06:57:17 2000
@@ -77,7 +77,6 @@
 #include <net/dn_route.h>
 #include <net/dn_neigh.h>
 #include <net/dn_fib.h>
-#include <net/dn_raw.h>
 
 struct dn_rt_hash_bucket
 {
@@ -426,10 +425,6 @@
 			"dn_route_rcv: got 0x%02x from %s [%d %d %d]\n",
 			(int)flags, (dev) ? dev->name : "???", len, skb->len, 
 			padlen);
-
-#ifdef CONFIG_DECNET_RAW
-	dn_raw_rx_routing(skb);
-#endif /* CONFIG_DECNET_RAW */
 
         if (flags & DN_RT_PKT_CNTL) {
                 switch(flags & DN_RT_CNTL_MSK) {
diff -u --recursive --new-file v2.3.50/linux/net/decnet/sysctl_net_decnet.c linux/net/decnet/sysctl_net_decnet.c
--- v2.3.50/linux/net/decnet/sysctl_net_decnet.c	Tue Jan 11 22:31:46 2000
+++ linux/net/decnet/sysctl_net_decnet.c	Thu Mar  9 06:57:17 2000
@@ -29,9 +29,9 @@
 
 int decnet_debug_level = 0;
 int decnet_time_wait = 30;
-int decnet_dn_count = 3;
-int decnet_di_count = 5;
-int decnet_dr_count = 5;
+int decnet_dn_count = 1;
+int decnet_di_count = 3;
+int decnet_dr_count = 3;
 
 #ifdef CONFIG_SYSCTL
 extern int decnet_dst_gc_interval;
diff -u --recursive --new-file v2.3.50/linux/net/econet/Makefile linux/net/econet/Makefile
--- v2.3.50/linux/net/econet/Makefile	Tue Apr 28 11:10:11 1998
+++ linux/net/econet/Makefile	Thu Mar  9 06:57:17 2000
@@ -7,17 +7,10 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
+O_TARGET := econet.o
 MOD_LIST_NAME := NET_MISC_MODULES
 
-O_OBJS :=
-M_OBJS :=
-
-ifeq ($(CONFIG_ECONET),y)
-  O_OBJS += econet.o
-else
-  ifeq ($(CONFIG_ECONET), m)
-    M_OBJS += econet.o
-  endif
-endif
+O_OBJS := af_econet.o sysctl_net_ec.o
+M_OBJS := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.50/linux/net/econet/af_econet.c linux/net/econet/af_econet.c
--- v2.3.50/linux/net/econet/af_econet.c	Wed Dec 31 16:00:00 1969
+++ linux/net/econet/af_econet.c	Thu Mar  9 23:31:43 2000
@@ -0,0 +1,1153 @@
+/*
+ *	An implementation of the Acorn Econet and AUN protocols.
+ *	Philip Blundell <philb@gnu.org>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/in.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/route.h>
+#include <linux/inet.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/inet_common.h>
+#include <linux/stat.h>
+#include <linux/init.h>
+#include <linux/if_ec.h>
+#include <net/udp.h>
+#include <net/ip.h>
+#include <linux/spinlock.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+
+static struct proto_ops econet_ops;
+static struct sock *econet_sklist;
+
+/* Since there are only 256 possible network numbers (or fewer, depends
+   how you count) it makes sense to use a simple lookup table. */
+static struct net_device *net2dev_map[256];
+
+#ifdef CONFIG_ECONET_AUNUDP
+static spinlock_t aun_queue_lock;
+static struct socket *udpsock;
+#define AUN_PORT	0x8000
+
+#define EC_PORT_IP	0xd2
+
+struct aunhdr
+{
+	unsigned char code;		/* AUN magic protocol byte */
+	unsigned char port;
+	unsigned char cb;
+	unsigned char pad;
+	unsigned long handle;
+};
+
+static unsigned long aun_seq = 0;
+
+/* Queue of packets waiting to be transmitted. */
+static struct sk_buff_head aun_queue;
+static struct timer_list ab_cleanup_timer;
+
+#endif		/* CONFIG_ECONET_AUNUDP */
+
+/* Per-packet information */
+struct ec_cb
+{
+	struct sockaddr_ec sec;
+	unsigned long cookie;		/* Supplied by user. */
+#ifdef CONFIG_ECONET_AUNUDP
+	int done;
+	unsigned long seq;		/* Sequencing */
+	unsigned long timeout;		/* Timeout */
+	unsigned long start;		/* jiffies */
+#endif
+#ifdef CONFIG_ECONET_NATIVE
+	void (*sent)(struct sk_buff *, int result);
+#endif
+};
+
+/*
+ *	Pull a packet from our receive queue and hand it to the user.
+ *	If necessary we block.
+ */
+
+static int econet_recvmsg(struct socket *sock, struct msghdr *msg, int len,
+			  int flags, struct scm_cookie *scm)
+{
+	struct sock *sk = sock->sk;
+	struct sk_buff *skb;
+	int copied, err;
+
+	msg->msg_namelen = sizeof(struct sockaddr_ec);
+
+	/*
+	 *	Call the generic datagram receiver. This handles all sorts
+	 *	of horrible races and re-entrancy so we can forget about it
+	 *	in the protocol layers.
+	 *
+	 *	Now it will return ENETDOWN, if device have just gone down,
+	 *	but then it will block.
+	 */
+
+	skb=skb_recv_datagram(sk,flags,flags&MSG_DONTWAIT,&err);
+
+	/*
+	 *	An error occurred so return it. Because skb_recv_datagram() 
+	 *	handles the blocking we don't see and worry about blocking
+	 *	retries.
+	 */
+
+	if(skb==NULL)
+		goto out;
+
+	/*
+	 *	You lose any data beyond the buffer you gave. If it worries a
+	 *	user program they can ask the device for its MTU anyway.
+	 */
+
+	copied = skb->len;
+	if (copied > len)
+	{
+		copied=len;
+		msg->msg_flags|=MSG_TRUNC;
+	}
+
+	/* We can't use skb_copy_datagram here */
+	err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
+	if (err)
+		goto out_free;
+	sk->stamp=skb->stamp;
+
+	if (msg->msg_name)
+		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
+
+	/*
+	 *	Free or return the buffer as appropriate. Again this
+	 *	hides all the races and re-entrancy issues from us.
+	 */
+	err = copied;
+
+out_free:
+	skb_free_datagram(sk, skb);
+out:
+	return err;
+}
+
+/*
+ *	Bind an Econet socket.
+ */
+
+static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
+	struct sock *sk=sock->sk;
+	
+	/*
+	 *	Check legality
+	 */
+	 
+	if (addr_len < sizeof(struct sockaddr_ec))
+		return -EINVAL;
+	if (sec->sec_family != AF_ECONET)
+		return -EINVAL;
+	
+	sk->protinfo.af_econet->cb = sec->cb;
+	sk->protinfo.af_econet->port = sec->port;
+	sk->protinfo.af_econet->station = sec->addr.station;
+	sk->protinfo.af_econet->net = sec->addr.net;
+
+	return 0;
+}
+
+/*
+ *	Queue a transmit result for the user to be told about.
+ */
+
+static void tx_result(struct sock *sk, unsigned long cookie, int result)
+{
+	struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
+	struct ec_cb *eb;
+	struct sockaddr_ec *sec;
+
+	if (skb == NULL)
+	{
+		printk(KERN_DEBUG "ec: memory squeeze, transmit result dropped.\n");
+		return;
+	}
+
+	eb = (struct ec_cb *)&skb->cb;
+	sec = (struct sockaddr_ec *)&eb->sec;
+	memset(sec, 0, sizeof(struct sockaddr_ec));
+	sec->cookie = cookie;
+	sec->type = ECTYPE_TRANSMIT_STATUS | result;
+	sec->sec_family = AF_ECONET;
+
+	if (sock_queue_rcv_skb(sk, skb) < 0)
+		kfree_skb(skb);
+}
+
+#ifdef CONFIG_ECONET_NATIVE
+/*
+ *	Called by the Econet hardware driver when a packet transmit
+ *	has completed.  Tell the user.
+ */
+
+static void ec_tx_done(struct sk_buff *skb, int result)
+{
+	struct ec_cb *eb = (struct ec_cb *)&skb->cb;
+	tx_result(skb->sk, eb->cookie, result);
+}
+#endif
+
+/*
+ *	Send a packet.  We have to work out which device it's going out on
+ *	and hence whether to use real Econet or the UDP emulation.
+ */
+
+static int econet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
+			  struct scm_cookie *scm)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name;
+	struct net_device *dev;
+	struct ec_addr addr;
+	int err;
+	unsigned char port, cb;
+	struct sk_buff *skb;
+	struct ec_cb *eb;
+#ifdef CONFIG_ECONET_NATIVE
+	unsigned short proto = 0;
+#endif
+#ifdef CONFIG_ECONET_AUNUDP
+	struct msghdr udpmsg;
+	struct iovec iov[msg->msg_iovlen+1];
+	struct aunhdr ah;
+	struct sockaddr_in udpdest;
+	__kernel_size_t size;
+	int i;
+	mm_segment_t oldfs;
+#endif
+		
+	/*
+	 *	Check the flags. 
+	 */
+
+	if (msg->msg_flags&~MSG_DONTWAIT) 
+		return(-EINVAL);
+
+	/*
+	 *	Get and verify the address. 
+	 */
+	 
+	if (saddr == NULL) {
+		addr.station = sk->protinfo.af_econet->station;
+		addr.net = sk->protinfo.af_econet->net;
+		port = sk->protinfo.af_econet->port;
+		cb = sk->protinfo.af_econet->cb;
+	} else {
+		if (msg->msg_namelen < sizeof(struct sockaddr_ec)) 
+			return -EINVAL;
+		addr.station = saddr->addr.station;
+		addr.net = saddr->addr.net;
+		port = saddr->port;
+		cb = saddr->cb;
+	}
+
+	/* Look for a device with the right network number. */
+	dev = net2dev_map[addr.net];
+
+	/* If not directly reachable, use some default */
+	if (dev == NULL)
+	{
+		dev = net2dev_map[0];
+		/* No interfaces at all? */
+		if (dev == NULL)
+			return -ENETDOWN;
+	}
+
+	if (dev->type == ARPHRD_ECONET)
+	{
+		/* Real hardware Econet.  We're not worthy etc. */
+#ifdef CONFIG_ECONET_NATIVE
+		atomic_inc(&dev->refcnt);
+		
+		skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, 
+					  msg->msg_flags & MSG_DONTWAIT, &err);
+		if (skb==NULL)
+			goto out_unlock;
+		
+		skb_reserve(skb, (dev->hard_header_len+15)&~15);
+		skb->nh.raw = skb->data;
+		
+		eb = (struct ec_cb *)&skb->cb;
+		
+		eb->cookie = saddr->cookie;
+		eb->sec = *saddr;
+		eb->sent = ec_tx_done;
+
+		if (dev->hard_header) {
+			int res;
+			struct ec_framehdr *fh;
+			err = -EINVAL;
+			res = dev->hard_header(skb, dev, ntohs(proto), 
+					       &addr, NULL, len);
+			/* Poke in our control byte and
+			   port number.  Hack, hack.  */
+			fh = (struct ec_framehdr *)(skb->data);
+			fh->cb = cb;
+			fh->port = port;
+			if (sock->type != SOCK_DGRAM) {
+				skb->tail = skb->data;
+				skb->len = 0;
+			} else if (res < 0)
+				goto out_free;
+		}
+		
+		/* Copy the data. Returns -EFAULT on error */
+		err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
+		skb->protocol = proto;
+		skb->dev = dev;
+		skb->priority = sk->priority;
+		if (err)
+			goto out_free;
+		
+		err = -ENETDOWN;
+		if (!(dev->flags & IFF_UP))
+			goto out_free;
+		
+		/*
+		 *	Now send it
+		 */
+		
+		dev_queue_xmit(skb);
+		dev_put(dev);
+		return(len);
+
+	out_free:
+		kfree_skb(skb);
+	out_unlock:
+		if (dev)
+			dev_put(dev);
+#else
+		err = -EPROTOTYPE;
+#endif
+		return err;
+	}
+
+#ifdef CONFIG_ECONET_AUNUDP
+	/* AUN virtual Econet. */
+
+	if (udpsock == NULL)
+		return -ENETDOWN;		/* No socket - can't send */
+	
+	/* Make up a UDP datagram and hand it off to some higher intellect. */
+
+	memset(&udpdest, 0, sizeof(udpdest));
+	udpdest.sin_family = AF_INET;
+	udpdest.sin_port = htons(AUN_PORT);
+
+	/* At the moment we use the stupid Acorn scheme of Econet address
+	   y.x maps to IP a.b.c.x.  This should be replaced with something
+	   more flexible and more aware of subnet masks.  */
+	{
+		struct in_device *idev = in_dev_get(dev);
+		unsigned long network = 0;
+		if (idev) {
+			read_lock(&idev->lock);
+			if (idev->ifa_list)
+				network = ntohl(idev->ifa_list->ifa_address) & 
+					0xffffff00;		/* !!! */
+			read_unlock(&idev->lock);
+			in_dev_put(idev);
+		}
+		udpdest.sin_addr.s_addr = htonl(network | addr.station);
+	}
+
+	ah.port = port;
+	ah.cb = cb & 0x7f;
+	ah.code = 2;		/* magic */
+	ah.pad = 0;
+
+	/* tack our header on the front of the iovec */
+	size = sizeof(struct aunhdr);
+	iov[0].iov_base = (void *)&ah;
+	iov[0].iov_len = size;
+	for (i = 0; i < msg->msg_iovlen; i++) {
+		void *base = msg->msg_iov[i].iov_base;
+		size_t len = msg->msg_iov[i].iov_len;
+		/* Check it now since we switch to KERNEL_DS later. */
+		if ((err = verify_area(VERIFY_READ, base, len)) < 0)
+			return err;
+		iov[i+1].iov_base = base;
+		iov[i+1].iov_len = len;
+		size += len;
+	}
+
+	/* Get a skbuff (no data, just holds our cb information) */
+	if ((skb = sock_alloc_send_skb(sk, 0, 0, 
+			     msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
+		return err;
+
+	eb = (struct ec_cb *)&skb->cb;
+
+	eb->cookie = saddr->cookie;
+	eb->timeout = (5*HZ);
+	eb->start = jiffies;
+	ah.handle = aun_seq;
+	eb->seq = (aun_seq++);
+	eb->sec = *saddr;
+
+	skb_queue_tail(&aun_queue, skb);
+
+	udpmsg.msg_name = (void *)&udpdest;
+	udpmsg.msg_namelen = sizeof(udpdest);
+	udpmsg.msg_iov = &iov[0];
+	udpmsg.msg_iovlen = msg->msg_iovlen + 1;
+	udpmsg.msg_control = NULL;
+	udpmsg.msg_controllen = 0;
+	udpmsg.msg_flags=0;
+
+	oldfs = get_fs(); set_fs(KERNEL_DS);	/* More privs :-) */
+	err = sock_sendmsg(udpsock, &udpmsg, size);
+	set_fs(oldfs);
+#else
+	err = -EPROTOTYPE;
+#endif
+	return err;
+}
+
+/*
+ *	Look up the address of a socket.
+ */
+
+static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
+			  int *uaddr_len, int peer)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
+
+	if (peer)
+		return -EOPNOTSUPP;
+
+	sec->sec_family = AF_ECONET;
+	sec->port = sk->protinfo.af_econet->port;
+	sec->addr.station = sk->protinfo.af_econet->station;
+	sec->addr.net = sk->protinfo.af_econet->net;
+
+	*uaddr_len = sizeof(*sec);
+	return 0;
+}
+
+static void econet_destroy_timer(unsigned long data)
+{
+	struct sock *sk=(struct sock *)data;
+
+	if (!atomic_read(&sk->wmem_alloc) && !atomic_read(&sk->rmem_alloc)) {
+		sk_free(sk);
+		MOD_DEC_USE_COUNT;
+		return;
+	}
+
+	sk->timer.expires=jiffies+10*HZ;
+	add_timer(&sk->timer);
+	printk(KERN_DEBUG "econet socket destroy delayed\n");
+}
+
+/*
+ *	Close an econet socket.
+ */
+
+static int econet_release(struct socket *sock)
+{
+	struct sk_buff	*skb;
+	struct sock *sk = sock->sk;
+
+	if (!sk)
+		return 0;
+
+	sklist_remove_socket(&econet_sklist, sk);
+
+	/*
+	 *	Now the socket is dead. No more input will appear.
+	 */
+
+	sk->state_change(sk);	/* It is useless. Just for sanity. */
+
+	sock->sk = NULL;
+	sk->socket = NULL;
+	sk->dead = 1;
+
+	/* Purge queues */
+
+	while ((skb=skb_dequeue(&sk->receive_queue))!=NULL)
+		kfree_skb(skb);
+
+	if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) {
+		sk->timer.data=(unsigned long)sk;
+		sk->timer.expires=jiffies+HZ;
+		sk->timer.function=econet_destroy_timer;
+		add_timer(&sk->timer);
+		return 0;
+	}
+
+	sk_free(sk);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/*
+ *	Create an Econet socket
+ */
+
+static int econet_create(struct socket *sock, int protocol)
+{
+	struct sock *sk;
+	int err;
+
+	/* Econet only provides datagram services. */
+	if (sock->type != SOCK_DGRAM)
+		return -ESOCKTNOSUPPORT;
+
+	sock->state = SS_UNCONNECTED;
+	MOD_INC_USE_COUNT;
+
+	err = -ENOBUFS;
+	sk = sk_alloc(PF_ECONET, GFP_KERNEL, 1);
+	if (sk == NULL)
+		goto out;
+
+	sk->reuse = 1;
+	sock->ops = &econet_ops;
+	sock_init_data(sock,sk);
+
+	sk->protinfo.af_econet = kmalloc(sizeof(struct econet_opt), GFP_KERNEL);
+	if (sk->protinfo.af_econet == NULL)
+		goto out_free;
+	memset(sk->protinfo.af_econet, 0, sizeof(struct econet_opt));
+	sk->zapped=0;
+	sk->family = PF_ECONET;
+	sk->num = protocol;
+
+	sklist_insert_socket(&econet_sklist, sk);
+	return(0);
+
+out_free:
+	sk_free(sk);
+out:
+	MOD_DEC_USE_COUNT;
+	return err;
+}
+
+/*
+ *	Handle Econet specific ioctls
+ */
+
+static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void *arg)
+{
+	struct ifreq ifr;
+	struct ec_device *edev;
+	struct net_device *dev;
+	struct sockaddr_ec *sec;
+
+	/*
+	 *	Fetch the caller's info block into kernel space
+	 */
+
+	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
+		return -EFAULT;
+
+	if ((dev = dev_get_by_name(ifr.ifr_name)) == NULL) 
+		return -ENODEV;
+
+	sec = (struct sockaddr_ec *)&ifr.ifr_addr;
+
+	switch (cmd)
+	{
+	case SIOCSIFADDR:
+		edev = dev->ec_ptr;
+		if (edev == NULL)
+		{
+			/* Magic up a new one. */
+			edev = kmalloc(GFP_KERNEL, sizeof(struct ec_device));
+			if (edev == NULL) {
+				printk("af_ec: memory squeeze.\n");
+				dev_put(dev);
+				return -ENOMEM;
+			}
+			memset(edev, 0, sizeof(struct ec_device));
+			dev->ec_ptr = edev;
+		}
+		else
+			net2dev_map[edev->net] = NULL;
+		edev->station = sec->addr.station;
+		edev->net = sec->addr.net;
+		net2dev_map[sec->addr.net] = dev;
+		if (!net2dev_map[0])
+			net2dev_map[0] = dev;
+		dev_put(dev);
+		return 0;
+
+	case SIOCGIFADDR:
+		edev = dev->ec_ptr;
+		if (edev == NULL)
+		{
+			dev_put(dev);
+			return -ENODEV;
+		}
+		memset(sec, 0, sizeof(struct sockaddr_ec));
+		sec->addr.station = edev->station;
+		sec->addr.net = edev->net;
+		sec->sec_family = AF_ECONET;
+		dev_put(dev);
+		if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
+			return -EFAULT;
+		return 0;
+	}
+
+	dev_put(dev);
+	return -EINVAL;
+}
+
+/*
+ *	Handle generic ioctls
+ */
+
+static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+	struct sock *sk = sock->sk;
+	int err;
+	int pid;
+
+	switch(cmd) 
+	{
+		case FIOSETOWN:
+		case SIOCSPGRP:
+			err = get_user(pid, (int *) arg);
+			if (err)
+				return err; 
+			if (current->pid != pid && current->pgrp != -pid && !suser())
+				return -EPERM;
+			sk->proc = pid;
+			return(0);
+		case FIOGETOWN:
+		case SIOCGPGRP:
+			return put_user(sk->proc, (int *)arg);
+		case SIOCGSTAMP:
+			if(sk->stamp.tv_sec==0)
+				return -ENOENT;
+			err = -EFAULT;
+			if (!copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
+				err = 0;
+			return err;
+		case SIOCGIFFLAGS:
+		case SIOCSIFFLAGS:
+		case SIOCGIFCONF:
+		case SIOCGIFMETRIC:
+		case SIOCSIFMETRIC:
+		case SIOCGIFMEM:
+		case SIOCSIFMEM:
+		case SIOCGIFMTU:
+		case SIOCSIFMTU:
+		case SIOCSIFLINK:
+		case SIOCGIFHWADDR:
+		case SIOCSIFHWADDR:
+		case SIOCSIFMAP:
+		case SIOCGIFMAP:
+		case SIOCSIFSLAVE:
+		case SIOCGIFSLAVE:
+		case SIOCGIFINDEX:
+		case SIOCGIFNAME:
+		case SIOCGIFCOUNT:
+		case SIOCSIFHWBROADCAST:
+			return(dev_ioctl(cmd,(void *) arg));
+
+		case SIOCSIFADDR:
+		case SIOCGIFADDR:
+			return ec_dev_ioctl(sock, cmd, (void *)arg);
+			break;
+
+		default:
+			return(dev_ioctl(cmd,(void *) arg));
+	}
+	/*NOTREACHED*/
+	return 0;
+}
+
+static struct net_proto_family econet_family_ops = {
+	PF_ECONET,
+	econet_create
+};
+
+static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
+	PF_ECONET,
+
+	econet_release,
+	econet_bind,
+	sock_no_connect,
+	sock_no_socketpair,
+	sock_no_accept,
+	econet_getname, 
+	datagram_poll,
+	econet_ioctl,
+	sock_no_listen,
+	sock_no_shutdown,
+	sock_no_setsockopt,
+	sock_no_getsockopt,
+	sock_no_fcntl,
+	econet_sendmsg,
+	econet_recvmsg,
+	sock_no_mmap
+};
+
+#include <linux/smp_lock.h>
+SOCKOPS_WRAP(econet, PF_ECONET);
+
+/*
+ *	Find the listening socket, if any, for the given data.
+ */
+
+struct sock *ec_listening_socket(unsigned char port, unsigned char
+				 station, unsigned char net)
+{
+	struct sock *sk = econet_sklist;
+
+	while (sk)
+	{
+		struct econet_opt *opt = sk->protinfo.af_econet;
+		if ((opt->port == port || opt->port == 0) && 
+		    (opt->station == station || opt->station == 0) &&
+		    (opt->net == net || opt->net == 0))
+			return sk;
+
+		sk = sk->next;
+	}
+
+	return NULL;
+}
+
+#ifdef CONFIG_ECONET_AUNUDP
+
+/*
+ *	Send an AUN protocol response. 
+ */
+
+static void aun_send_response(__u32 addr, unsigned long seq, int code, int cb)
+{
+	struct sockaddr_in sin;
+	struct iovec iov;
+	struct aunhdr ah;
+	struct msghdr udpmsg;
+	int err;
+	mm_segment_t oldfs;
+	
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_family = AF_INET;
+	sin.sin_port = htons(AUN_PORT);
+	sin.sin_addr.s_addr = addr;
+
+	ah.code = code;
+	ah.pad = 0;
+	ah.port = 0;
+	ah.cb = cb;
+	ah.handle = seq;
+
+	iov.iov_base = (void *)&ah;
+	iov.iov_len = sizeof(ah);
+
+	udpmsg.msg_name = (void *)&sin;
+	udpmsg.msg_namelen = sizeof(sin);
+	udpmsg.msg_iov = &iov;
+	udpmsg.msg_iovlen = 1;
+	udpmsg.msg_control = NULL;
+	udpmsg.msg_controllen = 0;
+	udpmsg.msg_flags=0;
+
+	oldfs = get_fs(); set_fs(KERNEL_DS);
+	err = sock_sendmsg(udpsock, &udpmsg, sizeof(ah));
+	set_fs(oldfs);
+}
+
+/*
+ *	Queue a received packet for a socket.
+ */
+
+static int ec_queue_packet(struct sock *sk, struct sk_buff *skb,
+			   unsigned char stn, unsigned char net,
+			   unsigned char cb, unsigned char port)
+{
+	struct ec_cb *eb = (struct ec_cb *)&skb->cb;
+	struct sockaddr_ec *sec = (struct sockaddr_ec *)&eb->sec;
+
+	memset(sec, 0, sizeof(struct sockaddr_ec));
+	sec->sec_family = AF_ECONET;
+	sec->type = ECTYPE_PACKET_RECEIVED;
+	sec->port = port;
+	sec->cb = cb;
+	sec->addr.net = net;
+	sec->addr.station = stn;
+
+	return sock_queue_rcv_skb(sk, skb);
+}
+
+/*
+ *	Handle incoming AUN packets.  Work out if anybody wants them,
+ *	and send positive or negative acknowledgements as appropriate.
+ */
+
+static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
+{
+	struct iphdr *ip = skb->nh.iph;
+	unsigned char stn = ntohl(ip->saddr) & 0xff;
+	struct sock *sk;
+	struct sk_buff *newskb;
+	struct ec_device *edev = skb->dev->ec_ptr;
+
+	if (! edev)
+		goto bad;
+
+	if ((sk = ec_listening_socket(ah->port, stn, edev->net)) == NULL)
+		goto bad;		/* Nobody wants it */
+
+	newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15, 
+			   GFP_ATOMIC);
+	if (newskb == NULL)
+	{
+		printk(KERN_DEBUG "AUN: memory squeeze, dropping packet.\n");
+		/* Send nack and hope sender tries again */
+		goto bad;
+	}
+
+	memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah+1), 
+	       len - sizeof(struct aunhdr));
+
+	if (ec_queue_packet(sk, newskb, stn, edev->net, ah->cb, ah->port))
+	{
+		/* Socket is bankrupt. */
+		kfree_skb(newskb);
+		goto bad;
+	}
+
+	aun_send_response(ip->saddr, ah->handle, 3, 0);
+	return;
+
+bad:
+	aun_send_response(ip->saddr, ah->handle, 4, 0);
+}
+
+/*
+ *	Handle incoming AUN transmit acknowledgements.  If the sequence
+ *      number matches something in our backlog then kill it and tell
+ *	the user.  If the remote took too long to reply then we may have
+ *	dropped the packet already.
+ */
+
+static void aun_tx_ack(unsigned long seq, int result)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+	struct ec_cb *eb;
+
+	spin_lock_irqsave(&aun_queue_lock, flags);
+	skb = skb_peek(&aun_queue);
+	while (skb && skb != (struct sk_buff *)&aun_queue)
+	{
+		struct sk_buff *newskb = skb->next;
+		eb = (struct ec_cb *)&skb->cb;
+		if (eb->seq == seq)
+			goto foundit;
+
+		skb = newskb;
+	}
+	spin_unlock_irqrestore(&aun_queue_lock, flags);
+	printk(KERN_DEBUG "AUN: unknown sequence %ld\n", seq);
+	return;
+
+foundit:
+	tx_result(skb->sk, eb->cookie, result);
+	skb_unlink(skb);
+	spin_unlock_irqrestore(&aun_queue_lock, flags);
+	kfree_skb(skb);
+}
+
+/*
+ *	Deal with received AUN frames - sort out what type of thing it is
+ *	and hand it to the right function.
+ */
+
+static void aun_data_available(struct sock *sk, int slen)
+{
+	int err;
+	struct sk_buff *skb;
+	unsigned char *data;
+	struct aunhdr *ah;
+	struct iphdr *ip;
+	size_t len;
+
+	while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) {
+		if (err == -EAGAIN) {
+			printk(KERN_ERR "AUN: no data available?!");
+			return;
+		}
+		printk(KERN_DEBUG "AUN: recvfrom() error %d\n", -err);
+	}
+
+	data = skb->h.raw + sizeof(struct udphdr);
+	ah = (struct aunhdr *)data;
+	len = skb->len - sizeof(struct udphdr);
+	ip = skb->nh.iph;
+
+	switch (ah->code)
+	{
+	case 2:
+		aun_incoming(skb, ah, len);
+		break;
+	case 3:
+		aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_OK);
+		break;
+	case 4:
+		aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING);
+		break;
+#if 0
+		/* This isn't quite right yet. */
+	case 5:
+		aun_send_response(ip->saddr, ah->handle, 6, ah->cb);
+		break;
+#endif
+	default:
+		printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]);
+	}
+
+	skb_free_datagram(sk, skb);
+}
+
+/*
+ *	Called by the timer to manage the AUN transmit queue.  If a packet
+ *	was sent to a dead or nonexistent host then we will never get an
+ *	acknowledgement back.  After a few seconds we need to spot this and
+ *	drop the packet.
+ */
+
+static void ab_cleanup(unsigned long h)
+{
+	struct sk_buff *skb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&aun_queue_lock, flags);
+	skb = skb_peek(&aun_queue);
+	while (skb && skb != (struct sk_buff *)&aun_queue)
+	{
+		struct sk_buff *newskb = skb->next;
+		struct ec_cb *eb = (struct ec_cb *)&skb->cb;
+		if ((jiffies - eb->start) > eb->timeout)
+		{
+			tx_result(skb->sk, eb->cookie, 
+				  ECTYPE_TRANSMIT_NOT_PRESENT);
+			skb_unlink(skb);
+			kfree_skb(skb);
+		}
+		skb = newskb;
+	}
+	spin_unlock_irqrestore(&aun_queue_lock, flags);
+
+	mod_timer(&ab_cleanup_timer, jiffies + (HZ*2));
+}
+
+static int __init aun_udp_initialise(void)
+{
+	int error;
+	struct sockaddr_in sin;
+
+	skb_queue_head_init(&aun_queue);
+	spin_lock_init(&aun_queue_lock);
+	init_timer(&ab_cleanup_timer);
+	ab_cleanup_timer.expires = jiffies + (HZ*2);
+	ab_cleanup_timer.function = ab_cleanup;
+	add_timer(&ab_cleanup_timer);
+
+	memset(&sin, 0, sizeof(sin));
+	sin.sin_port = htons(AUN_PORT);
+
+	/* We can count ourselves lucky Acorn machines are too dim to
+	   speak IPv6. :-) */
+	if ((error = sock_create(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
+	{
+		printk("AUN: socket error %d\n", -error);
+		return error;
+	}
+	
+	udpsock->sk->reuse = 1;
+	udpsock->sk->allocation = GFP_ATOMIC;	/* we're going to call it
+						   from interrupts */
+	
+	error = udpsock->ops->bind(udpsock, (struct sockaddr *)&sin,
+				sizeof(sin));
+	if (error < 0)
+	{
+		printk("AUN: bind error %d\n", -error);
+		goto release;
+	}
+
+	udpsock->sk->data_ready = aun_data_available;
+
+	return 0;
+
+release:
+	sock_release(udpsock);
+	udpsock = NULL;
+	return error;
+}
+#endif
+
+#ifdef CONFIG_ECONET_NATIVE
+
+/*
+ *	Receive an Econet frame from a device.
+ */
+
+static int econet_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
+{
+	struct ec_framehdr *hdr = (struct ec_framehdr *)skb->data;
+	struct sock *sk;
+	struct ec_device *edev = dev->ec_ptr;
+
+	if (! edev)
+	{
+		kfree_skb(skb);
+		return 0;
+	}
+
+	if (skb->len < sizeof(struct ec_framehdr))
+	{
+		/* Frame is too small to be any use */
+		kfree_skb(skb);
+		return 0;
+	}
+
+	/* First check for encapsulated IP */
+	if (hdr->port == EC_PORT_IP)
+	{
+		skb->protocol = htons(ETH_P_IP);
+		skb_pull(skb, sizeof(struct ec_framehdr));
+		netif_rx(skb);
+		return 0;
+	}
+
+	sk = ec_listening_socket(hdr->port, hdr->src_stn, hdr->src_net);
+	if (!sk) 
+	{
+		kfree_skb(skb);
+		return 0;
+	}
+
+	return ec_queue_packet(sk, skb, edev->net, hdr->src_stn, hdr->cb, 
+			       hdr->port);
+}
+
+struct packet_type econet_packet_type=
+{
+	0,
+	NULL,
+	econet_rcv,
+	NULL,
+	NULL
+};
+
+static void econet_hw_initialise(void)
+{
+	econet_packet_type.type = htons(ETH_P_ECONET);
+	dev_add_pack(&econet_packet_type);
+}
+
+#endif
+
+static int econet_notifier(struct notifier_block *this, unsigned long msg, void *data)
+{
+	struct net_device *dev = (struct net_device *)data;
+	struct ec_device *edev;
+
+	switch (msg) {
+	case NETDEV_UNREGISTER:
+		/* A device has gone down - kill any data we hold for it. */
+		edev = dev->ec_ptr;
+		if (edev)
+		{
+			if (net2dev_map[0] == dev)
+				net2dev_map[0] = 0;
+			net2dev_map[edev->net] = NULL;
+			kfree(edev);
+			dev->ec_ptr = NULL;
+		}
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+struct notifier_block econet_netdev_notifier={
+	econet_notifier,
+	NULL,
+	0
+};
+
+void __exit econet_proto_exit(void)
+{
+	extern void econet_sysctl_unregister(void);
+#ifdef CONFIG_ECONET_AUNUDP
+	del_timer(&ab_cleanup_timer);
+	if (udpsock)
+		sock_release(udpsock);
+#endif
+	unregister_netdevice_notifier(&econet_netdev_notifier);
+	sock_unregister(econet_family_ops.family);
+#ifdef CONFIG_SYSCTL
+	econet_sysctl_unregister();
+#endif
+}
+
+int __init econet_proto_init(struct net_proto *pro)
+{
+	extern void econet_sysctl_register(void);
+	spin_lock_init(&aun_queue_lock);
+	sock_register(&econet_family_ops);
+#ifdef CONFIG_ECONET_AUNUDP
+	aun_udp_initialise();
+#endif
+#ifdef CONFIG_ECONET_NATIVE
+	econet_hw_initialise();
+#endif
+	register_netdevice_notifier(&econet_netdev_notifier);
+#ifdef CONFIG_SYSCTL
+	econet_sysctl_register();
+#endif
+	return 0;
+}
+
+#ifdef MODULE
+module_init(econet_proto_init);
+module_exit(econet_proto_exit);
+#endif
diff -u --recursive --new-file v2.3.50/linux/net/econet/econet.c linux/net/econet/econet.c
--- v2.3.50/linux/net/econet/econet.c	Fri Sep 10 23:57:38 1999
+++ linux/net/econet/econet.c	Wed Dec 31 16:00:00 1969
@@ -1,1125 +0,0 @@
-/*
- *	An implementation of the Acorn Econet and AUN protocols.
- *	Philip Blundell <philb@gnu.org>
- *
- *	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.
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/bitops.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/route.h>
-#include <linux/inet.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-#include <net/inet_common.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/if_ec.h>
-#include <net/udp.h>
-#include <net/ip.h>
-#include <linux/spinlock.h>
-
-static struct proto_ops econet_ops;
-static struct sock *econet_sklist;
-
-static spinlock_t aun_queue_lock;
-
-#ifdef CONFIG_ECONET_AUNUDP
-static struct socket *udpsock;
-#define AUN_PORT	0x8000
-
-struct aunhdr
-{
-	unsigned char code;		/* AUN magic protocol byte */
-	unsigned char port;
-	unsigned char cb;
-	unsigned char pad;
-	unsigned long handle;
-};
-
-static unsigned long aun_seq = 0;
-
-/* Queue of packets waiting to be transmitted. */
-static struct sk_buff_head aun_queue;
-static struct timer_list ab_cleanup_timer;
-
-#endif		/* CONFIG_ECONET_AUNUDP */
-
-/* Per-packet information */
-struct ec_cb
-{
-	struct sockaddr_ec sec;
-	unsigned long cookie;		/* Supplied by user. */
-#ifdef CONFIG_ECONET_AUNUDP
-	int done;
-	unsigned long seq;		/* Sequencing */
-	unsigned long timeout;		/* Timeout */
-	unsigned long start;		/* jiffies */
-#endif
-#ifdef CONFIG_ECONET_NATIVE
-	void (*sent)(struct sk_buff *, int result);
-#endif
-};
-
-struct ec_device
-{
-	struct net_device *dev;		/* Real device structure */
-	unsigned char station, net;	/* Econet protocol address */
-	struct ec_device *prev, *next;	/* Linked list */
-};
-
-static struct ec_device *edevlist = NULL;
-
-static spinlock_t edevlist_lock;
-
-/*
- *	Faster version of edev_get - call with IRQs off
- */
-
-static __inline__ struct ec_device *__edev_get(struct net_device *dev)
-{
-	struct ec_device *edev;
-	for (edev = edevlist; edev; edev = edev->next)
-	{
-		if (edev->dev == dev)
-			break;
-	}
-	return edev;
-}
-
-/*
- *	Find an Econet device given its `dev' pointer.  This is IRQ safe.
- *
- *	Against what is it safe? --ANK
- */
-
-static struct ec_device *edev_get(struct net_device *dev)
-{
-	struct ec_device *edev;
-	unsigned long flags;
-	spin_lock_irqsave(&edevlist_lock, flags);
-	edev = __edev_get(dev);
-	spin_unlock_irqrestore(&edevlist_lock, flags);
-	return edev;
-}
-
-/*
- *	Pull a packet from our receive queue and hand it to the user.
- *	If necessary we block.
- */
-
-static int econet_recvmsg(struct socket *sock, struct msghdr *msg, int len,
-			  int flags, struct scm_cookie *scm)
-{
-	struct sock *sk = sock->sk;
-	struct sk_buff *skb;
-	int copied, err;
-
-	msg->msg_namelen = sizeof(struct sockaddr_ec);
-
-	/*
-	 *	Call the generic datagram receiver. This handles all sorts
-	 *	of horrible races and re-entrancy so we can forget about it
-	 *	in the protocol layers.
-	 *
-	 *	Now it will return ENETDOWN, if device have just gone down,
-	 *	but then it will block.
-	 */
-
-	skb=skb_recv_datagram(sk,flags,flags&MSG_DONTWAIT,&err);
-
-	/*
-	 *	An error occurred so return it. Because skb_recv_datagram() 
-	 *	handles the blocking we don't see and worry about blocking
-	 *	retries.
-	 */
-
-	if(skb==NULL)
-		goto out;
-
-	/*
-	 *	You lose any data beyond the buffer you gave. If it worries a
-	 *	user program they can ask the device for its MTU anyway.
-	 */
-
-	copied = skb->len;
-	if (copied > len)
-	{
-		copied=len;
-		msg->msg_flags|=MSG_TRUNC;
-	}
-
-	/* We can't use skb_copy_datagram here */
-	err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
-	if (err)
-		goto out_free;
-	sk->stamp=skb->stamp;
-
-	if (msg->msg_name)
-		memcpy(msg->msg_name, skb->cb, msg->msg_namelen);
-
-	/*
-	 *	Free or return the buffer as appropriate. Again this
-	 *	hides all the races and re-entrancy issues from us.
-	 */
-	err = copied;
-
-out_free:
-	skb_free_datagram(sk, skb);
-out:
-	return err;
-}
-
-/*
- *	Bind an Econet socket.
- */
-
-static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
-{
-	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
-	struct sock *sk=sock->sk;
-	
-	/*
-	 *	Check legality
-	 */
-	 
-	if (addr_len < sizeof(struct sockaddr_ec))
-		return -EINVAL;
-	if (sec->sec_family != AF_ECONET)
-		return -EINVAL;
-	
-	sk->protinfo.af_econet->cb = sec->cb;
-	sk->protinfo.af_econet->port = sec->port;
-	sk->protinfo.af_econet->station = sec->addr.station;
-	sk->protinfo.af_econet->net = sec->addr.net;
-
-	return 0;
-}
-
-/*
- *	Queue a transmit result for the user to be told about.
- */
-
-static void tx_result(struct sock *sk, unsigned long cookie, int result)
-{
-	struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
-	struct ec_cb *eb;
-	struct sockaddr_ec *sec;
-
-	if (skb == NULL)
-	{
-		printk(KERN_DEBUG "ec: memory squeeze, transmit result dropped.\n");
-		return;
-	}
-
-	eb = (struct ec_cb *)&skb->cb;
-	sec = (struct sockaddr_ec *)&eb->sec;
-	memset(sec, 0, sizeof(struct sockaddr_ec));
-	sec->cookie = cookie;
-	sec->type = ECTYPE_TRANSMIT_STATUS | result;
-	sec->sec_family = AF_ECONET;
-
-	if (sock_queue_rcv_skb(sk, skb) < 0)
-		kfree_skb(skb);
-}
-
-#ifdef CONFIG_ECONET_NATIVE
-/*
- *	Called by the Econet hardware driver when a packet transmit
- *	has completed.  Tell the user.
- */
-
-static void ec_tx_done(struct sk_buff *skb, int result)
-{
-	struct ec_cb *eb = (struct ec_cb *)&skb->cb;
-	tx_result(skb->sk, eb->cookie, result);
-}
-#endif
-
-/*
- *	Send a packet.  We have to work out which device it's going out on
- *	and hence whether to use real Econet or the UDP emulation.
- */
-
-static int econet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
-			  struct scm_cookie *scm)
-{
-	struct sock *sk = sock->sk;
-	struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name;
-	struct net_device *dev;
-	struct ec_addr addr;
-	struct ec_device *edev;
-	int err;
-	unsigned char port, cb;
-	struct sk_buff *skb;
-	struct ec_cb *eb;
-#ifdef CONFIG_ECONET_NATIVE
-	unsigned short proto = 0;
-#endif
-#ifdef CONFIG_ECONET_AUNUDP
-	struct msghdr udpmsg;
-	struct iovec iov[msg->msg_iovlen+1];
-	struct aunhdr ah;
-	struct sockaddr_in udpdest;
-	__kernel_size_t size;
-	int i;
-	mm_segment_t oldfs;
-#endif
-		
-	/*
-	 *	Check the flags. 
-	 */
-
-	if (msg->msg_flags&~MSG_DONTWAIT) 
-		return(-EINVAL);
-
-	/*
-	 *	Get and verify the address. 
-	 */
-	 
-	if (saddr == NULL) {
-		addr.station = sk->protinfo.af_econet->station;
-		addr.net = sk->protinfo.af_econet->net;
-		port = sk->protinfo.af_econet->port;
-		cb = sk->protinfo.af_econet->cb;
-	} else {
-		if (msg->msg_namelen < sizeof(struct sockaddr_ec)) 
-			return -EINVAL;
-		addr.station = saddr->addr.station;
-		addr.net = saddr->addr.net;
-		port = saddr->port;
-		cb = saddr->cb;
-	}
-
-	/* Look for a device with the right network number. */
-	for (edev = edevlist; edev && (edev->net != addr.net); 
-	     edev = edev->next);
-
-	/* Bridge?  What's that? */
-	if (edev == NULL) 
-		return -ENETUNREACH;
-
-	dev = edev->dev;
-
-	if (dev->type == ARPHRD_ECONET)
-	{
-		/* Real hardware Econet.  We're not worthy etc. */
-#ifdef CONFIG_ECONET_NATIVE
-		atomic_inc(&dev->refcnt);
-		
-		skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, 
-					  msg->msg_flags & MSG_DONTWAIT, &err);
-		if (skb==NULL)
-			goto out_unlock;
-		
-		skb_reserve(skb, (dev->hard_header_len+15)&~15);
-		skb->nh.raw = skb->data;
-		
-		eb = (struct ec_cb *)&skb->cb;
-		
-		eb->cookie = saddr->cookie;
-		eb->sec = *saddr;
-		eb->sent = ec_tx_done;
-
-		if (dev->hard_header) {
-			int res;
-			err = -EINVAL;
-			res = dev->hard_header(skb, dev, ntohs(proto), &addr, NULL, len);
-			if (sock->type != SOCK_DGRAM) {
-				skb->tail = skb->data;
-				skb->len = 0;
-			} else if (res < 0)
-				goto out_free;
-		}
-		
-		/* Copy the data. Returns -EFAULT on error */
-		err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
-		skb->protocol = proto;
-		skb->dev = dev;
-		skb->priority = sk->priority;
-		if (err)
-			goto out_free;
-		
-		err = -ENETDOWN;
-		if (!(dev->flags & IFF_UP))
-			goto out_free;
-		
-		/*
-		 *	Now send it
-		 */
-		
-		dev_queue_xmit(skb);
-		dev_put(dev);
-		return(len);
-
-	out_free:
-		kfree_skb(skb);
-	out_unlock:
-		if (dev)
-			dev_put(dev);
-#else
-		err = -EPROTOTYPE;
-#endif
-		return err;
-	}
-
-#ifdef CONFIG_ECONET_AUNUDP
-	/* AUN virtual Econet. */
-
-	if (udpsock == NULL)
-		return -ENETDOWN;		/* No socket - can't send */
-	
-	/* Make up a UDP datagram and hand it off to some higher intellect. */
-
-	memset(&udpdest, 0, sizeof(udpdest));
-	udpdest.sin_family = AF_INET;
-	udpdest.sin_port = htons(AUN_PORT);
-
-	/* At the moment we use the stupid Acorn scheme of Econet address
-	   y.x maps to IP a.b.c.x.  This should be replaced with something
-	   more flexible and more aware of subnet masks.  */
-	{
-		struct in_device *idev = in_dev_get(dev);
-		unsigned long network = 0;
-		if (idev) {
-			read_lock(&idev->lock);
-			if (idev->ifa_list)
-				network = ntohl(idev->ifa_list->ifa_address) & 
-					0xffffff00;		/* !!! */
-			read_unlock(&idev->lock);
-			in_dev_put(idev);
-		}
-		udpdest.sin_addr.s_addr = htonl(network | addr.station);
-	}
-
-	ah.port = port;
-	ah.cb = cb & 0x7f;
-	ah.code = 2;		/* magic */
-	ah.pad = 0;
-
-	/* tack our header on the front of the iovec */
-	size = sizeof(struct aunhdr);
-	iov[0].iov_base = (void *)&ah;
-	iov[0].iov_len = size;
-	for (i = 0; i < msg->msg_iovlen; i++) {
-		void *base = msg->msg_iov[i].iov_base;
-		size_t len = msg->msg_iov[i].iov_len;
-		/* Check it now since we switch to KERNEL_DS later. */
-		if ((err = verify_area(VERIFY_READ, base, len)) < 0)
-			return err;
-		iov[i+1].iov_base = base;
-		iov[i+1].iov_len = len;
-		size += len;
-	}
-
-	/* Get a skbuff (no data, just holds our cb information) */
-	if ((skb = sock_alloc_send_skb(sk, 0, 0, 
-			     msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
-		return err;
-
-	eb = (struct ec_cb *)&skb->cb;
-
-	eb->cookie = saddr->cookie;
-	eb->timeout = (5*HZ);
-	eb->start = jiffies;
-	ah.handle = aun_seq;
-	eb->seq = (aun_seq++);
-	eb->sec = *saddr;
-
-	skb_queue_tail(&aun_queue, skb);
-
-	udpmsg.msg_name = (void *)&udpdest;
-	udpmsg.msg_namelen = sizeof(udpdest);
-	udpmsg.msg_iov = &iov[0];
-	udpmsg.msg_iovlen = msg->msg_iovlen + 1;
-	udpmsg.msg_control = NULL;
-	udpmsg.msg_controllen = 0;
-	udpmsg.msg_flags=0;
-
-	oldfs = get_fs(); set_fs(KERNEL_DS);	/* More privs :-) */
-	err = sock_sendmsg(udpsock, &udpmsg, size);
-	set_fs(oldfs);
-#else
-	err = -EPROTOTYPE;
-#endif
-	return err;
-}
-
-/*
- *	Look up the address of a socket.
- */
-
-static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
-			  int *uaddr_len, int peer)
-{
-	struct sock *sk = sock->sk;
-	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
-
-	if (peer)
-		return -EOPNOTSUPP;
-
-	sec->sec_family = AF_ECONET;
-	sec->port = sk->protinfo.af_econet->port;
-	sec->addr.station = sk->protinfo.af_econet->station;
-	sec->addr.net = sk->protinfo.af_econet->net;
-
-	*uaddr_len = sizeof(*sec);
-	return 0;
-}
-
-static void econet_destroy_timer(unsigned long data)
-{
-	struct sock *sk=(struct sock *)data;
-
-	if (!atomic_read(&sk->wmem_alloc) && !atomic_read(&sk->rmem_alloc)) {
-		sk_free(sk);
-		MOD_DEC_USE_COUNT;
-		return;
-	}
-
-	sk->timer.expires=jiffies+10*HZ;
-	add_timer(&sk->timer);
-	printk(KERN_DEBUG "econet socket destroy delayed\n");
-}
-
-/*
- *	Close an econet socket.
- */
-
-static int econet_release(struct socket *sock)
-{
-	struct sk_buff	*skb;
-	struct sock *sk = sock->sk;
-
-	if (!sk)
-		return 0;
-
-	sklist_remove_socket(&econet_sklist, sk);
-
-	/*
-	 *	Now the socket is dead. No more input will appear.
-	 */
-
-	sk->state_change(sk);	/* It is useless. Just for sanity. */
-
-	sock->sk = NULL;
-	sk->socket = NULL;
-	sk->dead = 1;
-
-	/* Purge queues */
-
-	while ((skb=skb_dequeue(&sk->receive_queue))!=NULL)
-		kfree_skb(skb);
-
-	if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) {
-		sk->timer.data=(unsigned long)sk;
-		sk->timer.expires=jiffies+HZ;
-		sk->timer.function=econet_destroy_timer;
-		add_timer(&sk->timer);
-		return 0;
-	}
-
-	sk_free(sk);
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-/*
- *	Create an Econet socket
- */
-
-static int econet_create(struct socket *sock, int protocol)
-{
-	struct sock *sk;
-	int err;
-
-	/* Econet only provides datagram services. */
-	if (sock->type != SOCK_DGRAM)
-		return -ESOCKTNOSUPPORT;
-
-	sock->state = SS_UNCONNECTED;
-	MOD_INC_USE_COUNT;
-
-	err = -ENOBUFS;
-	sk = sk_alloc(PF_ECONET, GFP_KERNEL, 1);
-	if (sk == NULL)
-		goto out;
-
-	sk->reuse = 1;
-	sock->ops = &econet_ops;
-	sock_init_data(sock,sk);
-
-	sk->protinfo.af_econet = kmalloc(sizeof(struct econet_opt), GFP_KERNEL);
-	if (sk->protinfo.af_econet == NULL)
-		goto out_free;
-	memset(sk->protinfo.af_econet, 0, sizeof(struct econet_opt));
-	sk->zapped=0;
-	sk->family = PF_ECONET;
-	sk->num = protocol;
-
-	sklist_insert_socket(&econet_sklist, sk);
-	return(0);
-
-out_free:
-	sk_free(sk);
-out:
-	MOD_DEC_USE_COUNT;
-	return err;
-}
-
-/*
- *	Handle Econet specific ioctls
- */
-
-static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void *arg)
-{
-	struct ifreq ifr;
-	struct ec_device *edev;
-	struct net_device *dev;
-	unsigned long flags;
-	struct sockaddr_ec *sec;
-
-	/*
-	 *	Fetch the caller's info block into kernel space
-	 */
-
-	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
-		return -EFAULT;
-
-	if ((dev = dev_get_by_name(ifr.ifr_name)) == NULL) 
-		return -ENODEV;
-
-	sec = (struct sockaddr_ec *)&ifr.ifr_addr;
-
-	switch (cmd)
-	{
-	case SIOCSIFADDR:
-		spin_lock_irqsave(&edevlist_lock, flags);
-		edev = __edev_get(dev);
-		if (edev == NULL)
-		{
-			/* Magic up a new one. */
-			printk("Get fascist grenade!!!\n");
-			*(int*)0 = 0;
-			/* Note to author: please, remove this spinlock.
-			   You do not change edevlist from interrupts,
-			   so that such aggressive protection is redundant.
-
-			   BTW not all scans of edev_list are protected.
-			 */
-			edev = kmalloc(GFP_KERNEL, sizeof(struct ec_device));
-			if (edev == NULL) {
-				printk("af_ec: memory squeeze.\n");
-				spin_unlock_irqrestore(&edevlist_lock, flags);
-				dev_put(dev);
-				return -ENOMEM;
-			}
-			memset(edev, 0, sizeof(struct ec_device));
-			edev->dev = dev;
-			edev->next = edevlist;
-			edevlist = edev;
-		}
-		edev->station = sec->addr.station;
-		edev->net = sec->addr.net;
-		spin_unlock_irqrestore(&edevlist_lock, flags);
-		dev_put(dev);
-		return 0;
-
-	case SIOCGIFADDR:
-		spin_lock_irqsave(&edevlist_lock, flags);
-		edev = __edev_get(dev);
-		if (edev == NULL)
-		{
-			spin_unlock_irqrestore(&edevlist_lock, flags);
-			dev_put(dev);
-			return -ENODEV;
-		}
-		memset(sec, 0, sizeof(struct sockaddr_ec));
-		sec->addr.station = edev->station;
-		sec->addr.net = edev->net;
-		sec->sec_family = AF_ECONET;
-		spin_unlock_irqrestore(&edevlist_lock, flags);
-		dev_put(dev);
-		if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
-			return -EFAULT;
-		return 0;
-	}
-
-	dev_put(dev);
-	return -EINVAL;
-}
-
-/*
- *	Handle generic ioctls
- */
-
-static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-	struct sock *sk = sock->sk;
-	int err;
-	int pid;
-
-	switch(cmd) 
-	{
-		case FIOSETOWN:
-		case SIOCSPGRP:
-			err = get_user(pid, (int *) arg);
-			if (err)
-				return err; 
-			if (current->pid != pid && current->pgrp != -pid && !suser())
-				return -EPERM;
-			sk->proc = pid;
-			return(0);
-		case FIOGETOWN:
-		case SIOCGPGRP:
-			return put_user(sk->proc, (int *)arg);
-		case SIOCGSTAMP:
-			if(sk->stamp.tv_sec==0)
-				return -ENOENT;
-			err = -EFAULT;
-			if (!copy_to_user((void *)arg, &sk->stamp, sizeof(struct timeval)))
-				err = 0;
-			return err;
-		case SIOCGIFFLAGS:
-		case SIOCSIFFLAGS:
-		case SIOCGIFCONF:
-		case SIOCGIFMETRIC:
-		case SIOCSIFMETRIC:
-		case SIOCGIFMEM:
-		case SIOCSIFMEM:
-		case SIOCGIFMTU:
-		case SIOCSIFMTU:
-		case SIOCSIFLINK:
-		case SIOCGIFHWADDR:
-		case SIOCSIFHWADDR:
-		case SIOCSIFMAP:
-		case SIOCGIFMAP:
-		case SIOCSIFSLAVE:
-		case SIOCGIFSLAVE:
-		case SIOCGIFINDEX:
-		case SIOCGIFNAME:
-		case SIOCGIFCOUNT:
-		case SIOCSIFHWBROADCAST:
-			return(dev_ioctl(cmd,(void *) arg));
-
-		case SIOCSIFADDR:
-		case SIOCGIFADDR:
-			return ec_dev_ioctl(sock, cmd, (void *)arg);
-			break;
-
-		default:
-			return(dev_ioctl(cmd,(void *) arg));
-	}
-	/*NOTREACHED*/
-	return 0;
-}
-
-static struct net_proto_family econet_family_ops = {
-	PF_ECONET,
-	econet_create
-};
-
-static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
-	PF_ECONET,
-
-	econet_release,
-	econet_bind,
-	sock_no_connect,
-	sock_no_socketpair,
-	sock_no_accept,
-	econet_getname, 
-	datagram_poll,
-	econet_ioctl,
-	sock_no_listen,
-	sock_no_shutdown,
-	sock_no_setsockopt,
-	sock_no_getsockopt,
-	sock_no_fcntl,
-	econet_sendmsg,
-	econet_recvmsg,
-	sock_no_mmap
-};
-
-#include <linux/smp_lock.h>
-SOCKOPS_WRAP(econet, PF_ECONET);
-
-/*
- *	Find the listening socket, if any, for the given data.
- */
-
-static struct sock *ec_listening_socket(unsigned char port, unsigned char
-					station, unsigned char net)
-{
-	struct sock *sk = econet_sklist;
-
-	while (sk)
-	{
-		struct econet_opt *opt = sk->protinfo.af_econet;
-		if ((opt->port == port || opt->port == 0) && 
-		    (opt->station == station || opt->station == 0) &&
-		    (opt->net == net || opt->net == 0))
-			return sk;
-
-		sk = sk->next;
-	}
-
-	return NULL;
-}
-
-#ifdef CONFIG_ECONET_AUNUDP
-
-/*
- *	Send an AUN protocol response. 
- */
-
-static void aun_send_response(__u32 addr, unsigned long seq, int code, int cb)
-{
-	struct sockaddr_in sin;
-	struct iovec iov;
-	struct aunhdr ah;
-	struct msghdr udpmsg;
-	int err;
-	mm_segment_t oldfs;
-	
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_family = AF_INET;
-	sin.sin_port = htons(AUN_PORT);
-	sin.sin_addr.s_addr = addr;
-
-	ah.code = code;
-	ah.pad = 0;
-	ah.port = 0;
-	ah.cb = cb;
-	ah.handle = seq;
-
-	iov.iov_base = (void *)&ah;
-	iov.iov_len = sizeof(ah);
-
-	udpmsg.msg_name = (void *)&sin;
-	udpmsg.msg_namelen = sizeof(sin);
-	udpmsg.msg_iov = &iov;
-	udpmsg.msg_iovlen = 1;
-	udpmsg.msg_control = NULL;
-	udpmsg.msg_controllen = 0;
-	udpmsg.msg_flags=0;
-
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	err = sock_sendmsg(udpsock, &udpmsg, sizeof(ah));
-	set_fs(oldfs);
-}
-
-/*
- *	Handle incoming AUN packets.  Work out if anybody wants them,
- *	and send positive or negative acknowledgements as appropriate.
- */
-
-static void aun_incoming(struct sk_buff *skb, struct aunhdr *ah, size_t len)
-{
-	struct ec_device *edev = edev_get(skb->dev);
-	struct iphdr *ip = skb->nh.iph;
-	unsigned char stn = ntohl(ip->saddr) & 0xff;
-	struct sock *sk;
-	struct sk_buff *newskb;
-	struct ec_cb *eb;
-	struct sockaddr_ec *sec;
-
-	if (edev == NULL)
-		return;		/* Device not configured for AUN */
-	
-	if ((sk = ec_listening_socket(ah->port, stn, edev->net)) == NULL)
-		goto bad;		/* Nobody wants it */
-
-	newskb = alloc_skb((len - sizeof(struct aunhdr) + 15) & ~15, 
-			   GFP_ATOMIC);
-	if (newskb == NULL)
-	{
-		printk(KERN_DEBUG "AUN: memory squeeze, dropping packet.\n");
-		/* Send nack and hope sender tries again */
-		goto bad;
-	}
-
-	eb = (struct ec_cb *)&newskb->cb;
-	sec = (struct sockaddr_ec *)&eb->sec;
-	memset(sec, 0, sizeof(struct sockaddr_ec));
-	sec->sec_family = AF_ECONET;
-	sec->type = ECTYPE_PACKET_RECEIVED;
-	sec->port = ah->port;
-	sec->cb = ah->cb;
-	sec->addr.net = edev->net;
-	sec->addr.station = stn;
-
-	memcpy(skb_put(newskb, len - sizeof(struct aunhdr)), (void *)(ah+1), 
-	       len - sizeof(struct aunhdr));
-
-	if (sock_queue_rcv_skb(sk, newskb) < 0)
-	{
-		/* Socket is bankrupt. */
-		kfree_skb(newskb);
-		goto bad;
-	}
-
-	aun_send_response(ip->saddr, ah->handle, 3, 0);
-	return;
-
-bad:
-	aun_send_response(ip->saddr, ah->handle, 4, 0);
-}
-
-/*
- *	Handle incoming AUN transmit acknowledgements.  If the sequence
- *      number matches something in our backlog then kill it and tell
- *	the user.  If the remote took too long to reply then we may have
- *	dropped the packet already.
- */
-
-static void aun_tx_ack(unsigned long seq, int result)
-{
-	struct sk_buff *skb;
-	unsigned long flags;
-	struct ec_cb *eb;
-
-	spin_lock_irqsave(&aun_queue_lock, flags);
-	skb = skb_peek(&aun_queue);
-	while (skb && skb != (struct sk_buff *)&aun_queue)
-	{
-		struct sk_buff *newskb = skb->next;
-		eb = (struct ec_cb *)&skb->cb;
-		if (eb->seq == seq)
-			goto foundit;
-
-		skb = newskb;
-	}
-	spin_unlock_irqrestore(&aun_queue_lock, flags);
-	printk(KERN_DEBUG "AUN: unknown sequence %ld\n", seq);
-	return;
-
-foundit:
-	tx_result(skb->sk, eb->cookie, result);
-	skb_unlink(skb);
-	spin_unlock_irqrestore(&aun_queue_lock, flags);
-}
-
-/*
- *	Deal with received AUN frames - sort out what type of thing it is
- *	and hand it to the right function.
- */
-
-static void aun_data_available(struct sock *sk, int slen)
-{
-	int err;
-	struct sk_buff *skb;
-	unsigned char *data;
-	struct aunhdr *ah;
-	struct iphdr *ip;
-	size_t len;
-
-	while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) {
-		if (err == -EAGAIN) {
-			printk(KERN_ERR "AUN: no data available?!");
-			return;
-		}
-		printk(KERN_DEBUG "AUN: recvfrom() error %d\n", -err);
-	}
-
-	data = skb->h.raw + sizeof(struct udphdr);
-	ah = (struct aunhdr *)data;
-	len = skb->len - sizeof(struct udphdr);
-	ip = skb->nh.iph;
-
-	switch (ah->code)
-	{
-	case 2:
-		aun_incoming(skb, ah, len);
-		break;
-	case 3:
-		aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_OK);
-		break;
-	case 4:
-		aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING);
-		break;
-#if 0
-		/* This isn't quite right yet. */
-	case 5:
-		aun_send_response(ip->saddr, ah->handle, 6, ah->cb);
-		break;
-#endif
-	default:
-		printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]);
-	}
-
-	skb_free_datagram(sk, skb);
-}
-
-/*
- *	Called by the timer to manage the AUN transmit queue.  If a packet
- *	was sent to a dead or nonexistent host then we will never get an
- *	acknowledgement back.  After a few seconds we need to spot this and
- *	drop the packet.
- */
-
-
-static void ab_cleanup(unsigned long h)
-{
-	struct sk_buff *skb;
-	unsigned long flags;
-
-	spin_lock_irqsave(&aun_queue_lock, flags);
-	skb = skb_peek(&aun_queue);
-	while (skb && skb != (struct sk_buff *)&aun_queue)
-	{
-		struct sk_buff *newskb = skb->next;
-		struct ec_cb *eb = (struct ec_cb *)&skb->cb;
-		if ((jiffies - eb->start) > eb->timeout)
-		{
-			tx_result(skb->sk, eb->cookie, 
-				  ECTYPE_TRANSMIT_NOT_PRESENT);
-			skb_unlink(skb);
-		}
-		skb = newskb;
-	}
-	spin_unlock_irqrestore(&aun_queue_lock, flags);
-
-	mod_timer(&ab_cleanup_timer, jiffies + (HZ*2));
-}
-
-static int __init aun_udp_initialise(void)
-{
-	int error;
-	struct sockaddr_in sin;
-
-	skb_queue_head_init(&aun_queue);
-	spin_lock_init(&aun_queue_lock);
-	init_timer(&ab_cleanup_timer);
-	ab_cleanup_timer.expires = jiffies + (HZ*2);
-	ab_cleanup_timer.function = ab_cleanup;
-	add_timer(&ab_cleanup_timer);
-
-	memset(&sin, 0, sizeof(sin));
-	sin.sin_port = htons(AUN_PORT);
-
-	/* We can count ourselves lucky Acorn machines are too dim to
-	   speak IPv6. :-) */
-	if ((error = sock_create(PF_INET, SOCK_DGRAM, 0, &udpsock)) < 0)
-	{
-		printk("AUN: socket error %d\n", -error);
-		return error;
-	}
-	
-	udpsock->sk->reuse = 1;
-	udpsock->sk->allocation = GFP_ATOMIC;	/* we're going to call it
-						   from interrupts */
-	
-	error = udpsock->ops->bind(udpsock, (struct sockaddr *)&sin,
-				sizeof(sin));
-	if (error < 0)
-	{
-		printk("AUN: bind error %d\n", -error);
-		goto release;
-	}
-
-	udpsock->sk->data_ready = aun_data_available;
-
-	return 0;
-
-release:
-	sock_release(udpsock);
-	udpsock = NULL;
-	return error;
-}
-#endif
-
-static int econet_notifier(struct notifier_block *this, unsigned long msg, void *data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct ec_device *edev;
-	unsigned long flags;
-
-	switch (msg) {
-	case NETDEV_UNREGISTER:
-		/* A device has gone down - kill any data we hold for it. */
-		spin_lock_irqsave(&edevlist_lock, flags);
-		for (edev = edevlist; edev; edev = edev->next)
-		{
-			if (edev->dev == dev)
-			{
-				if (edev->prev)
-					edev->prev->next = edev->next;
-				else
-					edevlist = edev->next;
-				if (edev->next)
-					edev->next->prev = edev->prev;
-				kfree(edev);
-				break;
-			}
-		}
-		spin_unlock_irqrestore(&edevlist_lock, flags);
-		break;
-	}
-
-	return NOTIFY_DONE;
-}
-
-struct notifier_block econet_netdev_notifier={
-	econet_notifier,
-	NULL,
-	0
-};
-
-#ifdef MODULE
-void cleanup_module(void)
-{
-#ifdef CONFIG_ECONET_AUNUDP
-	del_timer(&ab_cleanup_timer);
-	if (udpsock)
-		sock_release(udpsock);
-#endif
-	unregister_netdevice_notifier(&econet_netdev_notifier);
-	sock_unregister(econet_family_ops.family);
-	return;
-}
-
-int init_module(void)
-#else
-void __init econet_proto_init(struct net_proto *pro)
-#endif
-{
-	spin_lock_init(&edevlist_lock);
-	spin_lock_init(&aun_queue_lock);
-	/* Stop warnings from happening on UP systems. */
-	(void)edevlist_lock;
-	(void)aun_queue_lock;
-	sock_register(&econet_family_ops);
-#ifdef CONFIG_ECONET_AUNUDP
-	aun_udp_initialise();
-#endif
-	register_netdevice_notifier(&econet_netdev_notifier);
-#ifdef MODULE
-	return 0;
-#endif
-}
diff -u --recursive --new-file v2.3.50/linux/net/econet/sysctl_net_ec.c linux/net/econet/sysctl_net_ec.c
--- v2.3.50/linux/net/econet/sysctl_net_ec.c	Wed Dec 31 16:00:00 1969
+++ linux/net/econet/sysctl_net_ec.c	Thu Mar  9 06:57:17 2000
@@ -0,0 +1,43 @@
+/*
+ *	An implementation of the Acorn Econet and AUN protocols.
+ *	Philip Blundell <philb@gnu.org>
+ *
+ *	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.
+ *
+ */
+
+#include <linux/mm.h>
+#include <linux/sysctl.h>
+
+ctl_table econet_table[] = {
+	{0}
+};
+
+static struct ctl_table_header *econet_sysctl_header;
+
+static ctl_table econet_net_table[] = {
+	{NET_ECONET, "econet", NULL, 0, 0555, econet_table},
+        {0}
+};
+
+static ctl_table econet_root_table[] = {
+	{CTL_NET, "net", NULL, 0, 0555, econet_net_table},
+        {0}
+};
+
+void econet_sysctl_register(void)
+{
+	econet_sysctl_header = register_sysctl_table(econet_root_table, 0);
+}
+
+#ifdef MODULE
+void econet_sysctl_unregister(void)
+{
+	unregister_sysctl_table(econet_sysctl_header);
+}
+#endif	/* MODULE */
diff -u --recursive --new-file v2.3.50/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.3.50/linux/net/ipv4/tcp.c	Thu Feb 10 17:11:24 2000
+++ linux/net/ipv4/tcp.c	Thu Mar  9 06:57:17 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.163 2000/02/08 21:27:13 davem Exp $
+ * Version:	$Id: tcp.c,v 1.164 2000/03/08 19:36:40 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -624,28 +624,29 @@
 	tp->listen_opt = lopt;
 	write_unlock_bh(&tp->syn_wait_lock);
 
+	/* There is race window here: we announce ourselves listening,
+	 * but this transition is still not validated by get_port().
+	 * It is OK, because this socket enters to hash table only
+	 * after validation is complete.
+	 */
 	sk->state = TCP_LISTEN;
-	if (sk->num == 0) {
-		if (sk->prot->get_port(sk, 0) != 0) {
-			sk->state = TCP_CLOSE;
-			write_lock_bh(&tp->syn_wait_lock);
-			tp->listen_opt = NULL;
-			write_unlock_bh(&tp->syn_wait_lock);
-			kfree(lopt);
-			return -EAGAIN;
-		}
+	if (sk->prot->get_port(sk, sk->num) == 0) {
 		sk->sport = htons(sk->num);
-	} else {
-		if (sk->prev)
-			((struct tcp_bind_bucket*)sk->prev)->fastreuse = 0;
-	}
 
-	sk_dst_reset(sk);
-	sk->prot->hash(sk);
-	sk->socket->flags |= SO_ACCEPTCON;
-	sk->write_space = tcp_listen_write_space;
+		sk->write_space = tcp_listen_write_space;
+		sk_dst_reset(sk);
+		sk->prot->hash(sk);
+		sk->socket->flags |= SO_ACCEPTCON;
 
-	return 0;
+		return 0;
+	}
+
+	sk->state = TCP_CLOSE;
+	write_lock_bh(&tp->syn_wait_lock);
+	tp->listen_opt = NULL;
+	write_unlock_bh(&tp->syn_wait_lock);
+	kfree(lopt);
+	return -EADDRINUSE;
 }
 
 /*
diff -u --recursive --new-file v2.3.50/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.3.50/linux/net/ipv4/tcp_ipv4.c	Sat Feb 12 11:22:11 2000
+++ linux/net/ipv4/tcp_ipv4.c	Thu Mar  9 06:57:17 2000
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_ipv4.c,v 1.200 2000/02/11 22:27:26 davem Exp $
+ * Version:	$Id: tcp_ipv4.c,v 1.201 2000/03/08 19:36:42 davem Exp $
  *
  *		IPv4 specific functions
  *
@@ -231,14 +231,15 @@
 				break;
 	}
 	if (tb != NULL && tb->owners != NULL) {
-		if (tb->fastreuse != 0 && sk->reuse != 0) {
+		if (tb->fastreuse != 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
 			goto success;
 		} else {
 			struct sock *sk2 = tb->owners;
 			int sk_reuse = sk->reuse;
 
 			for( ; sk2 != NULL; sk2 = sk2->bind_next) {
-				if (sk->bound_dev_if == sk2->bound_dev_if) {
+				if (sk != sk2 &&
+				    sk->bound_dev_if == sk2->bound_dev_if) {
 					if (!sk_reuse	||
 					    !sk2->reuse	||
 					    sk2->state == TCP_LISTEN) {
@@ -269,11 +270,15 @@
 		tb->fastreuse = 0;
 success:
 	sk->num = snum;
-	if ((sk->bind_next = tb->owners) != NULL)
-		tb->owners->bind_pprev = &sk->bind_next;
-	tb->owners = sk;
-	sk->bind_pprev = &tb->owners;
-	sk->prev = (struct sock *) tb;
+	if (sk->prev == NULL) {
+		if ((sk->bind_next = tb->owners) != NULL)
+			tb->owners->bind_pprev = &sk->bind_next;
+		tb->owners = sk;
+		sk->bind_pprev = &tb->owners;
+		sk->prev = (struct sock *) tb;
+	} else {
+		BUG_TRAP(sk->prev == (struct sock *) tb);
+	}
 	ret = 0;
 
 fail_unlock:
diff -u --recursive --new-file v2.3.50/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.3.50/linux/net/ipv6/tcp_ipv6.c	Thu Mar  2 14:36:23 2000
+++ linux/net/ipv6/tcp_ipv6.c	Thu Mar  9 06:57:17 2000
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.120 2000/02/27 19:51:49 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.121 2000/03/08 19:36:47 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -132,7 +132,7 @@
 				break;
 	}
 	if (tb != NULL && tb->owners != NULL) {
-		if (tb->fastreuse != 0 && sk->reuse != 0) {
+		if (tb->fastreuse != 0 && sk->reuse != 0 && sk->state != TCP_LISTEN) {
 			goto success;
 		} else {
 			struct sock *sk2 = tb->owners;
@@ -141,7 +141,8 @@
 
 			/* We must walk the whole port owner list in this case. -DaveM */
 			for( ; sk2 != NULL; sk2 = sk2->bind_next) {
-				if (sk->bound_dev_if == sk2->bound_dev_if) {
+				if (sk != sk2 &&
+				    sk->bound_dev_if == sk2->bound_dev_if) {
 					if (!sk_reuse	||
 					    !sk2->reuse	||
 					    sk2->state == TCP_LISTEN) {
@@ -177,11 +178,15 @@
 
 success:
 	sk->num = snum;
-	if ((sk->bind_next = tb->owners) != NULL)
-		tb->owners->bind_pprev = &sk->bind_next;
-	tb->owners = sk;
-	sk->bind_pprev = &tb->owners;
-	sk->prev = (struct sock *) tb;
+	if (sk->prev == NULL) {
+		if ((sk->bind_next = tb->owners) != NULL)
+			tb->owners->bind_pprev = &sk->bind_next;
+		tb->owners = sk;
+		sk->bind_pprev = &tb->owners;
+		sk->prev = (struct sock *) tb;
+	} else {
+		BUG_TRAP(sk->prev == (struct sock *) tb);
+	}
 	ret = 0;
 
 fail_unlock:
diff -u --recursive --new-file v2.3.50/linux/net/netsyms.c linux/net/netsyms.c
--- v2.3.50/linux/net/netsyms.c	Tue Mar  7 14:32:26 2000
+++ linux/net/netsyms.c	Fri Mar 10 16:12:16 2000
@@ -216,8 +216,10 @@
 
 #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
 EXPORT_SYMBOL(br_handle_frame_hook);
+#ifdef CONFIG_INET
 EXPORT_SYMBOL(br_ioctl_hook);
 #endif
+#endif
 
 #ifdef CONFIG_INET
 /* Internet layer registration */
@@ -534,7 +536,9 @@
 #ifdef CONFIG_SYSCTL
 EXPORT_SYMBOL(sysctl_wmem_max);
 EXPORT_SYMBOL(sysctl_rmem_max);
+#ifdef CONFIG_INET
 EXPORT_SYMBOL(sysctl_ip_default_ttl);
+#endif
 #endif
 
 #if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE) 
diff -u --recursive --new-file v2.3.50/linux/net/sysctl_net.c linux/net/sysctl_net.c
--- v2.3.50/linux/net/sysctl_net.c	Sun Feb 20 21:12:40 2000
+++ linux/net/sysctl_net.c	Thu Mar  9 06:57:17 2000
@@ -42,6 +42,10 @@
 extern ctl_table tr_table[];
 #endif
 
+#ifdef CONFIG_ECONET
+extern ctl_table econet_table[];
+#endif
+
 ctl_table net_table[] = {
 	{NET_CORE,   "core",      NULL, 0, 0555, core_table},      
 #ifdef CONFIG_UNIX
@@ -62,6 +66,9 @@
 #endif
 #ifdef CONFIG_TR
 	{NET_TR, "token-ring", NULL, 0, 0555, tr_table},
+#endif
+#ifdef CONFIG_ECONET
+	{NET_ECONET, "econet",    NULL, 0, 0555, econet_table},
 #endif
 	{0}
 };
